From patchwork Fri Oct 12 19:11:24 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roland Stigge X-Patchwork-Id: 1588081 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 2A37C3FC1A for ; Fri, 12 Oct 2012 19:14:38 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TMkf7-0000U2-SD; Fri, 12 Oct 2012 19:12:45 +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 1TMke9-0000Fs-GT for linux-arm-kernel@lists.infradead.org; Fri, 12 Oct 2012 19:11:47 +0000 Received: from rst-pc1.lan.work-microwave.de ([192.168.11.78]) (authenticated bits=0) by mail.work-microwave.de with ESMTP id q9CJBgQv008899 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 12 Oct 2012 20:11:42 +0100 Received: by rst-pc1.lan.work-microwave.de (Postfix, from userid 1000) id 0BD96AE06B; Fri, 12 Oct 2012 21:11:41 +0200 (CEST) From: Roland Stigge To: 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 Subject: [PATCH RFC 5/6 v3] gpio-lpc32xx: Add block GPIO API Date: Fri, 12 Oct 2012 21:11:24 +0200 Message-Id: <1350069085-13283-6-git-send-email-stigge@antcom.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1350069085-13283-1-git-send-email-stigge@antcom.de> References: <1350069085-13283-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: -4.0 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.1 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 | 78 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) --- linux-2.6.orig/drivers/gpio/gpio-lpc32xx.c +++ linux-2.6/drivers/gpio/gpio-lpc32xx.c @@ -297,6 +297,21 @@ static int lpc32xx_gpio_get_value_p3(str return __get_gpio_state_p3(group, pin); } +static unsigned lpc32xx_gpio_get_block_p3(struct gpio_chip *chip, unsigned 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 +319,14 @@ static int lpc32xx_gpi_get_value(struct return __get_gpi_state_p3(group, pin); } +static unsigned lpc32xx_gpi_get_block(struct gpio_chip *chip, unsigned 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 +374,26 @@ 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 mask, + unsigned 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 +409,30 @@ 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 mask, + unsigned 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 lpc32xx_gpo_get_block(struct gpio_chip *chip, unsigned 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 +507,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 +525,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 +543,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 +560,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 +578,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 +593,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,