1 /** @file
2 Implementation for SMBus DXE driver entry point and SMBus Host
3 Controller protocol.
4 
5 Copyright (c) 2013-2015 Intel Corporation.
6 
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 #include "CommonHeader.h"
11 
12 #include "DxeQNCSmbus.h"
13 
14 //
15 // Interface defintion of SMBUS Host Controller Protocol.
16 //
17 EFI_SMBUS_HC_PROTOCOL mSmbusHc = {
18   SmbusExecute,
19   SmbusArpDevice,
20   SmbusGetArpMap,
21   SmbusNotify
22 };
23 
24 //
25 // Handle to install SMBus Host Controller protocol.
26 //
27 EFI_HANDLE                   mSmbusHcHandle = NULL;
28 UINT8                        mDeviceMapEntries = 0;
29 EFI_SMBUS_DEVICE_MAP         mDeviceMap[MAX_SMBUS_DEVICES];
30 UINT8                        mPlatformNumRsvd = 0;
31 UINT8                        *mPlatformAddrRsvd = NULL;
32 
33 //
34 // These addresses are reserved by the SMBus 2.0 specification
35 //
36 UINT8    mReservedAddress[SMBUS_NUM_RESERVED] = {
37   0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x18, 0x50, 0x6E, 0xC2,
38   0xF0, 0xF2, 0xF4, 0xF6, 0xF8, 0xFA, 0xFC, 0xFE
39 };
40 
41 
42 /**
43   Gets Io port base address of Smbus Host Controller.
44 
45   This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress
46   to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base
47   address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always
48   read Pci configuration space to get that value in each Smbus bus transaction.
49 
50   @return The Io port base address of Smbus host controller.
51 
52 **/
53 UINTN
GetSmbusIoPortBaseAddress(VOID)54 GetSmbusIoPortBaseAddress (
55   VOID
56   )
57 {
58   UINTN     IoPortBaseAddress;
59 
60   if (FeaturePcdGet (PcdSmbaIoBaseAddressFixed)) {
61     IoPortBaseAddress = (UINTN) PcdGet16 (PcdSmbaIoBaseAddress);
62   } else {
63     IoPortBaseAddress = (UINTN) LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) & B_QNC_LPC_SMBUS_BASE_MASK;
64   }
65 
66   //
67   // Make sure that the IO port base address has been properly set.
68   //
69   ASSERT (IoPortBaseAddress != 0);
70 
71   return IoPortBaseAddress;
72 }
73 
74 
75 VOID
InitializeInternal()76 InitializeInternal (
77   )
78 {
79   UINTN     IoPortBaseAddress;
80 
81   IoPortBaseAddress = GetSmbusIoPortBaseAddress ();
82 
83   //
84   // Step1: Enable QNC SMBUS I/O space.
85   //
86   LpcPciCfg32Or(R_QNC_LPC_SMBUS_BASE, B_QNC_LPC_SMBUS_BASE_EN);
87 
88   //
89   // Step2: Clear Status Register before anyone uses the interfaces.
90   //
91   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
92 
93   //
94   // Step3: Program the correct smbus clock
95   //
96   IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCLK, V_QNC_SMBUS_HCLK_100KHZ);
97 }
98 
99 
100 
101 
102 BOOLEAN
IsAddressAvailable(IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress)103 IsAddressAvailable (
104   IN      EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress
105   )
106 {
107   UINT8         Index;
108 
109   //
110   // See if we have already assigned this address to a device
111   //
112   for (Index = 0; Index < mDeviceMapEntries; Index++) {
113     if (SlaveAddress.SmbusDeviceAddress ==
114          mDeviceMap[Index].SmbusDeviceAddress.SmbusDeviceAddress) {
115       return FALSE;
116     }
117   }
118 
119   //
120   // See if this address is claimed by a platform non-ARP-capable device
121   //
122   for (Index = 0; Index < mPlatformNumRsvd; Index++) {
123     if ((SlaveAddress.SmbusDeviceAddress << 1) == mPlatformAddrRsvd[Index]) {
124       return FALSE;
125     }
126   }
127 
128   //
129   // See if this is a reserved address
130   //
131   for (Index = 0; Index < SMBUS_NUM_RESERVED; Index++) {
132     if (SlaveAddress.SmbusDeviceAddress == (UINTN) mReservedAddress[Index]) {
133       return FALSE;
134     }
135   }
136 
137   return TRUE;
138 }
139 
140 
141 EFI_STATUS
GetNextAvailableAddress(IN EFI_SMBUS_DEVICE_ADDRESS * SlaveAddress)142 GetNextAvailableAddress (
143   IN EFI_SMBUS_DEVICE_ADDRESS  *SlaveAddress
144   )
145 {
146   for (SlaveAddress->SmbusDeviceAddress = 0x03;
147     SlaveAddress->SmbusDeviceAddress < 0x7F;
148     SlaveAddress->SmbusDeviceAddress++
149     ) {
150     if (IsAddressAvailable (*SlaveAddress)) {
151       return EFI_SUCCESS;
152     }
153   }
154 
155   return EFI_OUT_OF_RESOURCES;
156 }
157 
158 EFI_STATUS
SmbusPrepareToArp()159 SmbusPrepareToArp (
160   )
161 {
162   EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress;
163   EFI_STATUS                Status;
164   UINTN                     Length;
165   UINT8                     Buffer;
166 
167   SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP;
168   Length = 1;
169   Buffer = SMBUS_DATA_PREPARE_TO_ARP;
170 
171   Status = Execute (
172              SlaveAddress,
173              0,
174              EfiSmbusSendByte,
175              TRUE,
176              &Length,
177              &Buffer
178              );
179   return Status;
180 }
181 
182 EFI_STATUS
SmbusGetUdidGeneral(IN OUT EFI_SMBUS_DEVICE_MAP * DeviceMap)183 SmbusGetUdidGeneral (
184   IN OUT  EFI_SMBUS_DEVICE_MAP  *DeviceMap
185   )
186 {
187   EFI_SMBUS_DEVICE_ADDRESS      SlaveAddress;
188   EFI_STATUS                    Status;
189   UINTN                         Length;
190   UINT8                         Buffer[SMBUS_GET_UDID_LENGTH];
191 
192   SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP;
193   Length = SMBUS_GET_UDID_LENGTH;
194 
195   Status = Execute (
196              SlaveAddress,
197              SMBUS_DATA_GET_UDID_GENERAL,
198              EfiSmbusReadBlock,
199              TRUE,
200              &Length,
201              Buffer
202              );
203 
204   if (!EFI_ERROR(Status)) {
205     if (Length == SMBUS_GET_UDID_LENGTH) {
206       DeviceMap->SmbusDeviceUdid.DeviceCapabilities = Buffer[0];
207       DeviceMap->SmbusDeviceUdid.VendorRevision = Buffer[1];
208       DeviceMap->SmbusDeviceUdid.VendorId = (UINT16)((Buffer[2] << 8) + Buffer[3]);
209       DeviceMap->SmbusDeviceUdid.DeviceId = (UINT16)((Buffer[4] << 8) + Buffer[5]);
210       DeviceMap->SmbusDeviceUdid.Interface = (UINT16)((Buffer[6] << 8) + Buffer[7]);
211       DeviceMap->SmbusDeviceUdid.SubsystemVendorId = (UINT16)((Buffer[8] << 8) + Buffer[9]);
212       DeviceMap->SmbusDeviceUdid.SubsystemDeviceId = (UINT16)((Buffer[10] << 8) + Buffer[11]);
213       DeviceMap->SmbusDeviceUdid.VendorSpecificId = (UINT32)((Buffer[12] << 24) + (Buffer[13] << 16) + (Buffer[14] << 8) + Buffer[15]);
214       DeviceMap->SmbusDeviceAddress.SmbusDeviceAddress = (UINT8)(Buffer[16] >> 1);
215     } else {
216       Status = EFI_DEVICE_ERROR;
217     }
218   }
219 
220   return Status;
221 }
222 
223 EFI_STATUS
SmbusAssignAddress(IN OUT EFI_SMBUS_DEVICE_MAP * DeviceMap)224 SmbusAssignAddress (
225   IN OUT  EFI_SMBUS_DEVICE_MAP  *DeviceMap
226   )
227 {
228   EFI_SMBUS_DEVICE_ADDRESS      SlaveAddress;
229   EFI_STATUS                    Status;
230   UINTN                         Length;
231   UINT8                         Buffer[SMBUS_GET_UDID_LENGTH];
232 
233   Buffer[0] = DeviceMap->SmbusDeviceUdid.DeviceCapabilities;
234   Buffer[1] = DeviceMap->SmbusDeviceUdid.VendorRevision;
235   Buffer[2] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorId >> 8);
236   Buffer[3] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorId);
237   Buffer[4] = (UINT8)(DeviceMap->SmbusDeviceUdid.DeviceId >> 8);
238   Buffer[5] = (UINT8)(DeviceMap->SmbusDeviceUdid.DeviceId);
239   Buffer[6] = (UINT8)(DeviceMap->SmbusDeviceUdid.Interface >> 8);
240   Buffer[7] = (UINT8)(DeviceMap->SmbusDeviceUdid.Interface);
241   Buffer[8] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemVendorId >> 8);
242   Buffer[9] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemVendorId);
243   Buffer[10] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemDeviceId >> 8);
244   Buffer[11] = (UINT8)(DeviceMap->SmbusDeviceUdid.SubsystemDeviceId);
245   Buffer[12] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 24);
246   Buffer[13] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 16);
247   Buffer[14] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId >> 8);
248   Buffer[15] = (UINT8)(DeviceMap->SmbusDeviceUdid.VendorSpecificId);
249   Buffer[16] = (UINT8)(DeviceMap->SmbusDeviceAddress.SmbusDeviceAddress << 1);
250 
251   SlaveAddress.SmbusDeviceAddress = SMBUS_ADDRESS_ARP;
252   Length = SMBUS_GET_UDID_LENGTH;
253 
254   Status = Execute (
255              SlaveAddress,
256              SMBUS_DATA_ASSIGN_ADDRESS,
257              EfiSmbusWriteBlock,
258              TRUE,
259              &Length,
260              Buffer
261              );
262   return Status;
263 }
264 
265 
266 EFI_STATUS
SmbusFullArp()267 SmbusFullArp (
268   )
269 {
270   EFI_STATUS              Status;
271   EFI_SMBUS_DEVICE_MAP    *CurrentDeviceMap;
272 
273   Status = SmbusPrepareToArp ();
274   if (EFI_ERROR(Status)) {
275     if (Status == EFI_DEVICE_ERROR) {
276       //
277       //  ARP is complete
278       //
279       return EFI_SUCCESS;
280     } else {
281       return Status;
282     }
283   }
284 
285   //
286   //  Main loop to ARP all ARP-capable devices
287   //
288   do {
289     CurrentDeviceMap = &mDeviceMap[mDeviceMapEntries];
290     Status = SmbusGetUdidGeneral (CurrentDeviceMap);
291     if (EFI_ERROR(Status)) {
292       break;
293     }
294 
295     if (CurrentDeviceMap->SmbusDeviceAddress.SmbusDeviceAddress == (0xFF >> 1)) {
296       //
297       // If address is unassigned, assign it
298       //
299       Status = GetNextAvailableAddress (
300                  &CurrentDeviceMap->SmbusDeviceAddress
301                  );
302       if (EFI_ERROR(Status)) {
303         return EFI_OUT_OF_RESOURCES;
304       }
305     } else if (((CurrentDeviceMap->SmbusDeviceUdid.DeviceCapabilities) & 0xC0) != 0) {
306       //
307       // if address is not fixed, check if the current address is available
308       //
309       if (!IsAddressAvailable (
310              CurrentDeviceMap->SmbusDeviceAddress
311              )) {
312         //
313         // if currently assigned address is already used, get a new one
314         //
315         Status = GetNextAvailableAddress (
316                    &CurrentDeviceMap->SmbusDeviceAddress
317                    );
318         if (EFI_ERROR(Status)) {
319           return EFI_OUT_OF_RESOURCES;
320         }
321       }
322     }
323 
324     Status = SmbusAssignAddress (CurrentDeviceMap);
325     if (EFI_ERROR(Status)) {
326       //
327       // If there was a device error, just continue on and try again.
328       // Other errors should be reported.
329       //
330       if (Status != EFI_DEVICE_ERROR) {
331         return Status;
332       }
333     } else {
334       //
335       // If there was no error, the address was assigned and we must update our
336       // records.
337       //
338       mDeviceMapEntries++;
339     }
340 
341   } while (mDeviceMapEntries < MAX_SMBUS_DEVICES);
342 
343   return EFI_SUCCESS;
344 }
345 
346 
347 EFI_STATUS
SmbusDirectedArp(IN EFI_SMBUS_UDID * SmbusUdid,IN OUT EFI_SMBUS_DEVICE_ADDRESS * SlaveAddress)348 SmbusDirectedArp (
349   IN      EFI_SMBUS_UDID            *SmbusUdid,
350   IN OUT  EFI_SMBUS_DEVICE_ADDRESS  *SlaveAddress
351   )
352 {
353   EFI_STATUS                        Status;
354   EFI_SMBUS_DEVICE_MAP              *CurrentDeviceMap;
355 
356   if (mDeviceMapEntries >= MAX_SMBUS_DEVICES) {
357     return EFI_OUT_OF_RESOURCES;
358   }
359 
360   CurrentDeviceMap = &mDeviceMap[mDeviceMapEntries];
361 
362   //
363   // Find an available address to assign
364   //
365   Status = GetNextAvailableAddress (
366              &CurrentDeviceMap->SmbusDeviceAddress
367              );
368   if (EFI_ERROR(Status)) {
369     return EFI_OUT_OF_RESOURCES;
370   }
371 
372   CurrentDeviceMap->SmbusDeviceUdid.DeviceCapabilities  = SmbusUdid->DeviceCapabilities;
373   CurrentDeviceMap->SmbusDeviceUdid.DeviceId            = SmbusUdid->DeviceId;
374   CurrentDeviceMap->SmbusDeviceUdid.Interface           = SmbusUdid->Interface;
375   CurrentDeviceMap->SmbusDeviceUdid.SubsystemDeviceId   = SmbusUdid->SubsystemDeviceId;
376   CurrentDeviceMap->SmbusDeviceUdid.SubsystemVendorId   = SmbusUdid->SubsystemVendorId;
377   CurrentDeviceMap->SmbusDeviceUdid.VendorId            = SmbusUdid->VendorId;
378   CurrentDeviceMap->SmbusDeviceUdid.VendorRevision      = SmbusUdid->VendorRevision;
379   CurrentDeviceMap->SmbusDeviceUdid.VendorSpecificId    = SmbusUdid->VendorSpecificId;
380 
381   Status = SmbusAssignAddress (CurrentDeviceMap);
382   if (EFI_ERROR(Status)) {
383     return Status;
384   }
385 
386   mDeviceMapEntries++;
387   SlaveAddress->SmbusDeviceAddress = CurrentDeviceMap->SmbusDeviceAddress.SmbusDeviceAddress;
388 
389   return EFI_SUCCESS;
390 }
391 
392 
393 
394 /**
395   Executes an SMBus operation to an SMBus controller. Returns when either the command has been
396   executed or an error is encountered in doing the operation.
397 
398   The Execute() function provides a standard way to execute an operation as defined in the System
399   Management Bus (SMBus) Specification. The resulting transaction will be either that the SMBus
400   slave devices accept this transaction or that this function returns with error.
401 
402   @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
403   @param  SlaveAddress            The SMBus slave address of the device with which to communicate.
404   @param  Command                 This command is transmitted by the SMBus host controller to the
405                                   SMBus slave device and the interpretation is SMBus slave device
406                                   specific. It can mean the offset to a list of functions inside an
407                                   SMBus slave device. Not all operations or slave devices support
408                                   this command's registers.
409   @param  Operation               Signifies which particular SMBus hardware protocol instance that
410                                   it will use to execute the SMBus transactions. This SMBus
411                                   hardware protocol is defined by the SMBus Specification and is
412                                   not related to EFI.
413   @param  PecCheck                Defines if Packet Error Code (PEC) checking is required for this
414                                   operation.
415   @param  Length                  Signifies the number of bytes that this operation will do. The
416                                   maximum number of bytes can be revision specific and operation
417                                   specific. This field will contain the actual number of bytes that
418                                   are executed for this operation. Not all operations require this
419                                   argument.
420   @param  Buffer                  Contains the value of data to execute to the SMBus slave device.
421                                   Not all operations require this argument. The length of this
422                                   buffer is identified by Length.
423 
424   @retval EFI_SUCCESS             The last data that was returned from the access matched the poll
425                                   exit criteria.
426   @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).
427   @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is
428                                   determined by the SMBus host controller device.
429   @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
430   @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was
431                                   reflected in the Host Status Register bit. Device errors are a
432                                   result of a transaction collision, illegal command field,
433                                   unclaimed cycle (host initiated), or bus errors (collisions).
434   @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.
435   @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead
436                                   and EfiSmbusQuickWrite. Length is outside the range of valid
437                                   values.
438   @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.
439   @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.
440 
441 **/
442 EFI_STATUS
443 EFIAPI
SmbusExecute(IN CONST EFI_SMBUS_HC_PROTOCOL * This,IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,IN CONST EFI_SMBUS_DEVICE_COMMAND Command,IN CONST EFI_SMBUS_OPERATION Operation,IN CONST BOOLEAN PecCheck,IN OUT UINTN * Length,IN OUT VOID * Buffer)444 SmbusExecute (
445   IN CONST  EFI_SMBUS_HC_PROTOCOL     *This,
446   IN CONST  EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress,
447   IN CONST  EFI_SMBUS_DEVICE_COMMAND  Command,
448   IN CONST  EFI_SMBUS_OPERATION       Operation,
449   IN CONST  BOOLEAN                   PecCheck,
450   IN OUT    UINTN                     *Length,
451   IN OUT    VOID                      *Buffer
452   )
453 {
454   InitializeInternal ();
455   return Execute (
456            SlaveAddress,
457            Command,
458            Operation,
459            PecCheck,
460            Length,
461            Buffer
462            );
463 }
464 
465 /**
466   Sets the SMBus slave device addresses for the device with a given unique ID or enumerates the
467   entire bus.
468 
469   The ArpDevice() function provides a standard way for a device driver to enumerate the entire
470   SMBus or specific devices on the bus.
471 
472   @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
473   @param  ArpAll                  A Boolean expression that indicates if the host drivers need to
474                                   enumerate all the devices or enumerate only the device that is
475                                   identified by SmbusUdid. If ArpAll is TRUE, SmbusUdid and
476                                   SlaveAddress are optional. If ArpAll is FALSE, ArpDevice will
477                                   enumerate SmbusUdid and the address will be at SlaveAddress.
478   @param  SmbusUdid               The Unique Device Identifier (UDID) that is associated with this
479                                   device.
480   @param  SlaveAddress            The SMBus slave address that is associated with an SMBus UDID.
481 
482   @retval EFI_SUCCESS             The last data that was returned from the access matched the poll
483                                   exit criteria.
484   @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).
485   @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is
486                                   determined by the SMBus host controller device.
487   @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
488   @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was
489                                   reflected in the Host Status Register bit. Device errors are a
490                                   result of a transaction collision, illegal command field,
491                                   unclaimed cycle (host initiated), or bus errors (collisions).
492   @retval EFI_UNSUPPORTED         The corresponding SMBus operation is not supported.
493 
494 **/
495 EFI_STATUS
496 EFIAPI
SmbusArpDevice(IN CONST EFI_SMBUS_HC_PROTOCOL * This,IN BOOLEAN ArpAll,IN EFI_SMBUS_UDID * SmbusUdid,OPTIONAL IN OUT EFI_SMBUS_DEVICE_ADDRESS * SlaveAddress OPTIONAL)497 SmbusArpDevice (
498   IN CONST  EFI_SMBUS_HC_PROTOCOL     *This,
499   IN        BOOLEAN                   ArpAll,
500   IN        EFI_SMBUS_UDID            *SmbusUdid,   OPTIONAL
501   IN OUT    EFI_SMBUS_DEVICE_ADDRESS  *SlaveAddress OPTIONAL
502   )
503 {
504     InitializeInternal ();
505 
506     if (ArpAll) {
507     return SmbusFullArp ();
508   } else {
509     if ((SmbusUdid == NULL) || (SlaveAddress == NULL)) {
510       return EFI_INVALID_PARAMETER;
511     }
512     return SmbusDirectedArp ((EFI_SMBUS_UDID *)SmbusUdid, SlaveAddress);
513   }
514 }
515 
516 /**
517   Returns a pointer to the Address Resolution Protocol (ARP) map that contains the ID/address pair
518   of the slave devices that were enumerated by the SMBus host controller driver.
519 
520   The GetArpMap() function returns the mapping of all the SMBus devices that were enumerated by the
521   SMBus host driver.
522 
523   @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
524   @param  Length                  Size of the buffer that contains the SMBus device map.
525   @param  SmbusDeviceMap          The pointer to the device map as enumerated by the SMBus
526                                   controller driver.
527 
528   @retval EFI_SUCCESS             The SMBus returned the current device map.
529   @retval EFI_UNSUPPORTED         The corresponding operation is not supported.
530 
531 **/
532 EFI_STATUS
533 EFIAPI
SmbusGetArpMap(IN CONST EFI_SMBUS_HC_PROTOCOL * This,IN OUT UINTN * Length,IN OUT EFI_SMBUS_DEVICE_MAP ** SmbusDeviceMap)534 SmbusGetArpMap (
535   IN CONST  EFI_SMBUS_HC_PROTOCOL   *This,
536   IN OUT    UINTN                   *Length,
537   IN OUT    EFI_SMBUS_DEVICE_MAP    **SmbusDeviceMap
538   )
539 {
540   *Length = mDeviceMapEntries;
541   *SmbusDeviceMap = mDeviceMap;
542   return EFI_SUCCESS;
543 }
544 
545 
546 /**
547   Allows a device driver to register for a callback when the bus driver detects a state that it
548   needs to propagate to other drivers that are registered for a callback.
549 
550   The Notify() function registers all the callback functions to allow the bus driver to call these
551   functions when the SlaveAddress/Data pair happens.
552   If NotifyFunction is NULL, then ASSERT ().
553 
554   @param  This                    A pointer to the EFI_SMBUS_HC_PROTOCOL instance.
555   @param  SlaveAddress            The SMBUS hardware address to which the SMBUS device is
556                                   preassigned or allocated.
557   @param  Data                    Data of the SMBus host notify command that the caller wants to be
558                                   called.
559   @param  NotifyFunction          The function to call when the bus driver detects the SlaveAddress
560                                   and Data pair.
561 
562   @retval EFI_SUCCESS             NotifyFunction was registered.
563   @retval EFI_UNSUPPORTED         The corresponding operation is not supported.
564 
565 **/
566 EFI_STATUS
567 EFIAPI
SmbusNotify(IN CONST EFI_SMBUS_HC_PROTOCOL * This,IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,IN CONST UINTN Data,IN CONST EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction)568 SmbusNotify (
569   IN CONST  EFI_SMBUS_HC_PROTOCOL     *This,
570   IN CONST  EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress,
571   IN CONST  UINTN                     Data,
572   IN CONST  EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction
573   )
574 {
575   return EFI_UNSUPPORTED;
576 }
577 
578 /**
579   Entry point to the DXE Driver that produces the SMBus Host Controller Protocol.
580 
581   @param  ImageHandle      ImageHandle of the loaded driver.
582   @param  SystemTable      Pointer to the EFI System Table.
583 
584   @retval EFI_SUCCESS      The entry point of SMBus DXE driver is executed successfully.
585   @retval !EFI_SUCESS      Some error occurs in the entry point of SMBus DXE driver.
586 
587 **/
588 EFI_STATUS
589 EFIAPI
InitializeQNCSmbus(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)590 InitializeQNCSmbus (
591   IN EFI_HANDLE            ImageHandle,
592   IN EFI_SYSTEM_TABLE      *SystemTable
593   )
594 {
595   EFI_STATUS    Status;
596 
597   mPlatformNumRsvd = (UINT8)PcdGet32 (PcdPlatformSmbusAddrNum);
598   mPlatformAddrRsvd = (UINT8 *)(UINTN) PcdGet64 (PcdPlatformSmbusAddrTable);
599 
600   //
601   // Install SMBus Host Controller protocol interface.
602   //
603   Status = gBS->InstallMultipleProtocolInterfaces (
604                   &mSmbusHcHandle,
605                   &gEfiSmbusHcProtocolGuid,
606                   &mSmbusHc,
607                   NULL
608                   );
609   ASSERT_EFI_ERROR (Status);
610 
611   return Status;
612 }
613