public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Leif Lindholm <leif.lindholm@linaro.org>
To: Marcin Wojtas <mw@semihalf.com>
Cc: edk2-devel@lists.01.org, ard.biesheuvel@linaro.org,
	nadavh@marvell.com, jsd@semihalf.com, jaz@semihalf.com,
	kostap@marvell.com, jinghua <jinghua@marvell.com>
Subject: Re: [platforms: PATCH 08/12] Marvell/Drivers: MvGpioDxe: Introduce platform GPIO driver
Date: Tue, 4 Dec 2018 16:37:26 +0000	[thread overview]
Message-ID: <20181204163726.4j5pm4cbwlmb5oea@bivouac.eciton.net> (raw)
In-Reply-To: <1540000661-1956-9-git-send-email-mw@semihalf.com>

On Sat, Oct 20, 2018 at 03:57:37AM +0200, Marcin Wojtas wrote:
> From: jinghua <jinghua@marvell.com>
> 
> Marvell Armada 7k/8k SoCs comprise integrated GPIO controllers,
> one in AP and two in each possible CP hardware blocks.
> 
> This patch introduces support for them, which is a producer of
> MARVELL_GPIO_PROTOCOL, which add necessary routines.
> Hardware description of the controllers is placed in MvHwDescLib.c,
> same as other devices.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
>  Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.inf |  43 +++
>  Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.h   |  52 ++++
>  Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.c   | 298 ++++++++++++++++++++
>  3 files changed, 393 insertions(+)
>  create mode 100644 Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.inf
>  create mode 100644 Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.h
>  create mode 100644 Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.c
> 
> diff --git a/Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.inf b/Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.inf
> new file mode 100644
> index 0000000..2d56433
> --- /dev/null
> +++ b/Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.inf
> @@ -0,0 +1,43 @@
> +## @file
> +#
> +#  Copyright (c) 2017, Marvell International 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                      = MvGpioDxe
> +  FILE_GUID                      = 706eb761-b3b5-4f41-8558-5fd9217c0079
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = MvGpioEntryPoint
> +
> +[Sources]
> +  MvGpioDxe.c
> +  MvGpioDxe.h
> +
> +[Packages]
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Marvell/Marvell.dec
> +
> +[LibraryClasses]
> +  ArmadaSoCDescLib
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiDriverEntryPoint
> +  UefiLib
> +
> +[Protocols]
> +  gMarvellBoardDescProtocolGuid
> +  gMarvellGpioProtocolGuid
> +
> +[Depex]
> +  TRUE
> diff --git a/Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.h b/Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.h
> new file mode 100644
> index 0000000..48744dc
> --- /dev/null
> +++ b/Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.h
> @@ -0,0 +1,52 @@
> +/**
> +*
> +*  Copyright (c) 2018, Marvell International Ltd. All rights reserved.
> +*
> +*  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.
> +*
> +**/
> +#ifndef __MV_GPIO_H__
> +#define __MV_GPIO_H__
> +
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +
> +#include <Protocol/BoardDesc.h>
> +#include <Protocol/MvGpio.h>
> +
> +#include <Uefi/UefiBaseType.h>
> +
> +#define GPIO_SIGNATURE                   SIGNATURE_32 ('G', 'P', 'I', 'O')

Needs more MV.

> +
> +#ifndef BIT
> +#define BIT(nr)                          (1 << (nr))
> +#endif

OK, you are using this with non-constants.
But please drop the #ifndef and submit a patch to add a BIT macro to
MdePkg/Include/Base.h. (And drop this if you get it accepted :)

> +
> +// Marvell GPIO Controller Registers
> +#define GPIO_DATA_OUT_REG                (0x0)
> +#define GPIO_OUT_EN_REG                  (0x4)
> +#define GPIO_BLINK_EN_REG                (0x8)
> +#define GPIO_DATA_IN_POL_REG             (0xc)
> +#define GPIO_DATA_IN_REG                 (0x10)

Needs more MV.

> +
> +typedef struct {
> +  MARVELL_GPIO_PROTOCOL   GpioProtocol;
> +  MV_BOARD_GPIO_DESC      *Desc;
> +  UINTN                   Signature;
> +  EFI_HANDLE              Handle;
> +} MV_GPIO;
> +
> +#endif // __MV_GPIO_H__
> diff --git a/Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.c b/Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.c
> new file mode 100644
> index 0000000..fc2d416
> --- /dev/null
> +++ b/Silicon/Marvell/Drivers/Gpio/MvGpioDxe/MvGpioDxe.c
> @@ -0,0 +1,298 @@
> +/**
> +*
> +*  Copyright (c) 2018, Marvell International Ltd. All rights reserved.
> +*
> +*  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 "MvGpioDxe.h"
> +
> +STATIC MV_GPIO *mGpioInstance;
> +
> +STATIC MV_GPIO_DEVICE_PATH mGpioDevicePathTemplate = {

(Again, not used outside this file, doesn't really need the Gpio bit
in the name. Up to you.)

> +  {
> +    {
> +      HARDWARE_DEVICE_PATH,
> +      HW_VENDOR_DP,
> +      {
> +        (UINT8) (sizeof (VENDOR_DEVICE_PATH) +
> +                 sizeof (MARVELL_GPIO_DRIVER_TYPE)),
> +        (UINT8) ((sizeof (VENDOR_DEVICE_PATH) +
> +                 sizeof (MARVELL_GPIO_DRIVER_TYPE)) >> 8),
> +      },
> +    },
> +    EFI_CALLER_ID_GUID
> +  },
> +  GPIO_DRIVER_TYPE_SOC_CONTROLLER,
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      sizeof(EFI_DEVICE_PATH_PROTOCOL),
> +      0
> +    }
> +  }
> +};
> +
> +STATIC
> +EFI_STATUS
> +MvGpioValidate (
> +  IN  UINTN ControllerIndex,
> +  IN  UINTN GpioPin
> +  )
> +{

Please add a comment header for this function explaining what it does.
(I will start becoming more strict on this in general, but I know I've
been lax in the past, so I'll ease into it.)

> +  if (ControllerIndex >= mGpioInstance->Desc->GpioDevCount) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Invalid GPIO ControllerIndex: %d\n",
> +      __FUNCTION__,
> +      ControllerIndex));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (GpioPin >= mGpioInstance->Desc->SoC[ControllerIndex].GpioPinCount) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: GPIO pin #%d not available in Controller#%d\n",
> +      __FUNCTION__,
> +      GpioPin,
> +      ControllerIndex));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MvGpioDirectionOutput (
> +  IN  MARVELL_GPIO_PROTOCOL *This,
> +  IN  UINTN ControllerIndex,
> +  IN  UINTN GpioPin,
> +  IN  BOOLEAN Value
> +  )
> +{
> +  UINTN BaseAddress;
> +  EFI_STATUS Status;
> +
> +  Status = MvGpioValidate (ControllerIndex, GpioPin);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Fail to set output for pin #%d\n",
> +      __FUNCTION__,
> +      GpioPin));
> +    return Status;
> +  }

So, I'm on the fence here. Do we need to validate that we're not
trying to write pins that don't exist all the time?

I could see why it may be useful for DEBUG builds and new board
bringup, but even then - could it be a helper function that is called
from an ASSERT and only included ifndef MDEPKG_NDEBUG?

> +
> +  BaseAddress = mGpioInstance->Desc->SoC[ControllerIndex].GpioBaseAddress;
> +
> +  MmioAndThenOr32 (BaseAddress + GPIO_DATA_OUT_REG,
> +    ~BIT (GpioPin),
> +    (Value) << GpioPin);

Would be cleaner to have a BITPOSITION macro to match the BIT one.

> +
> +  MmioAnd32 (BaseAddress + GPIO_OUT_EN_REG, ~BIT (GpioPin));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MvGpioDirectionInput (
> +  IN  MARVELL_GPIO_PROTOCOL *This,
> +  IN  UINTN ControllerIndex,
> +  IN  UINTN GpioPin
> +  )
> +{
> +  UINTN BaseAddress;
> +  EFI_STATUS Status;
> +
> +  Status = MvGpioValidate (ControllerIndex, GpioPin);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Fail to set input for pin #%d\n",
> +      __FUNCTION__,
> +      GpioPin));
> +    return Status;
> +  }
> +
> +  BaseAddress = mGpioInstance->Desc->SoC[ControllerIndex].GpioBaseAddress;
> +
> +  MmioOr32 (BaseAddress + GPIO_OUT_EN_REG, BIT (GpioPin));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MvGpioGetFunction (
> +  IN  MARVELL_GPIO_PROTOCOL *This,
> +  IN  UINTN ControllerIndex,
> +  IN  UINTN GpioPin,
> +  OUT MARVELL_GPIO_MODE *Mode
> +  )
> +{
> +  UINT32 RegVal;
> +  UINTN BaseAddress;
> +  EFI_STATUS Status;
> +
> +  Status = MvGpioValidate (ControllerIndex, GpioPin);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Fail to get function of pin #%d\n",
> +      __FUNCTION__,
> +      GpioPin));
> +    return Status;
> +  }
> +
> +  BaseAddress = mGpioInstance->Desc->SoC[ControllerIndex].GpioBaseAddress;
> +
> +  RegVal = MmioRead32 (BaseAddress + GPIO_OUT_EN_REG);
> +  *Mode = ((RegVal & BIT (GpioPin)) ? GPIO_MODE_INPUT : GPIO_MODE_OUTPUT);

Not a fan of this. This is abusing the fact that the programmer knows
the numeric values of the enum members. At which point, why not nuke
the ternary overhead and go
  *Mode = (RegVal & BIT (GpioPin)) >> BIT (GpioPin);
?

An alternative interpretation is that the enum is the software view
only, and that the bit meaning is hardware dependent. In that case, we
additionally need a #define for that.

> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MvGpioGetValue (
> +  IN     MARVELL_GPIO_PROTOCOL *This,
> +  IN     UINTN ControllerIndex,
> +  IN     UINTN GpioPin,
> +  IN OUT BOOLEAN *Value
> +  )
> +{
> +  UINTN BaseAddress;
> +  EFI_STATUS Status;
> +
> +  Status = MvGpioValidate (ControllerIndex, GpioPin);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Fail to get value of pin #%d\n",
> +      __FUNCTION__,
> +      GpioPin));
> +    return Status;
> +  }
> +
> +  BaseAddress = mGpioInstance->Desc->SoC[ControllerIndex].GpioBaseAddress;
> +
> +  *Value = !!(MmioRead32 (BaseAddress + GPIO_DATA_IN_REG) & BIT (GpioPin));

Please don't !!.
If necessary, please shift.

/
    Leif

> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +EFI_STATUS
> +MvGpioSetValue (
> +  IN  MARVELL_GPIO_PROTOCOL *This,
> +  IN  UINTN ControllerIndex,
> +  IN  UINTN GpioPin,
> +  IN  BOOLEAN Value
> +  )
> +{
> +  UINTN BaseAddress;
> +  EFI_STATUS Status;
> +
> +  Status = MvGpioValidate (ControllerIndex, GpioPin);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Fail to get value of pin #%d\n",
> +      __FUNCTION__,
> +      GpioPin));
> +    return Status;
> +  }
> +
> +  BaseAddress = mGpioInstance->Desc->SoC[ControllerIndex].GpioBaseAddress;
> +
> +  MmioAndThenOr32 (BaseAddress + GPIO_DATA_OUT_REG,
> +    ~BIT (GpioPin),
> +    Value << GpioPin);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +STATIC
> +VOID
> +MvGpioInitProtocol (
> +  IN MARVELL_GPIO_PROTOCOL *GpioProtocol
> +  )
> +{
> +  GpioProtocol->DirectionInput  = MvGpioDirectionInput;
> +  GpioProtocol->DirectionOutput = MvGpioDirectionOutput;
> +  GpioProtocol->GetFunction     = MvGpioGetFunction;
> +  GpioProtocol->GetValue        = MvGpioGetValue;
> +  GpioProtocol->SetValue        = MvGpioSetValue;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +MvGpioEntryPoint (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  MARVELL_BOARD_DESC_PROTOCOL *BoardDescProtocol;
> +  MV_GPIO_DEVICE_PATH *GpioDevicePath;
> +  MV_BOARD_GPIO_DESC *Desc;
> +  EFI_STATUS Status;
> +
> +  GpioDevicePath = AllocateCopyPool (sizeof (MV_GPIO_DEVICE_PATH),
> +                     &mGpioDevicePathTemplate);
> +  if (GpioDevicePath == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  mGpioInstance = AllocateZeroPool (sizeof (MV_GPIO));
> +  if (mGpioInstance == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ErrGpioInstanceAlloc;
> +  }
> +
> +  /* Obtain list of available controllers */
> +  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
> +                  NULL,
> +                  (VOID **)&BoardDescProtocol);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot locate BoardDesc protocol\n",
> +      __FUNCTION__));
> +    goto ErrLocateBoardDesc;
> +  }
> +
> +  Status = BoardDescProtocol->BoardDescGpioGet (BoardDescProtocol, &Desc);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR,
> +      "%a: Cannot get GPIO board desc from BoardDesc protocol\n",
> +      __FUNCTION__));
> +    goto ErrLocateBoardDesc;
> +  }
> +
> +  mGpioInstance->Signature = GPIO_SIGNATURE;
> +  mGpioInstance->Desc = Desc;
> +
> +  MvGpioInitProtocol (&mGpioInstance->GpioProtocol);
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (&(mGpioInstance->Handle),
> +                  &gMarvellGpioProtocolGuid,
> +                  &(mGpioInstance->GpioProtocol),
> +                  &gEfiDevicePathProtocolGuid,
> +                  (EFI_DEVICE_PATH_PROTOCOL *)GpioDevicePath,
> +                  NULL);
> +  if (EFI_ERROR (Status)) {
> +    goto ErrLocateBoardDesc;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ErrLocateBoardDesc:
> +  gBS->FreePool (mGpioInstance);
> +
> +ErrGpioInstanceAlloc:
> +  gBS->FreePool (GpioDevicePath);
> +
> +  return Status;
> +}
> -- 
> 2.7.4
> 


  reply	other threads:[~2018-12-04 16:37 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-20  1:57 [platforms: PATCH 00/12] Armada7k8k GPIO support Marcin Wojtas
2018-10-20  1:57 ` [platforms: PATCH 01/12] Marvell/Library: ArmadaSoCDescLib: Add GPIO information Marcin Wojtas
2018-11-14  1:10   ` Leif Lindholm
2018-11-14  6:05     ` Marcin Wojtas
2018-11-14 17:33       ` Leif Lindholm
2018-11-21  1:26         ` Marcin Wojtas
2018-11-26 14:49           ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 02/12] Marvell/Library: ArmadaBoardDescLib: " Marcin Wojtas
2018-11-14  1:12   ` Leif Lindholm
2018-11-14  6:16     ` Marcin Wojtas
2018-11-14 17:29       ` Leif Lindholm
2018-12-04 15:18     ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 03/12] SolidRun/Armada80x0McBin: Introduce board description library Marcin Wojtas
2018-12-04 15:23   ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 04/12] Marvell/Armada70x0Db: " Marcin Wojtas
2018-12-04 15:27   ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 05/12] Marvell/Armada80x0Db: " Marcin Wojtas
2018-12-04 15:31   ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 06/12] Marvell/Drivers: MvBoardDesc: Extend protocol with GPIO support Marcin Wojtas
2018-12-04 15:42   ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 07/12] Marvell/Protocol: Introduce MARVELL_GPIO_PROTOCOL Marcin Wojtas
2018-12-04 16:00   ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 08/12] Marvell/Drivers: MvGpioDxe: Introduce platform GPIO driver Marcin Wojtas
2018-12-04 16:37   ` Leif Lindholm [this message]
2018-12-04 16:40     ` Ard Biesheuvel
2018-12-04 17:19       ` Leif Lindholm
2018-12-04 17:20         ` Ard Biesheuvel
2018-10-20  1:57 ` [platforms: PATCH 09/12] Marvell/Drivers: I2c: Use common header for macros Marcin Wojtas
2018-12-04 16:38   ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 10/12] Marvell/Drivers: MvPca95xxDxe: Introduce I2C GPIO driver Marcin Wojtas
2018-12-04 17:02   ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 11/12] Marvell/Armada7k8k: Enable GPIO drivers compilation Marcin Wojtas
2018-12-04 17:06   ` Leif Lindholm
2018-10-20  1:57 ` [platforms: PATCH 12/12] Marvell/Armada7k8k: Introduce NonDiscoverable device init routines Marcin Wojtas
2018-12-04 17:16   ` Leif Lindholm

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=20181204163726.4j5pm4cbwlmb5oea@bivouac.eciton.net \
    --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