From patchwork Wed Oct 17 12:31:38 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roland Stigge X-Patchwork-Id: 1605771 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 45D3DDFABE for ; Wed, 17 Oct 2012 12:43:27 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TOSvc-0005vF-De; Wed, 17 Oct 2012 12:40:52 +0000 Received: from mail.work-microwave.de ([62.245.205.51] helo=work-microwave.de) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TOSsM-00046F-GT for linux-arm-kernel@lists.infradead.org; Wed, 17 Oct 2012 12:37:34 +0000 Received: from rst-pc1.lan.work-microwave.de ([192.168.11.78]) (authenticated bits=0) by mail.work-microwave.de with ESMTP id q9HCbMqe025484 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 17 Oct 2012 13:37:23 +0100 Received: by rst-pc1.lan.work-microwave.de (Postfix, from userid 1000) id 9B224AE06B; Wed, 17 Oct 2012 14:37:22 +0200 (CEST) From: Roland Stigge To: gregkh@linuxfoundation.org, grant.likely@secretlab.ca, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, w.sang@pengutronix.de, jbe@pengutronix.de, plagnioj@jcrosoft.com, highguy@gmail.com, broonie@opensource.wolfsonmicro.com, daniel-gl@gmx.net, rmallon@gmail.com Subject: [PATCH RFC 06/15 v5] gpio-lpc32xx: Add block GPIO API Date: Wed, 17 Oct 2012 14:31:38 +0200 Message-Id: <1350477107-26512-7-git-send-email-stigge@antcom.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1350477107-26512-1-git-send-email-stigge@antcom.de> References: <1350477107-26512-1-git-send-email-stigge@antcom.de> X-FEAS-SYSTEM-WL: rst@work-microwave.de, 192.168.11.78 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.4 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Roland Stigge X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This patch adds block GPIO API support to the LPC32xx driver. Signed-off-by: Roland Stigge --- drivers/gpio/gpio-lpc32xx.c | 82 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) --- linux-2.6.orig/drivers/gpio/gpio-lpc32xx.c +++ linux-2.6/drivers/gpio/gpio-lpc32xx.c @@ -297,6 +297,22 @@ static int lpc32xx_gpio_get_value_p3(str return __get_gpio_state_p3(group, pin); } +static unsigned long lpc32xx_gpio_get_block_p3(struct gpio_chip *chip, + unsigned long mask) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + u32 bits = __raw_readl(group->gpio_grp->inp_state); + + /* In P3_INP_STATE, the 6 GPIOs are scattered over the register, + * rearranging to bits 0-5 + */ + bits >>= 10; + bits &= 0x401F; + bits |= (bits & 0x4000) >> 9; + + return bits & mask & 0x3F; +} + static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin) { struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); @@ -304,6 +320,15 @@ static int lpc32xx_gpi_get_value(struct return __get_gpi_state_p3(group, pin); } +static unsigned long lpc32xx_gpi_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + u32 bits = __raw_readl(group->gpio_grp->inp_state); + + return bits & mask; +} + static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin, int value) { @@ -351,6 +376,27 @@ static void lpc32xx_gpio_set_value_p3(st __set_gpio_level_p3(group, pin, value); } +static void lpc32xx_gpio_set_block_p3(struct gpio_chip *chip, + unsigned long mask, + unsigned long values) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + u32 set_bits = values & mask; + u32 clr_bits = ~values & mask; + + /* States of GPIO 0-5 start at bit 25 */ + set_bits <<= 25; + clr_bits <<= 25; + + /* Note: On LPC32xx, GPOs can only be set at once or cleared at once, + * but not set and cleared at once + */ + if (set_bits) + __raw_writel(set_bits, group->gpio_grp->outp_set); + if (clr_bits) + __raw_writel(clr_bits, group->gpio_grp->outp_clr); +} + static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin, int value) { @@ -366,6 +412,31 @@ static int lpc32xx_gpo_get_value(struct return __get_gpo_state_p3(group, pin); } +static void lpc32xx_gpo_set_block(struct gpio_chip *chip, unsigned long mask, + unsigned long values) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + u32 set_bits = values & mask; + u32 clr_bits = ~values & mask; + + /* Note: On LPC32xx, GPOs can only be set at once or cleared at once, + * but not set and cleared at once + */ + if (set_bits) + __raw_writel(set_bits, group->gpio_grp->outp_set); + if (clr_bits) + __raw_writel(clr_bits, group->gpio_grp->outp_clr); +} + +static unsigned long lpc32xx_gpo_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + u32 bits = __raw_readl(group->gpio_grp->outp_state); + + return bits & mask; +} + static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin) { if (pin < chip->ngpio) @@ -440,8 +511,10 @@ static struct lpc32xx_gpio_chip lpc32xx_ .label = "gpio_p0", .direction_input = lpc32xx_gpio_dir_input_p012, .get = lpc32xx_gpio_get_value_p012, + .get_block = lpc32xx_gpi_get_block, .direction_output = lpc32xx_gpio_dir_output_p012, .set = lpc32xx_gpio_set_value_p012, + .set_block = lpc32xx_gpo_set_block, .request = lpc32xx_gpio_request, .to_irq = lpc32xx_gpio_to_irq_p01, .base = LPC32XX_GPIO_P0_GRP, @@ -456,8 +529,10 @@ static struct lpc32xx_gpio_chip lpc32xx_ .label = "gpio_p1", .direction_input = lpc32xx_gpio_dir_input_p012, .get = lpc32xx_gpio_get_value_p012, + .get_block = lpc32xx_gpi_get_block, .direction_output = lpc32xx_gpio_dir_output_p012, .set = lpc32xx_gpio_set_value_p012, + .set_block = lpc32xx_gpo_set_block, .request = lpc32xx_gpio_request, .to_irq = lpc32xx_gpio_to_irq_p01, .base = LPC32XX_GPIO_P1_GRP, @@ -472,8 +547,10 @@ static struct lpc32xx_gpio_chip lpc32xx_ .label = "gpio_p2", .direction_input = lpc32xx_gpio_dir_input_p012, .get = lpc32xx_gpio_get_value_p012, + .get_block = lpc32xx_gpi_get_block, .direction_output = lpc32xx_gpio_dir_output_p012, .set = lpc32xx_gpio_set_value_p012, + .set_block = lpc32xx_gpo_set_block, .request = lpc32xx_gpio_request, .base = LPC32XX_GPIO_P2_GRP, .ngpio = LPC32XX_GPIO_P2_MAX, @@ -487,8 +564,10 @@ static struct lpc32xx_gpio_chip lpc32xx_ .label = "gpio_p3", .direction_input = lpc32xx_gpio_dir_input_p3, .get = lpc32xx_gpio_get_value_p3, + .get_block = lpc32xx_gpio_get_block_p3, .direction_output = lpc32xx_gpio_dir_output_p3, .set = lpc32xx_gpio_set_value_p3, + .set_block = lpc32xx_gpio_set_block_p3, .request = lpc32xx_gpio_request, .to_irq = lpc32xx_gpio_to_irq_gpio_p3, .base = LPC32XX_GPIO_P3_GRP, @@ -503,6 +582,7 @@ static struct lpc32xx_gpio_chip lpc32xx_ .label = "gpi_p3", .direction_input = lpc32xx_gpio_dir_in_always, .get = lpc32xx_gpi_get_value, + .get_block = lpc32xx_gpi_get_block, .request = lpc32xx_gpio_request, .to_irq = lpc32xx_gpio_to_irq_gpi_p3, .base = LPC32XX_GPI_P3_GRP, @@ -517,7 +597,9 @@ static struct lpc32xx_gpio_chip lpc32xx_ .label = "gpo_p3", .direction_output = lpc32xx_gpio_dir_out_always, .set = lpc32xx_gpo_set_value, + .set_block = lpc32xx_gpo_set_block, .get = lpc32xx_gpo_get_value, + .get_block = lpc32xx_gpo_get_block, .request = lpc32xx_gpio_request, .base = LPC32XX_GPO_P3_GRP, .ngpio = LPC32XX_GPO_P3_MAX,