]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/I2c/I2cDxe/I2cHost.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
846 return Status;
847 }
848
849 /**
850 Queue an I2C operation for execution on the I2C controller.
851
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.
854
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.
861
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.
873
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.
881
882 @param[in] This Address of an EFI_I2C_HOST_PROTOCOL instance.
883 @param[in] I2cBusConfiguration I2C bus configuration to access the I2C
884 device.
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
891 completion status
892
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
907 the request packet.
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.
911
912 **/
913 EFI_STATUS
914 EFIAPI
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
922 )
923 {
924 EFI_STATUS Status;
925 EFI_EVENT SyncEvent;
926 EFI_TPL TplPrevious;
927 I2C_REQUEST *I2cRequest;
928 I2C_HOST_CONTEXT *I2cHostContext;
929 BOOLEAN FirstRequest;
930 UINTN RequestPacketSize;
931 UINTN StartBit;
932
933 SyncEvent = NULL;
934 FirstRequest = FALSE;
935 Status = EFI_SUCCESS;
936
937 if (RequestPacket == NULL) {
938 return EFI_INVALID_PARAMETER;
939 }
940
941 if ((SlaveAddress & I2C_ADDRESSING_10_BIT) != 0) {
942 //
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
945 //
946 StartBit = 10;
947 } else {
948 //
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
951 //
952 StartBit = 7;
953 }
954
955 if (BitFieldRead32 ((UINT32)SlaveAddress, StartBit, 30) != 0) {
956 //
957 // Reserved bit set in the SlaveAddress parameter
958 //
959 return EFI_NOT_FOUND;
960 }
961
962 I2cHostContext = I2C_HOST_CONTEXT_FROM_PROTOCOL (This);
963
964 if (Event == NULL) {
965 //
966 // For synchronous transaction, register an event used to wait for finishing synchronous transaction
967 //
968 Status = gBS->CreateEvent (
969 0,
970 TPL_I2C_SYNC,
971 NULL,
972 NULL,
973 &SyncEvent
974 );
975 if (EFI_ERROR (Status)) {
976 return Status;
977 }
978 }
979
980 //
981 // TPL should be at or below TPL_NOTIFY.
982 // For synchronous requests this routine must be called at or below TPL_CALLBACK.
983 //
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;
988 }
989
990 //
991 // Allocate the request structure
992 //
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;
997 }
998
999 //
1000 // Initialize the request
1001 //
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;
1007
1008 //
1009 // Copy request packet into private buffer, as RequestPacket may be freed during asynchronous transaction
1010 //
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);
1015
1016 //
1017 // Synchronize with the other threads
1018 //
1019 gBS->RaiseTPL (TPL_I2C_SYNC);
1020
1021 FirstRequest = IsListEmpty (&I2cHostContext->RequestList);
1022
1023 //
1024 // Insert new I2C request in the list
1025 //
1026 InsertTailList (&I2cHostContext->RequestList, &I2cRequest->Link);
1027
1028 //
1029 // Release the thread synchronization
1030 //
1031 gBS->RestoreTPL (TplPrevious);
1032
1033 if (FirstRequest) {
1034 //
1035 // Start the first I2C request, then the subsequent of I2C request will continue
1036 //
1037 Status = I2cHostRequestEnable (I2cHostContext);
1038 }
1039
1040 if (Event != NULL) {
1041 //
1042 // For asynchronous, return EFI_SUCCESS indicating that the asynchronously I2C transaction was queued.
1043 // No real I2C operation status in I2cStatus
1044 //
1045 return EFI_SUCCESS;
1046 }
1047
1048 //
1049 // For synchronous transaction, wait for the operation completion
1050 //
1051 do {
1052 Status = gBS->CheckEvent (SyncEvent);
1053 } while (Status == EFI_NOT_READY);
1054
1055 //
1056 // Get the I2C operation status
1057 //
1058 Status = I2cHostContext->Status;
1059
1060 //
1061 // Return the I2C operation status
1062 //
1063 if (I2cStatus != NULL) {
1064 *I2cStatus = Status;
1065 }
1066
1067 //
1068 // Close the event if necessary
1069 //
1070 if (SyncEvent != NULL) {
1071 gBS->CloseEvent (SyncEvent);
1072 }
1073
1074 return Status;
1075 }
1076
1077 /**
1078 The user Entry Point for I2C host module. The user code starts with this function.
1079
1080 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1081 @param[in] SystemTable A pointer to the EFI System Table.
1082
1083 @retval EFI_SUCCESS The entry point is executed successfully.
1084 @retval other Some error occurs when executing this entry point.
1085
1086 **/
1087 EFI_STATUS
1088 EFIAPI
1089 InitializeI2cHost (
1090 IN EFI_HANDLE ImageHandle,
1091 IN EFI_SYSTEM_TABLE *SystemTable
1092 )
1093 {
1094 EFI_STATUS Status;
1095
1096 //
1097 // Install driver model protocol(s).
1098 //
1099 Status = EfiLibInstallDriverBindingComponentName2 (
1100 ImageHandle,
1101 SystemTable,
1102 &gI2cHostDriverBinding,
1103 ImageHandle,
1104 &gI2cHostComponentName,
1105 &gI2cHostComponentName2
1106 );
1107 ASSERT_EFI_ERROR (Status);
1108 return Status;
1109 }
1110
1111 /**
1112 This is the unload handle for I2C host module.
1113
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.
1116
1117 @param[in] ImageHandle The drivers' driver image.
1118
1119 @retval EFI_SUCCESS The image is unloaded.
1120 @retval Others Failed to unload the image.
1121
1122 **/
1123 EFI_STATUS
1124 EFIAPI
1125 I2cHostUnload (
1126 IN EFI_HANDLE ImageHandle
1127 )
1128 {
1129 EFI_STATUS Status;
1130 EFI_HANDLE *DeviceHandleBuffer;
1131 UINTN DeviceHandleCount;
1132 UINTN Index;
1133 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
1134 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
1135
1136 //
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
1139 // operation fails.
1140 //
1141 Status = gBS->LocateHandleBuffer (
1142 ByProtocol,
1143 &gEfiI2cHostProtocolGuid,
1144 NULL,
1145 &DeviceHandleCount,
1146 &DeviceHandleBuffer
1147 );
1148
1149 if (!EFI_ERROR (Status)) {
1150 //
1151 // Disconnect the driver specified by ImageHandle from all
1152 // the devices in the handle database.
1153 //
1154 for (Index = 0; Index < DeviceHandleCount; Index++) {
1155 Status = gBS->DisconnectController (
1156 DeviceHandleBuffer[Index],
1157 ImageHandle,
1158 NULL
1159 );
1160 if (EFI_ERROR (Status)) {
1161 goto Done;
1162 }
1163 }
1164 }
1165
1166 //
1167 // Uninstall all the protocols installed in the driver entry point
1168 //
1169 Status = gBS->UninstallMultipleProtocolInterfaces (
1170 gI2cHostDriverBinding.DriverBindingHandle,
1171 &gEfiDriverBindingProtocolGuid,
1172 &gI2cHostDriverBinding,
1173 NULL
1174 );
1175 ASSERT_EFI_ERROR (Status);
1176
1177 //
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
1185 //
1186 Status = gBS->HandleProtocol (
1187 gI2cHostDriverBinding.DriverBindingHandle,
1188 &gEfiComponentNameProtocolGuid,
1189 (VOID **)&ComponentName
1190 );
1191 if (!EFI_ERROR (Status)) {
1192 gBS->UninstallProtocolInterface (
1193 gI2cHostDriverBinding.DriverBindingHandle,
1194 &gEfiComponentNameProtocolGuid,
1195 ComponentName
1196 );
1197 }
1198
1199 Status = gBS->HandleProtocol (
1200 gI2cHostDriverBinding.DriverBindingHandle,
1201 &gEfiComponentName2ProtocolGuid,
1202 (VOID **)&ComponentName2
1203 );
1204 if (!EFI_ERROR (Status)) {
1205 gBS->UninstallProtocolInterface (
1206 gI2cHostDriverBinding.DriverBindingHandle,
1207 &gEfiComponentName2ProtocolGuid,
1208 ComponentName2
1209 );
1210 }
1211
1212 Status = EFI_SUCCESS;
1213
1214 Done:
1215 //
1216 // Free the buffer containing the list of handles from the handle database
1217 //
1218 if (DeviceHandleBuffer != NULL) {
1219 gBS->FreePool (DeviceHandleBuffer);
1220 }
1221
1222 return Status;
1223 }