1 /********************************************************************************
2 Copyright (C) 2016 Marvell International Ltd.
3 
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5 
6 *******************************************************************************/
7 
8 #include <Protocol/BoardDesc.h>
9 #include <Protocol/I2cMaster.h>
10 #include <Protocol/I2cEnumerate.h>
11 #include <Protocol/I2cBusConfigurationManagement.h>
12 #include <Protocol/DevicePath.h>
13 #include <Protocol/MvI2c.h>
14 
15 #include <Library/BaseLib.h>
16 #include <Library/IoLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/PcdLib.h>
19 #include <Library/UefiLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 
23 #include "MvI2cDxe.h"
24 
25 STATIC MV_I2C_BAUD_RATE baud_rate;
26 
27 STATIC MV_I2C_DEVICE_PATH MvI2cDevicePathProtocol = {
28   {
29     {
30       HARDWARE_DEVICE_PATH,
31       HW_VENDOR_DP,
32       {
33         (UINT8)(OFFSET_OF (MV_I2C_DEVICE_PATH, End)),
34         (UINT8)(OFFSET_OF (MV_I2C_DEVICE_PATH, End) >> 8),
35       },
36     },
37     EFI_CALLER_ID_GUID
38   },
39   0,  // Instance
40   {
41     END_DEVICE_PATH_TYPE,
42     END_ENTIRE_DEVICE_PATH_SUBTYPE,
43     {
44       sizeof(EFI_DEVICE_PATH_PROTOCOL),
45       0
46     }
47   }
48 };
49 
50 STATIC
51 UINT32
I2C_READ(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN UINTN off)52 I2C_READ(
53   IN I2C_MASTER_CONTEXT *I2cMasterContext,
54   IN UINTN off)
55 {
56   ASSERT (I2cMasterContext != NULL);
57   return MmioRead32 (I2cMasterContext->BaseAddress + off);
58 }
59 
60 STATIC
61 EFI_STATUS
I2C_WRITE(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN UINTN off,IN UINT32 Value)62 I2C_WRITE (
63   IN I2C_MASTER_CONTEXT *I2cMasterContext,
64   IN UINTN off,
65   IN UINT32 Value)
66 {
67   ASSERT (I2cMasterContext != NULL);
68   return MmioWrite32 (I2cMasterContext->BaseAddress + off, Value);
69 }
70 
71 EFI_STATUS
72 EFIAPI
MvI2cInitialiseController(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable,IN EFI_PHYSICAL_ADDRESS BaseAddress)73 MvI2cInitialiseController (
74   IN EFI_HANDLE  ImageHandle,
75   IN EFI_SYSTEM_TABLE  *SystemTable,
76   IN EFI_PHYSICAL_ADDRESS BaseAddress
77   )
78 {
79   EFI_STATUS Status;
80   I2C_MASTER_CONTEXT *I2cMasterContext;
81   STATIC INTN Bus = 0;
82   MV_I2C_DEVICE_PATH *DevicePath;
83 
84   DevicePath = AllocateCopyPool (sizeof(MvI2cDevicePathProtocol),
85                                  &MvI2cDevicePathProtocol);
86   if (DevicePath == NULL) {
87     DEBUG((DEBUG_ERROR, "MvI2cDxe: I2C device path allocation failed\n"));
88     return EFI_OUT_OF_RESOURCES;
89   }
90   DevicePath->Instance = Bus;
91 
92   /* if attachment succeeds, this gets freed at ExitBootServices */
93   I2cMasterContext = AllocateZeroPool (sizeof (I2C_MASTER_CONTEXT));
94   if (I2cMasterContext == NULL) {
95     DEBUG((DEBUG_ERROR, "MvI2cDxe: I2C master context allocation failed\n"));
96     return EFI_OUT_OF_RESOURCES;
97   }
98   I2cMasterContext->Signature = I2C_MASTER_SIGNATURE;
99   I2cMasterContext->I2cMaster.Reset = MvI2cReset;
100   I2cMasterContext->I2cMaster.StartRequest = MvI2cStartRequest;
101   I2cMasterContext->I2cEnumerate.Enumerate = MvI2cEnumerate;
102   I2cMasterContext->I2cBusConf.EnableI2cBusConfiguration = MvI2cEnableConf;
103   I2cMasterContext->TclkFrequency = PcdGet32 (PcdI2cClockFrequency);
104   I2cMasterContext->BaseAddress = BaseAddress;
105   I2cMasterContext->Bus = Bus;
106   /* I2cMasterContext->Lock is responsible for serializing I2C operations */
107   EfiInitializeLock(&I2cMasterContext->Lock, TPL_NOTIFY);
108 
109   MvI2cCalBaudRate( I2cMasterContext,
110                     PcdGet32 (PcdI2cBaudRate),
111                     &baud_rate,
112                     I2cMasterContext->TclkFrequency
113                   );
114 
115   Status = gBS->InstallMultipleProtocolInterfaces(
116       &I2cMasterContext->Controller,
117       &gEfiI2cMasterProtocolGuid,
118       &I2cMasterContext->I2cMaster,
119       &gEfiI2cEnumerateProtocolGuid,
120       &I2cMasterContext->I2cEnumerate,
121       &gEfiI2cBusConfigurationManagementProtocolGuid,
122       &I2cMasterContext->I2cBusConf,
123       &gEfiDevicePathProtocolGuid,
124       (EFI_DEVICE_PATH_PROTOCOL *) DevicePath,
125       NULL);
126 
127   if (EFI_ERROR(Status)) {
128     DEBUG((DEBUG_ERROR, "MvI2cDxe: Installing protocol interfaces failed!\n"));
129     goto fail;
130   }
131   DEBUG((DEBUG_ERROR, "Succesfully installed controller %d at 0x%llx\n", Bus,
132         I2cMasterContext->BaseAddress));
133 
134   Bus++;
135 
136   return EFI_SUCCESS;
137 
138 fail:
139   FreePool(I2cMasterContext);
140   return Status;
141 }
142 
143 STATIC
144 VOID
145 EFIAPI
OnEndOfDxe(IN EFI_EVENT Event,IN VOID * Context)146 OnEndOfDxe (
147   IN EFI_EVENT  Event,
148   IN VOID       *Context
149   )
150 {
151   MV_I2C_DEVICE_PATH        *DevicePath;
152   EFI_DEVICE_PATH_PROTOCOL  *DevicePathPointer;
153   EFI_HANDLE                DeviceHandle;
154   EFI_STATUS                Status;
155 
156   gBS->CloseEvent (Event);
157 
158   DevicePath = AllocateCopyPool (sizeof (MvI2cDevicePathProtocol),
159                  &MvI2cDevicePathProtocol);
160   if (DevicePath == NULL) {
161     DEBUG ((DEBUG_ERROR, "MvI2cDxe: I2C device path allocation failed\n"));
162     return;
163   }
164 
165   do {
166     DevicePathPointer = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
167     Status = gBS->LocateDevicePath (&gEfiI2cMasterProtocolGuid,
168                     &DevicePathPointer,
169                     &DeviceHandle);
170     if (EFI_ERROR (Status)) {
171       break;
172     }
173 
174     Status = gBS->ConnectController (DeviceHandle, NULL, NULL, TRUE);
175     DEBUG ((DEBUG_INFO,
176       "%a: ConnectController () returned %r\n",
177       __FUNCTION__,
178       Status));
179 
180     DevicePath->Instance++;
181   } while (TRUE);
182 
183   gBS->FreePool (DevicePath);
184 }
185 
186 
187 EFI_STATUS
188 EFIAPI
MvI2cInitialise(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)189 MvI2cInitialise (
190   IN EFI_HANDLE  ImageHandle,
191   IN EFI_SYSTEM_TABLE  *SystemTable
192   )
193 {
194   MARVELL_BOARD_DESC_PROTOCOL *BoardDescProtocol;
195   EFI_EVENT EndOfDxeEvent;
196   MV_BOARD_I2C_DESC *Desc;
197   EFI_STATUS Status;
198   UINTN Index;
199 
200   /* Obtain list of available controllers */
201   Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
202                   NULL,
203                   (VOID **)&BoardDescProtocol);
204   if (EFI_ERROR (Status)) {
205     return Status;
206   }
207 
208   Status = BoardDescProtocol->BoardDescI2cGet (BoardDescProtocol, &Desc);
209   if (EFI_ERROR (Status)) {
210     return Status;
211   }
212 
213   /* Initialize enabled chips */
214   for (Index = 0; Index < Desc->I2cDevCount; Index++) {
215     Status = MvI2cInitialiseController(
216         ImageHandle,
217         SystemTable,
218         Desc[Index].SoC->I2cBaseAddress
219         );
220     if (EFI_ERROR(Status))
221       return Status;
222   }
223 
224   BoardDescProtocol->BoardDescFree (Desc);
225 
226   Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
227                   TPL_CALLBACK,
228                   OnEndOfDxe,
229                   NULL,
230                   &gEfiEndOfDxeEventGroupGuid,
231                   &EndOfDxeEvent);
232   ASSERT_EFI_ERROR (Status);
233 
234   return EFI_SUCCESS;
235 }
236 
237 STATIC
238 VOID
MvI2cControlClear(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN UINT32 Mask)239 MvI2cControlClear (
240   IN I2C_MASTER_CONTEXT *I2cMasterContext,
241   IN UINT32 Mask)
242 {
243   UINT32 Value;
244 
245   /* clears given bits in I2C_CONTROL register */
246   Value = I2C_READ(I2cMasterContext, I2C_CONTROL);
247   Value &= ~Mask;
248   I2C_WRITE(I2cMasterContext, I2C_CONTROL, Value);
249 }
250 
251 STATIC
252 VOID
MvI2cControlSet(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN UINT32 Mask)253 MvI2cControlSet (
254   IN I2C_MASTER_CONTEXT *I2cMasterContext,
255   IN UINT32 Mask)
256 {
257   UINT32 Value;
258 
259   /* sets given bits in I2C_CONTROL register */
260   Value = I2C_READ(I2cMasterContext, I2C_CONTROL);
261   Value |= Mask;
262   I2C_WRITE(I2cMasterContext, I2C_CONTROL, Value);
263 }
264 
265 STATIC
266 VOID
MvI2cClearIflg(IN I2C_MASTER_CONTEXT * I2cMasterContext)267 MvI2cClearIflg (
268  IN I2C_MASTER_CONTEXT *I2cMasterContext
269  )
270 {
271   MvI2cPollCtrl (I2cMasterContext, I2C_OPERATION_TIMEOUT, I2C_CONTROL_IFLG);
272   MvI2cControlClear(I2cMasterContext, I2C_CONTROL_IFLG);
273 }
274 
275 /* Timeout is given in us */
276 STATIC
277 UINTN
MvI2cPollCtrl(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN UINTN Timeout,IN UINT32 Mask)278 MvI2cPollCtrl (
279   IN I2C_MASTER_CONTEXT *I2cMasterContext,
280   IN UINTN Timeout,
281   IN UINT32 Mask)
282 {
283   Timeout /= 10;
284   while (!(I2C_READ(I2cMasterContext, I2C_CONTROL) & Mask)) {
285     gBS->Stall(10);
286     if (--Timeout == 0)
287       return (Timeout);
288   }
289   return (0);
290 }
291 
292 /*
293  * 'Timeout' is given in us. Note also that Timeout handling is not exact --
294  * MvI2cLockedStart() total wait can be more than 2 x Timeout
295  * (MvI2cPollCtrl() is called twice). 'Mask' can be either I2C_STATUS_START
296  * or I2C_STATUS_RPTD_START
297  */
298 STATIC
299 EFI_STATUS
MvI2cLockedStart(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN INT32 Mask,IN UINT8 Slave,IN UINTN Timeout)300 MvI2cLockedStart (
301   IN I2C_MASTER_CONTEXT *I2cMasterContext,
302   IN INT32 Mask,
303   IN UINT8 Slave,
304   IN UINTN Timeout
305   )
306 {
307   UINTN ReadAccess, IflgSet = 0;
308   UINT32 I2cStatus;
309 
310   if (Mask == I2C_STATUS_RPTD_START) {
311     /* read IFLG to know if it should be cleared later */
312     IflgSet = I2C_READ(I2cMasterContext, I2C_CONTROL) & I2C_CONTROL_IFLG;
313   }
314 
315   MvI2cControlSet(I2cMasterContext, I2C_CONTROL_START);
316 
317   if (Mask == I2C_STATUS_RPTD_START && IflgSet) {
318     DEBUG((DEBUG_INFO, "MvI2cDxe: IFLG set, clearing\n"));
319     MvI2cClearIflg(I2cMasterContext);
320   }
321 
322   if (MvI2cPollCtrl(I2cMasterContext, Timeout, I2C_CONTROL_IFLG)) {
323     DEBUG((DEBUG_ERROR, "MvI2cDxe: Timeout sending %sSTART condition\n",
324         Mask == I2C_STATUS_START ? "" : "repeated "));
325     return EFI_NO_RESPONSE;
326   }
327 
328   I2cStatus = I2C_READ(I2cMasterContext, I2C_STATUS);
329   if (I2cStatus != Mask) {
330     DEBUG((DEBUG_ERROR, "MvI2cDxe: wrong I2cStatus (%02x) after sending %sSTART condition\n",
331         I2cStatus, Mask == I2C_STATUS_START ? "" : "repeated "));
332     return EFI_DEVICE_ERROR;
333   }
334 
335   I2C_WRITE(I2cMasterContext, I2C_DATA, Slave);
336   gBS->Stall(I2C_OPERATION_TIMEOUT);
337   MvI2cClearIflg(I2cMasterContext);
338 
339   if (MvI2cPollCtrl(I2cMasterContext, Timeout, I2C_CONTROL_IFLG)) {
340     DEBUG((DEBUG_ERROR, "MvI2cDxe: Timeout sending Slave address\n"));
341     return EFI_NO_RESPONSE;
342   }
343 
344   ReadAccess = (Slave & 0x1) ? 1 : 0;
345   I2cStatus = I2C_READ(I2cMasterContext, I2C_STATUS);
346   if (I2cStatus != (ReadAccess ?
347       I2C_STATUS_ADDR_R_ACK : I2C_STATUS_ADDR_W_ACK)) {
348     DEBUG((DEBUG_ERROR, "MvI2cDxe: no ACK (I2cStatus: %02x) after sending Slave address\n",
349         I2cStatus));
350     return EFI_NO_RESPONSE;
351   }
352 
353   return EFI_SUCCESS;
354 }
355 
356 #define  ABSSUB(a,b)  (((a) > (b)) ? (a) - (b) : (b) - (a))
357 STATIC
358 VOID
MvI2cCalBaudRate(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN CONST UINT32 target,IN OUT MV_I2C_BAUD_RATE * rate,UINT32 clk)359 MvI2cCalBaudRate (
360   IN I2C_MASTER_CONTEXT *I2cMasterContext,
361   IN CONST UINT32 target,
362   IN OUT MV_I2C_BAUD_RATE *rate,
363   UINT32 clk
364   )
365 {
366   UINT32 cur, diff, diff0, baud;
367   UINTN m, n, m0, n0;
368 
369   /* Read initial m0, n0 values from register */
370   baud = I2C_READ(I2cMasterContext, I2C_BAUD_RATE);
371   m0 = I2C_M_FROM_BAUD(baud);
372   n0 = I2C_N_FROM_BAUD(baud);
373   /* Calculate baud rate. */
374   diff0 = 0xffffffff;
375 
376   for (n = 0; n < 8; n++) {
377     for (m = 0; m < 16; m++) {
378       cur = I2C_BAUD_RATE_RAW(clk,m,n);
379       diff = ABSSUB(target, cur);
380       if (diff < diff0) {
381         m0 = m;
382         n0 = n;
383         diff0 = diff;
384       }
385     }
386   }
387   rate->raw = I2C_BAUD_RATE_RAW(clk, m0, n0);
388   rate->param = I2C_BAUD_RATE_PARAM(m0, n0);
389   rate->m = m0;
390   rate->n = n0;
391 }
392 
393 EFI_STATUS
394 EFIAPI
MvI2cReset(IN CONST EFI_I2C_MASTER_PROTOCOL * This)395 MvI2cReset (
396   IN CONST EFI_I2C_MASTER_PROTOCOL *This
397   )
398 {
399   UINT32 param;
400   I2C_MASTER_CONTEXT *I2cMasterContext = I2C_SC_FROM_MASTER(This);
401 
402   param = baud_rate.param;
403 
404   EfiAcquireLock (&I2cMasterContext->Lock);
405   I2C_WRITE(I2cMasterContext, I2C_SOFT_RESET, 0x0);
406   gBS->Stall(2 * I2C_OPERATION_TIMEOUT);
407   I2C_WRITE(I2cMasterContext, I2C_BAUD_RATE, param);
408   I2C_WRITE(I2cMasterContext, I2C_CONTROL, I2C_CONTROL_I2CEN | I2C_CONTROL_ACK);
409   gBS->Stall(I2C_OPERATION_TIMEOUT);
410   EfiReleaseLock (&I2cMasterContext->Lock);
411 
412   return EFI_SUCCESS;
413 }
414 
415 /*
416  * Timeout is given in us
417  */
418 STATIC
419 EFI_STATUS
MvI2cRepeatedStart(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN UINT8 Slave,IN UINTN Timeout)420 MvI2cRepeatedStart (
421   IN I2C_MASTER_CONTEXT *I2cMasterContext,
422   IN UINT8 Slave,
423   IN UINTN Timeout
424   )
425 {
426   EFI_STATUS Status;
427 
428   EfiAcquireLock (&I2cMasterContext->Lock);
429   Status = MvI2cLockedStart(I2cMasterContext, I2C_STATUS_RPTD_START, Slave,
430       Timeout);
431   EfiReleaseLock (&I2cMasterContext->Lock);
432 
433   if (EFI_ERROR(Status)) {
434     MvI2cStop(I2cMasterContext);
435   }
436   return Status;
437 }
438 
439 /*
440  * Timeout is given in us
441  */
442 STATIC
443 EFI_STATUS
MvI2cStart(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN UINT8 Slave,IN UINTN Timeout)444 MvI2cStart (
445   IN I2C_MASTER_CONTEXT *I2cMasterContext,
446   IN UINT8 Slave,
447   IN UINTN Timeout
448   )
449 {
450   EFI_STATUS Status;
451 
452   EfiAcquireLock (&I2cMasterContext->Lock);
453   Status = MvI2cLockedStart(I2cMasterContext, I2C_STATUS_START, Slave, Timeout);
454   EfiReleaseLock (&I2cMasterContext->Lock);
455 
456   if (EFI_ERROR(Status)) {
457     MvI2cStop(I2cMasterContext);
458   }
459   return Status;
460 }
461 
462 STATIC
463 EFI_STATUS
MvI2cStop(IN I2C_MASTER_CONTEXT * I2cMasterContext)464 MvI2cStop (
465   IN I2C_MASTER_CONTEXT *I2cMasterContext
466   )
467 {
468   EfiAcquireLock (&I2cMasterContext->Lock);
469   MvI2cControlSet(I2cMasterContext, I2C_CONTROL_STOP);
470   gBS->Stall(I2C_OPERATION_TIMEOUT);
471   MvI2cClearIflg(I2cMasterContext);
472   EfiReleaseLock (&I2cMasterContext->Lock);
473 
474   return EFI_SUCCESS;
475 }
476 
477 STATIC
478 EFI_STATUS
MvI2cRead(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN OUT UINT8 * Buf,IN UINTN Length,IN OUT UINTN * read,IN UINTN last,IN UINTN delay)479 MvI2cRead (
480   IN I2C_MASTER_CONTEXT *I2cMasterContext,
481   IN OUT UINT8 *Buf,
482   IN UINTN Length,
483   IN OUT UINTN *read,
484   IN UINTN last,
485   IN UINTN delay
486   )
487 {
488   UINT32 I2cStatus;
489   UINTN LastByte;
490   EFI_STATUS Status;
491 
492   EfiAcquireLock (&I2cMasterContext->Lock);
493   *read = 0;
494   while (*read < Length) {
495     /*
496      * Check if we are reading last byte of the last Buffer,
497      * do not send ACK then, per I2C specs
498      */
499     LastByte = ((*read == Length - 1) && last) ? 1 : 0;
500     if (LastByte)
501       MvI2cControlClear(I2cMasterContext, I2C_CONTROL_ACK);
502     else
503       MvI2cControlSet(I2cMasterContext, I2C_CONTROL_ACK);
504 
505     gBS->Stall (I2C_OPERATION_TIMEOUT);
506     MvI2cClearIflg(I2cMasterContext);
507 
508     if (MvI2cPollCtrl(I2cMasterContext, delay, I2C_CONTROL_IFLG)) {
509       DEBUG((DEBUG_ERROR, "MvI2cDxe: Timeout reading data\n"));
510       Status = EFI_NO_RESPONSE;
511       goto out;
512     }
513 
514     I2cStatus = I2C_READ(I2cMasterContext, I2C_STATUS);
515     if (I2cStatus != (LastByte ?
516         I2C_STATUS_DATA_RD_NOACK : I2C_STATUS_DATA_RD_ACK)) {
517       DEBUG((DEBUG_ERROR, "MvI2cDxe: wrong I2cStatus (%02x) while reading\n", I2cStatus));
518       Status = EFI_DEVICE_ERROR;
519       goto out;
520     }
521 
522     *Buf++ = I2C_READ(I2cMasterContext, I2C_DATA);
523     (*read)++;
524   }
525   Status = EFI_SUCCESS;
526 out:
527   EfiReleaseLock (&I2cMasterContext->Lock);
528   return (Status);
529 }
530 
531 STATIC
532 EFI_STATUS
MvI2cWrite(IN I2C_MASTER_CONTEXT * I2cMasterContext,IN OUT CONST UINT8 * Buf,IN UINTN Length,IN OUT UINTN * Sent,IN UINTN Timeout)533 MvI2cWrite (
534   IN I2C_MASTER_CONTEXT *I2cMasterContext,
535   IN OUT CONST UINT8 *Buf,
536   IN UINTN Length,
537   IN OUT UINTN *Sent,
538   IN UINTN Timeout
539   )
540 {
541   UINT32 status;
542   EFI_STATUS Status;
543 
544   EfiAcquireLock (&I2cMasterContext->Lock);
545   *Sent = 0;
546   while (*Sent < Length) {
547     I2C_WRITE(I2cMasterContext, I2C_DATA, *Buf++);
548 
549     MvI2cClearIflg(I2cMasterContext);
550     if (MvI2cPollCtrl(I2cMasterContext, Timeout, I2C_CONTROL_IFLG)) {
551       DEBUG((DEBUG_ERROR, "MvI2cDxe: Timeout writing data\n"));
552       Status = EFI_NO_RESPONSE;
553       goto out;
554     }
555 
556     status = I2C_READ(I2cMasterContext, I2C_STATUS);
557     if (status != I2C_STATUS_DATA_WR_ACK) {
558       DEBUG((DEBUG_ERROR, "MvI2cDxe: wrong status (%02x) while writing\n", status));
559       Status = EFI_DEVICE_ERROR;
560       goto out;
561     }
562     (*Sent)++;
563   }
564   Status = EFI_SUCCESS;
565 out:
566   EfiReleaseLock (&I2cMasterContext->Lock);
567   return (Status);
568 }
569 
570 /*
571  * MvI2cStartRequest should be called only by I2cHost.
572  * I2C device drivers ought to use EFI_I2C_IO_PROTOCOL instead.
573  */
574 STATIC
575 EFI_STATUS
MvI2cStartRequest(IN CONST EFI_I2C_MASTER_PROTOCOL * This,IN UINTN SlaveAddress,IN EFI_I2C_REQUEST_PACKET * RequestPacket,IN EFI_EVENT Event OPTIONAL,OUT EFI_STATUS * I2cStatus OPTIONAL)576 MvI2cStartRequest (
577   IN CONST EFI_I2C_MASTER_PROTOCOL *This,
578   IN UINTN                         SlaveAddress,
579   IN EFI_I2C_REQUEST_PACKET        *RequestPacket,
580   IN EFI_EVENT                     Event      OPTIONAL,
581   OUT EFI_STATUS                   *I2cStatus OPTIONAL
582   )
583 {
584   UINTN Count;
585   UINTN ReadMode;
586   UINTN Transmitted;
587   I2C_MASTER_CONTEXT *I2cMasterContext = I2C_SC_FROM_MASTER(This);
588   EFI_I2C_OPERATION *Operation;
589   EFI_STATUS Status = EFI_SUCCESS;
590 
591   ASSERT (RequestPacket != NULL);
592   ASSERT (I2cMasterContext != NULL);
593 
594   for (Count = 0; Count < RequestPacket->OperationCount; Count++) {
595     Operation = &RequestPacket->Operation[Count];
596     ReadMode = Operation->Flags & I2C_FLAG_READ;
597 
598     if (Count == 0) {
599       Status = MvI2cStart (I2cMasterContext,
600                  (SlaveAddress << 1) | ReadMode,
601                  I2C_TRANSFER_TIMEOUT);
602     } else if (!(Operation->Flags & I2C_FLAG_NORESTART)) {
603       Status = MvI2cRepeatedStart (I2cMasterContext,
604                  (SlaveAddress << 1) | ReadMode,
605                  I2C_TRANSFER_TIMEOUT);
606     }
607 
608     /* I2C transaction was aborted, so stop further transactions */
609     if (EFI_ERROR (Status)) {
610       MvI2cStop (I2cMasterContext);
611       break;
612     }
613 
614     /*
615      * If sending the slave address was successful,
616      * proceed to read or write section.
617      */
618     if (ReadMode) {
619       Status = MvI2cRead (I2cMasterContext,
620                  Operation->Buffer,
621                  Operation->LengthInBytes,
622                  &Transmitted,
623                  Count == 1,
624                  I2C_TRANSFER_TIMEOUT);
625       Operation->LengthInBytes = Transmitted;
626     } else {
627       Status = MvI2cWrite (I2cMasterContext,
628                  Operation->Buffer,
629                  Operation->LengthInBytes,
630                  &Transmitted,
631                  I2C_TRANSFER_TIMEOUT);
632       Operation->LengthInBytes = Transmitted;
633     }
634 
635     /*
636      * The I2C read or write transaction failed.
637      * Stop the I2C transaction.
638      */
639     if (EFI_ERROR (Status)) {
640       MvI2cStop (I2cMasterContext);
641       break;
642     }
643 
644     /* Check if there is any more data to be sent */
645     if (Count == RequestPacket->OperationCount - 1) {
646       MvI2cStop ( I2cMasterContext );
647     }
648   }
649 
650   if (I2cStatus != NULL)
651     *I2cStatus = EFI_SUCCESS;
652   if (Event != NULL)
653     gBS->SignalEvent(Event);
654   return EFI_SUCCESS;
655 }
656 
657 STATIC CONST EFI_GUID DevGuid = I2C_GUID;
658 
659 STATIC
660 EFI_STATUS
MvI2cAllocDevice(IN UINT8 SlaveAddress,IN UINT8 Bus,IN OUT CONST EFI_I2C_DEVICE ** Device)661 MvI2cAllocDevice (
662   IN UINT8 SlaveAddress,
663   IN UINT8 Bus,
664   IN OUT CONST EFI_I2C_DEVICE **Device
665   )
666 {
667   EFI_STATUS Status;
668   EFI_I2C_DEVICE *Dev;
669   UINT32 *TmpSlaveArray;
670   EFI_GUID *TmpGuidP;
671 
672   Status = gBS->AllocatePool ( EfiBootServicesData,
673              sizeof(EFI_I2C_DEVICE),
674              (VOID **) &Dev );
675   if (EFI_ERROR(Status)) {
676     DEBUG((DEBUG_ERROR, "MvI2cDxe: I2C device memory allocation failed\n"));
677     return Status;
678   }
679   *Device = Dev;
680   Dev->DeviceIndex = SlaveAddress;
681   Dev->DeviceIndex = I2C_DEVICE_INDEX(Bus, SlaveAddress);
682   Dev->SlaveAddressCount = 1;
683   Dev->I2cBusConfiguration = 0;
684   Status = gBS->AllocatePool ( EfiBootServicesData,
685              sizeof(UINT32),
686              (VOID **) &TmpSlaveArray);
687   if (EFI_ERROR(Status)) {
688     goto fail1;
689   }
690   TmpSlaveArray[0] = SlaveAddress;
691   Dev->SlaveAddressArray = TmpSlaveArray;
692 
693   Status = gBS->AllocatePool ( EfiBootServicesData,
694              sizeof(EFI_GUID),
695              (VOID **) &TmpGuidP);
696   if (EFI_ERROR(Status)) {
697     goto fail2;
698   }
699   *TmpGuidP = DevGuid;
700   Dev->DeviceGuid = TmpGuidP;
701 
702   DEBUG((DEBUG_INFO, "MvI2c: allocated device with address %x\n", (UINTN)SlaveAddress));
703   return EFI_SUCCESS;
704 
705 fail2:
706   FreePool(TmpSlaveArray);
707 fail1:
708   FreePool(Dev);
709 
710   return Status;
711 }
712 
713 /*
714  * It is called by I2cBus to enumerate devices on I2C bus. In this case,
715  * enumeration is based on PCD configuration - all Slave addresses specified
716  * in PCD get their corresponding EFI_I2C_DEVICE structures here.
717  *
718  * After enumeration succeeds, Supported() function of drivers that installed
719  * DriverBinding protocol is called.
720  */
721 STATIC
722 EFI_STATUS
723 EFIAPI
MvI2cEnumerate(IN CONST EFI_I2C_ENUMERATE_PROTOCOL * This,IN OUT CONST EFI_I2C_DEVICE ** Device)724 MvI2cEnumerate (
725   IN CONST EFI_I2C_ENUMERATE_PROTOCOL *This,
726   IN OUT CONST EFI_I2C_DEVICE         **Device
727   )
728 {
729   UINT8 *DevicesPcd;
730   UINT8 *DeviceBusPcd;
731   UINTN Index, NextIndex, DevCount;
732   UINT8 NextDeviceAddress;
733   I2C_MASTER_CONTEXT *I2cMasterContext = I2C_SC_FROM_ENUMERATE(This);
734 
735   DevCount = PcdGetSize (PcdI2cSlaveAddresses);
736   DevicesPcd = PcdGetPtr (PcdI2cSlaveAddresses);
737   DeviceBusPcd = PcdGetPtr (PcdI2cSlaveBuses);
738   if (*Device == NULL) {
739     for (Index = 0; Index < DevCount ; Index++) {
740       if (DeviceBusPcd[Index] != I2cMasterContext->Bus)
741         continue;
742       if (Index < DevCount)
743         MvI2cAllocDevice (DevicesPcd[Index], I2cMasterContext->Bus, Device);
744       return EFI_SUCCESS;
745     }
746   } else {
747     /* Device is not NULL, so something was already allocated */
748     for (Index = 0; Index < DevCount; Index++) {
749       if (DeviceBusPcd[Index] != I2cMasterContext->Bus)
750         continue;
751       if (DevicesPcd[Index] == I2C_DEVICE_ADDRESS((*Device)->DeviceIndex)) {
752         for (NextIndex = Index + 1; NextIndex < DevCount; NextIndex++) {
753           if (DeviceBusPcd[NextIndex] != I2cMasterContext->Bus)
754             continue;
755           NextDeviceAddress = DevicesPcd[NextIndex];
756           if (NextIndex < DevCount)
757             MvI2cAllocDevice(NextDeviceAddress, I2cMasterContext->Bus, Device);
758           return EFI_SUCCESS;
759         }
760       }
761     }
762     *Device = NULL;
763     return EFI_SUCCESS;
764   }
765   return EFI_SUCCESS;
766 }
767 
768 STATIC
769 EFI_STATUS
770 EFIAPI
MvI2cEnableConf(IN CONST EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL * This,IN UINTN I2cBusConfiguration,IN EFI_EVENT Event OPTIONAL,IN EFI_STATUS * I2cStatus OPTIONAL)771 MvI2cEnableConf (
772   IN CONST EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *This,
773   IN UINTN                                               I2cBusConfiguration,
774   IN EFI_EVENT                                           Event      OPTIONAL,
775   IN EFI_STATUS                                          *I2cStatus OPTIONAL
776   )
777 {
778   /* do nothing */
779   if (I2cStatus != NULL)
780     I2cStatus = EFI_SUCCESS;
781   if (Event != NULL)
782     gBS->SignalEvent(Event);
783   return EFI_SUCCESS;
784 }
785