From patchwork Mon Mar 14 05:30:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 63791 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp2288600lbc; Sun, 13 Mar 2016 22:31:08 -0700 (PDT) X-Received: by 10.98.34.205 with SMTP id p74mr27255878pfj.93.1457933468176; Sun, 13 Mar 2016 22:31:08 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id p8si10131828paq.179.2016.03.13.22.31.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 13 Mar 2016 22:31:08 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dkim=neutral (body hash did not verify) header.i=@linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 437D81A1FA0; Sun, 13 Mar 2016 22:31:25 -0700 (PDT) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received: from mail-pf0-x22b.google.com (mail-pf0-x22b.google.com [IPv6:2607:f8b0:400e:c00::22b]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 8679E1A1F3D for ; Sun, 13 Mar 2016 22:31:23 -0700 (PDT) Received: by mail-pf0-x22b.google.com with SMTP id 124so128889577pfg.0 for ; Sun, 13 Mar 2016 22:31:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=message-id:from:to:cc:subject:date:in-reply-to:references :mime-version; bh=lGf6K4XC6x2GRIJA0katkAGJdWA5nho1MiQBJtnPTgE=; b=WW580btlpq/t0/4ojg6XPymE1JdUg1KWu3LS3xF1v9BU4a+d3RsQh4fdhLMMU+g6dl 81pzr+Z7rIXVNerTFc7kK/2VuEo5215N7FyFAMDo8nxVDVLXKRMB+0x3odK1TNxu/P4G dsOU0LKGbtaZ66lZoO6GyEgPWE5S6WMH0Nz2Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:from:to:cc:subject:date:in-reply-to :references:mime-version; bh=lGf6K4XC6x2GRIJA0katkAGJdWA5nho1MiQBJtnPTgE=; b=KIxD9vILaI3+jjmXcYvc/lsPSe8YZXIbjvrRCVgStAe2wdQI3AGSMQ/3aIx32vHkD+ iYNEEwi50OdVXCdVFJAjb/eT5ttLNNWaiqcV2c7W29xbBFkDJVwqmqBCh8rnY6b8LScx LZHfx/0Kxenp8pp0vyI98FkTWP+9VFrvvBlqjUBgB0k6c8BJUQgvyQ63E9M314pAcys2 Ct8o+QoBpYGHXImVIKJnG8FvFqYGjXNFZo+s9rW0FcSd082h+v8qSpXz+/iMHz8U81uC kyePORYHcGnfSAHMOLJA6BUVZpO+Ev4dZIMZ90yV6jGz+4+b5M/gIbBBDHtA/4JGRp1W /TOA== X-Gm-Message-State: AD7BkJIhRUig1zbZrYqRxWt09GVjLwR+B1R7lFLEEpoRJCIyB/89zUE4VJ7oouHD8H7jsv+g X-Received: by 10.98.16.69 with SMTP id y66mr27290492pfi.86.1457933465813; Sun, 13 Mar 2016 22:31:05 -0700 (PDT) Received: from mail.hotmail.com (blu004-wss1s6.hotmail.com. [134.170.2.221]) by smtp.gmail.com with ESMTPSA id n19sm28644642pfi.53.2016.03.13.22.31.04 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 13 Mar 2016 22:31:04 -0700 (PDT) Received: from BLU436-SMTP12 ([134.170.2.215]) by BLU004-WSS1S6.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Sun, 13 Mar 2016 22:31:03 -0700 X-TMN: [XOcEKRSWeHe7WxaiN+UQ2Kco0u5/6pK/] Message-ID: From: Haojian Zhuang To: edk2-devel@lists.01.org, leif.lindholm@linaro.org, ard.biesheuvel@linaro.org Date: Mon, 14 Mar 2016 13:30:37 +0800 X-Mailer: git-send-email 1.9.1 In-Reply-To: <1457933437-17353-1-git-send-email-haojian.zhuang@linaro.org> References: <1457933437-17353-1-git-send-email-haojian.zhuang@linaro.org> X-OriginalArrivalTime: 14 Mar 2016 05:31:01.0197 (UTC) FILETIME=[B1DA27D0:01D17DB2] MIME-Version: 1.0 Cc: Haojian Zhuang Subject: [edk2] [PATCH v5 2/2] ArmPlatformPkg: PL061: support multiple controller X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" Support multiple PL061 controllers. If platform gpio driver couldn't be found, PL061 gpio driver will continue to load PcdPL061GpioBase as the register base. It could be compatible with the use case of current PL061 gpio driver. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang --- ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c | 141 ++++++++++++++++----- .../Drivers/PL061GpioDxe/PL061GpioDxe.inf | 1 + ArmPlatformPkg/Include/Drivers/PL061Gpio.h | 46 ++++--- 3 files changed, 129 insertions(+), 59 deletions(-) -- 1.9.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel Reviewed-by: Leif Lindholm diff --git a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c index 38341a3..59d615d 100644 --- a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c +++ b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,33 @@ #include #include +PLATFORM_GPIO_CONTROLLER *mPL061PlatformGpio; + +EFI_STATUS +EFIAPI +PL061Locate ( + IN EMBEDDED_GPIO_PIN Gpio, + OUT UINTN *ControllerIndex, + OUT UINTN *ControllerOffset, + OUT UINTN *RegisterBase + ) +{ + UINT32 Index; + + for (Index = 0; Index < mPL061PlatformGpio->GpioControllerCount; Index++) { + if ( (Gpio >= mPL061PlatformGpio->GpioController[Index].GpioIndex) + && (Gpio < mPL061PlatformGpio->GpioController[Index].GpioIndex + + mPL061PlatformGpio->GpioController[Index].InternalGpioCount)) { + *ControllerIndex = Index; + *ControllerOffset = Gpio % mPL061PlatformGpio->GpioController[Index].InternalGpioCount; + *RegisterBase = mPL061PlatformGpio->GpioController[Index].RegisterBase; + return EFI_SUCCESS; + } + } + DEBUG ((EFI_D_ERROR, "%a, failed to locate gpio %d\n", __func__, Gpio)); + return EFI_INVALID_PARAMETER; +} + // // The PL061 is a strange beast. The 8-bit data register is aliased across a // region 0x400 bytes in size, with bits [9:2] of the address operating as a @@ -88,20 +116,36 @@ PL061Identify ( VOID ) { - // Check if this is a PrimeCell Peripheral - if ( (MmioRead8 (PL061_GPIO_PCELL_ID0) != 0x0D) - || (MmioRead8 (PL061_GPIO_PCELL_ID1) != 0xF0) - || (MmioRead8 (PL061_GPIO_PCELL_ID2) != 0x05) - || (MmioRead8 (PL061_GPIO_PCELL_ID3) != 0xB1)) { - return EFI_NOT_FOUND; + UINTN Index; + UINTN RegisterBase; + + if ( (mPL061PlatformGpio->GpioCount == 0) + || (mPL061PlatformGpio->GpioControllerCount == 0)) { + return EFI_NOT_FOUND; } - // Check if this PrimeCell Peripheral is the PL061 GPIO - if ( (MmioRead8 (PL061_GPIO_PERIPH_ID0) != 0x61) - || (MmioRead8 (PL061_GPIO_PERIPH_ID1) != 0x10) - || ((MmioRead8 (PL061_GPIO_PERIPH_ID2) & 0xF) != 0x04) - || (MmioRead8 (PL061_GPIO_PERIPH_ID3) != 0x00)) { - return EFI_NOT_FOUND; + for (Index = 0; Index < mPL061PlatformGpio->GpioControllerCount; Index++) { + if (mPL061PlatformGpio->GpioController[Index].InternalGpioCount != PL061_GPIO_PINS) { + return EFI_INVALID_PARAMETER; + } + + RegisterBase = mPL061PlatformGpio->GpioController[Index].RegisterBase; + + // Check if this is a PrimeCell Peripheral + if ( (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID0) != 0x0D) + || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID1) != 0xF0) + || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID2) != 0x05) + || (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID3) != 0xB1)) { + return EFI_NOT_FOUND; + } + + // Check if this PrimeCell Peripheral is the PL061 GPIO + if ( (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID0) != 0x61) + || (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID1) != 0x10) + || ((MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID2) & 0xF) != 0x04) + || (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID3) != 0x00)) { + return EFI_NOT_FOUND; + } } return EFI_SUCCESS; @@ -132,13 +176,17 @@ Get ( OUT UINTN *Value ) { - if ( (Value == NULL) - || (Gpio > LAST_GPIO_PIN)) - { + EFI_STATUS Status = EFI_SUCCESS; + UINTN Index, Offset, RegisterBase; + + Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase); + ASSERT_EFI_ERROR (Status); + + if (Value == NULL) { return EFI_INVALID_PARAMETER; } - if (PL061GetPins (PL061_GPIO_DATA_REG, Gpio)) { + if (PL061GetPins (RegisterBase + PL061_GPIO_DATA_REG, Offset)) { *Value = 1; } else { *Value = 0; @@ -174,41 +222,39 @@ Set ( ) { EFI_STATUS Status = EFI_SUCCESS; + UINTN Index, Offset, RegisterBase; - // Check for errors - if (Gpio > LAST_GPIO_PIN) { - Status = EFI_INVALID_PARAMETER; - goto EXIT; - } + Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase); + ASSERT_EFI_ERROR (Status); switch (Mode) { case GPIO_MODE_INPUT: // Set the corresponding direction bit to LOW for input - MmioAnd8 (PL061_GPIO_DIR_REG, ~GPIO_PIN_MASK(Gpio) & 0xFF); + MmioAnd8 (RegisterBase + PL061_GPIO_DIR_REG, + ~GPIO_PIN_MASK(Offset) & 0xFF); break; case GPIO_MODE_OUTPUT_0: // Set the corresponding direction bit to HIGH for output - MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Gpio)); + MmioOr8 (RegisterBase + PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Offset)); // Set the corresponding data bit to LOW for 0 - PL061SetPins (PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Gpio), 0); + PL061SetPins (RegisterBase + PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Offset), 0); break; case GPIO_MODE_OUTPUT_1: // Set the corresponding direction bit to HIGH for output - MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Gpio)); + MmioOr8 (RegisterBase + PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Offset)); // Set the corresponding data bit to HIGH for 1 - PL061SetPins (PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Gpio), 0xff); - break; + PL061SetPins (RegisterBase + PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Offset), 0xff); + break; default: // Other modes are not supported return EFI_UNSUPPORTED; } -EXIT: - return Status; + return EFI_SUCCESS; } /** @@ -237,16 +283,21 @@ GetMode ( OUT EMBEDDED_GPIO_MODE *Mode ) { + EFI_STATUS Status = EFI_SUCCESS; + UINTN Index, Offset, RegisterBase; + + Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase); + ASSERT_EFI_ERROR (Status); + // Check for errors - if ( (Mode == NULL) - || (Gpio > LAST_GPIO_PIN)) { + if (Mode == NULL) { return EFI_INVALID_PARAMETER; } // Check if it is input or output - if (MmioRead8 (PL061_GPIO_DIR_REG) & GPIO_PIN_MASK(Gpio)) { + if (MmioRead8 (RegisterBase + PL061_GPIO_DIR_REG) & GPIO_PIN_MASK(Offset)) { // Pin set to output - if (PL061GetPins (PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Gpio))) { + if (PL061GetPins (RegisterBase + PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Offset))) { *Mode = GPIO_MODE_OUTPUT_1; } else { *Mode = GPIO_MODE_OUTPUT_0; @@ -315,14 +366,34 @@ PL061InstallProtocol ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; - EFI_HANDLE Handle; + EFI_STATUS Status; + EFI_HANDLE Handle; + GPIO_CONTROLLER *GpioController; // // Make sure the Gpio protocol has not been installed in the system yet. // ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEmbeddedGpioProtocolGuid); + Status = gBS->LocateProtocol (&gPlatformGpioProtocolGuid, NULL, (VOID **)&mPL061PlatformGpio); + if (EFI_ERROR (Status) && (Status == EFI_NOT_FOUND)) { + // Create the mPL061PlatformGpio + mPL061PlatformGpio = (PLATFORM_GPIO_CONTROLLER *)AllocateZeroPool (sizeof (PLATFORM_GPIO_CONTROLLER) + sizeof (GPIO_CONTROLLER)); + if (mPL061PlatformGpio == NULL) { + DEBUG ((EFI_D_ERROR, "%a: failed to allocate PLATFORM_GPIO_CONTROLLER\n", __func__)); + return EFI_BAD_BUFFER_SIZE; + } + + mPL061PlatformGpio->GpioCount = PL061_GPIO_PINS; + mPL061PlatformGpio->GpioControllerCount = 1; + mPL061PlatformGpio->GpioController = (GPIO_CONTROLLER *)((UINTN) mPL061PlatformGpio + sizeof (PLATFORM_GPIO_CONTROLLER)); + + GpioController = mPL061PlatformGpio->GpioController; + GpioController->RegisterBase = (UINTN) PcdGet32 (PcdPL061GpioBase); + GpioController->GpioIndex = 0; + GpioController->InternalGpioCount = PL061_GPIO_PINS; + } + Status = PL061Identify(); if (EFI_ERROR(Status)) { return EFI_DEVICE_ERROR; diff --git a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf index 9d9e4cd..405a3a9 100644 --- a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf +++ b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf @@ -45,6 +45,7 @@ [Protocols] gEmbeddedGpioProtocolGuid + gPlatformGpioProtocolGuid [Depex] TRUE diff --git a/ArmPlatformPkg/Include/Drivers/PL061Gpio.h b/ArmPlatformPkg/Include/Drivers/PL061Gpio.h index 8fde2bb..308f69f 100644 --- a/ArmPlatformPkg/Include/Drivers/PL061Gpio.h +++ b/ArmPlatformPkg/Include/Drivers/PL061Gpio.h @@ -20,30 +20,28 @@ // PL061 GPIO Registers #define PL061_GPIO_DATA_REG_OFFSET ((UINTN) 0x000) -#define PL061_GPIO_DATA_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x000) -#define PL061_GPIO_DIR_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x400) -#define PL061_GPIO_IS_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x404) -#define PL061_GPIO_IBE_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x408) -#define PL061_GPIO_IEV_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x40C) -#define PL061_GPIO_IE_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x410) -#define PL061_GPIO_RIS_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x414) -#define PL061_GPIO_MIS_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x410) -#define PL061_GPIO_IC_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x41C) -#define PL061_GPIO_AFSEL_REG ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0x420) - -#define PL061_GPIO_PERIPH_ID0 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFE0) -#define PL061_GPIO_PERIPH_ID1 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFE4) -#define PL061_GPIO_PERIPH_ID2 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFE8) -#define PL061_GPIO_PERIPH_ID3 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFEC) - -#define PL061_GPIO_PCELL_ID0 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFF0) -#define PL061_GPIO_PCELL_ID1 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFF4) -#define PL061_GPIO_PCELL_ID2 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFF8) -#define PL061_GPIO_PCELL_ID3 ((UINT32)PcdGet32 (PcdPL061GpioBase) + 0xFFC) - - -// GPIO pins are numbered 0..7 -#define LAST_GPIO_PIN 7 +#define PL061_GPIO_DATA_REG 0x000 +#define PL061_GPIO_DIR_REG 0x400 +#define PL061_GPIO_IS_REG 0x404 +#define PL061_GPIO_IBE_REG 0x408 +#define PL061_GPIO_IEV_REG 0x40C +#define PL061_GPIO_IE_REG 0x410 +#define PL061_GPIO_RIS_REG 0x414 +#define PL061_GPIO_MIS_REG 0x410 +#define PL061_GPIO_IC_REG 0x41C +#define PL061_GPIO_AFSEL_REG 0x420 + +#define PL061_GPIO_PERIPH_ID0 0xFE0 +#define PL061_GPIO_PERIPH_ID1 0xFE4 +#define PL061_GPIO_PERIPH_ID2 0xFE8 +#define PL061_GPIO_PERIPH_ID3 0xFEC + +#define PL061_GPIO_PCELL_ID0 0xFF0 +#define PL061_GPIO_PCELL_ID1 0xFF4 +#define PL061_GPIO_PCELL_ID2 0xFF8 +#define PL061_GPIO_PCELL_ID3 0xFFC + +#define PL061_GPIO_PINS 8 // All bits low except one bit high, native bit length #define GPIO_PIN_MASK(Pin) (1UL << ((UINTN)(Pin)))