public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
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



  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