From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id 52094AC0344 for ; Thu, 11 Jan 2024 00:04:32 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=CNLTNpshZnn4hC1b0qsevLIl72vv3SoGa2MU4jdYQho=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20140610; t=1704931471; v=1; b=uA3/FYOyjgpecvn+XKy2guLnjndvHIY9DYppdOnBW+YFZq/8ZvH4H2UfoBE2cR/dWmtso4IC MwhtiVzU/gm5Y+hgtPAk0aBlRpKXS+xYiAidiKnZNDX/+icJLWV9uKOP6SAQAcJvc+OLxDrHLXD rg4oBJy2E0xdXI7fkPz23dZI= X-Received: by 127.0.0.2 with SMTP id OJbVYY7687511xeyon8n9U87; Wed, 10 Jan 2024 16:04:31 -0800 X-Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web10.9467.1704931469122767513 for ; Wed, 10 Jan 2024 16:04:29 -0800 X-Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C24C4106F; Wed, 10 Jan 2024 16:05:14 -0800 (PST) X-Received: from u200865.usa.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 99ACA3F5A1; Wed, 10 Jan 2024 16:04:28 -0800 (PST) From: "Jeremy Linton" To: devel@edk2.groups.io Cc: ardb+tianocore@kernel.org, quic_llindhol@quicinc.com, Jeremy Linton Subject: [edk2-devel] [RFC 2/6] Silicon/Bcm283x: Add core I2C drivers Date: Wed, 10 Jan 2024 18:04:22 -0600 Message-ID: <20240111000426.2735007-3-jeremy.linton@arm.com> In-Reply-To: <20240111000426.2735007-1-jeremy.linton@arm.com> References: <20240111000426.2735007-1-jeremy.linton@arm.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,jeremy.linton@arm.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: x153eFxtwmuDtb5BRdoBkFe4x7686176AA= Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20140610 header.b="uA3/FYOy"; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=arm.com (policy=none); spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io There are a number of I2C interfaces on the rpi, some of which are available on the GPIO connector and are utilized by various HATs. In particular we are interested in the RTCs (usually based on DS1037) which are attached to GPIO2/3 which can be pin muxed to I2C #1. This commit adds a basic runtime utilizable I2C Dxe in preparation for a platform driver which can bind it to the ds1307 RTC driver. Signed-off-by: Jeremy Linton --- .../Broadcom/Drivers/I2cDxe/ComponentName.c | 181 ++++++++++ .../Broadcom/Drivers/I2cDxe/DriverBinding.c | 237 ++++++++++++++ Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.c | 309 ++++++++++++++++++ Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.h | 55 ++++ Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.inf | 56 ++++ 5 files changed, 838 insertions(+) create mode 100644 Silicon/Broadcom/Drivers/I2cDxe/ComponentName.c create mode 100644 Silicon/Broadcom/Drivers/I2cDxe/DriverBinding.c create mode 100644 Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.c create mode 100644 Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.h create mode 100644 Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.inf diff --git a/Silicon/Broadcom/Drivers/I2cDxe/ComponentName.c b/Silicon/Br= oadcom/Drivers/I2cDxe/ComponentName.c new file mode 100644 index 0000000000..75b4fdb3fe --- /dev/null +++ b/Silicon/Broadcom/Drivers/I2cDxe/ComponentName.c @@ -0,0 +1,181 @@ +/** @file + + Copyright 2018-2019 NXP + Sourced and reworked from edk2/NXP I2C stack + Copyright 2022 Arm, Jeremy Linton + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "I2cDxe.h" + +STATIC EFI_UNICODE_STRING_TABLE mBcmI2cDriverNameTable[] =3D { + { + "en", + (CHAR16 *)L"Bcm I2C Driver" + }, + { } +}; + +STATIC EFI_UNICODE_STRING_TABLE mBcmI2cControllerNameTable[] =3D { + { + "en", + (CHAR16 *)L"Bcm I2C Controller" + }, + { } +}; + +/** + Retrieves a Unicode string that is the user readable name of the drive= r. + + This function retrieves the user readable name of a driver in the form= of a + Unicode string. If the driver specified by This has a user readable na= me in + the language specified by Language, then a pointer to the driver name = is + returned in DriverName, and EFI_SUCCESS is returned. If the driver spe= cified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PRO= TOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII str= ing + array indicating the language. This is t= he + language of the driver name that the cal= ler is + requesting, and it must match one of the + languages specified in SupportedLanguage= s. The + number of languages supported by a drive= r is up + to the driver writer. Language is specif= ied + in RFC 4646 or ISO 639-2 language code f= ormat. + + @param DriverName[out] A pointer to the Unicode string to retur= n. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specif= ied by + This and the language specified by Langu= age was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not su= pport + the language specified by Language. + +**/ +STATIC +EFI_STATUS +EFIAPI +BcmI2cGetDriverName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 (Language, + This->SupportedLanguages, + mBcmI2cDriverNameTable, + DriverName, + FALSE); +} + +/** + Retrieves a Unicode string that is the user readable name of the contr= oller + that is being managed by a driver. + + This function retrieves the user readable name of the controller speci= fied by + ControllerHandle and ChildHandle in the form of a Unicode string. If t= he + driver specified by This has a user readable name in the language spec= ified by + Language, then a pointer to the controller name is returned in Control= lerName, + and EFI_SUCCESS is returned. If the driver specified by This is not c= urrently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This doe= s not + support the language specified by Language, then EFI_UNSUPPORTED is re= turned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PRO= TOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driv= er + specified by This is managing. This han= dle + specifies the controller whose name is t= o be + returned. + + @param ChildHandle[in] The handle of the child controller to re= trieve + the name of. This is an optional parame= ter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus= drivers + that wish to retrieve the name of the bu= s + controller. It will not be NULL for a b= us + driver that wishes to retrieve the name = of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII str= ing + array indicating the language. This is = the + language of the driver name that the cal= ler is + requesting, and it must match one of the + languages specified in SupportedLanguage= s. The + number of languages supported by a drive= r is up + to the driver writer. Language is specif= ied in + RFC 4646 or ISO 639-2 language code form= at. + + @param ControllerName[out] A pointer to the Unicode string to retur= n. + This Unicode string is the name of the + controller specified by ControllerHandle= and + ChildHandle in the language specified by + Language from the point of view of the d= river + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable= name in + the language specified by Language for t= he + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a = valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curr= ently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not su= pport + the language specified by Language. + +**/ +STATIC +EFI_STATUS +EFIAPI +BcmI2cGetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle = OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + if (ChildHandle !=3D NULL) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString2 (Language, + This->SupportedLanguages, + mBcmI2cControllerNameTable, + ControllerName, + FALSE); +} + +// +// EFI Component Name 2 Protocol +// +EFI_COMPONENT_NAME2_PROTOCOL gBcmI2cDriverComponentName2 =3D { + BcmI2cGetDriverName, + BcmI2cGetControllerName, + "en" +}; diff --git a/Silicon/Broadcom/Drivers/I2cDxe/DriverBinding.c b/Silicon/Br= oadcom/Drivers/I2cDxe/DriverBinding.c new file mode 100644 index 0000000000..a6cd7987eb --- /dev/null +++ b/Silicon/Broadcom/Drivers/I2cDxe/DriverBinding.c @@ -0,0 +1,237 @@ +/** @file + + Copyright 2018-2019 NXP + Sourced and reworked from edk2/NXP I2C stack + Copyright 2022 Arm, Jeremy Linton + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include + +#include "I2cDxe.h" + +/** + Tests to see if this driver supports a given controller. + + @param This[in] A pointer to the EFI_DRIVER_BINDING_P= ROTOCOL + instance. + @param ControllerHandle[in] The handle of the controller to test. + @param RemainingDevicePath[in] The remaining device path. + (Ignored - this is not a bus driver.) + + @retval EFI_SUCCESS The driver supports this controller. + @retval EFI_ALREADY_STARTED The device specified by ControllerHan= dle is + already being managed by the driver s= pecified + by This. + @retval EFI_UNSUPPORTED The device specified by ControllerHan= dle is + not supported by the driver specified= by This. + +**/ +EFI_STATUS +EFIAPI +BcmI2cDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + NON_DISCOVERABLE_DEVICE *Dev; + EFI_STATUS Status; + + // + // Connect to the non-discoverable device + // + Status =3D gBS->OpenProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + (VOID **) &Dev, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER); + if (EFI_ERROR (Status)) { + return Status; + } + + if (CompareGuid (Dev->Type, &gBcmNonDiscoverableI2cMasterGuid)) { + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_UNSUPPORTED; + } + + // + // Clean up. + // + gBS->CloseProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + This->DriverBindingHandle, + ControllerHandle); + + return Status; +} + + +/** + Starts a device controller or a bus controller. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_P= ROTOCOL + instance. + @param[in] ControllerHandle The handle of the device to start. Th= is + handle must support a protocol interf= ace that + supplies an I/O abstraction to the dr= iver. + @param[in] RemainingDevicePath The remaining portion of the device p= ath. + (Ignored - this is not a bus driver.) + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due t= o a + device error. + @retval EFI_OUT_OF_RESOURCES The request could not be completed du= e to a + lack of resources. + +**/ +EFI_STATUS +EFIAPI +BcmI2cDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return BcmI2cInit (This->DriverBindingHandle, ControllerHandle); +} + + +/** + Stops a device controller or a bus controller. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROT= OCOL + instance. + @param[in] ControllerHandle A handle to the device being stopped. Th= e handle + must support a bus specific I/O protocol= for the + driver to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in + ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. M= ay be + NULL if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a= device + error. + +**/ +EFI_STATUS +EFIAPI +BcmI2cDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + return BcmI2cRelease (This->DriverBindingHandle, ControllerHandle); +} + + +STATIC EFI_DRIVER_BINDING_PROTOCOL gBcmI2cDriverBinding =3D { + BcmI2cDriverBindingSupported, + BcmI2cDriverBindingStart, + BcmI2cDriverBindingStop, + 0xa, + NULL, + NULL +}; + + +/** + The entry point of I2c UEFI Driver. + + @param ImageHandle The image handle of the UEFI Driver= . + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The Driver or UEFI Driver exited no= rmally. + @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater tha= n + SystemTable->Hdr.Revision. + +**/ +EFI_STATUS +EFIAPI +I2cDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Add the driver to the list of drivers + // + Status =3D EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, SystemTable, &gBcmI2cDriverBinding, ImageHandl= e, + NULL, &gBcmI2cDriverComponentName2); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + +/** + Unload function for the I2c UEFI Driver. + + @param ImageHandle[in] The allocated handle for the EFI image + + @retval EFI_SUCCESS The driver was unloaded successfully + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle= . + +**/ +EFI_STATUS +EFIAPI +I2cDxeUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + + // + // Retrieve all USB I/O handles in the handle database + // + Status =3D gBS->LocateHandleBuffer (ByProtocol, + &gEdkiiNonDiscoverableDeviceProtocol= Guid, + NULL, + &HandleCount, + &HandleBuffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Disconnect the driver from the handles in the handle database + // + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->DisconnectController (HandleBuffer[Index], + gImageHandle, + NULL); + } + + // + // Free the handle array + // + gBS->FreePool (HandleBuffer); + + // + // Uninstall protocols installed by the driver in its entrypoint + // + Status =3D gBS->UninstallMultipleProtocolInterfaces (ImageHandle, + &gEfiDriverBindingProtocolGuid, + &gBcmI2cDriverBinding, + NULL + ); + + return EFI_SUCCESS; +} diff --git a/Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.c b/Silicon/Broadcom/= Drivers/I2cDxe/I2cDxe.c new file mode 100644 index 0000000000..8aedaa1f58 --- /dev/null +++ b/Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.c @@ -0,0 +1,309 @@ +/** I2cDxe.c + I2c driver APIs for read, write, initialize, set speed and reset + + Sourced and reworked from edk2/NXP I2C stack + Copyright 2022 Arm, Jeremy Linton + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "I2cDxe.h" + +STATIC CONST EFI_I2C_CONTROLLER_CAPABILITIES mI2cControllerCapabilities = =3D { + 0, + 0, + 0, + 0 +}; + +/** + Function to set i2c bus frequency + + @param This Pointer to I2c master protocol + @param BusClockHertz value to be set + + @retval EFI_SUCCESS Operation successfull +**/ +STATIC +EFI_STATUS +EFIAPI +SetBusFrequency ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This, + IN OUT UINTN *BusClockHertz + ) +{ + UINTN I2cBase; + UINT64 I2cClock; + BCM_I2C_MASTER *I2c; + + I2c =3D BCM_I2C_FROM_THIS (This); + + I2cBase =3D I2c->ControllerBase; + + // depend on ConfigDxe? On the NXP this only sets the clock and resets= the bus + // Here we are hardcoding the I2C clock until we have a need not to. + I2cClock =3D 50000; + + return EFI_SUCCESS; +} + +/** + Function to reset I2c Controller + + @param This Pointer to I2c master protocol + + @return EFI_SUCCESS Operation successfull +**/ +STATIC +EFI_STATUS +EFIAPI +Reset ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +STATIC +void +StatusPoll( + UINTN I2cBase, + UINTN Mask + ) +{ + UINTN Retry; + + Retry =3D 0; + while ((MmioRead32 (I2cBase + BCM2835_I2C_S) & Mask) !=3D Mask) { + Retry++; + } +} + + + +STATIC +EFI_STATUS +SingleTransfer( + UINTN I2cBase, + UINTN SlaveAddress, + EFI_I2C_OPERATION *Operation +) +{ + EFI_STATUS Status; + UINTN Index; + UINTN FifoState; + + // clear all the status + MmioWrite32 (I2cBase + BCM2835_I2C_C, 0x10 ); // fifo clear + MmioWrite32 (I2cBase + BCM2835_I2C_S, 0x302); + + // don't support 10 bit addr for now. (see 3.3 in 2711 manual) + // the problem with arm is that you never know if there are undocument= ed + // acces restrictions (aka 8 bit reg, but it needs to be read with a 3= 2-bit instr) + MmioWrite8 (I2cBase + BCM2835_I2C_A, (UINT8)SlaveAddress); + MmioWrite32 (I2cBase + BCM2835_I2C_DLEN, Operation->LengthInBytes ); + + if (Operation->Flags & I2C_FLAG_READ) { + FifoState =3D 0x20; // fifo has data + MmioWrite32 (I2cBase + BCM2835_I2C_C, 0x8081 ); // Enable, start, fi= fo clear, read + } else { + FifoState =3D 0x10; // fifo can accept data + MmioWrite32 (I2cBase + BCM2835_I2C_C, 0x8080 ); // Enable, start, fi= fo clear, write + } + + for (Index =3D 0; Index < Operation->LengthInBytes; Index++) { + + StatusPoll (I2cBase, FifoState); + + if (Operation->Flags & I2C_FLAG_READ) { + Operation->Buffer[Index] =3D MmioRead8 (I2cBase + BCM2835_I2C_FIFO= ); + } else { + MmioWrite8 (I2cBase + BCM2835_I2C_FIFO, Operation->Buffer[Index]); + } + } + + StatusPoll (I2cBase, 0x02); + + Status =3D 0; + return Status; +} + +volatile UINTN forcewrite; + +STATIC +EFI_STATUS +EFIAPI +StartRequest ( + 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 + ) +{ + BCM_I2C_MASTER *I2c; + UINTN I2cBase; + EFI_STATUS Status; + EFI_TPL Tpl; + BOOLEAN AtRuntime; + UINTN Index; + + AtRuntime =3D EfiAtRuntime (); + if (!AtRuntime) { + Tpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + } + + I2c =3D BCM_I2C_FROM_THIS (This); + + I2cBase =3D I2c->ControllerBase; + + for (Index =3D 0; Index < RequestPacket->OperationCount; Index++ ) { + + Status =3D SingleTransfer (I2cBase, SlaveAddress, &RequestPacket->O= peration[Index]); + + if (EFI_ERROR (Status)) { + break; + } + } + + if (!AtRuntime) { + gBS->RestoreTPL (Tpl); + } + + return Status; +} + +STATIC +VOID +EFIAPI +BcmI2cVirtualAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + BCM_I2C_MASTER *I2c; + + I2c =3D (BCM_I2C_MASTER *)Context; + + EfiConvertPointer (0x0, (VOID**)&I2c->ControllerBase); + EfiConvertPointer (0x0, (VOID**)&I2c); +} + + +EFI_STATUS +BcmI2cInit ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle + ) +{ + EFI_STATUS RetVal; + NON_DISCOVERABLE_DEVICE *Dev; + BCM_I2C_MASTER *I2c; + EFI_EVENT VirtualAddressChangeEvent; + + RetVal =3D gBS->OpenProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + (VOID **)&Dev, DriverBindingHandle, + ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRI= VER); + if (EFI_ERROR (RetVal)) { + return RetVal; + } + + I2c =3D AllocateRuntimeZeroPool (sizeof (BCM_I2C_MASTER)); + + I2c->Signature =3D BCM_I2C_SIGNATURE; + I2c->I2cMaster.SetBusFrequency =3D SetBusFrequency; + I2c->I2cMaster.Reset =3D Reset; + I2c->I2cMaster.StartRequest =3D StartRequest; + I2c->I2cMaster.I2cControllerCapabilities =3D &mI2cControllerCapabilit= ies; + I2c->Dev =3D Dev; + + CopyGuid (&I2c->DevicePath.Vendor.Guid, &gEfiCallerIdGuid); + I2c->DevicePath.MmioBase =3D I2c->Dev->Resources[0].AddrRangeMin; + I2c->ControllerBase =3D I2c->Dev->Resources[0].AddrRangeMin; + SetDevicePathNodeLength (&I2c->DevicePath.Vendor, + sizeof (I2c->DevicePath) - sizeof (I2c->DevicePath.End)); + SetDevicePathEndNode (&I2c->DevicePath.End); + + RetVal =3D gBS->InstallMultipleProtocolInterfaces (&ControllerHandle, + &gEfiI2cMasterProtocolGuid, (VOID**)&I2c->I2cMaster, + &gEfiDevicePathProtocolGuid, &I2c->DevicePath, + NULL); + + if (EFI_ERROR (RetVal)) { + FreePool (I2c); + gBS->CloseProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + DriverBindingHandle, + ControllerHandle); + } else { + RetVal =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + BcmI2cVirtualAddressChangeEvent, + (VOID *)I2c, + &gEfiEventVirtualAddressChangeGuid, + &VirtualAddressChangeEvent + ); + + ASSERT_EFI_ERROR (RetVal); + + } + + return RetVal; +} + +EFI_STATUS +BcmI2cRelease ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle + ) +{ + EFI_I2C_MASTER_PROTOCOL *I2cMaster; + EFI_STATUS RetVal; + BCM_I2C_MASTER *I2c; + + RetVal =3D gBS->HandleProtocol (ControllerHandle, + &gEfiI2cMasterProtocolGuid, + (VOID **)&I2cMaster); + ASSERT_EFI_ERROR (RetVal); + if (EFI_ERROR (RetVal)) { + return RetVal; + } + + I2c =3D BCM_I2C_FROM_THIS (I2cMaster); + + RetVal =3D gBS->UninstallMultipleProtocolInterfaces (ControllerHandle, + &gEfiI2cMasterProtocolGuid, I2cMaster, + &gEfiDevicePathProtocolGuid, &I2c->DevicePath, + NULL); + if (EFI_ERROR (RetVal)) { + return RetVal; + } + + RetVal =3D gBS->CloseProtocol (ControllerHandle, + &gEdkiiNonDiscoverableDeviceProtocolGuid, + DriverBindingHandle, + ControllerHandle); + ASSERT_EFI_ERROR (RetVal); + if (EFI_ERROR (RetVal)) { + return RetVal; + } + + gBS->FreePool (I2c); + + return EFI_SUCCESS; +} diff --git a/Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.h b/Silicon/Broadcom/= Drivers/I2cDxe/I2cDxe.h new file mode 100644 index 0000000000..e9ddc0e7bd --- /dev/null +++ b/Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.h @@ -0,0 +1,55 @@ +/** I2cDxe.h + Header defining the constant, base address amd function for I2C contro= ller + + Copyright 2017-2020 NXP + Sourced and reworked from edk2/NXP I2C stack + Copyright 2022 Arm, Jeremy Linton + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef I2C_DXE_H_ +#define I2C_DXE_H_ + +#include +#include + +#include +#include + +#define BCM_I2C_SIGNATURE SIGNATURE_32 ('B', 'I', '2', 'C') +#define BCM_I2C_FROM_THIS(a) CR ((a), BCM_I2C_MASTER, \ + I2cMaster, BCM_I2C_SIGNATURE) + +extern EFI_COMPONENT_NAME2_PROTOCOL gBcmI2cDriverComponentName2; + +#pragma pack(1) +typedef struct { + VENDOR_DEVICE_PATH Vendor; + UINT64 MmioBase; + EFI_DEVICE_PATH_PROTOCOL End; +} BCM_I2C_DEVICE_PATH; +#pragma pack() + +typedef struct { + UINT32 Signature; + EFI_I2C_MASTER_PROTOCOL I2cMaster; + BCM_I2C_DEVICE_PATH DevicePath; + NON_DISCOVERABLE_DEVICE *Dev; + UINTN ControllerBase; +} BCM_I2C_MASTER; + +EFI_STATUS +BcmI2cInit ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle + ); + +EFI_STATUS +BcmI2cRelease ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_HANDLE ControllerHandle + ); + +#endif //I2C_DXE_H_ diff --git a/Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.inf b/Silicon/Broadco= m/Drivers/I2cDxe/I2cDxe.inf new file mode 100644 index 0000000000..d8b6130616 --- /dev/null +++ b/Silicon/Broadcom/Drivers/I2cDxe/I2cDxe.inf @@ -0,0 +1,56 @@ +# @file +# +# Component description file for I2c driver +# +# Copyright (c) 2015, Freescale Semiconductor, Inc. All rights reserved= . +# Copyright 2017-2020 NXP +# Sourced and reworked from edk2/NXP I2C stack +# Copyright 2022 Arm, Jeremy Linton +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# + +[Defines] + INF_VERSION =3D 0x0001001A + BASE_NAME =3D I2cDxe + FILE_GUID =3D 09e767d9-9c1e-405d-86c3-fb7ce355f94= 8 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D I2cDxeEntryPoint + UNLOAD =3D I2cDxeUnload + +[Sources.common] + ComponentName.c + DriverBinding.c + I2cDxe.c + +[LibraryClasses] + ArmLib + BaseMemoryLib + DevicePathLib + IoLib + MemoryAllocationLib + PcdLib + TimerLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + UefiRuntimeLib + +[Guids] + gBcmNonDiscoverableI2cMasterGuid + gEfiEventVirtualAddressChangeGuid + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Platform/RaspberryPi/RaspberryPi.dec + Silicon/Broadcom/Bcm283x/Bcm283x.dec + +[Protocols] + gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START + gEfiI2cMasterProtocolGuid ## BY_START + +[Depex] + TRUE --=20 2.43.0 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#113559): https://edk2.groups.io/g/devel/message/113559 Mute This Topic: https://groups.io/mt/103653098/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-