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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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