• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Functions for accessing I2C registers.
3 
4   Copyright (c) 2004  - 2015, Intel Corporation. All rights reserved.<BR>
5 
6   This program and the accompanying materials are licensed and made available under
7   the terms and conditions of the BSD License that accompanies this distribution.
8   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 #include <Library/DebugLib.h>
17 #include <Library/TimerLib.h>
18 #include <PchRegs/PchRegsPcu.h>
19 #include <PchRegs.h>
20 #include <PlatformBaseAddresses.h>
21 #include <PchRegs/PchRegsLpss.h>
22 #include <Library/I2CLib.h>
23 #include <Protocol/GlobalNvsArea.h>
24 #include <Library/UefiBootServicesTableLib.h>
25 #include <I2CRegs.h>
26 
27 #define GLOBAL_NVS_OFFSET(Field)    (UINTN)((CHAR8*)&((EFI_GLOBAL_NVS_AREA*)0)->Field - (CHAR8*)0)
28 
29 #define PCIEX_BASE_ADDRESS  0xE0000000
30 #define PCI_EXPRESS_BASE_ADDRESS ((VOID *) (UINTN) PCIEX_BASE_ADDRESS)
31 #define MmPciAddress( Segment, Bus, Device, Function, Register ) \
32          ((UINTN)PCI_EXPRESS_BASE_ADDRESS + \
33          (UINTN)(Bus << 20) + \
34          (UINTN)(Device << 15) + \
35          (UINTN)(Function << 12) + \
36          (UINTN)(Register) \
37         )
38 #define PCI_D31F0_REG_BASE             PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)
39 
40 typedef struct _LPSS_PCI_DEVICE_INFO {
41   UINTN        Segment;
42   UINTN        BusNum;
43   UINTN        DeviceNum;
44   UINTN        FunctionNum;
45   UINTN        Bar0;
46   UINTN        Bar1;
47 } LPSS_PCI_DEVICE_INFO;
48 
49 LPSS_PCI_DEVICE_INFO  mLpssPciDeviceList[] = {
50   {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_DMAC1, PCI_FUNCTION_NUMBER_PCH_LPSS_DMAC, 0xFE900000, 0xFE908000},
51   {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C,   PCI_FUNCTION_NUMBER_PCH_LPSS_I2C0, 0xFE910000, 0xFE918000},
52   {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C,   PCI_FUNCTION_NUMBER_PCH_LPSS_I2C1, 0xFE920000, 0xFE928000},
53   {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C,   PCI_FUNCTION_NUMBER_PCH_LPSS_I2C2, 0xFE930000, 0xFE938000},
54   {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C,   PCI_FUNCTION_NUMBER_PCH_LPSS_I2C3, 0xFE940000, 0xFE948000},
55   {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C,   PCI_FUNCTION_NUMBER_PCH_LPSS_I2C4, 0xFE950000, 0xFE958000},
56   {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C,   PCI_FUNCTION_NUMBER_PCH_LPSS_I2C5, 0xFE960000, 0xFE968000},
57   {0, DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPSS_I2C,   PCI_FUNCTION_NUMBER_PCH_LPSS_I2C6, 0xFE970000, 0xFE978000}
58 };
59 
60 #define LPSS_PCI_DEVICE_NUMBER  sizeof(mLpssPciDeviceList)/sizeof(LPSS_PCI_DEVICE_INFO)
61 
62 STATIC UINTN mI2CBaseAddress = 0;
63 STATIC UINT16 mI2CSlaveAddress = 0;
64 
65 UINT16 mI2cMode=B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE ;
66 
67 UINTN mI2cNvsBaseAddress[] = {
68         GLOBAL_NVS_OFFSET(LDMA2Addr),
69         GLOBAL_NVS_OFFSET(I2C1Addr),
70         GLOBAL_NVS_OFFSET(I2C2Addr),
71         GLOBAL_NVS_OFFSET(I2C3Addr),
72         GLOBAL_NVS_OFFSET(I2C4Addr),
73         GLOBAL_NVS_OFFSET(I2C5Addr),
74         GLOBAL_NVS_OFFSET(I2C6Addr),
75         GLOBAL_NVS_OFFSET(I2C7Addr)
76       };
77 
78 /**
79   This function get I2Cx controller base address (BAR0).
80 
81   @param I2cControllerIndex  Bus Number of I2C controller.
82 
83   @return I2C BAR.
84 **/
85 UINTN
GetI2cBarAddr(IN UINT8 I2cControllerIndex)86 GetI2cBarAddr(
87   IN    UINT8 I2cControllerIndex
88   )
89 {
90   EFI_STATUS           Status;
91   EFI_GLOBAL_NVS_AREA_PROTOCOL  *GlobalNvsArea;
92   UINTN  AcpiBaseAddr;
93   UINTN  PciMmBase=0;
94 
95   ASSERT(gBS!=NULL);
96 
97   Status = gBS->LocateProtocol (
98                   &gEfiGlobalNvsAreaProtocolGuid,
99                   NULL,
100                   &GlobalNvsArea
101                   );
102 
103   //
104   // PCI mode from PEI ( Global NVS is not ready).
105   //
106   if (EFI_ERROR(Status)) {
107     DEBUG ((EFI_D_INFO, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status));
108     //
109     // Global NVS is not ready.
110     //
111     return 0;
112   }
113 
114   AcpiBaseAddr =  *(UINTN*)((CHAR8*)GlobalNvsArea->Area + mI2cNvsBaseAddress[I2cControllerIndex + 1]);
115 
116   //
117   //PCI mode from DXE (global NVS protocal) to LPSS OnReadytoBoot(swith to ACPI).
118   //
119   if(AcpiBaseAddr==0) {
120     PciMmBase = MmPciAddress (
121                   mLpssPciDeviceList[I2cControllerIndex + 1].Segment,
122                   mLpssPciDeviceList[I2cControllerIndex + 1].BusNum,
123                   mLpssPciDeviceList[I2cControllerIndex + 1].DeviceNum,
124                   mLpssPciDeviceList[I2cControllerIndex + 1].FunctionNum,
125                   0
126                   );
127     DEBUG((EFI_D_ERROR, "\nGetI2cBarAddr() I2C Device %x %x %x PciMmBase:%x\n", \
128            mLpssPciDeviceList[I2cControllerIndex + 1].BusNum, \
129            mLpssPciDeviceList[I2cControllerIndex + 1].DeviceNum, \
130            mLpssPciDeviceList[I2cControllerIndex + 1].FunctionNum, PciMmBase));
131 
132     if (MmioRead32 (PciMmBase) != 0xFFFFFFFF)    {
133       if((MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_STSCMD)& B_PCH_LPSS_I2C_STSCMD_MSE)) {
134         //
135         // Get the address allocted.
136         //
137         mLpssPciDeviceList[I2cControllerIndex + 1].Bar0=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR);
138         mLpssPciDeviceList[I2cControllerIndex + 1].Bar1=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR1);
139       }
140     }
141     AcpiBaseAddr =mLpssPciDeviceList[I2cControllerIndex+1].Bar0;
142   }
143 
144   //
145   // ACPI mode from BDS: LPSS OnReadytoBoot
146   //
147   else {
148     DEBUG ((EFI_D_INFO, "GetI2cBarAddr() NVS Varialable is updated by this LIB or LPSS  \n"));
149   }
150 
151   DEBUG ((EFI_D_INFO, "GetI2cBarAddr() I2cControllerIndex+1 0x%x AcpiBaseAddr:0x%x \n", (I2cControllerIndex + 1), AcpiBaseAddr));
152   return AcpiBaseAddr;
153 }
154 
155 
156 /**
157   This function enables I2C controllers.
158 
159   @param I2cControllerIndex  Bus Number of I2C controllers.
160 
161   @return Result of the I2C initialization.
162 **/
163 EFI_STATUS
ProgramPciLpssI2C(IN UINT8 I2cControllerIndex)164 ProgramPciLpssI2C (
165   IN  UINT8 I2cControllerIndex
166   )
167 {
168   UINT32                        PmcBase;
169   UINTN                         PciMmBase=0;
170   EFI_STATUS                    Status;
171   EFI_GLOBAL_NVS_AREA_PROTOCOL  *GlobalNvsArea;
172 
173   UINT32 PmcFunctionDsiable[]= {
174     B_PCH_PMC_FUNC_DIS_LPSS2_FUNC1,
175     B_PCH_PMC_FUNC_DIS_LPSS2_FUNC2,
176     B_PCH_PMC_FUNC_DIS_LPSS2_FUNC3,
177     B_PCH_PMC_FUNC_DIS_LPSS2_FUNC4,
178     B_PCH_PMC_FUNC_DIS_LPSS2_FUNC5,
179     B_PCH_PMC_FUNC_DIS_LPSS2_FUNC6,
180     B_PCH_PMC_FUNC_DIS_LPSS2_FUNC7
181   };
182 
183   DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() Start\n"));
184 
185   //
186   // Set the VLV Function Disable Register to ZERO
187   //
188   PmcBase = MmioRead32 (PCI_D31F0_REG_BASE + R_PCH_LPC_PMC_BASE) & B_PCH_LPC_PMC_BASE_BAR;
189   if(MmioRead32(PmcBase+R_PCH_PMC_FUNC_DIS)&PmcFunctionDsiable[I2cControllerIndex]) {
190     DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() End:I2C[%x] is disabled\n",I2cControllerIndex));
191     return EFI_NOT_READY;
192   }
193 
194   DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C()------------I2cControllerIndex=%x,PMC=%x\n",I2cControllerIndex,MmioRead32(PmcBase+R_PCH_PMC_FUNC_DIS)));
195 
196   {
197     PciMmBase = MmPciAddress (
198                   mLpssPciDeviceList[I2cControllerIndex+1].Segment,
199                   mLpssPciDeviceList[I2cControllerIndex+1].BusNum,
200                   mLpssPciDeviceList[I2cControllerIndex+1].DeviceNum,
201                   mLpssPciDeviceList[I2cControllerIndex+1].FunctionNum,
202                   0
203                   );
204 
205     DEBUG((EFI_D_ERROR, "Program Pci Lpss I2C Device  %x %x %x PciMmBase:%x\n", \
206            mLpssPciDeviceList[I2cControllerIndex+1].BusNum, \
207            mLpssPciDeviceList[I2cControllerIndex+1].DeviceNum, \
208            mLpssPciDeviceList[I2cControllerIndex+1].FunctionNum, PciMmBase));
209 
210     if (MmioRead32 (PciMmBase) != 0xFFFFFFFF)     {
211       if((MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_STSCMD)& B_PCH_LPSS_I2C_STSCMD_MSE)) {
212         //
213         // Get the address allocted.
214         //
215         mLpssPciDeviceList[I2cControllerIndex+1].Bar0=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR);
216         mLpssPciDeviceList[I2cControllerIndex+1].Bar1=MmioRead32 (PciMmBase+R_PCH_LPSS_I2C_BAR1);
217         DEBUG((EFI_D_ERROR, "ProgramPciLpssI2C() bar0:0x%x bar1:0x%x\n",mLpssPciDeviceList[I2cControllerIndex+1].Bar0, mLpssPciDeviceList[I2cControllerIndex+1].Bar1));
218       } else {
219 
220         //
221         // Program BAR 0
222         //
223         ASSERT (((mLpssPciDeviceList[I2cControllerIndex+1].Bar0 & B_PCH_LPSS_I2C_BAR_BA) == mLpssPciDeviceList[I2cControllerIndex+1].Bar0) && (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 != 0));
224         MmioWrite32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR), (UINT32) (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 & B_PCH_LPSS_I2C_BAR_BA));
225 
226         //
227         // Program BAR 1
228         //
229         ASSERT (((mLpssPciDeviceList[I2cControllerIndex+1].Bar1 & B_PCH_LPSS_I2C_BAR1_BA) == mLpssPciDeviceList[I2cControllerIndex+1].Bar1) && (mLpssPciDeviceList[I2cControllerIndex+1].Bar1 != 0));
230         MmioWrite32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_BAR1), (UINT32) (mLpssPciDeviceList[I2cControllerIndex+1].Bar1 & B_PCH_LPSS_I2C_BAR1_BA));
231 
232         //
233         // Bus Master Enable & Memory Space Enable
234         //
235         MmioOr32 ((UINTN) (PciMmBase + R_PCH_LPSS_I2C_STSCMD), (UINT32) (B_PCH_LPSS_I2C_STSCMD_BME | B_PCH_LPSS_I2C_STSCMD_MSE));
236         ASSERT (MmioRead32 (mLpssPciDeviceList[I2cControllerIndex+1].Bar0) != 0xFFFFFFFF);
237       }
238 
239       //
240       // Release Resets
241       //
242       MmioWrite32 (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 + R_PCH_LPIO_I2C_MEM_RESETS,(B_PCH_LPIO_I2C_MEM_RESETS_FUNC | B_PCH_LPIO_I2C_MEM_RESETS_APB));
243 
244       //
245       // Activate Clocks
246       //
247       MmioWrite32 (mLpssPciDeviceList[I2cControllerIndex+1].Bar0 + R_PCH_LPSS_I2C_MEM_PCP,0x80020003);//No use for A0
248 
249       DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() Programmed()\n"));
250     }
251 
252     //
253     // BDS: already switched to ACPI mode
254     //
255     else {
256       ASSERT(gBS!=NULL);
257       Status = gBS->LocateProtocol (
258                       &gEfiGlobalNvsAreaProtocolGuid,
259                       NULL,
260                       &GlobalNvsArea
261                       );
262       if (EFI_ERROR(Status)) {
263         DEBUG ((EFI_D_INFO, "GetI2cBarAddr() gEfiGlobalNvsAreaProtocolGuid:%r\n", Status));
264         //
265         // gEfiGlobalNvsAreaProtocolGuid is not ready.
266         //
267         return 0;
268       }
269       mLpssPciDeviceList[I2cControllerIndex + 1].Bar0 = *(UINTN*)((CHAR8*)GlobalNvsArea->Area + mI2cNvsBaseAddress[I2cControllerIndex + 1]);
270       DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C(): is switched to ACPI 0x:%x \n",mLpssPciDeviceList[I2cControllerIndex + 1].Bar0));
271     }
272   }
273 
274   DEBUG ((EFI_D_INFO, "ProgramPciLpssI2C() End\n"));
275 
276   return EFI_SUCCESS;
277 }
278 
279 /**
280   Disable I2C Bus.
281 
282   @param VOID.
283 
284   @return Result of the I2C disabling.
285 **/
286 RETURN_STATUS
I2cDisable(VOID)287 I2cDisable (
288   VOID
289   )
290 {
291   //
292   // 0.1 seconds
293   //
294   UINT32 NumTries = 10000;
295 
296   MmioWrite32 ( mI2CBaseAddress + R_IC_ENABLE, 0 );
297   while ( 0 != ( MmioRead32 ( mI2CBaseAddress + R_IC_ENABLE_STATUS) & 1)) {
298     MicroSecondDelay (10);
299     NumTries --;
300     if(0 == NumTries) {
301       return RETURN_NOT_READY;
302     }
303   }
304 
305   return RETURN_SUCCESS;
306 }
307 
308 /**
309   Enable I2C Bus.
310 
311   @param VOID.
312 
313   @return Result of the I2C disabling.
314 **/
315 RETURN_STATUS
I2cEnable(VOID)316 I2cEnable (
317   VOID
318   )
319 {
320   //
321   // 0.1 seconds
322   //
323   UINT32 NumTries = 10000;
324 
325   MmioWrite32 (mI2CBaseAddress + R_IC_ENABLE, 1);
326 
327   while (0 == (MmioRead32 (mI2CBaseAddress + R_IC_ENABLE_STATUS) & 1)) {
328     MicroSecondDelay (10);
329     NumTries --;
330     if(0 == NumTries){
331        return RETURN_NOT_READY;
332     }
333   }
334 
335   return RETURN_SUCCESS;
336 }
337 
338 /**
339   Enable I2C Bus.
340 
341   @param VOID.
342 
343   @return Result of the I2C enabling.
344 **/
345 RETURN_STATUS
I2cBusFrequencySet(IN UINTN BusClockHertz)346 I2cBusFrequencySet (
347   IN UINTN BusClockHertz
348   )
349 {
350   DEBUG((EFI_D_INFO,"InputFreq BusClockHertz: %d\r\n",BusClockHertz));
351 
352   //
353   //  Set the 100 KHz clock divider according to SV result and I2C spec
354   //
355   MmioWrite32 ( mI2CBaseAddress + R_IC_SS_SCL_HCNT, (UINT16)0x214 );
356   MmioWrite32 ( mI2CBaseAddress + R_IC_SS_SCL_LCNT, (UINT16)0x272 );
357 
358   //
359   //  Set the 400 KHz clock divider according to SV result and I2C spec
360   //
361   MmioWrite32 ( mI2CBaseAddress + R_IC_FS_SCL_HCNT, (UINT16)0x50 );
362   MmioWrite32 ( mI2CBaseAddress + R_IC_FS_SCL_LCNT, (UINT16)0xAD );
363 
364   switch ( BusClockHertz ) {
365     case 100 * 1000:
366       MmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x40);//100K
367       mI2cMode = V_SPEED_STANDARD;
368       break;
369     case 400 * 1000:
370       MmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x32);//400K
371       mI2cMode = V_SPEED_FAST;
372       break;
373     default:
374       MmioWrite32 ( mI2CBaseAddress + R_IC_SDA_HOLD, (UINT16)0x09);//3.4M
375       mI2cMode = V_SPEED_HIGH;
376   }
377 
378   //
379   //  Select the frequency counter,
380   //  Enable restart condition,
381   //  Enable master FSM, disable slave FSM.
382   //
383   mI2cMode |= B_IC_RESTART_EN | B_IC_SLAVE_DISABLE | B_MASTER_MODE;
384 
385   return EFI_SUCCESS;
386 }
387 
388 /**
389   Initializes the host controller to execute I2C commands.
390 
391   @param I2cControllerIndex Index of I2C controller in LPSS device. 0 represents I2C0, which is PCI function 1 of LPSS device.
392 
393   @return EFI_SUCCESS       Opcode initialization on the I2C host controller completed.
394   @return EFI_DEVICE_ERROR  Device error, operation failed.
395 **/
396 EFI_STATUS
I2CInit(IN UINT8 I2cControllerIndex,IN UINT16 SlaveAddress)397 I2CInit (
398   IN  UINT8  I2cControllerIndex,
399   IN  UINT16 SlaveAddress
400   )
401 {
402   EFI_STATUS Status=RETURN_SUCCESS;
403   UINT32    NumTries = 0;
404   UINTN    GnvsI2cBarAddr=0;
405 
406   //
407   // Verify the parameters
408   //
409   if ((1023 < SlaveAddress) || (6 < I2cControllerIndex)) {
410     Status =  RETURN_INVALID_PARAMETER;
411     DEBUG((EFI_D_INFO,"I2CInit Exit with RETURN_INVALID_PARAMETER\r\n"));
412     return Status;
413   }
414   MmioWrite32 ( mI2CBaseAddress + R_IC_TAR, (UINT16)SlaveAddress );
415   mI2CSlaveAddress = SlaveAddress;
416 
417   //
418   // 1.PEI: program and init ( before pci enumeration).
419   // 2.DXE:update address and re-init ( after pci enumeration).
420   // 3.BDS:update ACPI address and re-init ( after acpi mode is enabled).
421   //
422   if(mI2CBaseAddress == mLpssPciDeviceList[I2cControllerIndex + 1].Bar0) {
423 
424     //
425     // I2CInit is already  called.
426     //
427     GnvsI2cBarAddr=GetI2cBarAddr(I2cControllerIndex);
428 
429     if((GnvsI2cBarAddr == 0)||(GnvsI2cBarAddr == mI2CBaseAddress)) {
430       DEBUG((EFI_D_INFO,"I2CInit Exit with mI2CBaseAddress:%x == [%x].Bar0\r\n",mI2CBaseAddress,I2cControllerIndex+1));
431       return RETURN_SUCCESS;
432     }
433   }
434 
435   Status=ProgramPciLpssI2C(I2cControllerIndex);
436   if(Status!=EFI_SUCCESS) {
437     return Status;
438   }
439 
440 
441   mI2CBaseAddress = (UINT32) mLpssPciDeviceList[I2cControllerIndex + 1].Bar0;
442   DEBUG ((EFI_D_ERROR, "mI2CBaseAddress = 0x%x \n",mI2CBaseAddress));
443 
444   //
445   // 1 seconds.
446   //
447   NumTries = 10000;
448   while ((1 == ( MmioRead32 ( mI2CBaseAddress + R_IC_STATUS) & STAT_MST_ACTIVITY ))) {
449     MicroSecondDelay(10);
450     NumTries --;
451     if(0 == NumTries) {
452       DEBUG((EFI_D_INFO, "Try timeout\r\n"));
453       return RETURN_DEVICE_ERROR;
454     }
455   }
456 
457   Status = I2cDisable();
458   DEBUG((EFI_D_INFO, "I2cDisable Status = %r\r\n", Status));
459   I2cBusFrequencySet(400 * 1000);
460 
461   MmioWrite32(mI2CBaseAddress + R_IC_INTR_MASK, 0x0);
462   if (0x7f < SlaveAddress )
463     SlaveAddress = ( SlaveAddress & 0x3ff ) | IC_TAR_10BITADDR_MASTER;
464   MmioWrite32 ( mI2CBaseAddress + R_IC_TAR, (UINT16)SlaveAddress );
465   MmioWrite32 ( mI2CBaseAddress + R_IC_RX_TL, 0);
466   MmioWrite32 ( mI2CBaseAddress + R_IC_TX_TL, 0 );
467   MmioWrite32 ( mI2CBaseAddress + R_IC_CON, mI2cMode);
468   Status = I2cEnable();
469 
470   DEBUG((EFI_D_INFO, "I2cEnable Status = %r\r\n", Status));
471   MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT );
472 
473   return EFI_SUCCESS;
474 }
475 
476 /**
477   Reads a Byte from I2C Device.
478 
479   @param  I2cControllerIndex             I2C Bus no to which the I2C device has been connected
480   @param  SlaveAddress      Device Address from which the byte value has to be read
481   @param  Offset            Offset from which the data has to be read
482   @param  *Byte             Address to which the value read has to be stored
483   @param  Start               Whether a RESTART is issued before the byte is sent or received
484   @param  End                 Whether STOP is generated after a data byte is sent or received
485 
486   @return  EFI_SUCCESS       IF the byte value has been successfully read
487   @return  EFI_DEVICE_ERROR  Operation Failed, Device Error
488 **/
489 EFI_STATUS
ByteReadI2CBasic(IN UINT8 I2cControllerIndex,IN UINT8 SlaveAddress,IN UINTN ReadBytes,OUT UINT8 * ReadBuffer,IN UINT8 Start,IN UINT8 End)490 ByteReadI2CBasic(
491   IN  UINT8 I2cControllerIndex,
492   IN  UINT8 SlaveAddress,
493   IN  UINTN ReadBytes,
494   OUT UINT8 *ReadBuffer,
495   IN  UINT8 Start,
496   IN  UINT8 End
497   )
498 {
499 
500   EFI_STATUS Status;
501   UINT32 I2cStatus;
502   UINT16 ReceiveData;
503   UINT8 *ReceiveDataEnd;
504   UINT8 *ReceiveRequest;
505   UINT16 RawIntrStat;
506   UINT32 Count=0;
507 
508   Status = EFI_SUCCESS;
509 
510   ReceiveDataEnd = &ReadBuffer [ReadBytes];
511   if( ReadBytes ) {
512 
513     ReceiveRequest = ReadBuffer;
514     DEBUG((EFI_D_INFO,"Read: ---------------%d bytes to RX\r\n",ReceiveDataEnd - ReceiveRequest));
515 
516     while ((ReceiveDataEnd > ReceiveRequest) || (ReceiveDataEnd > ReadBuffer)) {
517 
518       //
519       //  Check for NACK
520       //
521       RawIntrStat = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_RawIntrStat);
522       if ( 0 != ( RawIntrStat & I2C_INTR_TX_ABRT )) {
523         MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT );
524         Status = RETURN_DEVICE_ERROR;
525         DEBUG((EFI_D_INFO,"TX ABRT ,%d bytes hasn't been transferred\r\n",ReceiveDataEnd - ReceiveRequest));
526         break;
527       }
528 
529       //
530       // Determine if another byte was received
531       //
532       I2cStatus = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_STATUS);
533       if (0 != ( I2cStatus & STAT_RFNE )) {
534         ReceiveData = (UINT16)MmioRead32 ( mI2CBaseAddress + R_IC_DATA_CMD );
535         *ReadBuffer++ = (UINT8)ReceiveData;
536         DEBUG((EFI_D_INFO,"MmioRead32 ,1 byte 0x:%x is received\r\n",ReceiveData));
537       }
538 
539       if(ReceiveDataEnd == ReceiveRequest) {
540         MicroSecondDelay ( FIFO_WRITE_DELAY );
541         DEBUG((EFI_D_INFO,"ReceiveDataEnd==ReceiveRequest------------%x\r\n",I2cStatus & STAT_RFNE));
542         Count++;
543         if(Count<1024) {
544           //
545           // To avoid sys hung  without ul-pmc device  on RVP,
546           // waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
547           //
548           continue;
549         } else {
550           break;
551         }
552       }
553 
554       //
555       //  Wait until a read request will fit.
556       //
557       if (0 == (I2cStatus & STAT_TFNF)) {
558         DEBUG((EFI_D_INFO,"Wait until a read request will fit\r\n"));
559         MicroSecondDelay (10);
560         continue;
561       }
562 
563       //
564       //  Issue the next read request.
565       //
566       if(End && Start) {
567         MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART|B_CMD_STOP);
568       } else if (!End && Start) {
569         MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_RESTART);
570       } else if (End && !Start) {
571         MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD|B_CMD_STOP);
572       } else if (!End && !Start) {
573         MmioWrite32 ( mI2CBaseAddress + R_IC_DATA_CMD, B_READ_CMD);
574       }
575       MicroSecondDelay (FIFO_WRITE_DELAY);
576 
577       ReceiveRequest += 1;
578     }
579   }
580 
581   return Status;
582 }
583 
584 /**
585   Writes a Byte to I2C Device.
586 
587   @param  I2cControllerIndex   I2C Bus no to which the I2C device has been connected
588   @param  SlaveAddress         Device Address from which the byte value has to be written
589   @param  Offset               Offset from which the data has to be read
590   @param  *Byte                Address to which the value written is stored
591   @param  Start               Whether a RESTART is issued before the byte is sent or received
592   @param  End                 Whether STOP is generated after a data byte is sent or received
593 
594   @return  EFI_SUCCESS         IF the byte value has been successfully written
595   @return  EFI_DEVICE_ERROR    Operation Failed, Device Error
596 **/
ByteWriteI2CBasic(IN UINT8 I2cControllerIndex,IN UINT8 SlaveAddress,IN UINTN WriteBytes,IN UINT8 * WriteBuffer,IN UINT8 Start,IN UINT8 End)597 EFI_STATUS ByteWriteI2CBasic(
598   IN  UINT8 I2cControllerIndex,
599   IN  UINT8 SlaveAddress,
600   IN  UINTN WriteBytes,
601   IN  UINT8 *WriteBuffer,
602   IN  UINT8 Start,
603   IN  UINT8 End
604   )
605 {
606 
607   EFI_STATUS Status;
608   UINT32 I2cStatus;
609   UINT8 *TransmitEnd;
610   UINT16 RawIntrStat;
611   UINT32 Count=0;
612 
613   Status = EFI_SUCCESS;
614 
615   Status=I2CInit(I2cControllerIndex, SlaveAddress);
616   if(Status!=EFI_SUCCESS)
617     return Status;
618 
619   TransmitEnd = &WriteBuffer[WriteBytes];
620   if( WriteBytes ) {
621     DEBUG((EFI_D_INFO,"Write: --------------%d bytes to TX\r\n",TransmitEnd - WriteBuffer));
622     while (TransmitEnd > WriteBuffer) {
623       I2cStatus = MmioRead32 (mI2CBaseAddress + R_IC_STATUS);
624       RawIntrStat = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_RawIntrStat);
625       if (0 != ( RawIntrStat & I2C_INTR_TX_ABRT)) {
626         MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT);
627         Status = RETURN_DEVICE_ERROR;
628         DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));
629         break;
630       }
631       if (0 == (I2cStatus & STAT_TFNF)) {
632         //
633         // If TX not full , will  send cmd  or continue to wait
634         //
635         MicroSecondDelay (FIFO_WRITE_DELAY);
636         continue;
637       }
638 
639       if(End && Start) {
640         MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART|B_CMD_STOP);
641       } else if (!End && Start) {
642         MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART);
643       } else if (End && !Start) {
644         MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_STOP);
645       } else if (!End && !Start ) {
646         MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++));
647       }
648 
649       //
650       // Add a small delay to work around some odd behavior being seen.  Without this delay bytes get dropped.
651       //
652       MicroSecondDelay ( FIFO_WRITE_DELAY );//wait after send cmd
653 
654       //
655       // Time out
656       //
657       while(1) {
658         RawIntrStat = MmioRead16 ( mI2CBaseAddress + R_IC_RawIntrStat );
659         if (0 != ( RawIntrStat & I2C_INTR_TX_ABRT)) {
660           MmioRead16 (mI2CBaseAddress + R_IC_CLR_TX_ABRT);
661           Status = RETURN_DEVICE_ERROR;
662           DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));
663         }
664         if(0 == MmioRead16(mI2CBaseAddress + R_IC_TXFLR)) break;
665 
666         MicroSecondDelay (FIFO_WRITE_DELAY);
667         Count++;
668         if(Count<1024) {
669           //
670           // to avoid sys hung without ul-pmc device on RVP.
671           // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
672           //
673           continue;
674         } else {
675           break;
676         }
677       }//while( 1 )
678     }
679 
680   }
681 
682   return Status;
683 }
684 
685 /**
686   Reads a Byte from I2C Device.
687 
688   @param  I2cControllerIndex   I2C Bus no to which the I2C device has been connected
689   @param  SlaveAddress         Device Address from which the byte value has to be read
690   @param  Offset               Offset from which the data has to be read
691   @param  ReadBytes            Number of bytes to be read
692   @param  *ReadBuffer          Address to which the value read has to be stored
693 
694   @return  EFI_SUCCESS       IF the byte value has been successfully read
695   @return  EFI_DEVICE_ERROR  Operation Failed, Device Error
696 **/
ByteReadI2C(IN UINT8 I2cControllerIndex,IN UINT8 SlaveAddress,IN UINT8 Offset,IN UINTN ReadBytes,OUT UINT8 * ReadBuffer)697 EFI_STATUS ByteReadI2C(
698   IN  UINT8 I2cControllerIndex,
699   IN  UINT8 SlaveAddress,
700   IN  UINT8 Offset,
701   IN  UINTN ReadBytes,
702   OUT UINT8 *ReadBuffer
703   )
704 {
705   EFI_STATUS          Status;
706 
707   DEBUG ((EFI_D_INFO, "ByteReadI2C:---offset:0x%x\n",Offset));
708   Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress,1,&Offset,TRUE,FALSE);
709   Status = ByteReadI2CBasic(I2cControllerIndex, SlaveAddress,ReadBytes,ReadBuffer,TRUE,TRUE);
710 
711   return Status;
712 }
713 
714 /**
715   Writes a Byte to I2C Device.
716 
717   @param  I2cControllerIndex  I2C Bus no to which the I2C device has been connected
718   @param  SlaveAddress        Device Address from which the byte value has to be written
719   @param  Offset              Offset from which the data has to be written
720   @param  WriteBytes          Number of bytes to be written
721   @param  *Byte               Address to which the value written is stored
722 
723   @return  EFI_SUCCESS       IF the byte value has been successfully read
724   @return  EFI_DEVICE_ERROR  Operation Failed, Device Error
725 **/
ByteWriteI2C(IN UINT8 I2cControllerIndex,IN UINT8 SlaveAddress,IN UINT8 Offset,IN UINTN WriteBytes,IN UINT8 * WriteBuffer)726 EFI_STATUS ByteWriteI2C(
727   IN  UINT8 I2cControllerIndex,
728   IN  UINT8 SlaveAddress,
729   IN  UINT8 Offset,
730   IN  UINTN WriteBytes,
731   IN  UINT8 *WriteBuffer
732   )
733 {
734   EFI_STATUS          Status;
735 
736   DEBUG ((EFI_D_INFO, "ByteWriteI2C:---offset/bytes/buf:0x%x,0x%x,0x%x,0x%x\n",Offset,WriteBytes,WriteBuffer,*WriteBuffer));
737   Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress,1,&Offset,TRUE,FALSE);
738   Status = ByteWriteI2CBasic(I2cControllerIndex, SlaveAddress,WriteBytes,WriteBuffer,FALSE,TRUE);
739 
740   return Status;
741 }
742