From patchwork Thu Mar 23 15:19:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregory CLEMENT X-Patchwork-Id: 9641481 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 20E7C602CA for ; Thu, 23 Mar 2017 15:20:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1200F275A2 for ; Thu, 23 Mar 2017 15:20:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 06D0826E91; Thu, 23 Mar 2017 15:20:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4BBB6275A2 for ; Thu, 23 Mar 2017 15:20:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=pWvoyHkSMmtIxscM2E8E3m5evSEJfG4PunofExrcQto=; b=LVA+bgMeSFN6j2zVM94ddnUuT8 31XznQcGg1KEqki7zYUwE5mA4u2/mK996L8lnk8HTiH/yJDnZpacNWQPsVOi1fUE0lFAhAZcyWWfF D1RbdR/sg1rPXQ/G6Pae6YPXbqng8nBJydm84W5edUtTAf/kfJgeegKZB3UG5fTkvzFY66p0hsWGK 84AJZaJ8YByElD/dmrwTkw+S8YoUFVWYDM7rDhEBwC0y3ZnnxDsX/EO2coM3dFh17Ysl0PyMD4MMS dRu1gNXRzAR61V6zmVXHcNfBzxOqaGVj6QgPklOK2+fIYT020pqM7/fDWF4t/gJClyIB42jEvaro1 cpoVf+BA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cr4XU-0003e3-Du; Thu, 23 Mar 2017 15:20:36 +0000 Received: from mail.free-electrons.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cr4WZ-0001Mm-BB for linux-arm-kernel@lists.infradead.org; Thu, 23 Mar 2017 15:19:44 +0000 Received: by mail.free-electrons.com (Postfix, from userid 110) id 38D9F20D20; Thu, 23 Mar 2017 16:19:19 +0100 (CET) Received: from localhost (83.146.29.93.rev.sfr.net [93.29.146.83]) by mail.free-electrons.com (Postfix) with ESMTPSA id 0C72F2078A; Thu, 23 Mar 2017 16:19:19 +0100 (CET) From: Gregory CLEMENT To: Linus Walleij , linux-gpio@vger.kernel.org Subject: [PATCH v3 4/7] pinctrl: armada-37xx: Add gpio support Date: Thu, 23 Mar 2017 16:19:04 +0100 Message-Id: <33b78632f0f461f353dffbc75a80a2a9673fb0a6.1490282185.git-series.gregory.clement@free-electrons.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170323_081939_769491_F266D3AA X-CRM114-Status: GOOD ( 17.39 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Petazzoni , Andrew Lunn , Hua Jing , Jason Cooper , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Nadav Haklai , Rob Herring , Neta Zur Hershkovits , Gregory CLEMENT , Victor Gu , Marcin Wojtas , Wilson Ding , linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP GPIO management is pretty simple and is part of the same IP than the pin controller for the Armada 37xx SoCs. This patch adds the GPIO support to the pinctrl-armada-37xx.c file, it also allows sharing common functions between the gpiolib and the pinctrl drivers. Signed-off-by: Gregory CLEMENT --- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 127 ++++++++++++++++++--- 1 file changed, 113 insertions(+), 14 deletions(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index f2ff9801d0f4..31e921aa2f86 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -10,6 +10,7 @@ * without any warranty of any kind, whether express or implied. */ +#include #include #include #include @@ -24,6 +25,8 @@ #include "../pinctrl-utils.h" #define OUTPUT_EN 0x0 +#define INPUT_VAL 0x10 +#define OUTPUT_VAL 0x18 #define OUTPUT_CTL 0x20 #define SELECTION 0x30 @@ -73,6 +76,7 @@ struct armada_37xx_pinctrl { struct regmap *regmap; struct armada_37xx_pin_data *data; struct device *dev; + struct gpio_chip gpio_chip; struct pinctrl_desc pctl; struct pinctrl_dev *pctl_dev; struct armada_37xx_pin_group *groups; @@ -310,51 +314,99 @@ static int armada_37xx_pmx_set(struct pinctrl_dev *pctldev, return armada_37xx_pmx_set_by_name(pctldev, name, grp); } -static int armada_37xx_pmx_direction_input(struct armada_37xx_pinctrl *info, - unsigned int offset) +static inline void aramda_37xx_update_reg(unsigned int *reg, + unsigned int offset) { - unsigned int reg = OUTPUT_EN; - unsigned int mask; - + /* We never have more than 2 registers */ if (offset >= GPIO_PER_REG) { offset -= GPIO_PER_REG; - reg += sizeof(u32); + *reg += sizeof(u32); } +} + +static int armada_37xx_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct armada_37xx_pinctrl *info = gpiochip_get_data(chip); + unsigned int reg = OUTPUT_EN; + unsigned int mask; + + aramda_37xx_update_reg(®, offset); mask = BIT(offset); return regmap_update_bits(info->regmap, reg, mask, 0); } +static int armada_37xx_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + struct armada_37xx_pinctrl *info = gpiochip_get_data(chip); + unsigned int reg = OUTPUT_EN; + unsigned int val, mask; + + aramda_37xx_update_reg(®, offset); + mask = BIT(offset); + + regmap_read(info->regmap, reg, &val); + return !(val & mask); +} -static int armada_37xx_pmx_direction_output(struct armada_37xx_pinctrl *info, - unsigned int offset, int value) +static int armada_37xx_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) { + struct armada_37xx_pinctrl *info = gpiochip_get_data(chip); unsigned int reg = OUTPUT_EN; unsigned int mask; - if (offset >= GPIO_PER_REG) { - offset -= GPIO_PER_REG; - reg += sizeof(u32); - } + aramda_37xx_update_reg(®, offset); mask = BIT(offset); return regmap_update_bits(info->regmap, reg, mask, mask); } +static int armada_37xx_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct armada_37xx_pinctrl *info = gpiochip_get_data(chip); + unsigned int reg = INPUT_VAL; + unsigned int val, mask; + + aramda_37xx_update_reg(®, offset); + mask = BIT(offset); + + regmap_read(info->regmap, reg, &val); + + return (val & mask) != 0; +} + +static void armada_37xx_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct armada_37xx_pinctrl *info = gpiochip_get_data(chip); + unsigned int reg = OUTPUT_VAL; + unsigned int mask, val; + + aramda_37xx_update_reg(®, offset); + mask = BIT(offset); + val = value ? mask : 0; + + regmap_update_bits(info->regmap, reg, mask, val); +} + static int armada_37xx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned int offset, bool input) { struct armada_37xx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); + struct gpio_chip *chip = range->gc; dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n", offset, range->name, offset, input ? "input" : "output"); if (input) - armada_37xx_pmx_direction_input(info, offset); + armada_37xx_gpio_direction_input(chip, offset); else - armada_37xx_pmx_direction_output(info, offset, 0); + armada_37xx_gpio_direction_output(chip, offset, 0); return 0; } @@ -384,6 +436,49 @@ static const struct pinmux_ops armada_37xx_pmx_ops = { .gpio_set_direction = armada_37xx_pmx_gpio_set_direction, }; +static const struct gpio_chip armada_37xx_gpiolib_chip = { + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, + .set = armada_37xx_gpio_set, + .get = armada_37xx_gpio_get, + .get_direction = armada_37xx_gpio_get_direction, + .direction_input = armada_37xx_gpio_direction_input, + .direction_output = armada_37xx_gpio_direction_output, + .owner = THIS_MODULE, +}; + +static int armada_37xx_gpiochip_register(struct platform_device *pdev, + struct armada_37xx_pinctrl *info) +{ + struct device_node *np; + struct gpio_chip *gc; + int ret = -ENODEV; + + for_each_child_of_node(info->dev->of_node, np) { + if (of_find_property(np, "gpio-controller", NULL)) { + ret = 0; + break; + } + }; + if (ret) + return ret; + + info->gpio_chip = armada_37xx_gpiolib_chip; + + gc = &info->gpio_chip; + gc->ngpio = info->data->nr_pins; + gc->parent = &pdev->dev; + gc->base = -1; + gc->of_node = np; + gc->label = info->data->name; + + ret = gpiochip_add_data(gc, info); + if (ret) + return ret; + + return 0; +} + static int armada_37xx_add_function(struct armada_37xx_pmx_func *funcs, int *funcsize, const char *name) { @@ -586,6 +681,10 @@ static int armada_37xx_pinctrl_probe(struct platform_device *pdev) if (ret) return ret; + ret = armada_37xx_gpiochip_register(pdev, info); + if (ret) + return ret; + platform_set_drvdata(pdev, info); return 0;