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.
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
13 EFI_DRIVER_BINDING_PROTOCOL gI2cHostDriverBinding
= {
14 I2cHostDriverSupported
,
25 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mI2cHostDriverNameTable
[] = {
26 { "eng;en", L
"I2c Host Driver" },
31 // EFI Component Name Protocol
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
,
40 // EFI Component Name 2 Protocol
42 GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gI2cHostComponentName2
= {
43 I2cHostComponentNameGetDriverName
,
44 I2cHostComponentNameGetControllerName
,
49 Retrieves a Unicode string that is the user readable name of the driver.
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.
58 @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
59 EFI_COMPONENT_NAME_PROTOCOL instance.
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.
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.
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.
79 @retval EFI_INVALID_PARAMETER Language is NULL.
81 @retval EFI_INVALID_PARAMETER DriverName is NULL.
83 @retval EFI_UNSUPPORTED The driver specified by This does not support
84 the language specified by Language.
89 I2cHostComponentNameGetDriverName (
90 IN EFI_COMPONENT_NAME2_PROTOCOL
*This
,
92 OUT CHAR16
**DriverName
95 return LookupUnicodeString2 (
97 This
->SupportedLanguages
,
98 mI2cHostDriverNameTable
,
100 (BOOLEAN
)(This
!= &gI2cHostComponentName2
)
105 Retrieves a Unicode string that is the user readable name of the controller
106 that is being managed by a driver.
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.
117 @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
118 EFI_COMPONENT_NAME_PROTOCOL instance.
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
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
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.
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
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
155 @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
157 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
160 @retval EFI_INVALID_PARAMETER Language is NULL.
162 @retval EFI_INVALID_PARAMETER ControllerName is NULL.
164 @retval EFI_UNSUPPORTED The driver specified by This is not currently
165 managing the controller specified by
166 ControllerHandle and ChildHandle.
168 @retval EFI_UNSUPPORTED The driver specified by This does not support
169 the language specified by Language.
174 I2cHostComponentNameGetControllerName (
175 IN EFI_COMPONENT_NAME2_PROTOCOL
*This
,
176 IN EFI_HANDLE ControllerHandle
,
177 IN EFI_HANDLE ChildHandle OPTIONAL
,
179 OUT CHAR16
**ControllerName
182 return EFI_UNSUPPORTED
;
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.
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.
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
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
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.
229 I2cHostDriverSupported (
230 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
231 IN EFI_HANDLE Controller
,
232 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
235 EFI_I2C_MASTER_PROTOCOL
*I2cMaster
;
236 EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL
*I2cBusConfigurationManagement
;
240 // Locate I2C Bus Configuration Management Protocol
242 Status
= gBS
->OpenProtocol (
244 &gEfiI2cBusConfigurationManagementProtocolGuid
,
245 (VOID
**)&I2cBusConfigurationManagement
,
246 This
->DriverBindingHandle
,
248 EFI_OPEN_PROTOCOL_BY_DRIVER
250 if (EFI_ERROR (Status
)) {
255 // Close the protocol because we don't use it here
259 &gEfiI2cBusConfigurationManagementProtocolGuid
,
260 This
->DriverBindingHandle
,
265 // Locate I2C Master Protocol
267 Status
= gBS
->OpenProtocol (
269 &gEfiI2cMasterProtocolGuid
,
271 This
->DriverBindingHandle
,
273 EFI_OPEN_PROTOCOL_GET_PROTOCOL
275 if (EFI_ERROR (Status
)) {
283 Starts a device controller or a bus controller.
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.
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
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.
320 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
321 IN EFI_HANDLE Controller
,
322 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
326 EFI_I2C_MASTER_PROTOCOL
*I2cMaster
;
327 EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL
*I2cBusConfigurationManagement
;
328 I2C_HOST_CONTEXT
*I2cHostContext
;
331 I2cHostContext
= NULL
;
332 I2cBusConfigurationManagement
= NULL
;
335 // Locate I2C Bus Configuration Management Protocol
337 Status
= gBS
->OpenProtocol (
339 &gEfiI2cBusConfigurationManagementProtocolGuid
,
340 (VOID
**)&I2cBusConfigurationManagement
,
341 This
->DriverBindingHandle
,
343 EFI_OPEN_PROTOCOL_BY_DRIVER
345 if (EFI_ERROR (Status
)) {
346 DEBUG ((DEBUG_ERROR
, "I2cHost: Open I2C bus configuration error, Status = %r\n", Status
));
351 // Locate I2C Master Protocol
353 Status
= gBS
->OpenProtocol (
355 &gEfiI2cMasterProtocolGuid
,
357 This
->DriverBindingHandle
,
359 EFI_OPEN_PROTOCOL_GET_PROTOCOL
361 if (EFI_ERROR (Status
)) {
362 DEBUG ((DEBUG_ERROR
, "I2cHost: Open I2C master error, Status = %r\n", Status
));
367 // Allocate the I2C Host Context structure
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
;
377 // Initialize the context structure for the current I2C Controller
379 I2cHostContext
->Signature
= I2C_HOST_SIGNATURE
;
380 I2cHostContext
->I2cMaster
= I2cMaster
;
381 I2cHostContext
->I2cBusConfigurationManagement
= I2cBusConfigurationManagement
;
382 I2cHostContext
->I2cBusConfiguration
= (UINTN
)-1;
383 InitializeListHead (&I2cHostContext
->RequestList
);
386 // Reset the controller
388 Status
= I2cMaster
->Reset (I2cMaster
);
389 if (EFI_ERROR (Status
)) {
390 DEBUG ((DEBUG_ERROR
, "I2cHost: I2C controller reset failed!\n"));
395 // Create the I2C transaction complete event
397 Status
= gBS
->CreateEvent (
400 I2cHostRequestCompleteEvent
,
402 &I2cHostContext
->I2cEvent
404 if (EFI_ERROR (Status
)) {
405 DEBUG ((DEBUG_ERROR
, "I2cHost: create complete event error, Status = %r\n", Status
));
410 // Get the bus management event
412 Status
= gBS
->CreateEvent (
415 I2cHostI2cBusConfigurationAvailable
,
417 &I2cHostContext
->I2cBusConfigurationEvent
419 if (EFI_ERROR (Status
)) {
420 DEBUG ((DEBUG_ERROR
, "I2cHost: create bus available event error, Status = %r\n", Status
));
425 // Build the I2C host protocol for the current I2C controller
427 I2cHostContext
->I2cHost
.QueueRequest
= I2cHostQueueRequest
;
428 I2cHostContext
->I2cHost
.I2cControllerCapabilities
= I2cMaster
->I2cControllerCapabilities
;
431 // Install the driver protocol
433 Status
= gBS
->InstallMultipleProtocolInterfaces (
435 &gEfiI2cHostProtocolGuid
,
436 &I2cHostContext
->I2cHost
,
440 if (EFI_ERROR (Status
)) {
441 DEBUG ((DEBUG_ERROR
, "I2cHost: Start() function failed, Status = %r\n", Status
));
442 if (I2cBusConfigurationManagement
!= NULL
) {
445 &gEfiI2cBusConfigurationManagementProtocolGuid
,
446 This
->DriverBindingHandle
,
451 if ((I2cHostContext
!= NULL
) && (I2cHostContext
->I2cEvent
!= NULL
)) {
452 gBS
->CloseEvent (I2cHostContext
->I2cEvent
);
453 I2cHostContext
->I2cEvent
= NULL
;
456 if ((I2cHostContext
!= NULL
) && (I2cHostContext
->I2cBusConfigurationEvent
!= NULL
)) {
457 gBS
->CloseEvent (I2cHostContext
->I2cBusConfigurationEvent
);
458 I2cHostContext
->I2cBusConfigurationEvent
= NULL
;
462 // Release the context structure upon failure
464 if (I2cHostContext
!= NULL
) {
465 FreePool (I2cHostContext
);
470 // Return the operation status.
476 Stops a device controller or a bus controller.
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.
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.
497 @retval EFI_SUCCESS The device was stopped.
498 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
504 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
505 IN EFI_HANDLE Controller
,
506 IN UINTN NumberOfChildren
,
507 IN EFI_HANDLE
*ChildHandleBuffer
511 I2C_HOST_CONTEXT
*I2cHostContext
;
512 EFI_I2C_HOST_PROTOCOL
*I2cHost
;
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
;
521 Status
= gBS
->OpenProtocol (
523 &gEfiI2cHostProtocolGuid
,
525 This
->DriverBindingHandle
,
527 EFI_OPEN_PROTOCOL_GET_PROTOCOL
530 if (EFI_ERROR (Status
)) {
531 return EFI_DEVICE_ERROR
;
534 I2cHostContext
= I2C_HOST_CONTEXT_FROM_PROTOCOL (I2cHost
);
537 // Raise TPL for critical section
539 TplPrevious
= gBS
->RaiseTPL (TPL_I2C_SYNC
);
542 // If there is pending request or pending bus configuration, do not stop
544 Status
= EFI_DEVICE_ERROR
;
545 if ( (!I2cHostContext
->I2cBusConfigurationManagementPending
)
546 && IsListEmpty (&I2cHostContext
->RequestList
))
549 // Remove the I2C host protocol
551 Status
= gBS
->UninstallMultipleProtocolInterfaces (
553 &gEfiI2cHostProtocolGuid
,
560 // Leave critical section
562 gBS
->RestoreTPL (TplPrevious
);
563 if (!EFI_ERROR (Status
)) {
566 &gEfiI2cBusConfigurationManagementProtocolGuid
,
567 This
->DriverBindingHandle
,
572 // Release I2c Host resources
574 if (I2cHostContext
->I2cBusConfigurationEvent
!= NULL
) {
575 gBS
->CloseEvent (I2cHostContext
->I2cBusConfigurationEvent
);
576 I2cHostContext
->I2cBusConfigurationEvent
= NULL
;
579 if (I2cHostContext
->I2cEvent
!= NULL
) {
580 gBS
->CloseEvent (I2cHostContext
->I2cEvent
);
581 I2cHostContext
->I2cEvent
= NULL
;
584 FreePool (I2cHostContext
);
588 // Return the stop status
594 Handle the I2C bus configuration available event
596 This routine is called at TPL_I2C_SYNC.
598 @param[in] Event Address of an EFI_EVENT handle
599 @param[in] Context Address of an I2C_HOST_CONTEXT structure
604 I2cHostI2cBusConfigurationAvailable (
609 I2C_HOST_CONTEXT
*I2cHostContext
;
610 EFI_I2C_MASTER_PROTOCOL
*I2cMaster
;
611 I2C_REQUEST
*I2cRequest
;
612 LIST_ENTRY
*EntryHeader
;
617 // Mark this I2C bus configuration management operation as complete
619 I2cHostContext
= (I2C_HOST_CONTEXT
*)Context
;
620 I2cMaster
= I2cHostContext
->I2cMaster
;
621 ASSERT (I2cMaster
!= NULL
);
623 // Clear flag to indicate I2C bus configuration is finished
625 I2cHostContext
->I2cBusConfigurationManagementPending
= FALSE
;
628 // Validate the completion status
630 if (EFI_ERROR (I2cHostContext
->Status
)) {
632 // Setting I2C bus configuration failed before
634 I2cHostRequestComplete (I2cHostContext
, I2cHostContext
->Status
);
637 // Unknown I2C bus configuration
638 // Force next operation to enable the I2C bus configuration
640 I2cHostContext
->I2cBusConfiguration
= (UINTN
)-1;
643 // Do not continue current I2C request
649 // Get the first request in the link with FIFO order
651 EntryHeader
= &I2cHostContext
->RequestList
;
652 Entry
= GetFirstNode (EntryHeader
);
653 I2cRequest
= I2C_REQUEST_FROM_ENTRY (Entry
);
656 // Update the I2C bus configuration of the current I2C request
658 I2cHostContext
->I2cBusConfiguration
= I2cRequest
->I2cBusConfiguration
;
661 // Start an I2C operation on the host, the status is returned by I2cHostContext->Status
663 Status
= I2cMaster
->StartRequest (
665 I2cRequest
->SlaveAddress
,
666 I2cRequest
->RequestPacket
,
667 I2cHostContext
->I2cEvent
,
668 &I2cHostContext
->Status
671 if (EFI_ERROR (Status
)) {
672 DEBUG ((DEBUG_ERROR
, "I2cHostI2cBusConfigurationAvailable: Error starting I2C operation, %r\n", Status
));
677 Complete the current request
679 This routine is called at TPL_I2C_SYNC.
681 @param[in] I2cHostContext Address of an I2C_HOST_CONTEXT structure.
682 @param[in] Status Status of the I2C operation.
684 @return This routine returns the input status value.
688 I2cHostRequestComplete (
689 I2C_HOST_CONTEXT
*I2cHostContext
,
693 I2C_REQUEST
*I2cRequest
;
694 LIST_ENTRY
*EntryHeader
;
698 // Remove the current I2C request from the list
700 EntryHeader
= &I2cHostContext
->RequestList
;
701 Entry
= GetFirstNode (EntryHeader
);
702 I2cRequest
= I2C_REQUEST_FROM_ENTRY (Entry
);
705 // Save the status for QueueRequest
707 if ( NULL
!= I2cRequest
->Status
) {
708 *I2cRequest
->Status
= Status
;
712 // Notify the user of the I2C request completion
714 if ( NULL
!= I2cRequest
->Event
) {
715 gBS
->SignalEvent (I2cRequest
->Event
);
719 // Done with this request, remove the current request from list
721 RemoveEntryList (&I2cRequest
->Link
);
722 FreePool (I2cRequest
->RequestPacket
);
723 FreePool (I2cRequest
);
726 // If there is more I2C request, start next one
728 if (!IsListEmpty (EntryHeader
)) {
729 I2cHostRequestEnable (I2cHostContext
);
736 Handle the bus available event
738 This routine is called at TPL_I2C_SYNC.
740 @param[in] Event Address of an EFI_EVENT handle
741 @param[in] Context Address of an I2C_HOST_CONTEXT structure
746 I2cHostRequestCompleteEvent (
751 I2C_HOST_CONTEXT
*I2cHostContext
;
754 // Handle the completion event
756 I2cHostContext
= (I2C_HOST_CONTEXT
*)Context
;
757 I2cHostRequestComplete (I2cHostContext
, I2cHostContext
->Status
);
761 Enable access to the I2C bus configuration
763 @param[in] I2cHostContext Address of an I2C_HOST_CONTEXT structure
765 @retval EFI_SUCCESS The operation completed successfully.
766 @retval EFI_ABORTED The request did not complete because the driver
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.
786 I2cHostRequestEnable (
787 I2C_HOST_CONTEXT
*I2cHostContext
790 UINTN I2cBusConfiguration
;
791 CONST EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL
*I2cBusConfigurationManagement
;
792 I2C_REQUEST
*I2cRequest
;
795 LIST_ENTRY
*EntryHeader
;
799 // Assume pending request
801 Status
= EFI_NOT_READY
;
803 I2cBusConfigurationManagement
= I2cHostContext
->I2cBusConfigurationManagement
;
806 // Validate the I2c bus configuration
808 EntryHeader
= &I2cHostContext
->RequestList
;
809 Entry
= GetFirstNode (EntryHeader
);
810 I2cRequest
= I2C_REQUEST_FROM_ENTRY (Entry
);
812 I2cBusConfiguration
= I2cRequest
->I2cBusConfiguration
;
814 if (I2cHostContext
->I2cBusConfiguration
!= I2cBusConfiguration
) {
816 // Set flag to indicate I2C bus configuration is in progress
818 I2cHostContext
->I2cBusConfigurationManagementPending
= TRUE
;
820 // Update bus configuration for this device's requesting bus configuration
822 Status
= I2cBusConfigurationManagement
->EnableI2cBusConfiguration (
823 I2cBusConfigurationManagement
,
825 I2cHostContext
->I2cBusConfigurationEvent
,
826 &I2cHostContext
->Status
830 // I2C bus configuration is same, no need change configuration and start I2c transaction directly
832 TplPrevious
= gBS
->RaiseTPL (TPL_I2C_SYNC
);
835 // Same I2C bus configuration
837 I2cHostContext
->Status
= EFI_SUCCESS
;
838 I2cHostI2cBusConfigurationAvailable (I2cHostContext
->I2cBusConfigurationEvent
, I2cHostContext
);
841 // Release the thread synchronization
843 gBS
->RestoreTPL (TplPrevious
);
850 Queue an I2C operation for execution on the I2C controller.
852 This routine must be called at or below TPL_NOTIFY. For synchronous
853 requests this routine must be called at or below TPL_CALLBACK.
855 N.B. The typical consumers of this API are the I2C bus driver and
856 on rare occasions the I2C test application. Extreme care must be
857 taken by other consumers of this API to prevent confusing the
858 third party I2C drivers due to a state change at the I2C device
859 which the third party I2C drivers did not initiate. I2C platform
860 drivers may use this API within these guidelines.
862 This layer uses the concept of I2C bus configurations to describe
863 the I2C bus. An I2C bus configuration is defined as a unique
864 setting of the multiplexers and switches in the I2C bus which
865 enable access to one or more I2C devices. When using a switch
866 to divide a bus, due to speed differences, the I2C platform layer
867 would define an I2C bus configuration for the I2C devices on each
868 side of the switch. When using a multiplexer, the I2C platform
869 layer defines an I2C bus configuration for each of the selector
870 values required to control the multiplexer. See Figure 1 in the
871 <a href="http://www.nxp.com/documents/user_manual/UM10204.pdf">I<sup>2</sup>C
872 Specification</a> for a complex I2C bus configuration.
874 The I2C host driver processes all operations in FIFO order. Prior to
875 performing the operation, the I2C host driver calls the I2C platform
876 driver to reconfigure the switches and multiplexers in the I2C bus
877 enabling access to the specified I2C device. The I2C platform driver
878 also selects the maximum bus speed for the device. After the I2C bus
879 is configured, the I2C host driver calls the I2C port driver to
880 initialize the I2C controller and start the I2C operation.
882 @param[in] This Address of an EFI_I2C_HOST_PROTOCOL instance.
883 @param[in] I2cBusConfiguration I2C bus configuration to access the I2C
885 @param[in] SlaveAddress Address of the device on the I2C bus.
886 @param[in] Event Event to set for asynchronous operations,
887 NULL for synchronous operations
888 @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET
889 structure describing the I2C operation
890 @param[out] I2cStatus Optional buffer to receive the I2C operation
893 @retval EFI_SUCCESS The operation completed successfully.
894 @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large.
895 @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation.
896 This could indicate the slave device is not present.
897 @retval EFI_INVALID_PARAMETER RequestPacket is NULL
898 @retval EFI_INVALID_PARAMETER TPL is too high
899 @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value
900 @retval EFI_NO_RESPONSE The I2C device is not responding to the
901 slave address. EFI_DEVICE_ERROR may also be
902 returned if the controller can not distinguish
903 when the NACK occurred.
904 @retval EFI_NOT_FOUND I2C slave address exceeds maximum address
905 @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for
906 the event and then read status pointed to by
908 @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation
909 @retval EFI_TIMEOUT The transaction did not complete within an internally
910 specified timeout period.
915 I2cHostQueueRequest (
916 IN CONST EFI_I2C_HOST_PROTOCOL
*This
,
917 IN UINTN I2cBusConfiguration
,
918 IN UINTN SlaveAddress
,
919 IN EFI_EVENT Event OPTIONAL
,
920 IN EFI_I2C_REQUEST_PACKET
*RequestPacket
,
921 OUT EFI_STATUS
*I2cStatus OPTIONAL
927 I2C_REQUEST
*I2cRequest
;
928 I2C_HOST_CONTEXT
*I2cHostContext
;
929 BOOLEAN FirstRequest
;
930 UINTN RequestPacketSize
;
934 FirstRequest
= FALSE
;
935 Status
= EFI_SUCCESS
;
937 if (RequestPacket
== NULL
) {
938 return EFI_INVALID_PARAMETER
;
941 if ((SlaveAddress
& I2C_ADDRESSING_10_BIT
) != 0) {
943 // 10-bit address, bits 0-9 are used for 10-bit I2C slave addresses,
944 // bits 10-30 are reserved bits and must be zero
949 // 7-bit address, Bits 0-6 are used for 7-bit I2C slave addresses,
950 // bits 7-30 are reserved bits and must be zero
955 if (BitFieldRead32 ((UINT32
)SlaveAddress
, StartBit
, 30) != 0) {
957 // Reserved bit set in the SlaveAddress parameter
959 return EFI_NOT_FOUND
;
962 I2cHostContext
= I2C_HOST_CONTEXT_FROM_PROTOCOL (This
);
966 // For synchronous transaction, register an event used to wait for finishing synchronous transaction
968 Status
= gBS
->CreateEvent (
975 if (EFI_ERROR (Status
)) {
981 // TPL should be at or below TPL_NOTIFY.
982 // For synchronous requests this routine must be called at or below TPL_CALLBACK.
984 TplPrevious
= EfiGetCurrentTpl ();
985 if ((TplPrevious
> TPL_I2C_SYNC
) || ((Event
== NULL
) && (TplPrevious
> TPL_CALLBACK
))) {
986 DEBUG ((DEBUG_ERROR
, "ERROR - TPL %d is too high!\n", TplPrevious
));
987 return EFI_INVALID_PARAMETER
;
991 // Allocate the request structure
993 I2cRequest
= AllocateZeroPool (sizeof (I2C_REQUEST
));
994 if (I2cRequest
== NULL
) {
995 DEBUG ((DEBUG_ERROR
, "WARNING - Failed to allocate I2C_REQUEST!\n"));
996 return EFI_OUT_OF_RESOURCES
;
1000 // Initialize the request
1002 I2cRequest
->Signature
= I2C_REQUEST_SIGNATURE
;
1003 I2cRequest
->I2cBusConfiguration
= I2cBusConfiguration
;
1004 I2cRequest
->SlaveAddress
= SlaveAddress
;
1005 I2cRequest
->Event
= (Event
== NULL
) ? SyncEvent
: Event
;
1006 I2cRequest
->Status
= I2cStatus
;
1009 // Copy request packet into private buffer, as RequestPacket may be freed during asynchronous transaction
1011 RequestPacketSize
= sizeof (UINTN
) + RequestPacket
->OperationCount
* sizeof (EFI_I2C_OPERATION
);
1012 I2cRequest
->RequestPacket
= AllocateZeroPool (RequestPacketSize
);
1013 ASSERT (I2cRequest
->RequestPacket
!= NULL
);
1014 CopyMem (I2cRequest
->RequestPacket
, RequestPacket
, RequestPacketSize
);
1017 // Synchronize with the other threads
1019 gBS
->RaiseTPL (TPL_I2C_SYNC
);
1021 FirstRequest
= IsListEmpty (&I2cHostContext
->RequestList
);
1024 // Insert new I2C request in the list
1026 InsertTailList (&I2cHostContext
->RequestList
, &I2cRequest
->Link
);
1029 // Release the thread synchronization
1031 gBS
->RestoreTPL (TplPrevious
);
1035 // Start the first I2C request, then the subsequent of I2C request will continue
1037 Status
= I2cHostRequestEnable (I2cHostContext
);
1040 if (Event
!= NULL
) {
1042 // For asynchronous, return EFI_SUCCESS indicating that the asynchronously I2C transaction was queued.
1043 // No real I2C operation status in I2cStatus
1049 // For synchronous transaction, wait for the operation completion
1052 Status
= gBS
->CheckEvent (SyncEvent
);
1053 } while (Status
== EFI_NOT_READY
);
1056 // Get the I2C operation status
1058 Status
= I2cHostContext
->Status
;
1061 // Return the I2C operation status
1063 if (I2cStatus
!= NULL
) {
1064 *I2cStatus
= Status
;
1068 // Close the event if necessary
1070 if (SyncEvent
!= NULL
) {
1071 gBS
->CloseEvent (SyncEvent
);
1078 The user Entry Point for I2C host module. The user code starts with this function.
1080 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1081 @param[in] SystemTable A pointer to the EFI System Table.
1083 @retval EFI_SUCCESS The entry point is executed successfully.
1084 @retval other Some error occurs when executing this entry point.
1090 IN EFI_HANDLE ImageHandle
,
1091 IN EFI_SYSTEM_TABLE
*SystemTable
1097 // Install driver model protocol(s).
1099 Status
= EfiLibInstallDriverBindingComponentName2 (
1102 &gI2cHostDriverBinding
,
1104 &gI2cHostComponentName
,
1105 &gI2cHostComponentName2
1107 ASSERT_EFI_ERROR (Status
);
1112 This is the unload handle for I2C host module.
1114 Disconnect the driver specified by ImageHandle from all the devices in the handle database.
1115 Uninstall all the protocols installed in the driver entry point.
1117 @param[in] ImageHandle The drivers' driver image.
1119 @retval EFI_SUCCESS The image is unloaded.
1120 @retval Others Failed to unload the image.
1126 IN EFI_HANDLE ImageHandle
1130 EFI_HANDLE
*DeviceHandleBuffer
;
1131 UINTN DeviceHandleCount
;
1133 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1134 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1137 // Get the list of all I2C Controller handles in the handle database.
1138 // If there is an error getting the list, then the unload
1141 Status
= gBS
->LocateHandleBuffer (
1143 &gEfiI2cHostProtocolGuid
,
1149 if (!EFI_ERROR (Status
)) {
1151 // Disconnect the driver specified by ImageHandle from all
1152 // the devices in the handle database.
1154 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1155 Status
= gBS
->DisconnectController (
1156 DeviceHandleBuffer
[Index
],
1160 if (EFI_ERROR (Status
)) {
1167 // Uninstall all the protocols installed in the driver entry point
1169 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1170 gI2cHostDriverBinding
.DriverBindingHandle
,
1171 &gEfiDriverBindingProtocolGuid
,
1172 &gI2cHostDriverBinding
,
1175 ASSERT_EFI_ERROR (Status
);
1178 // Note we have to one by one uninstall the following protocols.
1179 // It's because some of them are optionally installed based on
1180 // the following PCD settings.
1181 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
1182 // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
1183 // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
1184 // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
1186 Status
= gBS
->HandleProtocol (
1187 gI2cHostDriverBinding
.DriverBindingHandle
,
1188 &gEfiComponentNameProtocolGuid
,
1189 (VOID
**)&ComponentName
1191 if (!EFI_ERROR (Status
)) {
1192 gBS
->UninstallProtocolInterface (
1193 gI2cHostDriverBinding
.DriverBindingHandle
,
1194 &gEfiComponentNameProtocolGuid
,
1199 Status
= gBS
->HandleProtocol (
1200 gI2cHostDriverBinding
.DriverBindingHandle
,
1201 &gEfiComponentName2ProtocolGuid
,
1202 (VOID
**)&ComponentName2
1204 if (!EFI_ERROR (Status
)) {
1205 gBS
->UninstallProtocolInterface (
1206 gI2cHostDriverBinding
.DriverBindingHandle
,
1207 &gEfiComponentName2ProtocolGuid
,
1212 Status
= EFI_SUCCESS
;
1216 // Free the buffer containing the list of handles from the handle database
1218 if (DeviceHandleBuffer
!= NULL
) {
1219 gBS
->FreePool (DeviceHandleBuffer
);