]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/DxeQNCSmbus.c
2731bfe1361d9caa58ea908c775680fea19c0d65
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / QNCInit / Dxe / DxeQNCSmbus.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }