]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/Library/I2CLibDxe/I2CLib.c
MdeModulePkg: Add DNS QType and QClass values definition
[mirror_edk2.git] / Vlv2TbltDevicePkg / Library / I2CLibDxe / I2CLib.c
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
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
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
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
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
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
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
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 **/
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 **/
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 **/
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 }