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