From patchwork Fri Feb 26 16:16:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leif Lindholm X-Patchwork-Id: 63083 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp802388lbc; Fri, 26 Feb 2016 08:17:12 -0800 (PST) X-Received: by 10.98.16.198 with SMTP id 67mr3223610pfq.21.1456503428971; Fri, 26 Feb 2016 08:17:08 -0800 (PST) Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id qy17si3289767pac.171.2016.02.26.08.17.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 26 Feb 2016 08:17:08 -0800 (PST) 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 23A741A1E33; Fri, 26 Feb 2016 08:17:11 -0800 (PST) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received: from mail-wm0-x231.google.com (mail-wm0-x231.google.com [IPv6:2a00:1450:400c:c09::231]) (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 8BA3F1A1E25 for ; Fri, 26 Feb 2016 08:17:09 -0800 (PST) Received: by mail-wm0-x231.google.com with SMTP id g62so78810448wme.0 for ; Fri, 26 Feb 2016 08:17:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Mjr3xJW/er7TiMyT3uaavFHk7GPwlihjnrd2WSlYelk=; b=H1lKC/7fxUL30WGA1qHFRxGRQIeltyxFFtfVcQ+5MsyTvGY5QtYVzcl2vmUdV6yWHZ bhlremST5spzIMhbDwD5cFkC6sC1aFc/jZn8K0czo15XvoY1LkH4n4xcNVMe+Nhj+x8c i4udZwR6sG7NfwHKtsE4mj9m9RaH3hrk++VvY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Mjr3xJW/er7TiMyT3uaavFHk7GPwlihjnrd2WSlYelk=; b=HSq7cETugMQ8hQPHz52F6BQXCvBMDfSmiTk2DByql9awPjMETVMH6L8jR4H/+bJIo3 nSfHwLlxzEs1AGb9ufmpqudoLV2XEjeNpAk8C071bj7S/wuD+FXs2nxBfCxgKfAHa5cQ ZgEZMRe/MAI41wKsmscrVG/HAGvCSkuEtnqfNDqkIdGkw+lLp3yPisWfolKAV/vefh3N G9lrjoz78C1W3VhR8ghamy6y4Srs46aFE03D00wjPUNAjIX2tILBL8wpaXssoz8GBDN7 /a3PabsjbALgcHPBf2xm5lsUr/a6AspM96nJlFZ74EaJvu1P9xm4VkvPQitChQKYue+x dbwQ== X-Gm-Message-State: AD7BkJKQA6qtBxy0Y1up8F7nTsIgmjpUeB4EbbM6CGOSYeLVX4NDJgnSi02+aVyQT9T+x7at X-Received: by 10.194.77.193 with SMTP id u1mr2482655wjw.73.1456503423060; Fri, 26 Feb 2016 08:17:03 -0800 (PST) Received: from mohikan.mushroom.smurfnet.nu (cpc92308-cmbg19-2-0-cust814.5-4.cable.virginm.net. [82.24.251.47]) by smtp.gmail.com with ESMTPSA id k8sm13067962wjr.38.2016.02.26.08.17.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 26 Feb 2016 08:17:02 -0800 (PST) From: Leif Lindholm To: edk2-devel@lists.01.org Date: Fri, 26 Feb 2016 16:16:55 +0000 Message-Id: <1456503415-17029-5-git-send-email-leif.lindholm@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1456503415-17029-1-git-send-email-leif.lindholm@linaro.org> References: <1456503415-17029-1-git-send-email-leif.lindholm@linaro.org> Cc: Haojian Zhuang , Ard Biesheuvel Subject: [edk2] [PATCH 4/4] ArmPlatformPkg: PL061 - rewrite the hardware interaction 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: , MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" The PL061 GPIO controller is a bit of an anachronism, and the existing driver does nothing to hide this - leading to it being very tricky to read. Rewrite it to document (in comments and code) what is actually happening, and fix some bugs in the process. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Leif Lindholm --- ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c | 72 +++++++++++++++++++++---- ArmPlatformPkg/Include/Drivers/PL061Gpio.h | 5 +- 2 files changed, 62 insertions(+), 15 deletions(-) -- 2.1.4 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c index 45897ca..38341a3 100644 --- a/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c +++ b/ArmPlatformPkg/Drivers/PL061GpioDxe/PL061Gpio.c @@ -28,6 +28,56 @@ #include #include +// +// 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 +// mask for both read and write operations: +// For reads: +// - All bits where their corresponding mask bit is 1 return the current +// value of that bit in the GPIO_DATA register. +// - All bits where their corresponding mask bit is 0 return 0. +// For writes: +// - All bits where their corresponding mask bit is 1 set the bit in the +// GPIO_DATA register to the written value. +// - All bits where their corresponding mask bit is 0 are left untouched +// in the GPIO_DATA register. +// +// To keep this driver intelligible, PL061EffectiveAddress, PL061GetPins and +// Pl061SetPins provide an internal abstraction from this interface. + +STATIC +UINTN +EFIAPI +PL061EffectiveAddress ( + IN UINTN Address, + IN UINTN Mask + ) +{ + return ((Address + PL061_GPIO_DATA_REG_OFFSET) + (Mask << 2)); +} + +STATIC +UINTN +EFIAPI +PL061GetPins ( + IN UINTN Address, + IN UINTN Mask + ) +{ + return MmioRead8 (PL061EffectiveAddress (Address, Mask)); +} + +STATIC +VOID +EFIAPI +PL061SetPins ( + IN UINTN Address, + IN UINTN Mask, + IN UINTN Value + ) +{ + MmioWrite8 (PL061EffectiveAddress (Address, Mask), Value); +} /** Function implementations @@ -88,7 +138,7 @@ Get ( return EFI_INVALID_PARAMETER; } - if (MmioRead8 (PL061_GPIO_DATA_REG) & GPIO_PIN_MASK_HIGH_8BIT(Gpio)) { + if (PL061GetPins (PL061_GPIO_DATA_REG, Gpio)) { *Value = 1; } else { *Value = 0; @@ -135,22 +185,22 @@ Set ( { case GPIO_MODE_INPUT: // Set the corresponding direction bit to LOW for input - MmioAnd8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK_LOW_8BIT(Gpio)); + MmioAnd8 (PL061_GPIO_DIR_REG, ~GPIO_PIN_MASK(Gpio) & 0xFF); break; case GPIO_MODE_OUTPUT_0: - // Set the corresponding data bit to LOW for 0 - MmioAnd8 (PL061_GPIO_DATA_REG, GPIO_PIN_MASK_LOW_8BIT(Gpio)); // Set the corresponding direction bit to HIGH for output - MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio)); + MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Gpio)); + // Set the corresponding data bit to LOW for 0 + PL061SetPins (PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Gpio), 0); break; case GPIO_MODE_OUTPUT_1: - // Set the corresponding data bit to HIGH for 1 - MmioOr8 (PL061_GPIO_DATA_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio)); // Set the corresponding direction bit to HIGH for output - MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio)); - break; + MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK(Gpio)); + // Set the corresponding data bit to HIGH for 1 + PL061SetPins (PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Gpio), 0xff); + break; default: // Other modes are not supported @@ -194,9 +244,9 @@ GetMode ( } // Check if it is input or output - if (MmioRead8 (PL061_GPIO_DIR_REG) & GPIO_PIN_MASK_HIGH_8BIT(Gpio)) { + if (MmioRead8 (PL061_GPIO_DIR_REG) & GPIO_PIN_MASK(Gpio)) { // Pin set to output - if (MmioRead8 (PL061_GPIO_DATA_REG) & GPIO_PIN_MASK_HIGH_8BIT(Gpio)) { + if (PL061GetPins (PL061_GPIO_DATA_REG, GPIO_PIN_MASK(Gpio))) { *Mode = GPIO_MODE_OUTPUT_1; } else { *Mode = GPIO_MODE_OUTPUT_0; diff --git a/ArmPlatformPkg/Include/Drivers/PL061Gpio.h b/ArmPlatformPkg/Include/Drivers/PL061Gpio.h index 38458f4..8fde2bb 100644 --- a/ArmPlatformPkg/Include/Drivers/PL061Gpio.h +++ b/ArmPlatformPkg/Include/Drivers/PL061Gpio.h @@ -19,6 +19,7 @@ #include // 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) @@ -46,9 +47,5 @@ // All bits low except one bit high, native bit length #define GPIO_PIN_MASK(Pin) (1UL << ((UINTN)(Pin))) -// All bits low except one bit high, restricted to 8 bits (i.e. ensures zeros above 8bits) -#define GPIO_PIN_MASK_HIGH_8BIT(Pin) (GPIO_PIN_MASK(Pin) && 0xFF) -// All bits high except one bit low, restricted to 8 bits (i.e. ensures zeros above 8bits) -#define GPIO_PIN_MASK_LOW_8BIT(Pin) ((~GPIO_PIN_MASK(Pin)) && 0xFF) #endif // __PL061_GPIO_H__