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