From patchwork Tue Dec 19 09:40:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ludovic Desroches X-Patchwork-Id: 10122885 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 78A4F603B5 for ; Tue, 19 Dec 2017 09:42:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 652AF291CB for ; Tue, 19 Dec 2017 09:42:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 57CC1291CD; Tue, 19 Dec 2017 09:42:27 +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=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=ham 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 90FE5291CB for ; Tue, 19 Dec 2017 09:42:26 +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:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version: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=4FL/DxPGv8JkqWIkwyzQserRh7/ixS32Uz8IoygcCjk=; b=OEpAapPJsXBFeJ tSvbhKTfKRk1Qri/XuxWEvVTNFil/yJYhTPeOZBpjktTPD4loXLl0llavgNh4WmqOYWVLQd2Mppoh DmgdajUA3EpMHAdniaImztLLuMTqPIO5TrvrszW8l+ootCRseeQOkxUvT6CBYkmQ2e1HqtIFnI/wJ NC8BosDhw0YyFU4XJJtcsPi3TAP5qvX0IMHEzmvP4YTdQykL+e+448rt7CITrgxb6PZHsoIaKhua4 exJpvGQRwLmh6/5ni4cWpYk4bYP4B4YKvwMBc06d6ApQccLEZw1wW42sKpp9ZM28DZzJPJddQCY7o mKr1XEIux04ZjBaY/ihw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1eREPl-0005Tb-Q8; Tue, 19 Dec 2017 09:42:21 +0000 Received: from esa5.microchip.iphmx.com ([216.71.150.166]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1eREPe-0005S7-3H for linux-arm-kernel@lists.infradead.org; Tue, 19 Dec 2017 09:42:19 +0000 X-IronPort-AV: E=Sophos;i="5.45,425,1508828400"; d="scan'208";a="7513168" Received: from exsmtp01.microchip.com (HELO email.microchip.com) ([198.175.253.37]) by esa5.microchip.iphmx.com with ESMTP/TLS/AES128-SHA; 19 Dec 2017 02:42:02 -0700 Received: from ibiza.rfo.atmel.com (10.10.76.4) by CHN-SV-EXCH01.mchp-main.com (10.10.76.37) with Microsoft SMTP Server id 14.3.352.0; Tue, 19 Dec 2017 02:42:01 -0700 From: Ludovic Desroches To: , Subject: [RFC PATCH v2] draft for gpio pinconf Date: Tue, 19 Dec 2017 10:40:25 +0100 Message-ID: <20171219094025.6151-1-ludovic.desroches@microchip.com> X-Mailer: git-send-email 2.12.2 In-Reply-To: <20171214142138.23008-1-ludovic.desroches@microchip.com> References: <20171214142138.23008-1-ludovic.desroches@microchip.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171219_014214_172701_278726C5 X-CRM114-Status: GOOD ( 20.92 ) 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: Ludovic Desroches 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 Signed-off-by: Ludovic Desroches --- Hi, After discussing with Maxime Ripard, I realize that the first approach may not be a good one. For instance, the drive-strength is a digital value so it will take ake several bits. Having a whole pin configuration in 32 bits may not be the right solution. My aim is to use the existing pinconf bindings. This patch is a draft to test the feasibility. Sorry to provide it in this state (several ugly hacks) but I didn't want to spend time on a clean solution if it will be rejected. arch/arm/boot/dts/at91-sama5d2_xplained.dts | 6 +----- arch/arm/boot/dts/sama5d2.dtsi | 2 +- drivers/gpio/gpiolib-of.c | 10 +++++++++- drivers/gpio/gpiolib.c | 24 +++++++++++++++++++----- drivers/gpio/gpiolib.h | 2 ++ drivers/pinctrl/core.c | 5 ++--- drivers/pinctrl/pinctrl-at91-pio4.c | 19 +++++++++++++++++++ include/linux/gpio/driver.h | 5 +++-- include/linux/pinctrl/consumer.h | 4 ++-- 9 files changed, 58 insertions(+), 19 deletions(-) diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts index 56de21de2779..709c9c3ae622 100644 --- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts @@ -413,7 +413,6 @@ }; pinctrl_key_gpio_default: key_gpio_default { - pinmux = ; bias-pull-up; }; @@ -545,12 +544,9 @@ gpio_keys { compatible = "gpio-keys"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_key_gpio_default>; - bp1 { label = "PB_USER"; - gpios = <&pioA PIN_PB9 GPIO_ACTIVE_LOW>; + gpios = <&pioA PIN_PB9 GPIO_ACTIVE_LOW &pinctrl_key_gpio_default>; linux,code = <0x104>; wakeup-source; }; diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index b44e63995583..cccd404192cc 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -1444,7 +1444,7 @@ interrupt-controller; #interrupt-cells = <2>; gpio-controller; - #gpio-cells = <2>; + #gpio-cells = <3>; clocks = <&pioA_clk>; }; diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 4a2b8d3397c7..605017a4d2d8 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -46,7 +46,7 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, { int ret; - if (chip->of_gpio_n_cells != gpiospec->args_count) + if (chip->of_gpio_n_cells > gpiospec->args_count) return ERR_PTR(-EINVAL); ret = chip->of_xlate(chip, gpiospec, flags); @@ -93,6 +93,14 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, if (IS_ERR(desc)) goto out; + if (gpiospec.args_count > chip->of_gpio_n_cells) { + desc->np_pincfg = of_parse_phandle(np, propname, gpiospec.args_count); + if (!desc->np_pincfg) { + printk("ERROR\n"); + goto out; + } + } + pr_debug("%s: parsed '%s' property of node '%pOF[%d]' - status (%d)\n", __func__, propname, np, index, PTR_ERR_OR_ZERO(desc)); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 0621baddfddc..543a120a0f84 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -29,6 +29,8 @@ #include #include "gpiolib.h" +#include "../pinctrl/core.h" +#include "../pinctrl/pinconf.h" #define CREATE_TRACE_POINTS #include @@ -1997,9 +1999,9 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_free); * @config: the configuration to be applied */ int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset, - unsigned long config) + unsigned long *configs, unsigned num_configs) { - return pinctrl_gpio_set_config(chip->gpiodev->base + offset, config); + return pinctrl_gpio_set_config(chip->gpiodev->base + offset, configs, num_configs); } EXPORT_SYMBOL_GPL(gpiochip_generic_config); @@ -2161,6 +2163,18 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) goto done; } } + if (chip->set_config) { + unsigned long *configs; + unsigned num_configs; + int ret; + + ret = pinconf_generic_parse_dt_config(desc->np_pincfg, NULL, &configs, &num_configs); + if (ret < 0) { + /* TODO */ + } + chip->set_config(chip, gpio_chip_hwgpio(desc), configs, num_configs); + kfree(configs); + } if (chip->get_direction) { /* chip->get_direction may sleep */ spin_unlock_irqrestore(&gpio_lock, flags); @@ -2404,7 +2418,7 @@ static int gpio_set_drive_single_ended(struct gpio_chip *gc, unsigned offset, { unsigned long config = { PIN_CONF_PACKED(mode, 0) }; - return gc->set_config ? gc->set_config(gc, offset, config) : -ENOTSUPP; + return gc->set_config ? gc->set_config(gc, offset, &config, 1) : -ENOTSUPP; } static int gpiod_direction_output_raw_commit(struct gpio_desc *desc, int value) @@ -2529,7 +2543,7 @@ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) } config = pinconf_to_config_packed(PIN_CONFIG_INPUT_DEBOUNCE, debounce); - return chip->set_config(chip, gpio_chip_hwgpio(desc), config); + return chip->set_config(chip, gpio_chip_hwgpio(desc), &config, 1); } EXPORT_SYMBOL_GPL(gpiod_set_debounce); @@ -2565,7 +2579,7 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory) packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE, !transitory); gpio = gpio_chip_hwgpio(desc); - rc = chip->set_config(chip, gpio, packed); + rc = chip->set_config(chip, gpio, &packed, 1); if (rc == -ENOTSUPP) { dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO %d\n", gpio); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 5e1f7cc6eeb6..79119548cc33 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -215,6 +215,8 @@ struct gpio_desc { const char *label; /* Name of the GPIO */ const char *name; + /* Pin configuration node */ + struct device_node *np_pincfg; }; int gpiod_request(struct gpio_desc *desc, const char *label); diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 4c8d5b23e4d0..89976f35a6a3 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -857,9 +857,8 @@ EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output); * they need to call the underlying pin controller to change GPIO config * (for example set debounce time). */ -int pinctrl_gpio_set_config(unsigned gpio, unsigned long config) +int pinctrl_gpio_set_config(unsigned gpio, unsigned long *configs, unsigned num_configs) { - unsigned long configs[] = { config }; struct pinctrl_gpio_range *range; struct pinctrl_dev *pctldev; int ret, pin; @@ -870,7 +869,7 @@ int pinctrl_gpio_set_config(unsigned gpio, unsigned long config) mutex_lock(&pctldev->mutex); pin = gpio_to_pin(range, gpio); - ret = pinconf_set_config(pctldev, pin, configs, ARRAY_SIZE(configs)); + ret = pinconf_set_config(pctldev, pin, configs, num_configs); mutex_unlock(&pctldev->mutex); return ret; diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index b1ca838dd80a..477a4d7ddbaf 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -358,12 +358,15 @@ static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset) } static struct gpio_chip atmel_gpio_chip = { + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, .direction_input = atmel_gpio_direction_input, .get = atmel_gpio_get, .direction_output = atmel_gpio_direction_output, .set = atmel_gpio_set, .to_irq = atmel_gpio_to_irq, .base = 0, + .set_config = gpiochip_generic_config, }; /* --- PINCTRL --- */ @@ -643,11 +646,26 @@ static int atmel_pmx_set_mux(struct pinctrl_dev *pctldev, return 0; } +static int atmel_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset) +{ + u32 conf; + + conf = atmel_pin_config_read(pctldev, offset); + conf &= (~ATMEL_PIO_CFGR_FUNC_MASK); + atmel_pin_config_write(pctldev, offset, conf); + + dev_dbg(pctldev->dev, "enable pin %u as GPIO\n", offset); + + return 0; +} + static const struct pinmux_ops atmel_pmxops = { + .gpio_request_enable = atmel_pmx_gpio_request_enable, .get_functions_count = atmel_pmx_get_functions_count, .get_function_name = atmel_pmx_get_function_name, .get_function_groups = atmel_pmx_get_function_groups, .set_mux = atmel_pmx_set_mux, + .strict = true, }; static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev, @@ -817,6 +835,7 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev, } static const struct pinconf_ops atmel_confops = { + .pin_config_set = atmel_conf_pin_config_group_set, .pin_config_group_get = atmel_conf_pin_config_group_get, .pin_config_group_set = atmel_conf_pin_config_group_set, .pin_config_dbg_show = atmel_conf_pin_config_dbg_show, diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 55e672592fa9..b54968cd6dfc 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -247,7 +247,8 @@ struct gpio_chip { unsigned long *bits); int (*set_config)(struct gpio_chip *chip, unsigned offset, - unsigned long config); + unsigned long *configs, + unsigned num_configs); int (*to_irq)(struct gpio_chip *chip, unsigned offset); @@ -490,7 +491,7 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip, int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset); void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset); int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset, - unsigned long config); + unsigned long *configs, unsigned num_configs); #ifdef CONFIG_PINCTRL diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h index 0412cc9833e9..14be53e1e053 100644 --- a/include/linux/pinctrl/consumer.h +++ b/include/linux/pinctrl/consumer.h @@ -29,7 +29,7 @@ extern int pinctrl_gpio_request(unsigned gpio); extern void pinctrl_gpio_free(unsigned gpio); extern int pinctrl_gpio_direction_input(unsigned gpio); extern int pinctrl_gpio_direction_output(unsigned gpio); -extern int pinctrl_gpio_set_config(unsigned gpio, unsigned long config); +extern int pinctrl_gpio_set_config(unsigned gpio, unsigned long *configs, unsigned num_configs); extern struct pinctrl * __must_check pinctrl_get(struct device *dev); extern void pinctrl_put(struct pinctrl *p); @@ -81,7 +81,7 @@ static inline int pinctrl_gpio_direction_output(unsigned gpio) return 0; } -static inline int pinctrl_gpio_set_config(unsigned gpio, unsigned long config) +static inline int pinctrl_gpio_set_config(unsigned gpio, unsigned long *configs, unsigned num_configs) { return 0; }