1 /** @file
2   Intel ICH9 SMBUS library implementation built upon I/O library.
3 
4   Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
5 
6 
7   This program and the accompanying materials are licensed and made available under
8 
9   the terms and conditions of the BSD License that accompanies this distribution.
10 
11   The full text of the license may be found at
12 
13   http://opensource.org/licenses/bsd-license.php.
14 
15 
16 
17   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 
19   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 
21 
22 
23 
24 **/
25 
26 #include "CommonHeader.h"
27 
28 /**
29   Gets Io port base address of Smbus Host Controller.
30 
InternalGetSmbusIoPortBaseAddress(VOID)31   This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress
32   to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base
33   address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always
34   read Pci configuration space to get that value in each Smbus bus transaction.
35 
36   @return The Io port base address of Smbus host controller.
37 
38 **/
39 UINTN
40 InternalGetSmbusIoPortBaseAddress (
41   VOID
42   )
43 {
44   UINTN     IoPortBaseAddress;
45 
46   IoPortBaseAddress = (UINTN) MmioRead32 (MmPciAddress (0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_SMBUS, PCI_FUNCTION_NUMBER_PCH_SMBUS, R_PCH_SMBUS_BASE)) & B_PCH_SMBUS_BASE_BAR;
47 
48   //
49   // Make sure that the IO port base address has been properly set.
50   //
51   ASSERT (IoPortBaseAddress != 0);
52 
53   return IoPortBaseAddress;
54 }
55 
56 /**
57   Acquires the ownership of SMBUS.
58 
59   This internal function reads the host state register.
60   If the SMBUS is not available, RETURN_TIMEOUT is returned;
61   Otherwise, it performs some basic initializations and returns
InternalSmBusAcquire(UINTN IoPortBaseAddress)62   RETURN_SUCCESS.
63 
64   @param  IoPortBaseAddress The Io port base address of Smbus Host controller.
65 
66   @retval RETURN_SUCCESS    The SMBUS command was executed successfully.
67   @retval RETURN_TIMEOUT    A timeout occurred while executing the SMBUS command.
68 
69 **/
70 RETURN_STATUS
71 InternalSmBusAcquire (
72   UINTN                     IoPortBaseAddress
73   )
74 {
75   UINT8   HostStatus;
76 
77   HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS);
78   if ((HostStatus & B_PCH_SMBUS_IUS) != 0) {
79     return RETURN_TIMEOUT;
80   } else if ((HostStatus & B_PCH_SMBUS_HBSY) != 0) {
81     //
82     // Clear host status register and exit.
83     //
84     IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
85     return RETURN_TIMEOUT;
86   }
87   //
88   // Clear out any odd status information (Will Not Clear In Use).
89   //
90   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, HostStatus);
91 
92   return RETURN_SUCCESS;
93 }
94 
95 /**
96   Starts the SMBUS transaction and waits until the end.
97 
98   This internal function start the SMBUS transaction and waits until the transaction
99   of SMBUS is over by polling the INTR bit of Host status register.
100   If the SMBUS is not available, RETURN_TIMEOUT is returned;
101   Otherwise, it performs some basic initializations and returns
102   RETURN_SUCCESS.
103 
104   @param  IoPortBaseAddress   The Io port base address of Smbus Host controller.
105   @param  HostControl         The Host control command to start SMBUS transaction.
106 
InternalSmBusStart(IN UINTN IoPortBaseAddress,IN UINT8 HostControl)107   @retval RETURN_SUCCESS      The SMBUS command was executed successfully.
108   @retval RETURN_CRC_ERROR    The checksum is not correct (PEC is incorrect).
109   @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected
110                               in the Host Status Register bit.  Device errors are
111                               a result of a transaction collision, illegal command field,
112                               unclaimed cycle (host initiated), or bus errors (collisions).
113 
114 **/
115 RETURN_STATUS
116 InternalSmBusStart (
117   IN  UINTN                   IoPortBaseAddress,
118   IN  UINT8                   HostControl
119   )
120 {
121   UINT8   HostStatus;
122   UINT8   AuxiliaryStatus;
123 
124   //
125   // Set Host Control Register (Initiate Operation, Interrupt disabled).
126   //
127   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL, (UINT8)(HostControl + B_PCH_SMBUS_START));
128 
129   do {
130     //
131     // Poll INTR bit of Host Status Register.
132     //
133     HostStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS);
134   } while ((HostStatus & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_ERRORS | B_PCH_SMBUS_BYTE_DONE_STS)) == 0);
135 
136   if ((HostStatus & B_PCH_SMBUS_ERRORS) == 0) {
137     return RETURN_SUCCESS;
138   }
139 
140   //
141   // Clear error bits of Host Status Register.
142   //
143   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_ERRORS);
144 
145   //
146   // Read Auxiliary Status Register to judge CRC error.
147   //
148   AuxiliaryStatus = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS);
149   if ((AuxiliaryStatus & B_PCH_SMBUS_CRCE) != 0) {
150     return RETURN_CRC_ERROR;
151   }
152 
153   return RETURN_DEVICE_ERROR;
154 }
155 
156 /**
157   Executes an SMBUS quick, byte or word command.
158 
159   This internal function executes an SMBUS quick, byte or word commond.
160   If Status is not NULL, then the status of the executed command is returned in Status.
161 
162   @param  HostControl     The value of Host Control Register to set.
163   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
InternalSmBusNonBlock(IN UINT8 HostControl,IN UINTN SmBusAddress,IN UINT16 Value,OUT RETURN_STATUS * Status)164                           SMBUS Command, SMBUS Data Length, and PEC.
165   @param  Value           The byte/word write to the SMBUS.
166   @param  Status          Return status for the executed command.
167                           This is an optional parameter and may be NULL.
168 
169   @return The byte/word read from the SMBUS.
170 
171 **/
172 UINT16
173 InternalSmBusNonBlock (
174   IN  UINT8                     HostControl,
175   IN  UINTN                     SmBusAddress,
176   IN  UINT16                    Value,
177   OUT RETURN_STATUS             *Status
178   )
179 {
180   RETURN_STATUS                 ReturnStatus;
181   UINTN                         IoPortBaseAddress;
182   UINT8                         AuxiliaryControl;
183 
184   IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
185 
186   //
187   // Try to acquire the ownership of ICH SMBUS.
188   //
189   ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
190   if (RETURN_ERROR (ReturnStatus)) {
191     goto Done;
192   }
193 
194   //
195   // Set the appropriate Host Control Register and auxiliary Control Register.
196   //
197   AuxiliaryControl = 0;
198   if (SMBUS_LIB_PEC (SmBusAddress)) {
199     AuxiliaryControl |= B_PCH_SMBUS_AAC;
200     HostControl      |= B_PCH_SMBUS_PEC_EN;
201   }
202 
203   //
204   // Set Host Command Register.
205   //
206   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
207 
208   //
209   // Write value to Host Data 0 and Host Data 1 Registers.
210   //
211   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) Value);
212   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD1, (UINT8) (Value >> 8));
213 
214   //
215   // Set Auxiliary Control Register.
216   //
217   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl);
218 
219   //
220   // Set SMBUS slave address for the device to send/receive from.
221   //
222   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress);
223 
224   //
225   // Start the SMBUS transaction and wait for the end.
226   //
227   ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
228 
229   //
230   // Read value from Host Data 0 and Host Data 1 Registers.
231   //
232   Value = (UINT16)(IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD1) << 8);
233   Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0));
234 
235   //
236   // Clear Host Status Register and Auxiliary Status Register.
237   //
238   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
239   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
240 
241 Done:
242   if (Status != NULL) {
243     *Status = ReturnStatus;
244   }
245 
246   return Value;
247 }
248 
249 /**
250   Executes an SMBUS quick read command.
251 
252   Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress.
253   Only the SMBUS slave address field of SmBusAddress is required.
254   If Status is not NULL, then the status of the executed command is returned in Status.
255   If PEC is set in SmBusAddress, then ASSERT().
256   If Command in SmBusAddress is not zero, then ASSERT().
257   If Length in SmBusAddress is not zero, then ASSERT().
258   If any reserved bits of SmBusAddress are set, then ASSERT().
SmBusQuickRead(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)259 
260   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
261                           SMBUS Command, SMBUS Data Length, and PEC.
262   @param  Status          Return status for the executed command.
263                           This is an optional parameter and may be NULL.
264 
265 **/
266 VOID
267 EFIAPI
268 SmBusQuickRead (
269   IN  UINTN                     SmBusAddress,
270   OUT RETURN_STATUS             *Status       OPTIONAL
271   )
272 {
273   ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
274   ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);
275   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
276   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress)  == 0);
277 
278   InternalSmBusNonBlock (
279     V_PCH_SMBUS_SMB_CMD_QUICK,
280     SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
281     0,
282     Status
283     );
284 }
285 
286 /**
287   Executes an SMBUS quick write command.
288 
289   Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress.
290   Only the SMBUS slave address field of SmBusAddress is required.
291   If Status is not NULL, then the status of the executed command is returned in Status.
292   If PEC is set in SmBusAddress, then ASSERT().
293   If Command in SmBusAddress is not zero, then ASSERT().
294   If Length in SmBusAddress is not zero, then ASSERT().
295   If any reserved bits of SmBusAddress are set, then ASSERT().
SmBusQuickWrite(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)296 
297   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
298                           SMBUS Command, SMBUS Data Length, and PEC.
299   @param  Status          Return status for the executed command.
300                           This is an optional parameter and may be NULL.
301 
302 **/
303 VOID
304 EFIAPI
305 SmBusQuickWrite (
306   IN  UINTN                     SmBusAddress,
307   OUT RETURN_STATUS             *Status       OPTIONAL
308   )
309 {
310   ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
311   ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);
312   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
313   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
314 
315   InternalSmBusNonBlock (
316     V_PCH_SMBUS_SMB_CMD_QUICK,
317     SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
318     0,
319     Status
320     );
321 }
322 
323 /**
324   Executes an SMBUS receive byte command.
325 
326   Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress.
327   Only the SMBUS slave address field of SmBusAddress is required.
328   The byte received from the SMBUS is returned.
329   If Status is not NULL, then the status of the executed command is returned in Status.
330   If Command in SmBusAddress is not zero, then ASSERT().
331   If Length in SmBusAddress is not zero, then ASSERT().
332   If any reserved bits of SmBusAddress are set, then ASSERT().
333 
334   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
SmBusReceiveByte(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)335                           SMBUS Command, SMBUS Data Length, and PEC.
336   @param  Status          Return status for the executed command.
337                           This is an optional parameter and may be NULL.
338 
339   @return The byte received from the SMBUS.
340 
341 **/
342 UINT8
343 EFIAPI
344 SmBusReceiveByte (
345   IN  UINTN          SmBusAddress,
346   OUT RETURN_STATUS  *Status        OPTIONAL
347   )
348 {
349   UINT8 ValueReturn = 0;
350 
351   ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);
352   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
353   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
354 
355   ValueReturn = (UINT8) InternalSmBusNonBlock (
356                    V_PCH_SMBUS_SMB_CMD_BYTE,
357                    SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
358                    0,
359                    Status
360                    );
361   return ValueReturn;
362 
363   }
364 
365 /**
366   Executes an SMBUS send byte command.
367 
368   Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress.
369   The byte specified by Value is sent.
370   Only the SMBUS slave address field of SmBusAddress is required.  Value is returned.
371   If Status is not NULL, then the status of the executed command is returned in Status.
372   If Command in SmBusAddress is not zero, then ASSERT().
373   If Length in SmBusAddress is not zero, then ASSERT().
374   If any reserved bits of SmBusAddress are set, then ASSERT().
375 
376   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
377                           SMBUS Command, SMBUS Data Length, and PEC.
SmBusSendByte(IN UINTN SmBusAddress,IN UINT8 Value,OUT RETURN_STATUS * Status OPTIONAL)378   @param  Value           The 8-bit value to send.
379   @param  Status          Return status for the executed command.
380                           This is an optional parameter and may be NULL.
381 
382   @return The parameter of Value.
383 
384 **/
385 UINT8
386 EFIAPI
387 SmBusSendByte (
388   IN  UINTN          SmBusAddress,
389   IN  UINT8          Value,
390   OUT RETURN_STATUS  *Status        OPTIONAL
391   )
392 {
393   UINT8 ValueReturn = 0;
394 
395   ASSERT (SMBUS_LIB_COMMAND (SmBusAddress)   == 0);
396   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
397   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
398 
399   ValueReturn = (UINT8) InternalSmBusNonBlock (
400                           V_PCH_SMBUS_SMB_CMD_BYTE,
401                           SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
402                           Value,
403                           Status
404                           );
405   return ValueReturn;
406 
407   }
408 
409 /**
410   Executes an SMBUS read data byte command.
411 
412   Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress.
413   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
414   The 8-bit value read from the SMBUS is returned.
415   If Status is not NULL, then the status of the executed command is returned in Status.
416   If Length in SmBusAddress is not zero, then ASSERT().
417   If any reserved bits of SmBusAddress are set, then ASSERT().
418 
419   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
SmBusReadDataByte(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)420                           SMBUS Command, SMBUS Data Length, and PEC.
421   @param  Status          Return status for the executed command.
422                           This is an optional parameter and may be NULL.
423 
424   @return The byte read from the SMBUS.
425 
426 **/
427 UINT8
428 EFIAPI
429 SmBusReadDataByte (
430   IN  UINTN          SmBusAddress,
431   OUT RETURN_STATUS  *Status        OPTIONAL
432   )
433 {
434   UINT8 ValueReturn = 0;
435 
436   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
437   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
438    ValueReturn = (UINT8) InternalSmBusNonBlock (
439                            V_PCH_SMBUS_SMB_CMD_BYTE_DATA,
440                            SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
441                            0,
442                            Status
443                            );
444   return ValueReturn;
445 }
446 
447 /**
448   Executes an SMBUS write data byte command.
449 
450   Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress.
451   The 8-bit value specified by Value is written.
452   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
453   Value is returned.
454   If Status is not NULL, then the status of the executed command is returned in Status.
455   If Length in SmBusAddress is not zero, then ASSERT().
456   If any reserved bits of SmBusAddress are set, then ASSERT().
457 
458   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
459                           SMBUS Command, SMBUS Data Length, and PEC.
SmBusWriteDataByte(IN UINTN SmBusAddress,IN UINT8 Value,OUT RETURN_STATUS * Status OPTIONAL)460   @param  Value           The 8-bit value to write.
461   @param  Status          Return status for the executed command.
462                           This is an optional parameter and may be NULL.
463 
464   @return The parameter of Value.
465 
466 **/
467 UINT8
468 EFIAPI
469 SmBusWriteDataByte (
470   IN  UINTN          SmBusAddress,
471   IN  UINT8          Value,
472   OUT RETURN_STATUS  *Status        OPTIONAL
473   )
474 {
475   UINT8 ValueReturn = 0;
476 
477   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
478   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
479 
480   ValueReturn = (UINT8) InternalSmBusNonBlock (
481                           V_PCH_SMBUS_SMB_CMD_BYTE_DATA,
482                           SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
483                           Value,
484                           Status
485                           );
486   return ValueReturn;
487 
488 }
489 
490 /**
491   Executes an SMBUS read data word command.
492 
493   Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress.
494   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
495   The 16-bit value read from the SMBUS is returned.
496   If Status is not NULL, then the status of the executed command is returned in Status.
497   If Length in SmBusAddress is not zero, then ASSERT().
498   If any reserved bits of SmBusAddress are set, then ASSERT().
499 
500   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
SmBusReadDataWord(IN UINTN SmBusAddress,OUT RETURN_STATUS * Status OPTIONAL)501                           SMBUS Command, SMBUS Data Length, and PEC.
502   @param  Status          Return status for the executed command.
503                           This is an optional parameter and may be NULL.
504 
505   @return The byte read from the SMBUS.
506 
507 **/
508 UINT16
509 EFIAPI
510 SmBusReadDataWord (
511   IN  UINTN          SmBusAddress,
512   OUT RETURN_STATUS  *Status        OPTIONAL
513   )
514 {
515   UINT16 ValueReturn = 0;
516   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
517   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
518 
519   ValueReturn = InternalSmBusNonBlock (
520                   V_PCH_SMBUS_SMB_CMD_WORD_DATA,
521                   SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
522                   0,
523                   Status
524                   );
525   return ValueReturn;
526 
527 }
528 
529 /**
530   Executes an SMBUS write data word command.
531 
532   Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress.
533   The 16-bit value specified by Value is written.
534   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
535   Value is returned.
536   If Status is not NULL, then the status of the executed command is returned in Status.
537   If Length in SmBusAddress is not zero, then ASSERT().
538   If any reserved bits of SmBusAddress are set, then ASSERT().
539 
540   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
541                           SMBUS Command, SMBUS Data Length, and PEC.
SmBusWriteDataWord(IN UINTN SmBusAddress,IN UINT16 Value,OUT RETURN_STATUS * Status OPTIONAL)542   @param  Value           The 16-bit value to write.
543   @param  Status          Return status for the executed command.
544                           This is an optional parameter and may be NULL.
545 
546   @return The parameter of Value.
547 
548 **/
549 UINT16
550 EFIAPI
551 SmBusWriteDataWord (
552   IN  UINTN          SmBusAddress,
553   IN  UINT16         Value,
554   OUT RETURN_STATUS  *Status        OPTIONAL
555   )
556 {
557   UINT16 ValueReturn = 0;
558   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
559   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
560 
561   ValueReturn = InternalSmBusNonBlock (
562                   V_PCH_SMBUS_SMB_CMD_WORD_DATA,
563                   SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
564                   Value,
565                   Status
566                   );
567   return ValueReturn;
568 }
569 
570 /**
571   Executes an SMBUS process call command.
572 
573   Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress.
574   The 16-bit value specified by Value is written.
575   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
576   The 16-bit value returned by the process call command is returned.
577   If Status is not NULL, then the status of the executed command is returned in Status.
578   If Length in SmBusAddress is not zero, then ASSERT().
579   If any reserved bits of SmBusAddress are set, then ASSERT().
580 
581   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
582                           SMBUS Command, SMBUS Data Length, and PEC.
SmBusProcessCall(IN UINTN SmBusAddress,IN UINT16 Value,OUT RETURN_STATUS * Status OPTIONAL)583   @param  Value           The 16-bit value to write.
584   @param  Status          Return status for the executed command.
585                           This is an optional parameter and may be NULL.
586 
587   @return The 16-bit value returned by the process call command.
588 
589 **/
590 UINT16
591 EFIAPI
592 SmBusProcessCall (
593   IN  UINTN          SmBusAddress,
594   IN  UINT16         Value,
595   OUT RETURN_STATUS  *Status        OPTIONAL
596   )
597 {
598   UINT16 ValueReturn = 0;
599   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress)    == 0);
600   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
601 
602   ValueReturn = InternalSmBusNonBlock (
603                   V_PCH_SMBUS_SMB_CMD_PROCESS_CALL,
604                   SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
605                   Value,
606                   Status
607                   );
608   return ValueReturn;
609 }
610 
611 /**
612   Executes an SMBUS block command.
613 
614   Executes an SMBUS block read, block write and block write-block read command
615   on the SMBUS device specified by SmBusAddress.
616   Bytes are read from the SMBUS and stored in Buffer.
617   The number of bytes read is returned, and will never return a value larger than 32-bytes.
618   If Status is not NULL, then the status of the executed command is returned in Status.
619   It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
620   SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
621 
622   @param  HostControl     The value of Host Control Register to set.
623   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
624                           SMBUS Command, SMBUS Data Length, and PEC.
InternalSmBusBlock(IN UINT8 HostControl,IN UINTN SmBusAddress,IN UINT8 * WriteBuffer,OUT UINT8 * ReadBuffer,OUT RETURN_STATUS * Status)625   @param  WriteBuffer     Pointer to the buffer of bytes to write to the SMBUS.
626   @param  ReadBuffer      Pointer to the buffer of bytes to read from the SMBUS.
627   @param  Status          Return status for the executed command.
628                           This is an optional parameter and may be NULL.
629 
630   @return The number of bytes read from the SMBUS.
631 
632 **/
633 UINTN
634 InternalSmBusBlock (
635   IN  UINT8                     HostControl,
636   IN  UINTN                     SmBusAddress,
637   IN  UINT8                     *WriteBuffer,
638   OUT UINT8                     *ReadBuffer,
639   OUT RETURN_STATUS             *Status
640   )
641 {
642   RETURN_STATUS                 ReturnStatus;
643   UINTN                         Index;
644   UINTN                         BytesCount;
645   UINTN                         IoPortBaseAddress;
646   UINT8                         AuxiliaryControl;
647 
648   IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
649 
650   BytesCount = SMBUS_LIB_LENGTH (SmBusAddress);
651 
652   //
653   // Try to acquire the ownership of ICH SMBUS.
654   //
655   ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
656   if (RETURN_ERROR (ReturnStatus)) {
657     goto Done;
658   }
659 
660   //
661   // Set the appropriate Host Control Register and auxiliary Control Register.
662   //
663   AuxiliaryControl = B_PCH_SMBUS_E32B;
664   if (SMBUS_LIB_PEC (SmBusAddress)) {
665     AuxiliaryControl |= B_PCH_SMBUS_AAC;
666     HostControl      |= B_PCH_SMBUS_PEC_EN;
667   }
668 
669   //
670   // Set Host Command Register.
671   //
672   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
673 
674   //
675   // Set Auxiliary Control Regiester.
676   //
677   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXC, AuxiliaryControl);
678 
679   //
680   // Clear byte pointer of 32-byte buffer.
681   //
682   IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HCTL);
683 
684   if (WriteBuffer != NULL) {
685     //
686     // Write the number of block to Host Block Data Byte Register.
687     //
688     IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HD0, (UINT8) BytesCount);
689 
690     //
691     // Write data block to Host Block Data Register.
692     //
693     for (Index = 0; Index < BytesCount; Index++) {
694       IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HBD, WriteBuffer[Index]);
695     }
696   }
697 
698   //
699   // Set SMBUS slave address for the device to send/receive from.
700   //
701   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_TSA, (UINT8) SmBusAddress);
702 
703   //
704   // Start the SMBUS transaction and wait for the end.
705   //
706   ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
707   if (RETURN_ERROR (ReturnStatus)) {
708     goto Done;
709   }
710 
711   if (ReadBuffer != NULL) {
712     //
713     // Read the number of block from host block data byte register.
714     //
715     BytesCount = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HD0);
716 
717     //
718     // Write data block from Host Block Data Register.
719     //
720     for (Index = 0; Index < BytesCount; Index++) {
721       ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_PCH_SMBUS_HBD);
722     }
723   }
724 
725 Done:
726   //
727   // Clear Host Status Register and Auxiliary Status Register.
728   //
729   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
730   IoWrite8 (IoPortBaseAddress + R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
731 
732   if (Status != NULL) {
733     *Status = ReturnStatus;
734   }
735 
736   return BytesCount;
737 }
738 
739 /**
740   Executes an SMBUS read block command.
741 
742   Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress.
743   Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
744   Bytes are read from the SMBUS and stored in Buffer.
745   The number of bytes read is returned, and will never return a value larger than 32-bytes.
746   If Status is not NULL, then the status of the executed command is returned in Status.
747   It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
748   SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
749   If Length in SmBusAddress is not zero, then ASSERT().
750   If Buffer is NULL, then ASSERT().
751   If any reserved bits of SmBusAddress are set, then ASSERT().
752 
753   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
754                           SMBUS Command, SMBUS Data Length, and PEC.
SmBusReadBlock(IN UINTN SmBusAddress,OUT VOID * Buffer,OUT RETURN_STATUS * Status OPTIONAL)755   @param  Buffer          Pointer to the buffer to store the bytes read from the SMBUS.
756   @param  Status          Return status for the executed command.
757                           This is an optional parameter and may be NULL.
758 
759   @return The number of bytes read.
760 
761 **/
762 UINTN
763 EFIAPI
764 SmBusReadBlock (
765   IN  UINTN          SmBusAddress,
766   OUT VOID           *Buffer,
767   OUT RETURN_STATUS  *Status        OPTIONAL
768   )
769 {
770   UINTN BytesCount = 0;
771 
772   ASSERT (Buffer != NULL);
773   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
774   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
775 
776 
777   BytesCount = InternalSmBusBlock (
778                  V_PCH_SMBUS_SMB_CMD_BLOCK,
779                  SmBusAddress | B_PCH_SMBUS_RW_SEL_READ,
780                  NULL,
781                  Buffer,
782                  Status
783                  );
784   return BytesCount;
785 
786 }
787 
788 /**
789   Executes an SMBUS write block command.
790 
791   Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress.
792   The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
793   Bytes are written to the SMBUS from Buffer.
794   The number of bytes written is returned, and will never return a value larger than 32-bytes.
795   If Status is not NULL, then the status of the executed command is returned in Status.
796   If Length in SmBusAddress is zero or greater than 32, then ASSERT().
797   If Buffer is NULL, then ASSERT().
798   If any reserved bits of SmBusAddress are set, then ASSERT().
799 
800   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
801                           SMBUS Command, SMBUS Data Length, and PEC.
SmBusWriteBlock(IN UINTN SmBusAddress,OUT VOID * Buffer,OUT RETURN_STATUS * Status OPTIONAL)802   @param  Buffer          Pointer to the buffer to store the bytes read from the SMBUS.
803   @param  Status          Return status for the executed command.
804                           This is an optional parameter and may be NULL.
805 
806   @return The number of bytes written.
807 
808 **/
809 UINTN
810 EFIAPI
811 SmBusWriteBlock (
812   IN  UINTN          SmBusAddress,
813   OUT VOID           *Buffer,
814   OUT RETURN_STATUS  *Status        OPTIONAL
815   )
816 {
817   UINTN	BytesCount = 0;
818 
819   ASSERT (Buffer != NULL);
820   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
821   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
822   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
823 
824 
825  BytesCount = InternalSmBusBlock (
826 
827                 V_PCH_SMBUS_SMB_CMD_BLOCK,
828                 SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
829                 Buffer,
830                 NULL,
831                 Status
832                 );
833 
834   return BytesCount;
835 }
836 
837 /**
838   Executes an SMBUS block process call command.
839 
840   Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress.
841   The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
842   Bytes are written to the SMBUS from WriteBuffer.  Bytes are then read from the SMBUS into ReadBuffer.
843   If Status is not NULL, then the status of the executed command is returned in Status.
844   It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read.
845   SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
846   If Length in SmBusAddress is zero or greater than 32, then ASSERT().
847   If WriteBuffer is NULL, then ASSERT().
848   If ReadBuffer is NULL, then ASSERT().
849   If any reserved bits of SmBusAddress are set, then ASSERT().
850 
851   @param  SmBusAddress    Address that encodes the SMBUS Slave Address,
852                           SMBUS Command, SMBUS Data Length, and PEC.
853   @param  WriteBuffer     Pointer to the buffer of bytes to write to the SMBUS.
SmBusBlockProcessCall(IN UINTN SmBusAddress,IN VOID * WriteBuffer,OUT VOID * ReadBuffer,OUT RETURN_STATUS * Status OPTIONAL)854   @param  ReadBuffer      Pointer to the buffer of bytes to read from the SMBUS.
855   @param  Status          Return status for the executed command.
856                           This is an optional parameter and may be NULL.
857 
858   @return The number of bytes written.
859 
860 **/
861 UINTN
862 EFIAPI
863 SmBusBlockProcessCall (
864   IN  UINTN          SmBusAddress,
865   IN  VOID           *WriteBuffer,
866   OUT VOID           *ReadBuffer,
867   OUT RETURN_STATUS  *Status        OPTIONAL
868   )
869 {
870   UINTN BytesCount = 0;
871 
872   ASSERT (WriteBuffer != NULL);
873   ASSERT (ReadBuffer  != NULL);
874   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
875   ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
876   ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
877 
878   BytesCount = InternalSmBusBlock (
879                  V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS,
880                  SmBusAddress | B_PCH_SMBUS_RW_SEL_WRITE,
881                  WriteBuffer,
882                  ReadBuffer,
883                  Status
884                  );
885   return BytesCount;
886 
887   }
888