/******************************************************************************** Copyright (C) 2016 Marvell International Ltd. SPDX-License-Identifier: BSD-2-Clause-Patent *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "I2cDemoDxe.h" STATIC CONST EFI_GUID I2cGuid = I2C_GUID; EFI_DRIVER_BINDING_PROTOCOL gDriverBindingProtocol = { I2cDemoSupported, I2cDemoStart, I2cDemoStop }; EFI_STATUS EFIAPI I2cDemoSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL ) { EFI_STATUS Status = EFI_UNSUPPORTED; EFI_I2C_IO_PROTOCOL *TmpI2cIo; UINT8 *I2cDemoAddresses; UINT8 *I2cDemoBuses; UINTN i; Status = gBS->OpenProtocol ( ControllerHandle, &gEfiI2cIoProtocolGuid, (VOID **) &TmpI2cIo, gImageHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR(Status)) { DEBUG ((DEBUG_INFO, "I2cDemoSupported Error status: %d\n", Status)); return EFI_UNSUPPORTED; } /* get I2CDEMO devices' addresses from PCD */ I2cDemoAddresses = PcdGetPtr (PcdI2cDemoAddresses); I2cDemoBuses = PcdGetPtr (PcdI2cDemoBuses); if (I2cDemoAddresses == 0) { Status = EFI_UNSUPPORTED; DEBUG((DEBUG_INFO, "I2cDemoSupported: I2C device found, but it's not I2CDEMO\n")); goto out; } Status = EFI_UNSUPPORTED; for (i = 0; I2cDemoAddresses[i] != '\0'; i++) { /* I2C guid must fit and valid DeviceIndex must be provided */ if (CompareGuid(TmpI2cIo->DeviceGuid, &I2cGuid) && TmpI2cIo->DeviceIndex == I2C_DEVICE_INDEX(I2cDemoBuses[i], I2cDemoAddresses[i])) { DEBUG ((DEBUG_INFO, "I2cDemoSupported: attached to I2CDEMO device\n")); Status = EFI_SUCCESS; break; } } out: gBS->CloseProtocol ( ControllerHandle, &gEfiI2cIoProtocolGuid, gImageHandle, ControllerHandle ); return Status; } EFI_STATUS EFIAPI I2cDemoRead ( IN CONST ROCKCHIP_I2CDEMO_PROTOCOL *This, IN UINT8 *RegAddress, IN UINT16 RegAddressLength, IN UINT8 *Buffer, IN UINT16 Length ) { EFI_I2C_REQUEST_PACKET *RequestPacket; UINTN RequestPacketSize; EFI_STATUS Status = EFI_SUCCESS; I2CDEMO_CONTEXT *I2cDemoContext = I2CDEMO_SC_FROM_I2CDEMO(This); ASSERT(I2cDemoContext != NULL); ASSERT(I2cDemoContext->I2cIo != NULL); RequestPacketSize = sizeof(UINTN) + sizeof (EFI_I2C_OPERATION) * 2; RequestPacket = AllocateZeroPool (RequestPacketSize); if (RequestPacket == NULL) return EFI_OUT_OF_RESOURCES; RequestPacket->OperationCount = 2; RequestPacket->Operation[0].Flags = 0; RequestPacket->Operation[0].LengthInBytes = RegAddressLength; RequestPacket->Operation[0].Buffer = RegAddress; RequestPacket->Operation[1].Flags = I2C_FLAG_READ; RequestPacket->Operation[1].LengthInBytes = Length; RequestPacket->Operation[1].Buffer = Buffer; Status = I2cDemoContext->I2cIo->QueueRequest(I2cDemoContext->I2cIo, 0, NULL, RequestPacket, NULL); if (EFI_ERROR(Status)) DEBUG((DEBUG_INFO, "I2cDemoTransfer: error %d during transmission\n", Status)); FreePool(RequestPacket); return Status; } EFI_STATUS EFIAPI I2cDemoWrite ( IN CONST ROCKCHIP_I2CDEMO_PROTOCOL *This, IN UINT8 *RegAddress, IN UINT16 RegAddressLength, IN UINT8 *Buffer, IN UINT16 Length ) { EFI_I2C_REQUEST_PACKET *RequestPacket; UINTN RequestPacketSize; EFI_STATUS Status = EFI_SUCCESS; I2CDEMO_CONTEXT *I2cDemoContext = I2CDEMO_SC_FROM_I2CDEMO(This); UINT8 *Data; UINT16 i; ASSERT(I2cDemoContext != NULL); ASSERT(I2cDemoContext->I2cIo != NULL); RequestPacketSize = sizeof(UINTN) + sizeof (EFI_I2C_OPERATION); RequestPacket = AllocateZeroPool (RequestPacketSize); if (RequestPacket == NULL) return EFI_OUT_OF_RESOURCES; Data = AllocateZeroPool ( RegAddressLength + Length ); if (Data == NULL) return EFI_OUT_OF_RESOURCES; for (i = 0; i < RegAddressLength; i++) Data[i] = RegAddress[i] & 0xff; for (i = RegAddressLength; i < RegAddressLength + Length; i++) Data[i] = Buffer[i - RegAddressLength] & 0xff; RequestPacket->OperationCount = 1; RequestPacket->Operation[0].Flags = 0; RequestPacket->Operation[0].LengthInBytes = RegAddressLength + Length; RequestPacket->Operation[0].Buffer = Data; Status = I2cDemoContext->I2cIo->QueueRequest(I2cDemoContext->I2cIo, 0, NULL, RequestPacket, NULL); if (EFI_ERROR(Status)) DEBUG((DEBUG_INFO, "I2cDemoTransfer: error %d during transmission\n", Status)); FreePool(Data); FreePool(RequestPacket); return Status; } EFI_STATUS EFIAPI I2cDemoStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL ) { EFI_STATUS Status = EFI_SUCCESS; I2CDEMO_CONTEXT *I2cDemoContext; I2cDemoContext = AllocateZeroPool (sizeof(I2CDEMO_CONTEXT)); if (I2cDemoContext == NULL) { DEBUG((DEBUG_ERROR, "I2cDemo: allocation fail\n")); return EFI_OUT_OF_RESOURCES; } I2cDemoContext->ControllerHandle = ControllerHandle; I2cDemoContext->Signature = I2CDEMO_SIGNATURE; I2cDemoContext->I2cDemoProtocol.Read = I2cDemoRead; I2cDemoContext->I2cDemoProtocol.Write = I2cDemoWrite; Status = gBS->OpenProtocol ( ControllerHandle, &gEfiI2cIoProtocolGuid, (VOID **) &I2cDemoContext->I2cIo, gImageHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR(Status)) { DEBUG((DEBUG_ERROR, "I2cDemo: failed to open I2cIo\n")); FreePool(I2cDemoContext); return EFI_UNSUPPORTED; } I2cDemoContext->I2cDemoProtocol.Identifier = I2cDemoContext->I2cIo->DeviceIndex; Status = gBS->InstallMultipleProtocolInterfaces ( &ControllerHandle, &gRockchipI2cDemoProtocolGuid, &I2cDemoContext->I2cDemoProtocol, NULL ); if (EFI_ERROR(Status)) { DEBUG((DEBUG_ERROR, "I2cDemo: failed to install I2CDEMO protocol\n")); goto fail; } return Status; fail: FreePool(I2cDemoContext); gBS->CloseProtocol ( ControllerHandle, &gEfiI2cIoProtocolGuid, gImageHandle, ControllerHandle ); return Status; } EFI_STATUS EFIAPI I2cDemoStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer OPTIONAL ) { ROCKCHIP_I2CDEMO_PROTOCOL *I2cDemoProtocol; EFI_STATUS Status; I2CDEMO_CONTEXT *I2cDemoContext; Status = gBS->OpenProtocol ( ControllerHandle, &gRockchipI2cDemoProtocolGuid, (VOID **) &I2cDemoProtocol, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } I2cDemoContext = I2CDEMO_SC_FROM_I2CDEMO(I2cDemoProtocol); gBS->UninstallMultipleProtocolInterfaces ( &ControllerHandle, &gRockchipI2cDemoProtocolGuid, &I2cDemoContext->I2cDemoProtocol, &gEfiDriverBindingProtocolGuid, &gDriverBindingProtocol, NULL ); gBS->CloseProtocol ( ControllerHandle, &gEfiI2cIoProtocolGuid, gImageHandle, ControllerHandle ); FreePool(I2cDemoContext); return EFI_SUCCESS; } EFI_STATUS EFIAPI I2cDemoInitialise ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; Status = gBS->InstallMultipleProtocolInterfaces ( &ImageHandle, &gEfiDriverBindingProtocolGuid, &gDriverBindingProtocol, NULL ); return Status; }