From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: edk2-devel@lists.01.org
Cc: leif.lindholm@linaro.org, Ard Biesheuvel <ard.biesheuvel@linaro.org>
Subject: [PATCH edk2-platforms v3 2/6] Platform/96Boards: introduce I2C driver
Date: Fri, 23 Feb 2018 15:40:48 +0000 [thread overview]
Message-ID: <20180223154052.9828-3-ard.biesheuvel@linaro.org> (raw)
In-Reply-To: <20180223154052.9828-1-ard.biesheuvel@linaro.org>
Implement a I2C DXE driver that wires up the I2C devices exposed by
a 96boards mezzanine into the EDK2 I2C stack. Note that this requires
the platform to identify its I2C master implementations using special
GUIDs-as-protocols. It also assumes [for now] that I2C buses are not
shared between the 96boards connector and other platform peripherals.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
Platform/96Boards/96BoardsI2cDxe/96BoardsI2cDxe.c | 206 ++++++++++++++++++++
Platform/96Boards/96BoardsI2cDxe/96BoardsI2cDxe.inf | 51 +++++
2 files changed, 257 insertions(+)
diff --git a/Platform/96Boards/96BoardsI2cDxe/96BoardsI2cDxe.c b/Platform/96Boards/96BoardsI2cDxe/96BoardsI2cDxe.c
new file mode 100644
index 000000000000..79bb9ed5ffee
--- /dev/null
+++ b/Platform/96Boards/96BoardsI2cDxe/96BoardsI2cDxe.c
@@ -0,0 +1,206 @@
+/** @file
+
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/I2cBusConfigurationManagement.h>
+#include <Protocol/I2cEnumerate.h>
+#include <Protocol/I2cMaster.h>
+#include <Protocol/Mezzanine.h>
+
+STATIC MEZZANINE_PROTOCOL *mMezzanine;
+
+typedef struct {
+ EFI_I2C_ENUMERATE_PROTOCOL I2cEnumerate;
+ EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL I2cConfigManagement;
+ EFI_HANDLE I2cMasterHandle;
+ UINT32 BusFrequency;
+ UINTN NumDevices;
+ CONST EFI_I2C_DEVICE *Devices;
+} I2C_BUS;
+
+STATIC
+EFI_STATUS
+EFIAPI
+I2cEnumerate (
+ IN CONST EFI_I2C_ENUMERATE_PROTOCOL *This,
+ IN OUT CONST EFI_I2C_DEVICE **Device
+ )
+{
+ I2C_BUS *Bus;
+
+ if (Device == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Bus = BASE_CR (This, I2C_BUS, I2cEnumerate);
+
+ if (Bus->NumDevices == 0 ||
+ (Bus->NumDevices > 0 && *Device == &Bus->Devices[Bus->NumDevices - 1])) {
+ *Device = NULL;
+ } else if (*Device == NULL) {
+ *Device = &Bus->Devices[0];
+ } else if (Bus->NumDevices > 1 &&
+ *Device >= &Bus->Devices[0] &&
+ *Device < &Bus->Devices[Bus->NumDevices - 1]) {
+ ++*Device;
+ } else {
+ return EFI_NO_MAPPING;
+ }
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+I2cGetBusFrequency (
+ IN CONST EFI_I2C_ENUMERATE_PROTOCOL *This,
+ IN UINTN I2cBusConfiguration,
+ OUT UINTN *BusClockHertz
+ )
+{
+ I2C_BUS *Bus;
+
+ if (BusClockHertz == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (I2cBusConfiguration > 0) {
+ return EFI_NO_MAPPING;
+ }
+
+ Bus = BASE_CR (This, I2C_BUS, I2cEnumerate);
+
+ *BusClockHertz = Bus->BusFrequency;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+EnableI2cBusConfiguration (
+ IN CONST EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *This,
+ IN UINTN I2cBusConfiguration,
+ IN EFI_EVENT Event OPTIONAL,
+ IN EFI_STATUS *I2cStatus OPTIONAL
+ )
+{
+ EFI_I2C_MASTER_PROTOCOL *I2cMaster;
+ EFI_STATUS Status;
+ UINTN BusClockHertz;
+ I2C_BUS *Bus;
+
+ if (I2cBusConfiguration > 0) {
+ return EFI_NO_MAPPING;
+ }
+
+ Bus = BASE_CR (This, I2C_BUS, I2cConfigManagement);
+
+ Status = gBS->HandleProtocol (Bus->I2cMasterHandle,
+ &gEfiI2cMasterProtocolGuid, (VOID **)&I2cMaster);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: gBS->HandleProtocol() failed - %r\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+
+ BusClockHertz = Bus->BusFrequency;
+ Status = I2cMaster->SetBusFrequency (I2cMaster, &BusClockHertz);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: I2cMaster->SetBusFrequency() failed - %r\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+
+ if (Event != NULL) {
+ *I2cStatus = EFI_SUCCESS;
+ gBS->SignalEvent (Event);
+ }
+ return EFI_SUCCESS;
+}
+
+STATIC I2C_BUS mI2cBus0 = {
+ { I2cEnumerate, I2cGetBusFrequency },
+ { EnableI2cBusConfiguration },
+ NULL,
+ FixedPcdGet32 (PcdI2c0BusFrequencyHz),
+ 0,
+ NULL,
+};
+
+STATIC I2C_BUS mI2cBus1 = {
+ { I2cEnumerate, I2cGetBusFrequency },
+ { EnableI2cBusConfiguration },
+ NULL,
+ FixedPcdGet32 (PcdI2c1BusFrequencyHz),
+ 0,
+ NULL,
+};
+
+STATIC
+VOID
+RegisterI2cBus (
+ IN EFI_GUID *Guid,
+ IN I2C_BUS *I2cBus,
+ IN UINTN NumDevices,
+ IN CONST EFI_I2C_DEVICE *Devices
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = gBS->LocateHandle (ByProtocol, Guid, NULL, &BufferSize,
+ &I2cBus->I2cMasterHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: gBS->LocateHandle() failed - %r\n", __FUNCTION__,
+ Status));
+ return;
+ }
+
+ I2cBus->NumDevices = NumDevices;
+ I2cBus->Devices = Devices;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (&I2cBus->I2cMasterHandle,
+ &gEfiI2cEnumerateProtocolGuid,
+ &I2cBus->I2cEnumerate,
+ &gEfiI2cBusConfigurationManagementProtocolGuid,
+ &I2cBus->I2cConfigManagement,
+ NULL);
+ ASSERT_EFI_ERROR (Status);
+}
+
+EFI_STATUS
+EFIAPI
+EntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&g96BoardsMezzanineProtocolGuid, NULL,
+ (VOID **)&mMezzanine);
+ ASSERT_EFI_ERROR (Status);
+
+ RegisterI2cBus (&g96BoardsI2c0MasterGuid, &mI2cBus0,
+ mMezzanine->I2c0NumDevices, mMezzanine->I2c0DeviceArray);
+ RegisterI2cBus (&g96BoardsI2c1MasterGuid, &mI2cBus1,
+ mMezzanine->I2c1NumDevices, mMezzanine->I2c1DeviceArray);
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/96Boards/96BoardsI2cDxe/96BoardsI2cDxe.inf b/Platform/96Boards/96BoardsI2cDxe/96BoardsI2cDxe.inf
new file mode 100644
index 000000000000..7eb1fc503062
--- /dev/null
+++ b/Platform/96Boards/96BoardsI2cDxe/96BoardsI2cDxe.inf
@@ -0,0 +1,51 @@
+## @file
+#
+# Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD
+# License which accompanies this distribution. The full text of the license may
+# be found at http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = 96BoardsI2cDxe
+ FILE_GUID = a59176bc-a151-49c8-b54a-b4ac96f436c3
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 0.1
+ ENTRY_POINT = EntryPoint
+
+[Sources]
+ 96BoardsI2cDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ Platform/96Boards/96Boards.dec
+
+[LibraryClasses]
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ g96BoardsMezzanineProtocolGuid ## CONSUMES
+ gEfiI2cBusConfigurationManagementProtocolGuid ## PRODUCES
+ gEfiI2cEnumerateProtocolGuid ## PRODUCES
+ gEfiI2cMasterProtocolGuid ## CONSUMES
+
+[Guids]
+ g96BoardsI2c0MasterGuid
+ g96BoardsI2c1MasterGuid
+
+[FixedPcd]
+ g96BoardsTokenSpaceGuid.PcdI2c0BusFrequencyHz
+ g96BoardsTokenSpaceGuid.PcdI2c1BusFrequencyHz
+
+[Depex]
+ g96BoardsMezzanineProtocolGuid AND g96BoardsI2c0MasterGuid OR g96BoardsI2c1MasterGuid
--
2.11.0
next prev parent reply other threads:[~2018-02-23 15:35 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-23 15:40 [PATCH edk2-platforms v3 0/6] Add Secure96 mezzanine support Ard Biesheuvel
2018-02-23 15:40 ` [PATCH edk2-platforms v3 1/6] Platform/96Boards: introduce package and mezzanine protocol Ard Biesheuvel
2018-02-23 15:40 ` Ard Biesheuvel [this message]
2018-02-23 15:40 ` [PATCH edk2-platforms v3 3/6] Platform/96Boards: introduce LsConnector protocol Ard Biesheuvel
2018-02-23 15:40 ` [PATCH edk2-platforms v3 4/6] Platform/96Boards: add a driver for the Secure96 mezzanine board Ard Biesheuvel
2018-02-23 15:40 ` [PATCH edk2-platforms v3 5/6] Platform/96Boards: add driver for low speed (LS) connector Ard Biesheuvel
2018-02-23 15:40 ` [PATCH edk2-platforms v3 6/6] Platform/Socionext/DeveloperBox: add 96Boards mezzanine support Ard Biesheuvel
2018-02-23 15:56 ` [PATCH edk2-platforms v3 0/6] Add Secure96 " Leif Lindholm
2018-02-23 16:02 ` Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180223154052.9828-3-ard.biesheuvel@linaro.org \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox