1 /** @file
2   PCH Smbus Executive Code (common PEI/DXE/SMM code)
3 
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 #include <Uefi/UefiBaseType.h>
9 #include <Library/IoLib.h>
10 #include <Library/DebugLib.h>
11 #include <Library/TimerLib.h>
12 #include <IndustryStandard/SmBus.h>
13 #include <IndustryStandard/Pci30.h>
14 #include <PchAccess.h>
15 #include <Library/MmPciLib.h>
16 #include <Library/PchSmbusCommonLib.h>
17 
18 /**
19   Get SMBUS IO Base address
20 
21 
22   @retval UINT32                  The SMBUS IO Base Address
23 **/
24 UINT32
25 SmbusGetIoBase (
26   VOID
27   )
28 {
SHNDecoder_new(PyTypeObject * type,PyObject * args,PyObject * kwds)29   UINT32  SmbusIoBase;
30 
31   SmbusIoBase = MmioRead32 (
32                   MmPciBase (
33                     DEFAULT_PCI_BUS_NUMBER_PCH,
34                     PCI_DEVICE_NUMBER_PCH_SMBUS,
35                     PCI_FUNCTION_NUMBER_PCH_SMBUS)
36                     + R_PCH_SMBUS_BASE) & B_PCH_SMBUS_BASE_BAR;
37 
38   ASSERT (SmbusIoBase != B_PCH_SMBUS_BASE_BAR && SmbusIoBase != 0);
39 
SHNDecoder_init(decoders_SHNDecoder * self,PyObject * args,PyObject * kwds)40   return SmbusIoBase;
41 }
42 
43 /**
44   This function provides a standard way to read PCH Smbus IO registers.
45 
46   @param[in] Offset               Register offset from Smbus base IO address.
47 
48   @retval UINT8                   Returns data read from IO.
49 **/
50 UINT8
51 EFIAPI
52 SmbusIoRead (
53   IN      UINT8           Offset
54   )
55 {
56   return IoRead8 (SmbusGetIoBase () + Offset);
57 }
58 
59 /**
60   This function provides a standard way to write PCH Smbus IO registers.
61 
62   @param[in] Offset               Register offset from Smbus base IO address.
63   @param[in] Data                 Data to write to register.
64 
65 **/
66 VOID
67 EFIAPI
68 SmbusIoWrite (
69   IN      UINT8           Offset,
70   IN      UINT8           Data
71   )
72 {
73   ///
74   /// Write New Value
75   ///
76   IoWrite8 (SmbusGetIoBase () + Offset, Data);
77   return;
78 }
79 
80 /**
81   This function provides a standard way to check if an SMBus transaction has
82   completed.
83 
84   @param[in] StsReg               Not used for input. On return, contains the
85                                   value of the SMBus status register.
86 
87   @retval TRUE                    Transaction is complete
88   @retval FALSE                   Otherwise.
89 **/
90 BOOLEAN
91 EFIAPI
92 IoDone (
93   IN      UINT8           *StsReg
94   )
95 {
96   ///
97   /// Wait for IO to complete
98   ///
99   UINTN StallIndex;
100   UINTN StallTries;
SHNDecoder_dealloc(decoders_SHNDecoder * self)101 
102   StallTries = STALL_TIME / STALL_PERIOD;
103 
104   for (StallIndex = 0; StallIndex < StallTries; StallIndex++) {
105     *StsReg = SmbusIoRead (R_PCH_SMBUS_HSTS);
106     if (*StsReg & (B_PCH_SMBUS_INTR | B_PCH_SMBUS_BYTE_DONE_STS | B_PCH_SMBUS_DERR | B_PCH_SMBUS_BERR)) {
107       return TRUE;
108     } else {
109       MicroSecondDelay (STALL_PERIOD);
110     }
111   }
112 
113   return FALSE;
114 }
115 
116 /**
117   Check if it's ok to use the bus.
118 
119 
SHNDecoder_close(decoders_SHNDecoder * self,PyObject * args)120   @retval EFI_SUCCESS             SmBus is acquired and it's safe to send commands.
121   @retval EFI_TIMEOUT             SmBus is busy, it's not safe to send commands.
122 **/
123 EFI_STATUS
124 AcquireBus (
125   VOID
126   )
127 {
128   UINT8 StsReg;
129 
130   StsReg  = 0;
131   StsReg  = SmbusIoRead (R_PCH_SMBUS_HSTS);
132   if (StsReg & B_PCH_SMBUS_IUS) {
133     return EFI_TIMEOUT;
134   } else if (StsReg & B_PCH_SMBUS_HBSY) {
135     ///
136     /// Clear Status Register and exit
137     ///
138     SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
139     return EFI_TIMEOUT;
140   } else {
141     ///
142     /// Clear out any odd status information (Will Not Clear In Use)
143     ///
144     SmbusIoWrite (R_PCH_SMBUS_HSTS, StsReg);
145     return EFI_SUCCESS;
146   }
147 }
148 
149 /**
150   This function provides a standard way to execute Smbus protocols
SHNDecoder_sample_rate(decoders_SHNDecoder * self,void * closure)151   as defined in the SMBus Specification. The data can either be of
152   the Length byte, word, or a block of data. The resulting transaction will be
153   either the SMBus Slave Device accepts this transaction or this function
154   returns with an error
155 
156   @param[in] SlaveAddress         Smbus Slave device the command is directed at
157   @param[in] Command              Slave Device dependent
158   @param[in] Operation            Which SMBus protocol will be used
159   @param[in] PecCheck             Defines if Packet Error Code Checking is to be used
160   @param[in, out] Length          How many bytes to read. Must be 0 <= Length <= 32 depending on Operation
161                                   It will contain the actual number of bytes read/written.
162   @param[in, out] Buffer          Contain the data read/written.
163 
164   @retval EFI_SUCCESS             The operation completed successfully.
165   @exception EFI_UNSUPPORTED      The operation is unsupported.
166 
167   @retval EFI_INVALID_PARAMETER   Length or Buffer is NULL for any operation besides
168                                   quick read or quick write.
169   @retval EFI_TIMEOUT             The transaction did not complete within an internally
170                                   specified timeout period, or the controller is not
171                                   available for use.
172   @retval EFI_DEVICE_ERROR        There was an Smbus error (NACK) during the operation.
173                                   This could indicate the slave device is not present
174                                   or is in a hung condition.
175 **/
176 EFI_STATUS
177 SmbusExec (
178   IN      EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress,
179   IN      EFI_SMBUS_DEVICE_COMMAND  Command,
180   IN      EFI_SMBUS_OPERATION       Operation,
181   IN      BOOLEAN                   PecCheck,
182   IN OUT  UINTN                     *Length,
183   IN OUT  VOID                      *Buffer
184   )
185 {
186   EFI_STATUS  Status;
187   UINT8       AuxcReg;
188   UINT8       AuxStsReg;
189   UINT8       SmbusOperation;
190   UINT8       StsReg;
191   UINT8       SlvAddrReg;
192   UINT8       HostCmdReg;
193   UINT8       BlockCount;
194   BOOLEAN     BufferTooSmall;
195   UINTN       Index;
196   UINTN       BusIndex;
197   UINT8       *CallBuffer;
198   UINT8       SmbusHctl;
199   UINT32      Timeout;
200 
201   CallBuffer  = Buffer;
202   BlockCount  = 0;
203 
204   ///
205   /// For any operations besides quick read & write, the pointers to
206   /// Length and Buffer must not be NULL.
207   ///
208   if ((Operation != EfiSmbusQuickRead) && (Operation != EfiSmbusQuickWrite)) {
209     if ((Length == NULL) || (Buffer == NULL)) {
210       return EFI_INVALID_PARAMETER;
211     }
212   }
213   ///
214   /// See if its ok to use the bus based upon INUSE_STS bit.
215   ///
216   Status = AcquireBus ();
217   if (EFI_ERROR (Status)) {
218     return Status;
219   }
220   ///
221   /// This is the main operation loop.  If the operation results in a Smbus
222   /// collision with another master on the bus, it attempts the requested
223   /// transaction again at least BUS_TRIES attempts.
224   ///
225   for (BusIndex = 0; BusIndex < BUS_TRIES; BusIndex++) {
226     ///
227     /// Operation Specifics (pre-execution)
228     ///
229     Status          = EFI_SUCCESS;
230     SmbusOperation  = V_PCH_SMBUS_SMB_CMD_QUICK;
231     SlvAddrReg      = (UINT8) ((SlaveAddress.SmbusDeviceAddress << 1) | 1);
232     HostCmdReg      = (UINT8) Command;
233     AuxcReg         = 0;
234 
235     switch (Operation) {
236 
237       case EfiSmbusQuickWrite:
238         SlvAddrReg--;
239 
240         ///
241         /// The "break;" command is not present here to allow code execution
242         /// do drop into the next case, which contains common code to this case.
243         ///
244       case EfiSmbusQuickRead:
245         if (PecCheck == TRUE) {
246           Status = EFI_UNSUPPORTED;
247         }
248         break;
249 
250       case EfiSmbusSendByte:
251         HostCmdReg = CallBuffer[0];
252         SlvAddrReg--;
253 
254         ///
255         /// The "break;" command is not present here to allow code execution
256         /// do drop into the next case, which contains common code to this case.
257         ///
258       case EfiSmbusReceiveByte:
259         SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE;
260         if (*Length < 1) {
261           Status = EFI_BUFFER_TOO_SMALL;
262         }
263 
264         *Length = 1;
265         break;
266 
267       case EfiSmbusWriteByte:
268         SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
269         SlvAddrReg--;
270         *Length = 1;
271 
272         ///
273         /// The "break;" command is not present here to allow code execution
274         /// do drop into the next case, which contains common code to this case.
275         ///
276       case EfiSmbusReadByte:
277         if (*Length < 1) {
278           Status = EFI_BUFFER_TOO_SMALL;
279         } else if (*Length == 1) {
280           SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA;
281         } else if (*Length <= 256) {
282           if (PecCheck == TRUE) {
283             ///
284             /// The I2C Read command with either PEC_EN or AAC bit set
285             /// produces undefined results.
286             ///
287             Status = EFI_UNSUPPORTED;
288           }
289 
290           SmbusOperation = V_PCH_SMBUS_SMB_CMD_IIC_READ;
291         } else {
292           Status = EFI_INVALID_PARAMETER;
293         }
294 
295         break;
296 
297       case EfiSmbusReadWord:
298         SmbusOperation = V_PCH_SMBUS_SMB_CMD_WORD_DATA;
299         if (*Length < 2) {
300           Status = EFI_BUFFER_TOO_SMALL;
301         }
302 
303         *Length = 2;
304         break;
305 
306       case EfiSmbusWriteWord:
307         SmbusOperation = V_PCH_SMBUS_SMB_CMD_WORD_DATA;
308         SlvAddrReg--;
309         SmbusIoWrite (R_PCH_SMBUS_HD1, CallBuffer[1]);
310         SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
311         if (*Length < 2) {
312           Status = EFI_BUFFER_TOO_SMALL;
313         }
314 
315         *Length = 2;
316         break;
317 
318       case EfiSmbusWriteBlock:
319         SmbusIoWrite (R_PCH_SMBUS_HD0, *(UINT8 *) Length);
320         SlvAddrReg--;
321         BlockCount = (UINT8) (*Length);
322 
323         ///
324         /// The "break;" command is not present here to allow code execution
325         /// do drop into the next case, which contains common code to this case.
326         ///
327       case EfiSmbusReadBlock:
328         SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK;
329         if ((*Length < 1) || (*Length > 32)) {
330           Status = EFI_INVALID_PARAMETER;
331           break;
332         }
333 
334         AuxcReg |= B_PCH_SMBUS_E32B;
335         break;
336 
337       case EfiSmbusProcessCall:
338         SmbusOperation = V_PCH_SMBUS_SMB_CMD_PROCESS_CALL;
339         SmbusIoWrite (R_PCH_SMBUS_HD1, CallBuffer[1]);
340         SmbusIoWrite (R_PCH_SMBUS_HD0, CallBuffer[0]);
341         if (*Length < 2) {
342           Status = EFI_BUFFER_TOO_SMALL;
343         }
344 
345         *Length = 2;
346         break;
347 
348       case EfiSmbusBWBRProcessCall:
349         ///
350         /// The write byte count cannot be zero or more than
351         /// 32 bytes.
352         ///
353         if ((*Length < 1) || (*Length > 32)) {
354           Status = EFI_INVALID_PARAMETER;
355           break;
356         }
357 
358         SmbusIoWrite (R_PCH_SMBUS_HD0, *(UINT8 *) Length);
359         BlockCount      = (UINT8) (*Length);
360         SmbusOperation  = V_PCH_SMBUS_SMB_CMD_BLOCK_PROCESS;
361 
362         AuxcReg |= B_PCH_SMBUS_E32B;
363         break;
364 
365       default:
366         Status = EFI_INVALID_PARAMETER;
367         break;
368     }
369 
370     if (EFI_ERROR (Status)) {
371       break;
372     }
373 
374     if (PecCheck == TRUE) {
375       AuxcReg |= B_PCH_SMBUS_AAC;
376     }
377     ///
378     /// Set Auxiliary Control register
379     ///
380     SmbusIoWrite (R_PCH_SMBUS_AUXC, AuxcReg);
381 
382     ///
383     /// Reset the pointer of the internal buffer
384     ///
385     SmbusIoRead (R_PCH_SMBUS_HCTL);
386 
387     ///
388     /// Now that the 32 byte buffer is turned on, we can write th block data
389     /// into it
390     ///
391     if ((Operation == EfiSmbusWriteBlock) || (Operation == EfiSmbusBWBRProcessCall)) {
392       for (Index = 0; Index < BlockCount; Index++) {
393         ///
394         /// Write next byte
395         ///
396         SmbusIoWrite (R_PCH_SMBUS_HBD, CallBuffer[Index]);
397       }
398     }
399     ///
400     /// Set SMBus slave address for the device to send/receive from
401     ///
402     SmbusIoWrite (R_PCH_SMBUS_TSA, SlvAddrReg);
403 
404     ///
405     /// For I2C read, send DATA1 register for the offset (address)
406     /// within the serial memory chips
407     ///
408     if ((Operation == EfiSmbusReadByte) && (*Length > 1)) {
409       SmbusIoWrite (R_PCH_SMBUS_HD1, HostCmdReg);
410     } else {
411       ///
412       /// Set Command register
413       ///
414       SmbusIoWrite (R_PCH_SMBUS_HCMD, HostCmdReg);
415     }
416     ///
417     /// Set Control Register (Initiate Operation, Interrupt disabled)
418     ///
419     SmbusIoWrite (R_PCH_SMBUS_HCTL, (UINT8) (SmbusOperation + B_PCH_SMBUS_START));
420 
421     ///
422     /// Wait for IO to complete
423     ///
424     if (!IoDone (&StsReg)) {
425       Status = EFI_TIMEOUT;
426       break;
427     } else if (StsReg & B_PCH_SMBUS_DERR) {
428       AuxStsReg = SmbusIoRead (R_PCH_SMBUS_AUXS);
429       if (AuxStsReg & B_PCH_SMBUS_CRCE) {
430         Status = EFI_CRC_ERROR;
431       } else {
432         Status = EFI_DEVICE_ERROR;
433       }
434       break;
435     } else if (StsReg & B_PCH_SMBUS_BERR) {
436       ///
437       /// Clear the Bus Error for another try
438       ///
439       Status = EFI_DEVICE_ERROR;
440       SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
441       ///
442       /// Clear Status Registers
443       ///
444       SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
445       SmbusIoWrite (R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
446       ///
447       /// If bus collision happens, stall some time, then try again
448       /// Here we choose 10 milliseconds to avoid MTCP transfer.
449       ///
450       MicroSecondDelay (STALL_PERIOD);
451       continue;
452     }
453     ///
454     /// successfull completion
455     /// Operation Specifics (post-execution)
456     ///
457     switch (Operation) {
458 
459       case EfiSmbusReadWord:
460         ///
461         /// The "break;" command is not present here to allow code execution
462         /// do drop into the next case, which contains common code to this case.
463         ///
464       case EfiSmbusProcessCall:
465         CallBuffer[1] = SmbusIoRead (R_PCH_SMBUS_HD1);
466         CallBuffer[0] = SmbusIoRead (R_PCH_SMBUS_HD0);
467         break;
468 
469       case EfiSmbusReadByte:
470         if (*Length > 1) {
471           for (Index = 0; Index < *Length; Index++) {
472             ///
473             /// Read the byte
474             ///
475             CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
476             ///
477             /// After receiving byte n-1 (1-base) of the message, the
478             /// software will then set the LAST BYTE bit. The software
479             /// will then clear the BYTE_DONE_STS bit.
480             ///
481             if (Index == ((*Length - 1) - 1)) {
482               SmbusHctl = SmbusIoRead (R_PCH_SMBUS_HCTL) | (UINT8) B_PCH_SMBUS_LAST_BYTE;
483               SmbusIoWrite (R_PCH_SMBUS_HCTL, SmbusHctl);
484             } else if (Index == (*Length - 1)) {
485               ///
486               /// Clear the LAST BYTE bit after receiving byte n (1-base) of the message
487               ///
488               SmbusHctl = SmbusIoRead (R_PCH_SMBUS_HCTL) & (UINT8) ~B_PCH_SMBUS_LAST_BYTE;
489               SmbusIoWrite (R_PCH_SMBUS_HCTL, SmbusHctl);
490             }
491             ///
492             /// Clear the BYTE_DONE_STS bit
493             ///
494             SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
495             ///
496             /// Check BYTE_DONE_STS bit to know if it has completed transmission
497             /// of a byte. No need to check it for the last byte.
498             ///
499             if (Index < (*Length - 1)) {
500               ///
501               /// If somehow board operates at 10Khz, it will take 0.9 ms (9/10Khz) for another byte.
502               /// Add 10 us delay for a loop of 100 that the total timeout is 1 ms to take care of
503               /// the slowest case.
504               ///
505               for (Timeout = 0; Timeout < 100; Timeout++) {
506                 if ((SmbusIoRead (R_PCH_SMBUS_HSTS) & (UINT8) B_PCH_SMBUS_BYTE_DONE_STS) != 0) {
507                   break;
508                 }
509                 ///
510                 /// Delay 10 us
511                 ///
512                 MicroSecondDelay (STALL_PERIOD);
513               }
514 
515               if (Timeout >= 100) {
516                 Status = EFI_TIMEOUT;
517                 break;
518               }
519             }
520           }
521           break;
522         }
523 
524       case EfiSmbusReceiveByte:
525         CallBuffer[0] = SmbusIoRead (R_PCH_SMBUS_HD0);
526         break;
527 
528       case EfiSmbusWriteBlock:
529         SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
530         break;
531 
532       case EfiSmbusReadBlock:
533         BufferTooSmall = FALSE;
534         ///
535         /// Find out how many bytes will be in the block
536         ///
537         BlockCount = SmbusIoRead (R_PCH_SMBUS_HD0);
538         if (*Length < BlockCount) {
539           BufferTooSmall = TRUE;
540         } else {
541           for (Index = 0; Index < BlockCount; Index++) {
542             ///
543             /// Read the byte
544             ///
545             CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
546           }
547         }
548 
549         *Length = BlockCount;
550         if (BufferTooSmall) {
551           Status = EFI_BUFFER_TOO_SMALL;
552         }
553         break;
554 
555       case EfiSmbusBWBRProcessCall:
556         ///
557         /// Find out how many bytes will be in the block
558         ///
559         BlockCount = SmbusIoRead (R_PCH_SMBUS_HD0);
560         ///
561         /// The read byte count cannot be zero.
562         ///
563         if (BlockCount < 1) {
564           Status = EFI_BUFFER_TOO_SMALL;
565           break;
566         }
567         ///
568         /// The combined data payload (the write byte count + the read byte count)
569         /// must not exceed 32 bytes
570         ///
571         if (((UINT8) (*Length) + BlockCount) > 32) {
572           Status = EFI_DEVICE_ERROR;
573           break;
574         }
575 
576         for (Index = 0; Index < BlockCount; Index++) {
577           ///
578           /// Read the byte
579           ///
580           CallBuffer[Index] = SmbusIoRead (R_PCH_SMBUS_HBD);
581         }
582 
583         *Length = BlockCount;
584         break;
585 
586       default:
587         break;
588     };
589 
590     if ((StsReg & B_PCH_SMBUS_BERR) && (Status != EFI_BUFFER_TOO_SMALL)) {
591       ///
592       /// Clear the Bus Error for another try
593       ///
594       Status = EFI_DEVICE_ERROR;
595       SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
596       ///
597       /// If bus collision happens, stall some time, then try again
598       /// Here we choose 10 milliseconds to avoid MTCP transfer.
599       ///
600       MicroSecondDelay (STALL_PERIOD);
601       continue;
602     } else {
603       break;
604     }
605   }
606   ///
607   /// Clear Status Registers and exit
608   ///
609   SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
610   SmbusIoWrite (R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
611   SmbusIoWrite (R_PCH_SMBUS_AUXC, 0);
612   return Status;
613 }
614 
615 /**
616   This function initializes the Smbus Registers.
617 
618 **/
619 VOID
620 InitializeSmbusRegisters (
read_qlpc(BitstreamReader * bs,unsigned block_length,a_int * previous_samples,a_int * means,a_int * samples)621   VOID
622   )
623 {
624   UINTN SmbusRegBase;
625 
626   SmbusRegBase = MmPciBase (
627                    DEFAULT_PCI_BUS_NUMBER_PCH,
628                    PCI_DEVICE_NUMBER_PCH_SMBUS,
629                    PCI_FUNCTION_NUMBER_PCH_SMBUS
630                    );
631   ///
632   /// Enable the Smbus I/O Enable
633   ///
634   MmioOr8 (SmbusRegBase + PCI_COMMAND_OFFSET, (UINT8) EFI_PCI_COMMAND_IO_SPACE);
635 
636   ///
637   /// Enable the Smbus host controller
638   ///
639   MmioAndThenOr8 (
640     SmbusRegBase + R_PCH_SMBUS_HOSTC,
641     (UINT8) (~(B_PCH_SMBUS_HOSTC_SMI_EN | B_PCH_SMBUS_HOSTC_I2C_EN)),
642     B_PCH_SMBUS_HOSTC_HST_EN
643     );
644 
645   SmbusIoWrite (R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
646 }