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