]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/I2c/I2cDxe/I2cHost.c
MdeModulePkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / MdeModulePkg / Bus / I2c / I2cDxe / I2cHost.c
1 /** @file
2 This file implements I2C Host Protocol which provides callers with the ability to
3 do I/O transactions to all of the devices on the I2C bus.
4
5 Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
6 Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "I2cDxe.h"
12
13 EFI_DRIVER_BINDING_PROTOCOL gI2cHostDriverBinding = {
14 I2cHostDriverSupported,
15 I2cHostDriverStart,
16 I2cHostDriverStop,
17 0x10,
18 NULL,
19 NULL
20 };
21
22 //
23 // Driver name table
24 //
25 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mI2cHostDriverNameTable[] = {
26 { "eng;en", L"I2c Host Driver" },
27 { NULL , NULL }
28 };
29
30 //
31 // EFI Component Name Protocol
32 //
33 GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gI2cHostComponentName = {
34 (EFI_COMPONENT_NAME_GET_DRIVER_NAME) I2cHostComponentNameGetDriverName,
35 (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) I2cHostComponentNameGetControllerName,
36 "eng"
37 };
38
39 //
40 // EFI Component Name 2 Protocol
41 //
42 GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gI2cHostComponentName2 = {
43 I2cHostComponentNameGetDriverName,
44 I2cHostComponentNameGetControllerName,
45 "en"
46 };
47
48 /**
49 Retrieves a Unicode string that is the user readable name of the driver.
50
51 This function retrieves the user readable name of a driver in the form of a
52 Unicode string. If the driver specified by This has a user readable name in
53 the language specified by Language, then a pointer to the driver name is
54 returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
55 by This does not support the language specified by Language,
56 then EFI_UNSUPPORTED is returned.
57
58 @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
59 EFI_COMPONENT_NAME_PROTOCOL instance.
60
61 @param Language[in] A pointer to a Null-terminated ASCII string
62 array indicating the language. This is the
63 language of the driver name that the caller is
64 requesting, and it must match one of the
65 languages specified in SupportedLanguages. The
66 number of languages supported by a driver is up
67 to the driver writer. Language is specified
68 in RFC 4646 or ISO 639-2 language code format.
69
70 @param DriverName[out] A pointer to the Unicode string to return.
71 This Unicode string is the name of the
72 driver specified by This in the language
73 specified by Language.
74
75 @retval EFI_SUCCESS The Unicode string for the Driver specified by
76 This and the language specified by Language was
77 returned in DriverName.
78
79 @retval EFI_INVALID_PARAMETER Language is NULL.
80
81 @retval EFI_INVALID_PARAMETER DriverName is NULL.
82
83 @retval EFI_UNSUPPORTED The driver specified by This does not support
84 the language specified by Language.
85
86 **/
87 EFI_STATUS
88 EFIAPI
89 I2cHostComponentNameGetDriverName (
90 IN EFI_COMPONENT_NAME2_PROTOCOL *This,
91 IN CHAR8 *Language,
92 OUT CHAR16 **DriverName
93 )
94 {
95 return LookupUnicodeString2 (
96 Language,
97 This->SupportedLanguages,
98 mI2cHostDriverNameTable,
99 DriverName,
100 (BOOLEAN)(This != &gI2cHostComponentName2)
101 );
102 }
103
104 /**
105 Retrieves a Unicode string that is the user readable name of the controller
106 that is being managed by a driver.
107
108 This function retrieves the user readable name of the controller specified by
109 ControllerHandle and ChildHandle in the form of a Unicode string. If the
110 driver specified by This has a user readable name in the language specified by
111 Language, then a pointer to the controller name is returned in ControllerName,
112 and EFI_SUCCESS is returned. If the driver specified by This is not currently
113 managing the controller specified by ControllerHandle and ChildHandle,
114 then EFI_UNSUPPORTED is returned. If the driver specified by This does not
115 support the language specified by Language, then EFI_UNSUPPORTED is returned.
116
117 @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
118 EFI_COMPONENT_NAME_PROTOCOL instance.
119
120 @param ControllerHandle[in] The handle of a controller that the driver
121 specified by This is managing. This handle
122 specifies the controller whose name is to be
123 returned.
124
125 @param ChildHandle[in] The handle of the child controller to retrieve
126 the name of. This is an optional parameter that
127 may be NULL. It will be NULL for device
128 drivers. It will also be NULL for a bus drivers
129 that wish to retrieve the name of the bus
130 controller. It will not be NULL for a bus
131 driver that wishes to retrieve the name of a
132 child controller.
133
134 @param Language[in] A pointer to a Null-terminated ASCII string
135 array indicating the language. This is the
136 language of the driver name that the caller is
137 requesting, and it must match one of the
138 languages specified in SupportedLanguages. The
139 number of languages supported by a driver is up
140 to the driver writer. Language is specified in
141 RFC 4646 or ISO 639-2 language code format.
142
143 @param ControllerName[out] A pointer to the Unicode string to return.
144 This Unicode string is the name of the
145 controller specified by ControllerHandle and
146 ChildHandle in the language specified by
147 Language from the point of view of the driver
148 specified by This.
149
150 @retval EFI_SUCCESS The Unicode string for the user readable name in
151 the language specified by Language for the
152 driver specified by This was returned in
153 DriverName.
154
155 @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
156
157 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
158 EFI_HANDLE.
159
160 @retval EFI_INVALID_PARAMETER Language is NULL.
161
162 @retval EFI_INVALID_PARAMETER ControllerName is NULL.
163
164 @retval EFI_UNSUPPORTED The driver specified by This is not currently
165 managing the controller specified by
166 ControllerHandle and ChildHandle.
167
168 @retval EFI_UNSUPPORTED The driver specified by This does not support
169 the language specified by Language.
170
171 **/
172 EFI_STATUS
173 EFIAPI
174 I2cHostComponentNameGetControllerName (
175 IN EFI_COMPONENT_NAME2_PROTOCOL *This,
176 IN EFI_HANDLE ControllerHandle,
177 IN EFI_HANDLE ChildHandle OPTIONAL,
178 IN CHAR8 *Language,
179 OUT CHAR16 **ControllerName
180 )
181 {
182 return EFI_UNSUPPORTED;
183 }
184
185 /**
186 Tests to see if this driver supports a given controller. If a child device is provided,
187 it further tests to see if this driver supports creating a handle for the specified child device.
188
189 This function checks to see if the driver specified by This supports the device specified by
190 ControllerHandle. Drivers will typically use the device path attached to
191 ControllerHandle and/or the services from the bus I/O abstraction attached to
192 ControllerHandle to determine if the driver supports ControllerHandle. This function
193 may be called many times during platform initialization. In order to reduce boot times, the tests
194 performed by this function must be very small, and take as little time as possible to execute. This
195 function must not change the state of any hardware devices, and this function must be aware that the
196 device specified by ControllerHandle may already be managed by the same driver or a
197 different driver. This function must match its calls to AllocatePages() with FreePages(),
198 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
199 Since ControllerHandle may have been previously started by the same driver, if a protocol is
200 already in the opened state, then it must not be closed with CloseProtocol(). This is required
201 to guarantee the state of ControllerHandle is not modified by this function.
202
203 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
204 @param[in] ControllerHandle The handle of the controller to test. This handle
205 must support a protocol interface that supplies
206 an I/O abstraction to the driver.
207 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
208 parameter is ignored by device drivers, and is optional for bus
209 drivers. For bus drivers, if this parameter is not NULL, then
210 the bus driver must determine if the bus controller specified
211 by ControllerHandle and the child controller specified
212 by RemainingDevicePath are both supported by this
213 bus driver.
214
215 @retval EFI_SUCCESS The device specified by ControllerHandle and
216 RemainingDevicePath is supported by the driver specified by This.
217 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
218 RemainingDevicePath is already being managed by the driver
219 specified by This.
220 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
221 RemainingDevicePath is already being managed by a different
222 driver or an application that requires exclusive access.
223 Currently not implemented.
224 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
225 RemainingDevicePath is not supported by the driver specified by This.
226 **/
227 EFI_STATUS
228 EFIAPI
229 I2cHostDriverSupported (
230 IN EFI_DRIVER_BINDING_PROTOCOL *This,
231 IN EFI_HANDLE Controller,
232 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
233 )
234 {
235 EFI_I2C_MASTER_PROTOCOL *I2cMaster;
236 EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
237 EFI_STATUS Status;
238
239 //
240 // Locate I2C Bus Configuration Management Protocol
241 //
242 Status = gBS->OpenProtocol (
243 Controller,
244 &gEfiI2cBusConfigurationManagementProtocolGuid,
245 (VOID **)&I2cBusConfigurationManagement,
246 This->DriverBindingHandle,
247 Controller,
248 EFI_OPEN_PROTOCOL_BY_DRIVER
249 );
250 if (EFI_ERROR (Status)) {
251 return Status;
252 }
253
254 //
255 // Close the protocol because we don't use it here
256 //
257 gBS->CloseProtocol (
258 Controller,
259 &gEfiI2cBusConfigurationManagementProtocolGuid,
260 This->DriverBindingHandle,
261 Controller
262 );
263
264 //
265 // Locate I2C Master Protocol
266 //
267 Status = gBS->OpenProtocol (
268 Controller,
269 &gEfiI2cMasterProtocolGuid,
270 (VOID **)&I2cMaster,
271 This->DriverBindingHandle,
272 Controller,
273 EFI_OPEN_PROTOCOL_GET_PROTOCOL
274 );
275 if (EFI_ERROR (Status)) {
276 return Status;
277 }
278
279 return EFI_SUCCESS;
280 }
281
282 /**
283 Starts a device controller or a bus controller.
284
285 The Start() function is designed to be invoked from the EFI boot service ConnectController().
286 As a result, much of the error checking on the parameters to Start() has been moved into this
287 common boot service. It is legal to call Start() from other locations,
288 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
289 1. ControllerHandle must be a valid EFI_HANDLE.
290 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
291 EFI_DEVICE_PATH_PROTOCOL.
292 3. Prior to calling Start(), the Supported() function for the driver specified by This must
293 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
294
295 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
296 @param[in] ControllerHandle The handle of the controller to start. This handle
297 must support a protocol interface that supplies
298 an I/O abstraction to the driver.
299 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
300 parameter is ignored by device drivers, and is optional for bus
301 drivers. For a bus driver, if this parameter is NULL, then handles
302 for all the children of Controller are created by this driver.
303 If this parameter is not NULL and the first Device Path Node is
304 not the End of Device Path Node, then only the handle for the
305 child device specified by the first Device Path Node of
306 RemainingDevicePath is created by this driver.
307 If the first Device Path Node of RemainingDevicePath is
308 the End of Device Path Node, no child handle is created by this
309 driver.
310
311 @retval EFI_SUCCESS The device was started.
312 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
313 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
314 @retval Others The driver failed to start the device.
315
316 **/
317 EFI_STATUS
318 EFIAPI
319 I2cHostDriverStart (
320 IN EFI_DRIVER_BINDING_PROTOCOL *This,
321 IN EFI_HANDLE Controller,
322 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
323 )
324 {
325 EFI_STATUS Status;
326 EFI_I2C_MASTER_PROTOCOL *I2cMaster;
327 EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
328 I2C_HOST_CONTEXT *I2cHostContext;
329
330 I2cMaster = NULL;
331 I2cHostContext = NULL;
332 I2cBusConfigurationManagement = NULL;
333
334 //
335 // Locate I2C Bus Configuration Management Protocol
336 //
337 Status = gBS->OpenProtocol (
338 Controller,
339 &gEfiI2cBusConfigurationManagementProtocolGuid,
340 (VOID **)&I2cBusConfigurationManagement,
341 This->DriverBindingHandle,
342 Controller,
343 EFI_OPEN_PROTOCOL_BY_DRIVER
344 );
345 if (EFI_ERROR (Status)) {
346 DEBUG ((DEBUG_ERROR, "I2cHost: Open I2C bus configuration error, Status = %r\n", Status));
347 return Status;
348 }
349
350 //
351 // Locate I2C Master Protocol
352 //
353 Status = gBS->OpenProtocol (
354 Controller,
355 &gEfiI2cMasterProtocolGuid,
356 (VOID **)&I2cMaster,
357 This->DriverBindingHandle,
358 Controller,
359 EFI_OPEN_PROTOCOL_GET_PROTOCOL
360 );
361 if (EFI_ERROR (Status)) {
362 DEBUG ((DEBUG_ERROR, "I2cHost: Open I2C master error, Status = %r\n", Status));
363 goto Exit;
364 }
365
366 //
367 // Allocate the I2C Host Context structure
368 //
369 I2cHostContext = AllocateZeroPool (sizeof (I2C_HOST_CONTEXT));
370 if (I2cHostContext == NULL) {
371 DEBUG ((DEBUG_ERROR, "I2cHost: there is no enough memory to allocate.\n"));
372 Status = EFI_OUT_OF_RESOURCES;
373 goto Exit;
374 }
375
376 //
377 // Initialize the context structure for the current I2C Controller
378 //
379 I2cHostContext->Signature = I2C_HOST_SIGNATURE;
380 I2cHostContext->I2cMaster = I2cMaster;
381 I2cHostContext->I2cBusConfigurationManagement = I2cBusConfigurationManagement;
382 I2cHostContext->I2cBusConfiguration = (UINTN) -1;
383 InitializeListHead(&I2cHostContext->RequestList);
384
385 //
386 // Reset the controller
387 //
388 Status = I2cMaster->Reset (I2cMaster);
389 if (EFI_ERROR (Status)) {
390 DEBUG ((DEBUG_ERROR, "I2cHost: I2C controller reset failed!\n"));
391 goto Exit;
392 }
393
394 //
395 // Create the I2C transaction complete event
396 //
397 Status = gBS->CreateEvent (
398 EVT_NOTIFY_SIGNAL,
399 TPL_I2C_SYNC,
400 I2cHostRequestCompleteEvent,
401 I2cHostContext,
402 &I2cHostContext->I2cEvent
403 );
404 if (EFI_ERROR (Status)) {
405 DEBUG ((DEBUG_ERROR, "I2cHost: create complete event error, Status = %r\n", Status));
406 goto Exit;
407 }
408
409 //
410 // Get the bus management event
411 //
412 Status = gBS->CreateEvent (
413 EVT_NOTIFY_SIGNAL,
414 TPL_I2C_SYNC,
415 I2cHostI2cBusConfigurationAvailable,
416 I2cHostContext,
417 &I2cHostContext->I2cBusConfigurationEvent
418 );
419 if (EFI_ERROR (Status)) {
420 DEBUG ((DEBUG_ERROR, "I2cHost: create bus available event error, Status = %r\n", Status));
421 goto Exit;
422 }
423
424 //
425 // Build the I2C host protocol for the current I2C controller
426 //
427 I2cHostContext->I2cHost.QueueRequest = I2cHostQueueRequest;
428 I2cHostContext->I2cHost.I2cControllerCapabilities = I2cMaster->I2cControllerCapabilities;
429
430 //
431 // Install the driver protocol
432 //
433 Status = gBS->InstallMultipleProtocolInterfaces (
434 &Controller,
435 &gEfiI2cHostProtocolGuid,
436 &I2cHostContext->I2cHost,
437 NULL
438 );
439 Exit:
440 if (EFI_ERROR (Status)) {
441 DEBUG ((DEBUG_ERROR, "I2cHost: Start() function failed, Status = %r\n", Status));
442 if (I2cBusConfigurationManagement != NULL) {
443 gBS->CloseProtocol (
444 Controller,
445 &gEfiI2cBusConfigurationManagementProtocolGuid,
446 This->DriverBindingHandle,
447 Controller
448 );
449 }
450
451 if ((I2cHostContext != NULL) && (I2cHostContext->I2cEvent != NULL)) {
452 gBS->CloseEvent (I2cHostContext->I2cEvent);
453 I2cHostContext->I2cEvent = NULL;
454 }
455
456 if ((I2cHostContext != NULL) && (I2cHostContext->I2cBusConfigurationEvent != NULL)) {
457 gBS->CloseEvent (I2cHostContext->I2cBusConfigurationEvent);
458 I2cHostContext->I2cBusConfigurationEvent = NULL;
459 }
460
461 //
462 // Release the context structure upon failure
463 //
464 if (I2cHostContext != NULL) {
465 FreePool (I2cHostContext);
466 }
467 }
468
469 //
470 // Return the operation status.
471 //
472 return Status;
473 }
474
475 /**
476 Stops a device controller or a bus controller.
477
478 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
479 As a result, much of the error checking on the parameters to Stop() has been moved
480 into this common boot service. It is legal to call Stop() from other locations,
481 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
482 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
483 same driver's Start() function.
484 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
485 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
486 Start() function, and the Start() function must have called OpenProtocol() on
487 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
488
489 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
490 @param[in] ControllerHandle A handle to the device being stopped. The handle must
491 support a bus specific I/O protocol for the driver
492 to use to stop the device.
493 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
494 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
495 if NumberOfChildren is 0.
496
497 @retval EFI_SUCCESS The device was stopped.
498 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
499
500 **/
501 EFI_STATUS
502 EFIAPI
503 I2cHostDriverStop (
504 IN EFI_DRIVER_BINDING_PROTOCOL *This,
505 IN EFI_HANDLE Controller,
506 IN UINTN NumberOfChildren,
507 IN EFI_HANDLE *ChildHandleBuffer
508 )
509 {
510 EFI_STATUS Status;
511 I2C_HOST_CONTEXT *I2cHostContext;
512 EFI_I2C_HOST_PROTOCOL *I2cHost;
513 EFI_TPL TplPrevious;
514
515 TplPrevious = EfiGetCurrentTpl ();
516 if (TplPrevious > TPL_I2C_SYNC) {
517 DEBUG ((DEBUG_ERROR, "I2cHost: TPL %d is too high in Stop.\n", TplPrevious));
518 return EFI_DEVICE_ERROR;
519 }
520
521 Status = gBS->OpenProtocol (
522 Controller,
523 &gEfiI2cHostProtocolGuid,
524 (VOID **) &I2cHost,
525 This->DriverBindingHandle,
526 Controller,
527 EFI_OPEN_PROTOCOL_GET_PROTOCOL
528 );
529
530 if (EFI_ERROR (Status)) {
531 return EFI_DEVICE_ERROR;
532 }
533
534 I2cHostContext = I2C_HOST_CONTEXT_FROM_PROTOCOL (I2cHost);
535
536 //
537 // Raise TPL for critical section
538 //
539 TplPrevious = gBS->RaiseTPL (TPL_I2C_SYNC);
540
541 //
542 // If there is pending request or pending bus configuration, do not stop
543 //
544 Status = EFI_DEVICE_ERROR;
545 if (( !I2cHostContext->I2cBusConfigurationManagementPending )
546 && IsListEmpty (&I2cHostContext->RequestList)) {
547
548 //
549 // Remove the I2C host protocol
550 //
551 Status = gBS->UninstallMultipleProtocolInterfaces (
552 Controller,
553 &gEfiI2cHostProtocolGuid,
554 I2cHost,
555 NULL
556 );
557 }
558
559 //
560 // Leave critical section
561 //
562 gBS->RestoreTPL (TplPrevious);
563 if (!EFI_ERROR (Status)) {
564 gBS->CloseProtocol (
565 Controller,
566 &gEfiI2cBusConfigurationManagementProtocolGuid,
567 This->DriverBindingHandle,
568 Controller
569 );
570
571 //
572 // Release I2c Host resources
573 //
574 if (I2cHostContext->I2cBusConfigurationEvent != NULL) {
575 gBS->CloseEvent (I2cHostContext->I2cBusConfigurationEvent);
576 I2cHostContext->I2cBusConfigurationEvent = NULL;
577 }
578
579 if (I2cHostContext->I2cEvent != NULL) {
580 gBS->CloseEvent (I2cHostContext->I2cEvent);
581 I2cHostContext->I2cEvent = NULL;
582 }
583
584 FreePool (I2cHostContext);
585 }
586
587 //
588 // Return the stop status
589 //
590 return Status;
591 }
592
593 /**
594 Handle the I2C bus configuration available event
595
596 This routine is called at TPL_I2C_SYNC.
597
598 @param[in] Event Address of an EFI_EVENT handle
599 @param[in] Context Address of an I2C_HOST_CONTEXT structure
600
601 **/
602 VOID
603 EFIAPI
604 I2cHostI2cBusConfigurationAvailable (
605 IN EFI_EVENT Event,
606 IN VOID *Context
607 )
608 {
609 I2C_HOST_CONTEXT *I2cHostContext;
610 EFI_I2C_MASTER_PROTOCOL *I2cMaster;
611 I2C_REQUEST *I2cRequest;
612 LIST_ENTRY *EntryHeader;
613 LIST_ENTRY *Entry;
614 EFI_STATUS Status;
615
616 //
617 // Mark this I2C bus configuration management operation as complete
618 //
619 I2cHostContext = (I2C_HOST_CONTEXT *)Context;
620 I2cMaster = I2cHostContext->I2cMaster;
621 ASSERT (I2cMaster != NULL);
622 //
623 // Clear flag to indicate I2C bus configuration is finished
624 //
625 I2cHostContext->I2cBusConfigurationManagementPending = FALSE;
626
627 //
628 // Validate the completion status
629 //
630 if (EFI_ERROR (I2cHostContext->Status)) {
631 //
632 // Setting I2C bus configuration failed before
633 //
634 I2cHostRequestComplete (I2cHostContext, I2cHostContext->Status);
635
636 //
637 // Unknown I2C bus configuration
638 // Force next operation to enable the I2C bus configuration
639 //
640 I2cHostContext->I2cBusConfiguration = (UINTN) -1;
641
642 //
643 // Do not continue current I2C request
644 //
645 return;
646 }
647
648 //
649 // Get the first request in the link with FIFO order
650 //
651 EntryHeader = &I2cHostContext->RequestList;
652 Entry = GetFirstNode (EntryHeader);
653 I2cRequest = I2C_REQUEST_FROM_ENTRY (Entry);
654
655 //
656 // Update the I2C bus configuration of the current I2C request
657 //
658 I2cHostContext->I2cBusConfiguration = I2cRequest->I2cBusConfiguration;
659
660 //
661 // Start an I2C operation on the host, the status is returned by I2cHostContext->Status
662 //
663 Status = I2cMaster->StartRequest (
664 I2cMaster,
665 I2cRequest->SlaveAddress,
666 I2cRequest->RequestPacket,
667 I2cHostContext->I2cEvent,
668 &I2cHostContext->Status
669 );
670
671 if (EFI_ERROR (Status)) {
672 DEBUG((DEBUG_ERROR, "I2cHostI2cBusConfigurationAvailable: Error starting I2C operation, %r\n", Status));
673 }
674 }
675
676 /**
677 Complete the current request
678
679 This routine is called at TPL_I2C_SYNC.
680
681 @param[in] I2cHostContext Address of an I2C_HOST_CONTEXT structure.
682 @param[in] Status Status of the I2C operation.
683
684 @return This routine returns the input status value.
685
686 **/
687 EFI_STATUS
688 I2cHostRequestComplete (
689 I2C_HOST_CONTEXT *I2cHostContext,
690 EFI_STATUS Status
691 )
692 {
693 I2C_REQUEST *I2cRequest;
694 LIST_ENTRY *EntryHeader;
695 LIST_ENTRY *Entry;
696
697 //
698 // Remove the current I2C request from the list
699 //
700 EntryHeader = &I2cHostContext->RequestList;
701 Entry = GetFirstNode (EntryHeader);
702 I2cRequest = I2C_REQUEST_FROM_ENTRY (Entry);
703
704 //
705 // Save the status for QueueRequest
706 //
707 if ( NULL != I2cRequest->Status ) {
708 *I2cRequest->Status = Status;
709 }
710
711 //
712 // Notify the user of the I2C request completion
713 //
714 if ( NULL != I2cRequest->Event ) {
715 gBS->SignalEvent (I2cRequest->Event);
716 }
717
718 //
719 // Done with this request, remove the current request from list
720 //
721 RemoveEntryList (&I2cRequest->Link);
722 FreePool (I2cRequest->RequestPacket);
723 FreePool (I2cRequest);
724
725 //
726 // If there is more I2C request, start next one
727 //
728 if(!IsListEmpty (EntryHeader)) {
729 I2cHostRequestEnable (I2cHostContext);
730 }
731
732 return Status;
733 }
734
735 /**
736 Handle the bus available event
737
738 This routine is called at TPL_I2C_SYNC.
739
740 @param[in] Event Address of an EFI_EVENT handle
741 @param[in] Context Address of an I2C_HOST_CONTEXT structure
742
743 **/
744 VOID
745 EFIAPI
746 I2cHostRequestCompleteEvent (
747 IN EFI_EVENT Event,
748 IN VOID *Context
749 )
750 {
751 I2C_HOST_CONTEXT *I2cHostContext;
752
753 //
754 // Handle the completion event
755 //
756 I2cHostContext = (I2C_HOST_CONTEXT *)Context;
757 I2cHostRequestComplete (I2cHostContext, I2cHostContext->Status);
758 }
759
760 /**
761 Enable access to the I2C bus configuration
762
763 @param[in] I2cHostContext Address of an I2C_HOST_CONTEXT structure
764
765 @retval EFI_SUCCESS The operation completed successfully.
766 @retval EFI_ABORTED The request did not complete because the driver
767 was shutdown.
768 @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large.
769 @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation.
770 This could indicate the slave device is not present.
771 @retval EFI_INVALID_PARAMETER RequestPacket is NULL
772 @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value
773 @retval EFI_NO_RESPONSE The I2C device is not responding to the
774 slave address. EFI_DEVICE_ERROR may also be
775 returned if the controller can not distinguish
776 when the NACK occurred.
777 @retval EFI_NOT_FOUND I2C slave address exceeds maximum address
778 @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for
779 the event and then read status.
780 @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation
781 @retval EFI_TIMEOUT The transaction did not complete within an internally
782 specified timeout period.
783
784 **/
785 EFI_STATUS
786 I2cHostRequestEnable (
787 I2C_HOST_CONTEXT *I2cHostContext
788 )
789 {
790 UINTN I2cBusConfiguration;
791 CONST EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
792 I2C_REQUEST *I2cRequest;
793 EFI_STATUS Status;
794 EFI_TPL TplPrevious;
795 LIST_ENTRY *EntryHeader;
796 LIST_ENTRY *Entry;
797
798 //
799 // Assume pending request
800 //
801 Status = EFI_NOT_READY;
802
803 I2cBusConfigurationManagement = I2cHostContext->I2cBusConfigurationManagement;
804
805 //
806 // Validate the I2c bus configuration
807 //
808 EntryHeader = &I2cHostContext->RequestList;
809 Entry = GetFirstNode (EntryHeader);
810 I2cRequest = I2C_REQUEST_FROM_ENTRY (Entry);
811
812 I2cBusConfiguration = I2cRequest->I2cBusConfiguration;
813
814 if (I2cHostContext->I2cBusConfiguration != I2cBusConfiguration ) {
815 //
816 // Set flag to indicate I2C bus configuration is in progress
817 //
818 I2cHostContext->I2cBusConfigurationManagementPending = TRUE;
819 //
820 // Update bus configuration for this device's requesting bus configuration
821 //
822 Status = I2cBusConfigurationManagement->EnableI2cBusConfiguration (
823 I2cBusConfigurationManagement,
824 I2cBusConfiguration,
825 I2cHostContext->I2cBusConfigurationEvent,
826 &I2cHostContext->Status
827 );
828 } else {
829 //
830 // I2C bus configuration is same, no need change configuration and start I2c transaction directly
831 //
832 TplPrevious = gBS->RaiseTPL ( TPL_I2C_SYNC );
833
834 //
835 // Same I2C bus configuration
836 //
837 I2cHostContext->Status = EFI_SUCCESS;
838 I2cHostI2cBusConfigurationAvailable (I2cHostContext->I2cBusConfigurationEvent, I2cHostContext);
839
840 //
841 // Release the thread synchronization
842 //
843 gBS->RestoreTPL ( TplPrevious );
844 }
845 return Status;
846 }
847
848 /**
849 Queue an I2C operation for execution on the I2C controller.
850
851 This routine must be called at or below TPL_NOTIFY. For synchronous
852 requests this routine must be called at or below TPL_CALLBACK.
853
854 N.B. The typical consumers of this API are the I2C bus driver and
855 on rare occasions the I2C test application. Extreme care must be
856 taken by other consumers of this API to prevent confusing the
857 third party I2C drivers due to a state change at the I2C device
858 which the third party I2C drivers did not initiate. I2C platform
859 drivers may use this API within these guidelines.
860
861 This layer uses the concept of I2C bus configurations to describe
862 the I2C bus. An I2C bus configuration is defined as a unique
863 setting of the multiplexers and switches in the I2C bus which
864 enable access to one or more I2C devices. When using a switch
865 to divide a bus, due to speed differences, the I2C platform layer
866 would define an I2C bus configuration for the I2C devices on each
867 side of the switch. When using a multiplexer, the I2C platform
868 layer defines an I2C bus configuration for each of the selector
869 values required to control the multiplexer. See Figure 1 in the
870 <a href="http://www.nxp.com/documents/user_manual/UM10204.pdf">I<sup>2</sup>C
871 Specification</a> for a complex I2C bus configuration.
872
873 The I2C host driver processes all operations in FIFO order. Prior to
874 performing the operation, the I2C host driver calls the I2C platform
875 driver to reconfigure the switches and multiplexers in the I2C bus
876 enabling access to the specified I2C device. The I2C platform driver
877 also selects the maximum bus speed for the device. After the I2C bus
878 is configured, the I2C host driver calls the I2C port driver to
879 initialize the I2C controller and start the I2C operation.
880
881 @param[in] This Address of an EFI_I2C_HOST_PROTOCOL instance.
882 @param[in] I2cBusConfiguration I2C bus configuration to access the I2C
883 device.
884 @param[in] SlaveAddress Address of the device on the I2C bus.
885 @param[in] Event Event to set for asynchronous operations,
886 NULL for synchronous operations
887 @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET
888 structure describing the I2C operation
889 @param[out] I2cStatus Optional buffer to receive the I2C operation
890 completion status
891
892 @retval EFI_SUCCESS The operation completed successfully.
893 @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large.
894 @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation.
895 This could indicate the slave device is not present.
896 @retval EFI_INVALID_PARAMETER RequestPacket is NULL
897 @retval EFI_INVALID_PARAMETER TPL is too high
898 @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value
899 @retval EFI_NO_RESPONSE The I2C device is not responding to the
900 slave address. EFI_DEVICE_ERROR may also be
901 returned if the controller can not distinguish
902 when the NACK occurred.
903 @retval EFI_NOT_FOUND I2C slave address exceeds maximum address
904 @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for
905 the event and then read status pointed to by
906 the request packet.
907 @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation
908 @retval EFI_TIMEOUT The transaction did not complete within an internally
909 specified timeout period.
910
911 **/
912 EFI_STATUS
913 EFIAPI
914 I2cHostQueueRequest (
915 IN CONST EFI_I2C_HOST_PROTOCOL *This,
916 IN UINTN I2cBusConfiguration,
917 IN UINTN SlaveAddress,
918 IN EFI_EVENT Event OPTIONAL,
919 IN EFI_I2C_REQUEST_PACKET *RequestPacket,
920 OUT EFI_STATUS *I2cStatus OPTIONAL
921 )
922 {
923 EFI_STATUS Status;
924 EFI_EVENT SyncEvent;
925 EFI_TPL TplPrevious;
926 I2C_REQUEST *I2cRequest;
927 I2C_HOST_CONTEXT *I2cHostContext;
928 BOOLEAN FirstRequest;
929 UINTN RequestPacketSize;
930 UINTN StartBit;
931
932 SyncEvent = NULL;
933 FirstRequest = FALSE;
934 Status = EFI_SUCCESS;
935
936 if (RequestPacket == NULL) {
937 return EFI_INVALID_PARAMETER;
938 }
939
940 if ((SlaveAddress & I2C_ADDRESSING_10_BIT) != 0) {
941 //
942 // 10-bit address, bits 0-9 are used for 10-bit I2C slave addresses,
943 // bits 10-30 are reserved bits and must be zero
944 //
945 StartBit = 10;
946 } else {
947 //
948 // 7-bit address, Bits 0-6 are used for 7-bit I2C slave addresses,
949 // bits 7-30 are reserved bits and must be zero
950 //
951 StartBit = 7;
952 }
953
954 if (BitFieldRead32 ((UINT32)SlaveAddress, StartBit, 30) != 0) {
955 //
956 // Reserved bit set in the SlaveAddress parameter
957 //
958 return EFI_NOT_FOUND;
959 }
960
961 I2cHostContext = I2C_HOST_CONTEXT_FROM_PROTOCOL (This);
962
963 if (Event == NULL) {
964 //
965 // For synchronous transaction, register an event used to wait for finishing synchronous transaction
966 //
967 Status = gBS->CreateEvent (
968 0,
969 TPL_I2C_SYNC,
970 NULL,
971 NULL,
972 &SyncEvent
973 );
974 if (EFI_ERROR (Status)) {
975 return Status;
976 }
977 }
978
979 //
980 // TPL should be at or below TPL_NOTIFY.
981 // For synchronous requests this routine must be called at or below TPL_CALLBACK.
982 //
983 TplPrevious = EfiGetCurrentTpl ();
984 if ((TplPrevious > TPL_I2C_SYNC) || ((Event == NULL) && (TplPrevious > TPL_CALLBACK))) {
985 DEBUG ((DEBUG_ERROR, "ERROR - TPL %d is too high!\n", TplPrevious));
986 return EFI_INVALID_PARAMETER;
987 }
988
989 //
990 // Allocate the request structure
991 //
992 I2cRequest = AllocateZeroPool (sizeof (I2C_REQUEST));
993 if (I2cRequest == NULL) {
994 DEBUG ((DEBUG_ERROR, "WARNING - Failed to allocate I2C_REQUEST!\n"));
995 return EFI_OUT_OF_RESOURCES;
996 }
997
998 //
999 // Initialize the request
1000 //
1001 I2cRequest->Signature = I2C_REQUEST_SIGNATURE;
1002 I2cRequest->I2cBusConfiguration = I2cBusConfiguration;
1003 I2cRequest->SlaveAddress = SlaveAddress;
1004 I2cRequest->Event = (Event == NULL) ? SyncEvent : Event;
1005 I2cRequest->Status = I2cStatus;
1006
1007 //
1008 // Copy request packet into private buffer, as RequestPacket may be freed during asynchronous transaction
1009 //
1010 RequestPacketSize = sizeof (UINTN) + RequestPacket->OperationCount * sizeof (EFI_I2C_OPERATION);
1011 I2cRequest->RequestPacket = AllocateZeroPool (RequestPacketSize);
1012 ASSERT (I2cRequest->RequestPacket != NULL);
1013 CopyMem (I2cRequest->RequestPacket, RequestPacket, RequestPacketSize);
1014
1015 //
1016 // Synchronize with the other threads
1017 //
1018 gBS->RaiseTPL ( TPL_I2C_SYNC );
1019
1020 FirstRequest = IsListEmpty (&I2cHostContext->RequestList);
1021
1022 //
1023 // Insert new I2C request in the list
1024 //
1025 InsertTailList (&I2cHostContext->RequestList, &I2cRequest->Link);
1026
1027 //
1028 // Release the thread synchronization
1029 //
1030 gBS->RestoreTPL (TplPrevious);
1031
1032 if (FirstRequest) {
1033 //
1034 // Start the first I2C request, then the subsequent of I2C request will continue
1035 //
1036 Status = I2cHostRequestEnable (I2cHostContext);
1037 }
1038
1039 if (Event != NULL) {
1040 //
1041 // For asynchronous, return EFI_SUCCESS indicating that the asynchronously I2C transaction was queued.
1042 // No real I2C operation status in I2cStatus
1043 //
1044 return EFI_SUCCESS;
1045 }
1046
1047 //
1048 // For synchronous transaction, wait for the operation completion
1049 //
1050 do {
1051 Status = gBS->CheckEvent (SyncEvent);
1052 } while (Status == EFI_NOT_READY);
1053
1054 //
1055 // Get the I2C operation status
1056 //
1057 Status = I2cHostContext->Status;
1058
1059 //
1060 // Return the I2C operation status
1061 //
1062 if (I2cStatus != NULL) {
1063 *I2cStatus = Status;
1064 }
1065
1066 //
1067 // Close the event if necessary
1068 //
1069 if (SyncEvent != NULL) {
1070 gBS->CloseEvent (SyncEvent);
1071 }
1072
1073 return Status;
1074 }
1075
1076 /**
1077 The user Entry Point for I2C host module. The user code starts with this function.
1078
1079 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1080 @param[in] SystemTable A pointer to the EFI System Table.
1081
1082 @retval EFI_SUCCESS The entry point is executed successfully.
1083 @retval other Some error occurs when executing this entry point.
1084
1085 **/
1086 EFI_STATUS
1087 EFIAPI
1088 InitializeI2cHost(
1089 IN EFI_HANDLE ImageHandle,
1090 IN EFI_SYSTEM_TABLE *SystemTable
1091 )
1092 {
1093 EFI_STATUS Status;
1094
1095 //
1096 // Install driver model protocol(s).
1097 //
1098 Status = EfiLibInstallDriverBindingComponentName2 (
1099 ImageHandle,
1100 SystemTable,
1101 &gI2cHostDriverBinding,
1102 ImageHandle,
1103 &gI2cHostComponentName,
1104 &gI2cHostComponentName2
1105 );
1106 ASSERT_EFI_ERROR (Status);
1107 return Status;
1108 }
1109
1110 /**
1111 This is the unload handle for I2C host module.
1112
1113 Disconnect the driver specified by ImageHandle from all the devices in the handle database.
1114 Uninstall all the protocols installed in the driver entry point.
1115
1116 @param[in] ImageHandle The drivers' driver image.
1117
1118 @retval EFI_SUCCESS The image is unloaded.
1119 @retval Others Failed to unload the image.
1120
1121 **/
1122 EFI_STATUS
1123 EFIAPI
1124 I2cHostUnload (
1125 IN EFI_HANDLE ImageHandle
1126 )
1127 {
1128 EFI_STATUS Status;
1129 EFI_HANDLE *DeviceHandleBuffer;
1130 UINTN DeviceHandleCount;
1131 UINTN Index;
1132 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
1133 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
1134
1135 //
1136 // Get the list of all I2C Controller handles in the handle database.
1137 // If there is an error getting the list, then the unload
1138 // operation fails.
1139 //
1140 Status = gBS->LocateHandleBuffer (
1141 ByProtocol,
1142 &gEfiI2cHostProtocolGuid,
1143 NULL,
1144 &DeviceHandleCount,
1145 &DeviceHandleBuffer
1146 );
1147
1148 if (!EFI_ERROR (Status)) {
1149 //
1150 // Disconnect the driver specified by ImageHandle from all
1151 // the devices in the handle database.
1152 //
1153 for (Index = 0; Index < DeviceHandleCount; Index++) {
1154 Status = gBS->DisconnectController (
1155 DeviceHandleBuffer[Index],
1156 ImageHandle,
1157 NULL
1158 );
1159 if (EFI_ERROR (Status)) {
1160 goto Done;
1161 }
1162 }
1163 }
1164
1165 //
1166 // Uninstall all the protocols installed in the driver entry point
1167 //
1168 Status = gBS->UninstallMultipleProtocolInterfaces (
1169 gI2cHostDriverBinding.DriverBindingHandle,
1170 &gEfiDriverBindingProtocolGuid,
1171 &gI2cHostDriverBinding,
1172 NULL
1173 );
1174 ASSERT_EFI_ERROR (Status);
1175
1176 //
1177 // Note we have to one by one uninstall the following protocols.
1178 // It's because some of them are optionally installed based on
1179 // the following PCD settings.
1180 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
1181 // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
1182 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
1183 // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
1184 //
1185 Status = gBS->HandleProtocol (
1186 gI2cHostDriverBinding.DriverBindingHandle,
1187 &gEfiComponentNameProtocolGuid,
1188 (VOID **) &ComponentName
1189 );
1190 if (!EFI_ERROR (Status)) {
1191 gBS->UninstallProtocolInterface (
1192 gI2cHostDriverBinding.DriverBindingHandle,
1193 &gEfiComponentNameProtocolGuid,
1194 ComponentName
1195 );
1196 }
1197
1198 Status = gBS->HandleProtocol (
1199 gI2cHostDriverBinding.DriverBindingHandle,
1200 &gEfiComponentName2ProtocolGuid,
1201 (VOID **) &ComponentName2
1202 );
1203 if (!EFI_ERROR (Status)) {
1204 gBS->UninstallProtocolInterface (
1205 gI2cHostDriverBinding.DriverBindingHandle,
1206 &gEfiComponentName2ProtocolGuid,
1207 ComponentName2
1208 );
1209 }
1210
1211 Status = EFI_SUCCESS;
1212
1213 Done:
1214 //
1215 // Free the buffer containing the list of handles from the handle database
1216 //
1217 if (DeviceHandleBuffer != NULL) {
1218 gBS->FreePool (DeviceHandleBuffer);
1219 }
1220
1221 return Status;
1222 }