Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1561092 > unrolled thread

[PATCH 00/13] Ingenic JZ4740 / JZ4780 pinctrl driver

Started byPaul Cercueil <paul@crapouillou.net>
First post2017-01-18 00:20 +0100
Last post2017-01-19 07:50 +0100
Articles 18 on this page of 78 — 8 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 00/13] Ingenic JZ4740 / JZ4780 pinctrl driver Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
    [PATCH 04/13] MIPS: ingenic: Enable pinctrl for all ingenic SoCs Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
    [PATCH 10/13] mtd: nand: jz4740: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
      Re: [PATCH 10/13] mtd: nand: jz4740: Let the pinctrl driver  configure the pins Boris Brezillon <boris.brezillon@free-electrons.com> - 2017-01-27 18:40 +0100
    [PATCH 11/13] fbdev: jz4740-fb: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
    [PATCH 08/13] MIPS: JZ4780: CI20: Add pinctrl configuration for several drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
    [PATCH 07/13] MIPS: JZ4740: Qi LB60: Add pinctrl configuration for several drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
    [PATCH 03/13] pinctrl-jz4780: add a pinctrl driver for the Ingenic jz4780 SoC Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
    [PATCH 02/13] pinctrl-jz4740: add a pinctrl driver for the Ingenic jz4740 SoC Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
      Re: [PATCH 02/13] pinctrl-jz4740: add a pinctrl driver for the  Ingenic jz4740 SoC Linus Walleij <linus.walleij@linaro.org> - 2017-01-18 11:20 +0100
    [PATCH 13/13] MIPS: jz4740: Remove custom GPIO code Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
      Re: [PATCH 13/13] MIPS: jz4740: Remove custom GPIO code Thierry Reding <thierry.reding@gmail.com> - 2017-01-18 08:30 +0100
        Re: [PATCH 13/13] MIPS: jz4740: Remove custom GPIO code Paul Cercueil <paul@crapouillou.net> - 2017-01-19 12:30 +0100
      Re: [PATCH 13/13] MIPS: jz4740: Remove custom GPIO code Linus Walleij <linus.walleij@linaro.org> - 2017-01-19 10:10 +0100
        Re: [PATCH 13/13] MIPS: jz4740: Remove custom GPIO code Paul Cercueil <paul@crapouillou.net> - 2017-01-20 11:10 +0100
    [PATCH 05/13] MIPS: jz4740: DTS: Add node for the jz4740-pinctrl driver Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
      Re: [PATCH 05/13] MIPS: jz4740: DTS: Add node for the jz4740-pinctrl driver Linus Walleij <linus.walleij@linaro.org> - 2017-01-19 01:10 +0100
    [PATCH 09/13] mmc: jz4740: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-18 00:20 +0100
      Re: [PATCH 09/13] mmc: jz4740: Let the pinctrl driver configure the pins Ulf Hansson <ulf.hansson@linaro.org> - 2017-01-19 12:00 +0100
        Re: [PATCH 09/13] mmc: jz4740: Let the pinctrl driver configure the  pins Paul Cercueil <paul@crapouillou.net> - 2017-01-20 13:00 +0100
    Re: [PATCH 00/13] Ingenic JZ4740 / JZ4780 pinctrl driver Thierry Reding <thierry.reding@gmail.com> - 2017-01-18 08:20 +0100
      Re: [PATCH 00/13] Ingenic JZ4740 / JZ4780 pinctrl driver Paul Cercueil <paul@crapouillou.net> - 2017-01-19 12:20 +0100
        Re: [PATCH 00/13] Ingenic JZ4740 / JZ4780 pinctrl driver Linus Walleij <linus.walleij@linaro.org> - 2017-01-20 09:50 +0100
          Re: [PATCH 00/13] Ingenic JZ4740 / JZ4780 pinctrl driver Paul Cercueil <paul@crapouillou.net> - 2017-01-20 11:20 +0100
        [PATCH v2 09/14] MIPS: JZ4780: CI20: Add pinctrl configuration for several drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
        [PATCH v2 10/14] mmc: jz4740: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
          Re: [PATCH v2 10/14] mmc: jz4740: Let the pinctrl driver configure  the pins Ulf Hansson <ulf.hansson@linaro.org> - 2017-01-23 11:50 +0100
        [PATCH v2 04/14] GPIO: Add gpio-ingenic driver Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
          [PATCH] GPIO: fix semicolon.cocci warnings kbuild test robot <lkp@intel.com> - 2017-01-22 19:00 +0100
          Re: [PATCH v2 04/14] GPIO: Add gpio-ingenic driver kbuild test robot <lkp@intel.com> - 2017-01-22 19:00 +0100
        [PATCH v2 06/14] MIPS: jz4740: DTS: Add nodes for ingenic pinctrl and gpio drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
        [PATCH v2 03/14] pinctrl-ingenic: add a pinctrl driver for the Ingenic jz47xx SoCs Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
        [PATCH v2 08/14] MIPS: JZ4740: Qi LB60: Add pinctrl configuration for several drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
        [PATCH v2 13/14] pwm: jz4740: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
        [PATCH v2 01/14] Documentation: dt/bindings: Document pinctrl-ingenic Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
          Re: [PATCH v2 01/14] Documentation: dt/bindings: Document pinctrl-ingenic Linus Walleij <linus.walleij@linaro.org> - 2017-01-27 13:00 +0100
            Re: [PATCH v2 01/14] Documentation: dt/bindings: Document  pinctrl-ingenic Paul Cercueil <paul@crapouillou.net> - 2017-01-27 16:40 +0100
              Re: [PATCH v2 01/14] Documentation: dt/bindings: Document pinctrl-ingenic Linus Walleij <linus.walleij@linaro.org> - 2017-01-31 14:00 +0100
        [PATCH v2 05/14] MIPS: ingenic: Enable pinctrl for all ingenic SoCs Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
        [PATCH v2 07/14] MIPS: jz4780: DTS: Add nodes for ingenic pinctrl and gpio drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
        [PATCH v2 00/14] Ingenic JZ4740 / JZ4780 pinctrl driver Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
          [PATCH v2 14/14] MIPS: jz4740: Remove custom GPIO code Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
          [PATCH v2 02/14] Documentation: dt/bindings: Document pinctrl-gpio Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
          [PATCH v2 11/14] mtd: nand: jz4740: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
          [PATCH v2 12/14] fbdev: jz4740-fb: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-22 16:00 +0100
        [PATCH v3 00/14] Ingenic JZ4740 / JZ4780 pinctrl driver Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
          [PATCH v3 06/14] MIPS: jz4740: DTS: Add nodes for ingenic pinctrl and gpio drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
            Re: [PATCH v3 06/14] MIPS: jz4740: DTS: Add nodes for ingenic pinctrl  and gpio drivers Linus Walleij <linus.walleij@linaro.org> - 2017-01-31 15:20 +0100
          [PATCH v3 01/14] Documentation: dt/bindings: Document pinctrl-ingenic Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
            Re: [PATCH v3 01/14] Documentation: dt/bindings: Document  pinctrl-ingenic Rob Herring <robh@kernel.org> - 2017-01-30 21:40 +0100
              Re: [PATCH v3 01/14] Documentation: dt/bindings: Document  pinctrl-ingenic Paul Cercueil <paul@crapouillou.net> - 2017-01-31 11:40 +0100
                Re: [PATCH v3 01/14] Documentation: dt/bindings: Document pinctrl-ingenic Linus Walleij <linus.walleij@linaro.org> - 2017-01-31 14:20 +0100
                  Re: [PATCH v3 01/14] Documentation: dt/bindings: Document  pinctrl-ingenic Paul Cercueil <paul@crapouillou.net> - 2017-02-09 18:30 +0100
          [PATCH v3 09/14] MIPS: JZ4780: CI20: Add pinctrl configuration for several drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
          [PATCH v3 14/14] MIPS: jz4740: Remove custom GPIO code Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
          [PATCH v3 07/14] MIPS: jz4780: DTS: Add nodes for ingenic pinctrl and gpio drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
          [PATCH v3 11/14] mtd: nand: jz4740: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
          [PATCH v3 05/14] MIPS: ingenic: Enable pinctrl for all ingenic SoCs Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
          [PATCH v3 08/14] MIPS: JZ4740: Qi LB60: Add pinctrl configuration for several drivers Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
          [PATCH v3 13/14] pwm: jz4740: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
          [PATCH v3 02/14] Documentation: dt/bindings: Document pinctrl-gpio Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
            Re: [PATCH v3 02/14] Documentation: dt/bindings: Document  pinctrl-gpio Rob Herring <robh@kernel.org> - 2017-01-30 21:40 +0100
          [PATCH v3 10/14] mmc: jz4740: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
            Re: [PATCH v3 10/14] mmc: jz4740: Let the pinctrl driver configure  the pins kbuild test robot <lkp@intel.com> - 2017-01-26 07:20 +0100
              Re: [PATCH v3 10/14] mmc: jz4740: Let the pinctrl driver configure  the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-26 11:20 +0100
          [PATCH v3 04/14] GPIO: Add gpio-ingenic driver Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
            Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver Linus Walleij <linus.walleij@linaro.org> - 2017-01-31 15:30 +0100
              Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver Paul Cercueil <paul@crapouillou.net> - 2017-02-09 18:20 +0100
                Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver Linus Walleij <linus.walleij@linaro.org> - 2017-02-12 21:50 +0100
            Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver Linus Walleij <linus.walleij@linaro.org> - 2017-01-31 15:30 +0100
              Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver Paul Cercueil <paul@crapouillou.net> - 2017-01-31 16:40 +0100
                Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver Linus Walleij <linus.walleij@linaro.org> - 2017-02-03 15:00 +0100
          [PATCH v3 12/14] fbdev: jz4740-fb: Let the pinctrl driver configure the pins Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
            Re: [PATCH v3 12/14] fbdev: jz4740-fb: Let the pinctrl driver  configure the pins Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> - 2017-01-30 17:50 +0100
          [PATCH v3 03/14] pinctrl-ingenic: add a pinctrl driver for the Ingenic jz47xx SoCs Paul Cercueil <paul@crapouillou.net> - 2017-01-25 20:00 +0100
            Re: [PATCH v3 03/14] pinctrl-ingenic: add a pinctrl driver for the  Ingenic jz47xx SoCs Linus Walleij <linus.walleij@linaro.org> - 2017-01-31 15:10 +0100
              Re: [PATCH v3 03/14] pinctrl-ingenic: add a pinctrl driver for the  Ingenic jz47xx SoCs Paul Cercueil <paul@crapouillou.net> - 2017-01-31 15:20 +0100
    Re: [PATCH 00/13] Ingenic JZ4740 / JZ4780 pinctrl driver Linus Walleij <linus.walleij@linaro.org> - 2017-01-19 07:50 +0100

Page 4 of 4 — ← Prev page 1 2 3 [4]


#1566858 — [PATCH v3 02/14] Documentation: dt/bindings: Document pinctrl-gpio

FromPaul Cercueil <paul@crapouillou.net>
Date2017-01-25 20:00 +0100
Subject[PATCH v3 02/14] Documentation: dt/bindings: Document pinctrl-gpio
Message-ID<t3AXw-5pP-33@gated-at.bofh.it>
In reply to#1566846
This commit adds documentation for the devicetree bidings of the
pinctrl-gpio driver, which handles GPIOs of the Ingenic SoCs
currently supported by the Linux kernel.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 .../devicetree/bindings/gpio/ingenic,gpio.txt      | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/ingenic,gpio.txt

v2: New patch
v3: No changes

diff --git a/Documentation/devicetree/bindings/gpio/ingenic,gpio.txt b/Documentation/devicetree/bindings/gpio/ingenic,gpio.txt
new file mode 100644
index 000000000000..b2eb20494365
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/ingenic,gpio.txt
@@ -0,0 +1,45 @@
+Ingenic jz47xx GPIO controller
+
+Required properties:
+  - compatible:
+    - "ingenic,jz4740-gpio" for the JZ4740 SoC
+    - "ingenic,jz4780-gpio" for the JZ4780 SoC
+
+  - reg: Base address and length of each memory resource used by the GPIO
+    controller hardware module.
+
+  - gpio-controller: Marks the device node as a GPIO controller.
+  - #gpio-cells: Should be 2. The first cell is the GPIO number and the second
+    cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
+    GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
+  - gpio-ranges: Range of pins managed by the GPIO controller.
+
+Optional properties:
+  - base: The GPIO number to use as the base for this driver.
+  - interrupt-controller: Marks the device node as an interrupt controller.
+  - interrupts: Interrupt specifier for the controllers interrupt.
+    Required if 'interrupt-controller' is specified.
+
+Please refer to gpio.txt in this directory for details of gpio-ranges property
+and the common GPIO bindings used by client devices.
+
+The GPIO controller also acts as an interrupt controller. It uses the default
+two cells specifier as described in Documentation/devicetree/bindings/
+interrupt-controller/interrupts.txt.
+
+Example:
+
+gpa: gpio-controller@10010000 {
+	compatible = "ingenic,jz4740-gpio";
+	reg = <0x10010000 0x100>;
+
+	gpio-controller;
+	gpio-ranges = <&pinctrl 0 0 32>;
+	#gpio-cells = <2>;
+
+	interrupt-controller;
+	#interrupt-cells = <2>;
+
+	interrupt-parent = <&intc>;
+	interrupts = <28>;
+};
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1570107 — Re: [PATCH v3 02/14] Documentation: dt/bindings: Document pinctrl-gpio

FromRob Herring <robh@kernel.org>
Date2017-01-30 21:40 +0100
SubjectRe: [PATCH v3 02/14] Documentation: dt/bindings: Document pinctrl-gpio
Message-ID<t5qU1-4V-15@gated-at.bofh.it>
In reply to#1566858
On Wed, Jan 25, 2017 at 07:51:55PM +0100, Paul Cercueil wrote:
> This commit adds documentation for the devicetree bidings of the

s/biding/bindings/

> pinctrl-gpio driver, which handles GPIOs of the Ingenic SoCs
> currently supported by the Linux kernel.

The subject makes no reference that this binding is for Ingenic GPIO. 
Also, drop the "Documentation: " part. It's redundant.

> 
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
>  .../devicetree/bindings/gpio/ingenic,gpio.txt      | 45 ++++++++++++++++++++++
>  1 file changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/ingenic,gpio.txt
> 
> v2: New patch
> v3: No changes
> 
> diff --git a/Documentation/devicetree/bindings/gpio/ingenic,gpio.txt b/Documentation/devicetree/bindings/gpio/ingenic,gpio.txt
> new file mode 100644
> index 000000000000..b2eb20494365
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/gpio/ingenic,gpio.txt
> @@ -0,0 +1,45 @@
> +Ingenic jz47xx GPIO controller
> +
> +Required properties:
> +  - compatible:
> +    - "ingenic,jz4740-gpio" for the JZ4740 SoC
> +    - "ingenic,jz4780-gpio" for the JZ4780 SoC
> +
> +  - reg: Base address and length of each memory resource used by the GPIO
> +    controller hardware module.
> +
> +  - gpio-controller: Marks the device node as a GPIO controller.
> +  - #gpio-cells: Should be 2. The first cell is the GPIO number and the second
> +    cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
> +    GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
> +  - gpio-ranges: Range of pins managed by the GPIO controller.
> +
> +Optional properties:
> +  - base: The GPIO number to use as the base for this driver.

Drop this please. This is a Linuxism.

> +  - interrupt-controller: Marks the device node as an interrupt controller.
> +  - interrupts: Interrupt specifier for the controllers interrupt.
> +    Required if 'interrupt-controller' is specified.

Some h/w doesn't have interrupt capability? If not, this should not be 
optional.

> +
> +Please refer to gpio.txt in this directory for details of gpio-ranges property
> +and the common GPIO bindings used by client devices.
> +
> +The GPIO controller also acts as an interrupt controller. It uses the default
> +two cells specifier as described in Documentation/devicetree/bindings/
> +interrupt-controller/interrupts.txt.

Just document #interrupt-cells and its value and drop this paragraph.

> +
> +Example:
> +
> +gpa: gpio-controller@10010000 {
> +	compatible = "ingenic,jz4740-gpio";
> +	reg = <0x10010000 0x100>;
> +
> +	gpio-controller;
> +	gpio-ranges = <&pinctrl 0 0 32>;
> +	#gpio-cells = <2>;
> +
> +	interrupt-controller;
> +	#interrupt-cells = <2>;
> +
> +	interrupt-parent = <&intc>;
> +	interrupts = <28>;
> +};
> -- 
> 2.11.0
> 

[toc] | [prev] | [next] | [standalone]


#1566859 — [PATCH v3 10/14] mmc: jz4740: Let the pinctrl driver configure the pins

FromPaul Cercueil <paul@crapouillou.net>
Date2017-01-25 20:00 +0100
Subject[PATCH v3 10/14] mmc: jz4740: Let the pinctrl driver configure the pins
Message-ID<t3AXw-5pP-27@gated-at.bofh.it>
In reply to#1566846
Now that the JZ4740 and similar SoCs have a pinctrl driver, we rely on
the pins being properly configured before the driver probes.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 drivers/mmc/host/jz4740_mmc.c | 45 +++++--------------------------------------
 1 file changed, 5 insertions(+), 40 deletions(-)

v2: Set pin sleep/default state in suspend/resume callbacks
v3: No changes

diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index 819ad32964fc..b5fec5b7ee7b 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -20,14 +20,13 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/scatterlist.h>
 #include <linux/clk.h>
 
 #include <linux/bitops.h>
-#include <linux/gpio.h>
-#include <asm/mach-jz4740/gpio.h>
 #include <asm/cacheflush.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
@@ -906,15 +905,6 @@ static const struct mmc_host_ops jz4740_mmc_ops = {
 	.enable_sdio_irq = jz4740_mmc_enable_sdio_irq,
 };
 
-static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = {
-	JZ_GPIO_BULK_PIN(MSC_CMD),
-	JZ_GPIO_BULK_PIN(MSC_CLK),
-	JZ_GPIO_BULK_PIN(MSC_DATA0),
-	JZ_GPIO_BULK_PIN(MSC_DATA1),
-	JZ_GPIO_BULK_PIN(MSC_DATA2),
-	JZ_GPIO_BULK_PIN(MSC_DATA3),
-};
-
 static int jz4740_mmc_request_gpio(struct device *dev, int gpio,
 	const char *name, bool output, int value)
 {
@@ -978,15 +968,6 @@ static void jz4740_mmc_free_gpios(struct platform_device *pdev)
 		gpio_free(pdata->gpio_power);
 }
 
-static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host)
-{
-	size_t num_pins = ARRAY_SIZE(jz4740_mmc_pins);
-	if (host->pdata && host->pdata->data_1bit)
-		num_pins -= 3;
-
-	return num_pins;
-}
-
 static int jz4740_mmc_probe(struct platform_device* pdev)
 {
 	int ret;
@@ -1027,15 +1008,9 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
 		goto err_free_host;
 	}
 
-	ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret);
-		goto err_free_host;
-	}
-
 	ret = jz4740_mmc_request_gpios(mmc, pdev);
 	if (ret)
-		goto err_gpio_bulk_free;
+		goto err_release_dma;
 
 	mmc->ops = &jz4740_mmc_ops;
 	mmc->f_min = JZ_MMC_CLK_RATE / 128;
@@ -1091,10 +1066,9 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
 	free_irq(host->irq, host);
 err_free_gpios:
 	jz4740_mmc_free_gpios(pdev);
-err_gpio_bulk_free:
+err_release_dma:
 	if (host->use_dma)
 		jz4740_mmc_release_dma_channels(host);
-	jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
 err_free_host:
 	mmc_free_host(mmc);
 
@@ -1114,7 +1088,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev)
 	free_irq(host->irq, host);
 
 	jz4740_mmc_free_gpios(pdev);
-	jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
 
 	if (host->use_dma)
 		jz4740_mmc_release_dma_channels(host);
@@ -1128,20 +1101,12 @@ static int jz4740_mmc_remove(struct platform_device *pdev)
 
 static int jz4740_mmc_suspend(struct device *dev)
 {
-	struct jz4740_mmc_host *host = dev_get_drvdata(dev);
-
-	jz_gpio_bulk_suspend(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
-
-	return 0;
+	return pinctrl_pm_select_sleep_state(dev);
 }
 
 static int jz4740_mmc_resume(struct device *dev)
 {
-	struct jz4740_mmc_host *host = dev_get_drvdata(dev);
-
-	jz_gpio_bulk_resume(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
-
-	return 0;
+	return pinctrl_pm_select_default_state(dev);
 }
 
 static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend,
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1567132 — Re: [PATCH v3 10/14] mmc: jz4740: Let the pinctrl driver configure the pins

Fromkbuild test robot <lkp@intel.com>
Date2017-01-26 07:20 +0100
SubjectRe: [PATCH v3 10/14] mmc: jz4740: Let the pinctrl driver configure the pins
Message-ID<t3Lzz-3RH-3@gated-at.bofh.it>
In reply to#1566859

[Multipart message — attachments visible in raw view] — view raw

Hi Paul,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.10-rc5 next-20170125]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Paul-Cercueil/Ingenic-JZ4740-JZ4780-pinctrl-driver/20170126-030028
config: mips-qi_lb60_defconfig (attached as .config)
compiler: mipsel-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=mips 

All errors (new ones prefixed by >>):

   drivers/mmc/host/jz4740_mmc.c: In function 'jz4740_mmc_set_ios':
>> drivers/mmc/host/jz4740_mmc.c:864:7: error: implicit declaration of function 'gpio_is_valid' [-Werror=implicit-function-declaration]
      if (gpio_is_valid(host->pdata->gpio_power))
          ^~~~~~~~~~~~~
>> drivers/mmc/host/jz4740_mmc.c:865:4: error: implicit declaration of function 'gpio_set_value' [-Werror=implicit-function-declaration]
       gpio_set_value(host->pdata->gpio_power,
       ^~~~~~~~~~~~~~
   drivers/mmc/host/jz4740_mmc.c: In function 'jz4740_mmc_request_gpio':
>> drivers/mmc/host/jz4740_mmc.c:916:8: error: implicit declaration of function 'gpio_request' [-Werror=implicit-function-declaration]
     ret = gpio_request(gpio, name);
           ^~~~~~~~~~~~
>> drivers/mmc/host/jz4740_mmc.c:923:3: error: implicit declaration of function 'gpio_direction_output' [-Werror=implicit-function-declaration]
      gpio_direction_output(gpio, value);
      ^~~~~~~~~~~~~~~~~~~~~
>> drivers/mmc/host/jz4740_mmc.c:925:3: error: implicit declaration of function 'gpio_direction_input' [-Werror=implicit-function-declaration]
      gpio_direction_input(gpio);
      ^~~~~~~~~~~~~~~~~~~~
   drivers/mmc/host/jz4740_mmc.c: In function 'jz4740_mmc_free_gpios':
>> drivers/mmc/host/jz4740_mmc.c:968:3: error: implicit declaration of function 'gpio_free' [-Werror=implicit-function-declaration]
      gpio_free(pdata->gpio_power);
      ^~~~~~~~~
   cc1: some warnings being treated as errors

vim +/gpio_is_valid +864 drivers/mmc/host/jz4740_mmc.c

61bfbdb8 Lars-Peter Clausen 2010-07-15  858  	if (ios->clock)
61bfbdb8 Lars-Peter Clausen 2010-07-15  859  		jz4740_mmc_set_clock_rate(host, ios->clock);
61bfbdb8 Lars-Peter Clausen 2010-07-15  860  
61bfbdb8 Lars-Peter Clausen 2010-07-15  861  	switch (ios->power_mode) {
61bfbdb8 Lars-Peter Clausen 2010-07-15  862  	case MMC_POWER_UP:
61bfbdb8 Lars-Peter Clausen 2010-07-15  863  		jz4740_mmc_reset(host);
61bfbdb8 Lars-Peter Clausen 2010-07-15 @864  		if (gpio_is_valid(host->pdata->gpio_power))
61bfbdb8 Lars-Peter Clausen 2010-07-15 @865  			gpio_set_value(host->pdata->gpio_power,
61bfbdb8 Lars-Peter Clausen 2010-07-15  866  					!host->pdata->power_active_low);
61bfbdb8 Lars-Peter Clausen 2010-07-15  867  		host->cmdat |= JZ_MMC_CMDAT_INIT;
fca9661c Lars-Peter Clausen 2013-05-12  868  		clk_prepare_enable(host->clk);
61bfbdb8 Lars-Peter Clausen 2010-07-15  869  		break;
61bfbdb8 Lars-Peter Clausen 2010-07-15  870  	case MMC_POWER_ON:
61bfbdb8 Lars-Peter Clausen 2010-07-15  871  		break;
61bfbdb8 Lars-Peter Clausen 2010-07-15  872  	default:
61bfbdb8 Lars-Peter Clausen 2010-07-15  873  		if (gpio_is_valid(host->pdata->gpio_power))
61bfbdb8 Lars-Peter Clausen 2010-07-15  874  			gpio_set_value(host->pdata->gpio_power,
61bfbdb8 Lars-Peter Clausen 2010-07-15  875  					host->pdata->power_active_low);
fca9661c Lars-Peter Clausen 2013-05-12  876  		clk_disable_unprepare(host->clk);
61bfbdb8 Lars-Peter Clausen 2010-07-15  877  		break;
61bfbdb8 Lars-Peter Clausen 2010-07-15  878  	}
61bfbdb8 Lars-Peter Clausen 2010-07-15  879  
61bfbdb8 Lars-Peter Clausen 2010-07-15  880  	switch (ios->bus_width) {
61bfbdb8 Lars-Peter Clausen 2010-07-15  881  	case MMC_BUS_WIDTH_1:
61bfbdb8 Lars-Peter Clausen 2010-07-15  882  		host->cmdat &= ~JZ_MMC_CMDAT_BUS_WIDTH_4BIT;
61bfbdb8 Lars-Peter Clausen 2010-07-15  883  		break;
61bfbdb8 Lars-Peter Clausen 2010-07-15  884  	case MMC_BUS_WIDTH_4:
61bfbdb8 Lars-Peter Clausen 2010-07-15  885  		host->cmdat |= JZ_MMC_CMDAT_BUS_WIDTH_4BIT;
61bfbdb8 Lars-Peter Clausen 2010-07-15  886  		break;
61bfbdb8 Lars-Peter Clausen 2010-07-15  887  	default:
61bfbdb8 Lars-Peter Clausen 2010-07-15  888  		break;
61bfbdb8 Lars-Peter Clausen 2010-07-15  889  	}
61bfbdb8 Lars-Peter Clausen 2010-07-15  890  }
61bfbdb8 Lars-Peter Clausen 2010-07-15  891  
61bfbdb8 Lars-Peter Clausen 2010-07-15  892  static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
61bfbdb8 Lars-Peter Clausen 2010-07-15  893  {
61bfbdb8 Lars-Peter Clausen 2010-07-15  894  	struct jz4740_mmc_host *host = mmc_priv(mmc);
61bfbdb8 Lars-Peter Clausen 2010-07-15  895  	jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable);
61bfbdb8 Lars-Peter Clausen 2010-07-15  896  }
61bfbdb8 Lars-Peter Clausen 2010-07-15  897  
61bfbdb8 Lars-Peter Clausen 2010-07-15  898  static const struct mmc_host_ops jz4740_mmc_ops = {
61bfbdb8 Lars-Peter Clausen 2010-07-15  899  	.request	= jz4740_mmc_request,
bb2f4592 Apelete Seketeli   2014-07-21  900  	.pre_req	= jz4740_mmc_pre_request,
bb2f4592 Apelete Seketeli   2014-07-21  901  	.post_req	= jz4740_mmc_post_request,
61bfbdb8 Lars-Peter Clausen 2010-07-15  902  	.set_ios	= jz4740_mmc_set_ios,
58e300af Lars-Peter Clausen 2013-06-09  903  	.get_ro		= mmc_gpio_get_ro,
58e300af Lars-Peter Clausen 2013-06-09  904  	.get_cd		= mmc_gpio_get_cd,
61bfbdb8 Lars-Peter Clausen 2010-07-15  905  	.enable_sdio_irq = jz4740_mmc_enable_sdio_irq,
61bfbdb8 Lars-Peter Clausen 2010-07-15  906  };
61bfbdb8 Lars-Peter Clausen 2010-07-15  907  
c3be1efd Bill Pemberton     2012-11-19  908  static int jz4740_mmc_request_gpio(struct device *dev, int gpio,
61bfbdb8 Lars-Peter Clausen 2010-07-15  909  	const char *name, bool output, int value)
61bfbdb8 Lars-Peter Clausen 2010-07-15  910  {
61bfbdb8 Lars-Peter Clausen 2010-07-15  911  	int ret;
61bfbdb8 Lars-Peter Clausen 2010-07-15  912  
61bfbdb8 Lars-Peter Clausen 2010-07-15  913  	if (!gpio_is_valid(gpio))
61bfbdb8 Lars-Peter Clausen 2010-07-15  914  		return 0;
61bfbdb8 Lars-Peter Clausen 2010-07-15  915  
61bfbdb8 Lars-Peter Clausen 2010-07-15 @916  	ret = gpio_request(gpio, name);
61bfbdb8 Lars-Peter Clausen 2010-07-15  917  	if (ret) {
61bfbdb8 Lars-Peter Clausen 2010-07-15  918  		dev_err(dev, "Failed to request %s gpio: %d\n", name, ret);
61bfbdb8 Lars-Peter Clausen 2010-07-15  919  		return ret;
61bfbdb8 Lars-Peter Clausen 2010-07-15  920  	}
61bfbdb8 Lars-Peter Clausen 2010-07-15  921  
61bfbdb8 Lars-Peter Clausen 2010-07-15  922  	if (output)
61bfbdb8 Lars-Peter Clausen 2010-07-15 @923  		gpio_direction_output(gpio, value);
61bfbdb8 Lars-Peter Clausen 2010-07-15  924  	else
61bfbdb8 Lars-Peter Clausen 2010-07-15 @925  		gpio_direction_input(gpio);
61bfbdb8 Lars-Peter Clausen 2010-07-15  926  
61bfbdb8 Lars-Peter Clausen 2010-07-15  927  	return 0;
61bfbdb8 Lars-Peter Clausen 2010-07-15  928  }
61bfbdb8 Lars-Peter Clausen 2010-07-15  929  
58e300af Lars-Peter Clausen 2013-06-09  930  static int jz4740_mmc_request_gpios(struct mmc_host *mmc,
58e300af Lars-Peter Clausen 2013-06-09  931  	struct platform_device *pdev)
61bfbdb8 Lars-Peter Clausen 2010-07-15  932  {
61bfbdb8 Lars-Peter Clausen 2010-07-15  933  	struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
58e300af Lars-Peter Clausen 2013-06-09  934  	int ret = 0;
61bfbdb8 Lars-Peter Clausen 2010-07-15  935  
61bfbdb8 Lars-Peter Clausen 2010-07-15  936  	if (!pdata)
61bfbdb8 Lars-Peter Clausen 2010-07-15  937  		return 0;
61bfbdb8 Lars-Peter Clausen 2010-07-15  938  
58e300af Lars-Peter Clausen 2013-06-09  939  	if (!pdata->card_detect_active_low)
58e300af Lars-Peter Clausen 2013-06-09  940  		mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
58e300af Lars-Peter Clausen 2013-06-09  941  	if (!pdata->read_only_active_low)
58e300af Lars-Peter Clausen 2013-06-09  942  		mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
61bfbdb8 Lars-Peter Clausen 2010-07-15  943  
58e300af Lars-Peter Clausen 2013-06-09  944  	if (gpio_is_valid(pdata->gpio_card_detect)) {
214fc309 Laurent Pinchart   2013-08-08  945  		ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect, 0);
61bfbdb8 Lars-Peter Clausen 2010-07-15  946  		if (ret)
61bfbdb8 Lars-Peter Clausen 2010-07-15  947  			return ret;
61bfbdb8 Lars-Peter Clausen 2010-07-15  948  	}
61bfbdb8 Lars-Peter Clausen 2010-07-15  949  
58e300af Lars-Peter Clausen 2013-06-09  950  	if (gpio_is_valid(pdata->gpio_read_only)) {
58e300af Lars-Peter Clausen 2013-06-09  951  		ret = mmc_gpio_request_ro(mmc, pdata->gpio_read_only);
58e300af Lars-Peter Clausen 2013-06-09  952  		if (ret)
58e300af Lars-Peter Clausen 2013-06-09  953  			return ret;
61bfbdb8 Lars-Peter Clausen 2010-07-15  954  	}
61bfbdb8 Lars-Peter Clausen 2010-07-15  955  
58e300af Lars-Peter Clausen 2013-06-09  956  	return jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power,
58e300af Lars-Peter Clausen 2013-06-09  957  			"MMC read only", true, pdata->power_active_low);
61bfbdb8 Lars-Peter Clausen 2010-07-15  958  }
61bfbdb8 Lars-Peter Clausen 2010-07-15  959  
61bfbdb8 Lars-Peter Clausen 2010-07-15  960  static void jz4740_mmc_free_gpios(struct platform_device *pdev)
61bfbdb8 Lars-Peter Clausen 2010-07-15  961  {
61bfbdb8 Lars-Peter Clausen 2010-07-15  962  	struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
61bfbdb8 Lars-Peter Clausen 2010-07-15  963  
61bfbdb8 Lars-Peter Clausen 2010-07-15  964  	if (!pdata)
61bfbdb8 Lars-Peter Clausen 2010-07-15  965  		return;
61bfbdb8 Lars-Peter Clausen 2010-07-15  966  
61bfbdb8 Lars-Peter Clausen 2010-07-15  967  	if (gpio_is_valid(pdata->gpio_power))
61bfbdb8 Lars-Peter Clausen 2010-07-15 @968  		gpio_free(pdata->gpio_power);
61bfbdb8 Lars-Peter Clausen 2010-07-15  969  }
61bfbdb8 Lars-Peter Clausen 2010-07-15  970  
c3be1efd Bill Pemberton     2012-11-19  971  static int jz4740_mmc_probe(struct platform_device* pdev)

:::::: The code at line 864 was first introduced by commit
:::::: 61bfbdb856879cff583fe53b2ab6ae907faedee7 MMC: Add support for the controller on JZ4740 SoCs.

:::::: TO: Lars-Peter Clausen <lars@metafoo.de>
:::::: CC: Ralf Baechle <ralf@linux-mips.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[toc] | [prev] | [next] | [standalone]


#1567274 — Re: [PATCH v3 10/14] mmc: jz4740: Let the pinctrl driver configure the pins

FromPaul Cercueil <paul@crapouillou.net>
Date2017-01-26 11:20 +0100
SubjectRe: [PATCH v3 10/14] mmc: jz4740: Let the pinctrl driver configure the pins
Message-ID<t3PjQ-65h-37@gated-at.bofh.it>
In reply to#1567132
Hi Kbuild Test Robot,

> 
> drivers/mmc/host/jz4740_mmc.c: In function 'jz4740_mmc_set_ios':
> drivers/mmc/host/jz4740_mmc.c:864:7: error: implicit declaration of 
> function 'gpio_is_valid' [-Werror=implicit-function-declaration]

  if (gpio_is_valid(host->pdata->gpio_power))
  ^~~~~~~~~~~~~

Uuh, I'm sorry about that. Looks like I removed one header too much 
(<linux/gpio.h>).
My fault, lately I was testing with ci20_defconfig which doesn't enable 
this driver.

Should I send a v4?

Apologies,
-Paul

[toc] | [prev] | [next] | [standalone]


#1566860 — [PATCH v3 04/14] GPIO: Add gpio-ingenic driver

FromPaul Cercueil <paul@crapouillou.net>
Date2017-01-25 20:00 +0100
Subject[PATCH v3 04/14] GPIO: Add gpio-ingenic driver
Message-ID<t3AXw-5pP-35@gated-at.bofh.it>
In reply to#1566846
This driver handles the GPIOs of all the Ingenic JZ47xx SoCs
currently supported by the upsteam Linux kernel.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 drivers/gpio/Kconfig        |  10 ++
 drivers/gpio/Makefile       |   1 +
 drivers/gpio/gpio-ingenic.c | 367 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 378 insertions(+)
 create mode 100644 drivers/gpio/gpio-ingenic.c

v2: Consider it's a new patch. Completely rewritten from v1.
v3: Add missing include <linux/pinctrl/consumer.h> and drop semicolon after }

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d5d36549ecc1..21992ca29342 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -225,6 +225,16 @@ config GPIO_ICH
 
 	  If unsure, say N.
 
+config GPIO_INGENIC
+	tristate "Ingenic JZ47xx SoCs GPIO support"
+	depends on MACH_INGENIC || COMPILE_TEST
+	select GPIOLIB_IRQCHIP
+	help
+	  Say yes here to support the GPIO functionality present on the
+	  JZ4740 and JZ4780 SoCs from Ingenic.
+
+	  If unsure, say N.
+
 config GPIO_IOP
 	tristate "Intel IOP GPIO"
 	depends on ARCH_IOP32X || ARCH_IOP33X || COMPILE_TEST
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index a7676b82de6f..3c5412ae56f0 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_GPIO_GPIO_MM)	+= gpio-gpio-mm.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_HTC_EGPIO)		+= gpio-htc-egpio.o
 obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
+obj-$(CONFIG_GPIO_INGENIC)	+= gpio-ingenic.o
 obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o
 obj-$(CONFIG_GPIO_IT87)		+= gpio-it87.o
 obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o
diff --git a/drivers/gpio/gpio-ingenic.c b/drivers/gpio/gpio-ingenic.c
new file mode 100644
index 000000000000..1bb6c4d5b8ba
--- /dev/null
+++ b/drivers/gpio/gpio-ingenic.c
@@ -0,0 +1,367 @@
+/*
+ * Ingenic JZ47xx GPIO driver
+ *
+ * Copyright (c) 2017 Paul Cercueil <paul@crapouillou.net>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+
+#define GPIO_PIN	0x00
+#define GPIO_MSK	0x20
+
+#define JZ4740_GPIO_DATA	0x10
+#define JZ4740_GPIO_SELECT	0x50
+#define JZ4740_GPIO_DIR		0x60
+#define JZ4740_GPIO_TRIG	0x70
+#define JZ4740_GPIO_FLAG	0x80
+
+#define JZ4780_GPIO_INT		0x10
+#define JZ4780_GPIO_PAT1	0x30
+#define JZ4780_GPIO_PAT0	0x40
+#define JZ4780_GPIO_FLAG	0x50
+
+#define REG_SET(x) ((x) + 0x4)
+#define REG_CLEAR(x) ((x) + 0x8)
+
+enum jz_version {
+	ID_JZ4740,
+	ID_JZ4780,
+};
+
+struct ingenic_gpio_chip {
+	void __iomem *base;
+	struct gpio_chip gc;
+	struct irq_chip irq_chip;
+	unsigned int irq;
+	enum jz_version version;
+};
+
+static inline bool gpio_get_value(struct ingenic_gpio_chip *jzgc, u8 offset)
+{
+	if (jzgc->version >= ID_JZ4780)
+		return readl(jzgc->base + GPIO_PIN) & BIT(offset);
+	else
+		return readl(jzgc->base + JZ4740_GPIO_DATA) & BIT(offset);
+}
+
+static void gpio_set_value(struct ingenic_gpio_chip *jzgc, u8 offset, int value)
+{
+	u8 reg;
+
+	if (jzgc->version >= ID_JZ4780)
+		reg = JZ4780_GPIO_PAT0;
+	else
+		reg = JZ4740_GPIO_DATA;
+
+	if (value)
+		writel(BIT(offset), jzgc->base + REG_SET(reg));
+	else
+		writel(BIT(offset), jzgc->base + REG_CLEAR(reg));
+}
+
+static void irq_set_type(struct ingenic_gpio_chip *jzgc,
+		u8 offset, unsigned int type)
+{
+	u8 reg1, reg2;
+
+	if (jzgc->version >= ID_JZ4780) {
+		reg1 = JZ4780_GPIO_PAT1;
+		reg2 = JZ4780_GPIO_PAT0;
+	} else {
+		reg1 = JZ4740_GPIO_TRIG;
+		reg2 = JZ4740_GPIO_DIR;
+	}
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		writel(BIT(offset), jzgc->base + REG_SET(reg2));
+		writel(BIT(offset), jzgc->base + REG_SET(reg1));
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		writel(BIT(offset), jzgc->base + REG_CLEAR(reg2));
+		writel(BIT(offset), jzgc->base + REG_SET(reg1));
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		writel(BIT(offset), jzgc->base + REG_SET(reg2));
+		writel(BIT(offset), jzgc->base + REG_CLEAR(reg1));
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+	default:
+		writel(BIT(offset), jzgc->base + REG_CLEAR(reg2));
+		writel(BIT(offset), jzgc->base + REG_CLEAR(reg1));
+		break;
+	}
+}
+
+static void ingenic_gpio_irq_mask(struct irq_data *irqd)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+
+	writel(BIT(irqd->hwirq), jzgc->base + REG_SET(GPIO_MSK));
+}
+
+static void ingenic_gpio_irq_unmask(struct irq_data *irqd)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+
+	writel(BIT(irqd->hwirq), jzgc->base + REG_CLEAR(GPIO_MSK));
+}
+
+static void ingenic_gpio_irq_enable(struct irq_data *irqd)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+	int irq = irqd->hwirq;
+
+	if (jzgc->version >= ID_JZ4780)
+		writel(BIT(irq), jzgc->base + REG_SET(JZ4780_GPIO_INT));
+	else
+		writel(BIT(irq), jzgc->base + REG_SET(JZ4740_GPIO_SELECT));
+
+	ingenic_gpio_irq_unmask(irqd);
+}
+
+static void ingenic_gpio_irq_disable(struct irq_data *irqd)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+	int irq = irqd->hwirq;
+
+	ingenic_gpio_irq_mask(irqd);
+
+	if (jzgc->version >= ID_JZ4780)
+		writel(BIT(irq), jzgc->base + REG_CLEAR(JZ4780_GPIO_INT));
+	else
+		writel(BIT(irq), jzgc->base + REG_CLEAR(JZ4740_GPIO_SELECT));
+}
+
+static void ingenic_gpio_irq_ack(struct irq_data *irqd)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+	int irq = irqd->hwirq;
+	bool high;
+
+	if (irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) {
+		/*
+		 * Switch to an interrupt for the opposite edge to the one that
+		 * triggered the interrupt being ACKed.
+		 */
+		high = gpio_get_value(jzgc, irq);
+		if (high)
+			irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_FALLING);
+		else
+			irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING);
+	}
+
+	if (jzgc->version >= ID_JZ4780)
+		writel(BIT(irq), jzgc->base + REG_CLEAR(JZ4780_GPIO_FLAG));
+	else
+		writel(BIT(irq), jzgc->base + REG_SET(JZ4740_GPIO_DATA));
+}
+
+static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_BOTH:
+	case IRQ_TYPE_EDGE_RISING:
+	case IRQ_TYPE_EDGE_FALLING:
+		irq_set_handler_locked(irqd, handle_edge_irq);
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+	case IRQ_TYPE_LEVEL_LOW:
+		irq_set_handler_locked(irqd, handle_level_irq);
+		break;
+	default:
+		irq_set_handler_locked(irqd, handle_bad_irq);
+	}
+
+	if (type == IRQ_TYPE_EDGE_BOTH) {
+		/*
+		 * The hardware does not support interrupts on both edges. The
+		 * best we can do is to set up a single-edge interrupt and then
+		 * switch to the opposing edge when ACKing the interrupt.
+		 */
+		bool high = gpio_get_value(jzgc, irqd->hwirq);
+
+		type = high ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
+	}
+
+	irq_set_type(jzgc, irqd->hwirq, type);
+	return 0;
+}
+
+static int ingenic_gpio_irq_set_wake(struct irq_data *irqd, unsigned int on)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+
+	return irq_set_irq_wake(jzgc->irq, on);
+}
+
+static void ingenic_gpio_irq_handler(struct irq_desc *desc)
+{
+	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+	struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data);
+	unsigned long flag, i;
+
+	chained_irq_enter(irq_chip, desc);
+
+	if (jzgc->version >= ID_JZ4780)
+		flag = readl(jzgc->base + JZ4780_GPIO_FLAG);
+	else
+		flag = readl(jzgc->base + JZ4740_GPIO_FLAG);
+
+	for_each_set_bit(i, &flag, 32)
+		generic_handle_irq(irq_linear_revmap(gc->irqdomain, i));
+	chained_irq_exit(irq_chip, desc);
+}
+
+static void ingenic_gpio_set(struct gpio_chip *gc,
+		unsigned int offset, int value)
+{
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+
+	gpio_set_value(jzgc, offset, value);
+}
+
+static int ingenic_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
+
+	return (int) gpio_get_value(jzgc, offset);
+}
+
+static int ingenic_gpio_direction_input(struct gpio_chip *gc,
+		unsigned int offset)
+{
+	return pinctrl_gpio_direction_input(gc->base + offset);
+}
+
+static int ingenic_gpio_direction_output(struct gpio_chip *gc,
+		unsigned int offset, int value)
+{
+	ingenic_gpio_set(gc, offset, value);
+	return pinctrl_gpio_direction_output(gc->base + offset);
+}
+
+static const struct of_device_id ingenic_gpio_of_match[] = {
+	{ .compatible = "ingenic,jz4740-gpio", .data = (void *)ID_JZ4740 },
+	{ .compatible = "ingenic,jz4780-gpio", .data = (void *)ID_JZ4780 },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ingenic_gpio_of_match);
+
+static int ingenic_gpio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct of_device_id *of_id = of_match_device(
+			ingenic_gpio_of_match, dev);
+	struct ingenic_gpio_chip *jzgc;
+	int err;
+
+	jzgc = devm_kzalloc(dev, sizeof(*jzgc), GFP_KERNEL);
+	if (!jzgc)
+		return -ENOMEM;
+
+	jzgc->base = of_iomap(dev->of_node, 0);
+	if (!jzgc->base) {
+		dev_err(dev, "failed to map IO memory\n");
+		return -ENXIO;
+	}
+
+	jzgc->gc.base = -1;
+	jzgc->gc.ngpio = 32;
+	jzgc->gc.parent = dev;
+	jzgc->gc.of_node = dev->of_node;
+	jzgc->gc.label = "";
+	jzgc->gc.owner = THIS_MODULE;
+	jzgc->version = (enum jz_version)of_id->data;
+
+	jzgc->gc.set = ingenic_gpio_set;
+	jzgc->gc.get = ingenic_gpio_get;
+	jzgc->gc.direction_input = ingenic_gpio_direction_input;
+	jzgc->gc.direction_output = ingenic_gpio_direction_output;
+
+	if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
+		jzgc->gc.request = gpiochip_generic_request;
+		jzgc->gc.free = gpiochip_generic_free;
+	}
+
+	of_property_read_u32(dev->of_node, "base", &jzgc->gc.base);
+
+	err = devm_gpiochip_add_data(dev, &jzgc->gc, jzgc);
+	if (err)
+		return err;
+
+	if (!of_property_read_bool(dev->of_node, "interrupt-controller"))
+		return 0;
+
+	jzgc->irq = irq_of_parse_and_map(dev->of_node, 0);
+	if (!jzgc->irq)
+		return -EINVAL;
+
+	jzgc->irq_chip.name = dev->of_node->name;
+	jzgc->irq_chip.irq_enable = ingenic_gpio_irq_enable;
+	jzgc->irq_chip.irq_disable = ingenic_gpio_irq_disable;
+	jzgc->irq_chip.irq_unmask = ingenic_gpio_irq_unmask;
+	jzgc->irq_chip.irq_mask = ingenic_gpio_irq_mask;
+	jzgc->irq_chip.irq_ack = ingenic_gpio_irq_ack;
+	jzgc->irq_chip.irq_set_type = ingenic_gpio_irq_set_type;
+	jzgc->irq_chip.irq_set_wake = ingenic_gpio_irq_set_wake;
+	jzgc->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
+
+	err = gpiochip_irqchip_add(&jzgc->gc, &jzgc->irq_chip, 0,
+			handle_level_irq, IRQ_TYPE_NONE);
+	if (err)
+		return err;
+
+	gpiochip_set_chained_irqchip(&jzgc->gc, &jzgc->irq_chip,
+			jzgc->irq, ingenic_gpio_irq_handler);
+	return 0;
+}
+
+static int ingenic_gpio_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver ingenic_gpio_driver = {
+	.driver = {
+		.name = "gpio-ingenic",
+		.of_match_table = of_match_ptr(ingenic_gpio_of_match),
+	},
+	.probe = ingenic_gpio_probe,
+	.remove = ingenic_gpio_remove,
+};
+
+static int __init ingenic_gpio_drv_register(void)
+{
+	return platform_driver_register(&ingenic_gpio_driver);
+}
+subsys_initcall(ingenic_gpio_drv_register);
+
+static void __exit ingenic_gpio_drv_unregister(void)
+{
+	platform_driver_unregister(&ingenic_gpio_driver);
+}
+module_exit(ingenic_gpio_drv_unregister);
+
+MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
+MODULE_DESCRIPTION("Ingenic JZ47xx GPIO driver");
+MODULE_LICENSE("GPL");
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1570780 — Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver

FromLinus Walleij <linus.walleij@linaro.org>
Date2017-01-31 15:30 +0100
SubjectRe: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver
Message-ID<t5HBv-1Ll-5@gated-at.bofh.it>
In reply to#1566860
On Wed, Jan 25, 2017 at 7:51 PM, Paul Cercueil <paul@crapouillou.net> wrote:

> This driver handles the GPIOs of all the Ingenic JZ47xx SoCs
> currently supported by the upsteam Linux kernel.
>
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>

Looking nice.

> +#define JZ4740_GPIO_DATA       0x10
> +#define JZ4740_GPIO_SELECT     0x50
> +#define JZ4740_GPIO_DIR                0x60
> +#define JZ4740_GPIO_TRIG       0x70
> +#define JZ4740_GPIO_FLAG       0x80
> +
> +#define JZ4780_GPIO_INT                0x10
> +#define JZ4780_GPIO_PAT1       0x30
> +#define JZ4780_GPIO_PAT0       0x40
> +#define JZ4780_GPIO_FLAG       0x50
> +
> +#define REG_SET(x) ((x) + 0x4)
> +#define REG_CLEAR(x) ((x) + 0x8)
(...)
> +enum jz_version {
> +       ID_JZ4740,
> +       ID_JZ4780,
> +};
(...)
> +static inline bool gpio_get_value(struct ingenic_gpio_chip *jzgc, u8 offset)
> +{
> +       if (jzgc->version >= ID_JZ4780)
> +               return readl(jzgc->base + GPIO_PIN) & BIT(offset);
> +       else
> +               return readl(jzgc->base + JZ4740_GPIO_DATA) & BIT(offset);
> +}

This works for me, for sure.

What some people do, is to put the right virtual address in to the state
container.

So it would be just:

return !!readl(jzgc->datareg) & BIT(offset));

Notice also the double-bang that clamps the value to a bool. I know
the core does it too but I like to see it in drivers just to be sure.

> +static void gpio_set_value(struct ingenic_gpio_chip *jzgc, u8 offset, int value)
> +{
> +       u8 reg;
> +
> +       if (jzgc->version >= ID_JZ4780)
> +               reg = JZ4780_GPIO_PAT0;
> +       else
> +               reg = JZ4740_GPIO_DATA;
> +
> +       if (value)
> +               writel(BIT(offset), jzgc->base + REG_SET(reg));
> +       else
> +               writel(BIT(offset), jzgc->base + REG_CLEAR(reg));
> +}

Same comment.

What some drivers do when they just get/set a bit in a register
to get/set or set the direction of a GPIO, is to select GPIO_GENERIC
and just bgpio_init() with the right iomem pointers, then the core
will register handlers for get, set, set_direcition callback and
get_direction and your driver can just focus on the remainders.

> +static void ingenic_gpio_set(struct gpio_chip *gc,
> +               unsigned int offset, int value)
> +{
> +       struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
> +
> +       gpio_set_value(jzgc, offset, value);
> +}
> +
> +static int ingenic_gpio_get(struct gpio_chip *gc, unsigned int offset)
> +{
> +       struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
> +
> +       return (int) gpio_get_value(jzgc, offset);
> +}
> +
> +static int ingenic_gpio_direction_input(struct gpio_chip *gc,
> +               unsigned int offset)
> +{
> +       return pinctrl_gpio_direction_input(gc->base + offset);
> +}
> +
> +static int ingenic_gpio_direction_output(struct gpio_chip *gc,
> +               unsigned int offset, int value)
> +{
> +       ingenic_gpio_set(gc, offset, value);
> +       return pinctrl_gpio_direction_output(gc->base + offset);
> +}

If you're not just replacing these with GPIO_GENERIC, please also
include a .get_direction() callback.

It's especially nice as it reads out the state at probe and "lsgpio"
lists if pins are inputs or outputs.

Yours,
Linus Walleij

[toc] | [prev] | [next] | [standalone]


#1577800 — Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver

FromPaul Cercueil <paul@crapouillou.net>
Date2017-02-09 18:20 +0100
SubjectRe: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver
Message-ID<t90xY-vh-41@gated-at.bofh.it>
In reply to#1570780
Hi,

> What some drivers do when they just get/set a bit in a register
> to get/set or set the direction of a GPIO, is to select GPIO_GENERIC
> and just bgpio_init() with the right iomem pointers, then the core
> will register handlers for get, set, set_direcition callback and
> get_direction and your driver can just focus on the remainders.

GPIO_GENERIC and bgpio_init() would work for my .set() / .get() 
callbacks,
not for my .direction_input() / .direction_output() callbacks which need
to set more than one register.

> If you're not just replacing these with GPIO_GENERIC, please also
> include a .get_direction() callback.

My .direction_input() and .direction_output() callbacks just call into
the pinctrl driver, using pinctrl_gpio_direction_[in,out]put().
I didn't find a way to get the direction info from the pinctrl driver,
is that something that the core should provide?

Thanks,
-Paul

[toc] | [prev] | [next] | [standalone]


#1579276 — Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver

FromLinus Walleij <linus.walleij@linaro.org>
Date2017-02-12 21:50 +0100
SubjectRe: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver
Message-ID<ta9fQ-2ui-51@gated-at.bofh.it>
In reply to#1577800
On Thu, Feb 9, 2017 at 6:14 PM, Paul Cercueil <paul@crapouillou.net> wrote:

>> If you're not just replacing these with GPIO_GENERIC, please also
>> include a .get_direction() callback.
>
> My .direction_input() and .direction_output() callbacks just call into
> the pinctrl driver, using pinctrl_gpio_direction_[in,out]put().
> I didn't find a way to get the direction info from the pinctrl driver,
> is that something that the core should provide?

Hm OK you have a clear point there, there is no such callback.

OK I do not require you to fix that at this time.

I am hesitant about providing ever more callbacks from GPIO
to pin control, I might need some help for consolidation here.

With Mika's patches we have a .set_config() call to
pinctrl_gpio_set_config() so essentially
we *could* actually refactor all pin control drivers providing
a GPIO back-end to use:

pinctrl_gpio_set_config(gpio, PIN_CONF_PACKED(PIN_CONFIG_INPUT_ENABLE, 0));
pinctrl_gpio_set_config(gpio, PIN_CONF_PACKED(PIN_CONFIG_OUTPUT, val));

And replace the calls to pinctrl_gpio_direction_input()
and pinctrl_gpio_direction_output() with this throughout.

It makes things a bit simpler. If we need to figure things
out the reverse direction then pinctrl_gpio_get_config()
should be implemented and used as back-end for
figuring out direction.

Yours,
Linus Walleij

[toc] | [prev] | [next] | [standalone]


#1570781 — Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver

FromLinus Walleij <linus.walleij@linaro.org>
Date2017-01-31 15:30 +0100
SubjectRe: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver
Message-ID<t5HBv-1Ll-7@gated-at.bofh.it>
In reply to#1566860
Forgot to mention this:

On Wed, Jan 25, 2017 at 7:51 PM, Paul Cercueil <paul@crapouillou.net> wrote:
> This driver handles the GPIOs of all the Ingenic JZ47xx SoCs
> currently supported by the upsteam Linux kernel.
>
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
(...)
> +       jzgc->gc.base = -1;

Nice

> +       of_property_read_u32(dev->of_node, "base", &jzgc->gc.base);

Remove this. Dynamic allocation should be fine, if you're using the
new userspace ABI like tools/gpio/* or libgpiod and only that and in-kernel
consumers, dynamic numbers are just fine.

If you have old sysfs userspace that you need to support using the
global GPIO numberspace, please look into ways to phase that out.

Yours,
Linus Walleij

[toc] | [prev] | [next] | [standalone]


#1570833 — Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver

FromPaul Cercueil <paul@crapouillou.net>
Date2017-01-31 16:40 +0100
SubjectRe: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver
Message-ID<t5IHf-2n8-17@gated-at.bofh.it>
In reply to#1570781
Le 2017-01-31 15:20, Linus Walleij a écrit :

>> + of_property_read_u32(dev->of_node, "base", &jzgc->gc.base);
> 
> Remove this. Dynamic allocation should be fine, if you're using the
> new userspace ABI like tools/gpio/* or libgpiod and only that and 
> in-kernel
> consumers, dynamic numbers are just fine.

The problem is that the QI_LB60 board code still have a lot of 
references
to global GPIO numbers. Just grep for JZ_GPIO_PORT in
arch/mips/jz4740/board-qi_lb60.c to see what I mean...

-Paul

[toc] | [prev] | [next] | [standalone]


#1573107 — Re: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver

FromLinus Walleij <linus.walleij@linaro.org>
Date2017-02-03 15:00 +0100
SubjectRe: [PATCH v3 04/14] GPIO: Add gpio-ingenic driver
Message-ID<t6Mz8-2gr-19@gated-at.bofh.it>
In reply to#1570833
On Tue, Jan 31, 2017 at 4:29 PM, Paul Cercueil <paul@crapouillou.net> wrote:
> Le 2017-01-31 15:20, Linus Walleij a écrit :
>
>>> + of_property_read_u32(dev->of_node, "base", &jzgc->gc.base);
>>
>>
>> Remove this. Dynamic allocation should be fine, if you're using the
>> new userspace ABI like tools/gpio/* or libgpiod and only that and
>> in-kernel
>> consumers, dynamic numbers are just fine.
>
>
> The problem is that the QI_LB60 board code still have a lot of references
> to global GPIO numbers. Just grep for JZ_GPIO_PORT in
> arch/mips/jz4740/board-qi_lb60.c to see what I mean...

OK I understand we might need a compromise here to get the code moving.

But we need to keep it out of the device tree.

I think it's better to put a base table relative to the memory base in
the driver in that case:

unsigned int gpio_global_base;

switch (memory_base_address) {
case 0x41000000:
    gpio_global_base = 0x00;
    break;
case 0x42000000:
    gpio_global_base = 0x20;

(...)

etc. (Those are not your base addresses but you get the idea).

Include a few comments like:

/*
 * DO NOT EXPAND THIS: FOR BACKWARD GPIO NUMBERSPACE
 * COMPATIBIBILITY ONLY: WORK TO TRANSITION CONSUMERS TO
 * USE THE GPIO DESCRIPTOR API IN <linux/gpio/consumer.h> INSTEAD.
 */

Then I'll be happy :)

Yours,
Linus Walleij

[toc] | [prev] | [next] | [standalone]


#1566861 — [PATCH v3 12/14] fbdev: jz4740-fb: Let the pinctrl driver configure the pins

FromPaul Cercueil <paul@crapouillou.net>
Date2017-01-25 20:00 +0100
Subject[PATCH v3 12/14] fbdev: jz4740-fb: Let the pinctrl driver configure the pins
Message-ID<t3AXw-5pP-37@gated-at.bofh.it>
In reply to#1566846
Now that the JZ4740 and similar SoCs have a pinctrl driver, we rely on
the pins being properly configured before the driver probes.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 drivers/video/fbdev/jz4740_fb.c | 104 ++--------------------------------------
 1 file changed, 3 insertions(+), 101 deletions(-)

v2: No changes
v3: No changes

diff --git a/drivers/video/fbdev/jz4740_fb.c b/drivers/video/fbdev/jz4740_fb.c
index 87790e9644d0..b57df83fdbd3 100644
--- a/drivers/video/fbdev/jz4740_fb.c
+++ b/drivers/video/fbdev/jz4740_fb.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -27,7 +28,6 @@
 #include <linux/dma-mapping.h>
 
 #include <asm/mach-jz4740/jz4740_fb.h>
-#include <asm/mach-jz4740/gpio.h>
 
 #define JZ_REG_LCD_CFG		0x00
 #define JZ_REG_LCD_VSYNC	0x04
@@ -146,93 +146,6 @@ static const struct fb_fix_screeninfo jzfb_fix = {
 	.accel		= FB_ACCEL_NONE,
 };
 
-static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = {
-	JZ_GPIO_BULK_PIN(LCD_PCLK),
-	JZ_GPIO_BULK_PIN(LCD_HSYNC),
-	JZ_GPIO_BULK_PIN(LCD_VSYNC),
-	JZ_GPIO_BULK_PIN(LCD_DE),
-	JZ_GPIO_BULK_PIN(LCD_PS),
-	JZ_GPIO_BULK_PIN(LCD_REV),
-	JZ_GPIO_BULK_PIN(LCD_CLS),
-	JZ_GPIO_BULK_PIN(LCD_SPL),
-};
-
-static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = {
-	JZ_GPIO_BULK_PIN(LCD_DATA0),
-	JZ_GPIO_BULK_PIN(LCD_DATA1),
-	JZ_GPIO_BULK_PIN(LCD_DATA2),
-	JZ_GPIO_BULK_PIN(LCD_DATA3),
-	JZ_GPIO_BULK_PIN(LCD_DATA4),
-	JZ_GPIO_BULK_PIN(LCD_DATA5),
-	JZ_GPIO_BULK_PIN(LCD_DATA6),
-	JZ_GPIO_BULK_PIN(LCD_DATA7),
-	JZ_GPIO_BULK_PIN(LCD_DATA8),
-	JZ_GPIO_BULK_PIN(LCD_DATA9),
-	JZ_GPIO_BULK_PIN(LCD_DATA10),
-	JZ_GPIO_BULK_PIN(LCD_DATA11),
-	JZ_GPIO_BULK_PIN(LCD_DATA12),
-	JZ_GPIO_BULK_PIN(LCD_DATA13),
-	JZ_GPIO_BULK_PIN(LCD_DATA14),
-	JZ_GPIO_BULK_PIN(LCD_DATA15),
-	JZ_GPIO_BULK_PIN(LCD_DATA16),
-	JZ_GPIO_BULK_PIN(LCD_DATA17),
-};
-
-static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
-{
-	unsigned int num;
-
-	switch (jzfb->pdata->lcd_type) {
-	case JZ_LCD_TYPE_GENERIC_16_BIT:
-		num = 4;
-		break;
-	case JZ_LCD_TYPE_GENERIC_18_BIT:
-		num = 4;
-		break;
-	case JZ_LCD_TYPE_8BIT_SERIAL:
-		num = 3;
-		break;
-	case JZ_LCD_TYPE_SPECIAL_TFT_1:
-	case JZ_LCD_TYPE_SPECIAL_TFT_2:
-	case JZ_LCD_TYPE_SPECIAL_TFT_3:
-		num = 8;
-		break;
-	default:
-		num = 0;
-		break;
-	}
-	return num;
-}
-
-static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
-{
-	unsigned int num;
-
-	switch (jzfb->pdata->lcd_type) {
-	case JZ_LCD_TYPE_GENERIC_16_BIT:
-		num = 16;
-		break;
-	case JZ_LCD_TYPE_GENERIC_18_BIT:
-		num = 18;
-		break;
-	case JZ_LCD_TYPE_8BIT_SERIAL:
-		num = 8;
-		break;
-	case JZ_LCD_TYPE_SPECIAL_TFT_1:
-	case JZ_LCD_TYPE_SPECIAL_TFT_2:
-	case JZ_LCD_TYPE_SPECIAL_TFT_3:
-		if (jzfb->pdata->bpp == 18)
-			num = 18;
-		else
-			num = 16;
-		break;
-	default:
-		num = 0;
-		break;
-	}
-	return num;
-}
-
 /* Based on CNVT_TOHW macro from skeletonfb.c */
 static inline uint32_t jzfb_convert_color_to_hw(unsigned val,
 	struct fb_bitfield *bf)
@@ -487,8 +400,7 @@ static void jzfb_enable(struct jzfb *jzfb)
 
 	clk_prepare_enable(jzfb->ldclk);
 
-	jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+	pinctrl_pm_select_default_state(&jzfb->pdev->dev);
 
 	writel(0, jzfb->base + JZ_REG_LCD_STATE);
 
@@ -511,8 +423,7 @@ static void jzfb_disable(struct jzfb *jzfb)
 		ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
 	} while (!(ctrl & JZ_LCD_STATE_DISABLED));
 
-	jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
+	pinctrl_pm_select_sleep_state(&jzfb->pdev->dev);
 
 	clk_disable_unprepare(jzfb->ldclk);
 }
@@ -701,9 +612,6 @@ static int jzfb_probe(struct platform_device *pdev)
 	fb->mode = NULL;
 	jzfb_set_par(fb);
 
-	jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
 	ret = register_framebuffer(fb);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
@@ -715,9 +623,6 @@ static int jzfb_probe(struct platform_device *pdev)
 	return 0;
 
 err_free_devmem:
-	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
 	fb_dealloc_cmap(&fb->cmap);
 	jzfb_free_devmem(jzfb);
 err_framebuffer_release:
@@ -731,9 +636,6 @@ static int jzfb_remove(struct platform_device *pdev)
 
 	jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
 
-	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
-	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
 	fb_dealloc_cmap(&jzfb->fb->cmap);
 	jzfb_free_devmem(jzfb);
 
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1569886 — Re: [PATCH v3 12/14] fbdev: jz4740-fb: Let the pinctrl driver configure the pins

FromBartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date2017-01-30 17:50 +0100
SubjectRe: [PATCH v3 12/14] fbdev: jz4740-fb: Let the pinctrl driver configure the pins
Message-ID<t5njs-6hh-25@gated-at.bofh.it>
In reply to#1566861
Hi,

On Wednesday, January 25, 2017 07:52:05 PM Paul Cercueil wrote:
> Now that the JZ4740 and similar SoCs have a pinctrl driver, we rely on
> the pins being properly configured before the driver probes.
> 
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>

Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> ---
>  drivers/video/fbdev/jz4740_fb.c | 104 ++--------------------------------------
>  1 file changed, 3 insertions(+), 101 deletions(-)
> 
> v2: No changes
> v3: No changes
> 
> diff --git a/drivers/video/fbdev/jz4740_fb.c b/drivers/video/fbdev/jz4740_fb.c
> index 87790e9644d0..b57df83fdbd3 100644
> --- a/drivers/video/fbdev/jz4740_fb.c
> +++ b/drivers/video/fbdev/jz4740_fb.c
> @@ -17,6 +17,7 @@
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/platform_device.h>
> +#include <linux/pinctrl/consumer.h>
>  
>  #include <linux/clk.h>
>  #include <linux/delay.h>
> @@ -27,7 +28,6 @@
>  #include <linux/dma-mapping.h>
>  
>  #include <asm/mach-jz4740/jz4740_fb.h>
> -#include <asm/mach-jz4740/gpio.h>
>  
>  #define JZ_REG_LCD_CFG		0x00
>  #define JZ_REG_LCD_VSYNC	0x04
> @@ -146,93 +146,6 @@ static const struct fb_fix_screeninfo jzfb_fix = {
>  	.accel		= FB_ACCEL_NONE,
>  };
>  
> -static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = {
> -	JZ_GPIO_BULK_PIN(LCD_PCLK),
> -	JZ_GPIO_BULK_PIN(LCD_HSYNC),
> -	JZ_GPIO_BULK_PIN(LCD_VSYNC),
> -	JZ_GPIO_BULK_PIN(LCD_DE),
> -	JZ_GPIO_BULK_PIN(LCD_PS),
> -	JZ_GPIO_BULK_PIN(LCD_REV),
> -	JZ_GPIO_BULK_PIN(LCD_CLS),
> -	JZ_GPIO_BULK_PIN(LCD_SPL),
> -};
> -
> -static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = {
> -	JZ_GPIO_BULK_PIN(LCD_DATA0),
> -	JZ_GPIO_BULK_PIN(LCD_DATA1),
> -	JZ_GPIO_BULK_PIN(LCD_DATA2),
> -	JZ_GPIO_BULK_PIN(LCD_DATA3),
> -	JZ_GPIO_BULK_PIN(LCD_DATA4),
> -	JZ_GPIO_BULK_PIN(LCD_DATA5),
> -	JZ_GPIO_BULK_PIN(LCD_DATA6),
> -	JZ_GPIO_BULK_PIN(LCD_DATA7),
> -	JZ_GPIO_BULK_PIN(LCD_DATA8),
> -	JZ_GPIO_BULK_PIN(LCD_DATA9),
> -	JZ_GPIO_BULK_PIN(LCD_DATA10),
> -	JZ_GPIO_BULK_PIN(LCD_DATA11),
> -	JZ_GPIO_BULK_PIN(LCD_DATA12),
> -	JZ_GPIO_BULK_PIN(LCD_DATA13),
> -	JZ_GPIO_BULK_PIN(LCD_DATA14),
> -	JZ_GPIO_BULK_PIN(LCD_DATA15),
> -	JZ_GPIO_BULK_PIN(LCD_DATA16),
> -	JZ_GPIO_BULK_PIN(LCD_DATA17),
> -};
> -
> -static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
> -{
> -	unsigned int num;
> -
> -	switch (jzfb->pdata->lcd_type) {
> -	case JZ_LCD_TYPE_GENERIC_16_BIT:
> -		num = 4;
> -		break;
> -	case JZ_LCD_TYPE_GENERIC_18_BIT:
> -		num = 4;
> -		break;
> -	case JZ_LCD_TYPE_8BIT_SERIAL:
> -		num = 3;
> -		break;
> -	case JZ_LCD_TYPE_SPECIAL_TFT_1:
> -	case JZ_LCD_TYPE_SPECIAL_TFT_2:
> -	case JZ_LCD_TYPE_SPECIAL_TFT_3:
> -		num = 8;
> -		break;
> -	default:
> -		num = 0;
> -		break;
> -	}
> -	return num;
> -}
> -
> -static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
> -{
> -	unsigned int num;
> -
> -	switch (jzfb->pdata->lcd_type) {
> -	case JZ_LCD_TYPE_GENERIC_16_BIT:
> -		num = 16;
> -		break;
> -	case JZ_LCD_TYPE_GENERIC_18_BIT:
> -		num = 18;
> -		break;
> -	case JZ_LCD_TYPE_8BIT_SERIAL:
> -		num = 8;
> -		break;
> -	case JZ_LCD_TYPE_SPECIAL_TFT_1:
> -	case JZ_LCD_TYPE_SPECIAL_TFT_2:
> -	case JZ_LCD_TYPE_SPECIAL_TFT_3:
> -		if (jzfb->pdata->bpp == 18)
> -			num = 18;
> -		else
> -			num = 16;
> -		break;
> -	default:
> -		num = 0;
> -		break;
> -	}
> -	return num;
> -}
> -
>  /* Based on CNVT_TOHW macro from skeletonfb.c */
>  static inline uint32_t jzfb_convert_color_to_hw(unsigned val,
>  	struct fb_bitfield *bf)
> @@ -487,8 +400,7 @@ static void jzfb_enable(struct jzfb *jzfb)
>  
>  	clk_prepare_enable(jzfb->ldclk);
>  
> -	jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
> -	jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
> +	pinctrl_pm_select_default_state(&jzfb->pdev->dev);
>  
>  	writel(0, jzfb->base + JZ_REG_LCD_STATE);
>  
> @@ -511,8 +423,7 @@ static void jzfb_disable(struct jzfb *jzfb)
>  		ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
>  	} while (!(ctrl & JZ_LCD_STATE_DISABLED));
>  
> -	jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
> -	jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
> +	pinctrl_pm_select_sleep_state(&jzfb->pdev->dev);
>  
>  	clk_disable_unprepare(jzfb->ldclk);
>  }
> @@ -701,9 +612,6 @@ static int jzfb_probe(struct platform_device *pdev)
>  	fb->mode = NULL;
>  	jzfb_set_par(fb);
>  
> -	jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
> -	jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
> -
>  	ret = register_framebuffer(fb);
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
> @@ -715,9 +623,6 @@ static int jzfb_probe(struct platform_device *pdev)
>  	return 0;
>  
>  err_free_devmem:
> -	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
> -	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
> -
>  	fb_dealloc_cmap(&fb->cmap);
>  	jzfb_free_devmem(jzfb);
>  err_framebuffer_release:
> @@ -731,9 +636,6 @@ static int jzfb_remove(struct platform_device *pdev)
>  
>  	jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
>  
> -	jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
> -	jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
> -
>  	fb_dealloc_cmap(&jzfb->fb->cmap);
>  	jzfb_free_devmem(jzfb);

[toc] | [prev] | [next] | [standalone]


#1566863 — [PATCH v3 03/14] pinctrl-ingenic: add a pinctrl driver for the Ingenic jz47xx SoCs

FromPaul Cercueil <paul@crapouillou.net>
Date2017-01-25 20:00 +0100
Subject[PATCH v3 03/14] pinctrl-ingenic: add a pinctrl driver for the Ingenic jz47xx SoCs
Message-ID<t3AXw-5pP-41@gated-at.bofh.it>
In reply to#1566846
This driver handles pin configuration and pin muxing for the
JZ4740 and JZ4780 SoCs from Ingenic.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 drivers/pinctrl/Kconfig           |   8 +
 drivers/pinctrl/Makefile          |   1 +
 drivers/pinctrl/pinctrl-ingenic.c | 488 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 497 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-ingenic.c

v2: Consider it's a new patch. Completely rewritten from v1.
v3: 'unsigned' -> 'unsigned int'

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 8f8c2af45781..2312e21ca48d 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -285,6 +285,14 @@ config PINCTRL_ZYNQ
 	help
 	  This selects the pinctrl driver for Xilinx Zynq.
 
+config PINCTRL_INGENIC
+	bool "Pinctrl driver for the Ingenic JZ47xx SoCs"
+	default y
+	depends on MACH_INGENIC || COMPILE_TEST
+	select GENERIC_PINCONF
+	select GENERIC_PINCTRL_GROUPS
+	select GENERIC_PINMUX_FUNCTIONS
+
 source "drivers/pinctrl/aspeed/Kconfig"
 source "drivers/pinctrl/bcm/Kconfig"
 source "drivers/pinctrl/berlin/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index a251f439626f..80f327239d4b 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_LPC18XX)	+= pinctrl-lpc18xx.o
 obj-$(CONFIG_PINCTRL_TB10X)	+= pinctrl-tb10x.o
 obj-$(CONFIG_PINCTRL_ST) 	+= pinctrl-st.o
 obj-$(CONFIG_PINCTRL_ZYNQ)	+= pinctrl-zynq.o
+obj-$(CONFIG_PINCTRL_INGENIC)	+= pinctrl-ingenic.o
 
 obj-$(CONFIG_ARCH_ASPEED)	+= aspeed/
 obj-y				+= bcm/
diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
new file mode 100644
index 000000000000..ce36cf509eb1
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -0,0 +1,488 @@
+/*
+ * Ingenic SoCs pinctrl driver
+ *
+ * Copyright (c) 2017 Paul Cercueil <paul@crapouillou.net>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/compiler.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "core.h"
+#include "pinconf.h"
+#include "pinmux.h"
+
+#define JZ4740_GPIO_DATA	0x10
+#define JZ4740_GPIO_PULL_DIS	0x30
+#define JZ4740_GPIO_FUNC	0x40
+#define JZ4740_GPIO_SELECT	0x50
+#define JZ4740_GPIO_DIR		0x60
+#define JZ4740_GPIO_TRIG	0x70
+#define JZ4740_GPIO_FLAG	0x80
+
+#define JZ4780_GPIO_INT		0x10
+#define JZ4780_GPIO_MSK		0x20
+#define JZ4780_GPIO_PAT1	0x30
+#define JZ4780_GPIO_PAT0	0x40
+#define JZ4780_GPIO_FLAG	0x50
+#define JZ4780_GPIO_PEN		0x70
+
+#define REG_SET(x) ((x) + 0x4)
+#define REG_CLEAR(x) ((x) + 0x8)
+
+#define PINS_PER_GPIO_CHIP 32
+#define NUM_MAX_GPIO_CHIPS 6
+
+enum jz_version {
+	ID_JZ4740,
+	ID_JZ4780,
+};
+
+struct ingenic_pinctrl {
+	struct device *dev;
+	void __iomem *base;
+	struct pinctrl_dev *pctl;
+	struct pinctrl_pin_desc *pdesc;
+	enum jz_version version;
+
+	u32 pull_ups[NUM_MAX_GPIO_CHIPS];
+	u32 pull_downs[NUM_MAX_GPIO_CHIPS];
+};
+
+static inline void ingenic_config_pin(struct ingenic_pinctrl *jzpc,
+		unsigned int pin, u8 reg, bool set)
+{
+	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
+	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
+
+	writel(BIT(idx), jzpc->base + offt * 0x100 +
+			(set ? REG_SET(reg) : REG_CLEAR(reg)));
+}
+
+static inline bool ingenic_get_pin_config(struct ingenic_pinctrl *jzpc,
+		unsigned int pin, u8 reg)
+{
+	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
+	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
+
+	return readl(jzpc->base + offt * 0x100 + reg) & BIT(idx);
+}
+
+static struct pinctrl_ops ingenic_pctlops = {
+	.get_groups_count = pinctrl_generic_get_group_count,
+	.get_group_name = pinctrl_generic_get_group_name,
+	.get_group_pins = pinctrl_generic_get_group_pins,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+	.dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc,
+		int pin, int func)
+{
+	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
+	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
+
+	dev_dbg(jzpc->dev, "set pin P%c%u to function %u\n",
+			'A' + offt, idx, func);
+
+	if (jzpc->version >= ID_JZ4780) {
+		ingenic_config_pin(jzpc, pin, JZ4780_GPIO_INT, false);
+		ingenic_config_pin(jzpc, pin, JZ4780_GPIO_MSK, false);
+		ingenic_config_pin(jzpc, pin, JZ4780_GPIO_PAT1, func & 0x2);
+		ingenic_config_pin(jzpc, pin, JZ4780_GPIO_PAT0, func & 0x1);
+	} else {
+		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, true);
+		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_TRIG, func & 0x2);
+		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func > 0);
+	}
+
+	return 0;
+}
+
+static int ingenic_pinmux_set_mux(struct pinctrl_dev *pctldev,
+		unsigned int selector, unsigned int group)
+{
+	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
+	struct function_desc *func;
+	struct group_desc *grp;
+	unsigned int i;
+
+	func = pinmux_generic_get_function(pctldev, selector);
+	if (!func)
+		return -EINVAL;
+
+	grp = pinctrl_generic_get_group(pctldev, group);
+	if (!grp)
+		return -EINVAL;
+
+	dev_dbg(pctldev->dev, "enable function %s group %s\n",
+		func->name, grp->name);
+
+	for (i = 0; i < grp->num_pins; i++) {
+		int *pin_modes = grp->data;
+
+		ingenic_pinmux_set_pin_fn(jzpc, grp->pins[i], pin_modes[i]);
+	}
+
+	return 0;
+}
+
+static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range,
+		unsigned int pin, bool input)
+{
+	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
+	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
+
+	dev_dbg(pctldev->dev, "set pin P%c%u to %sput\n",
+			'A' + offt, idx, input ? "in" : "out");
+
+	if (jzpc->version >= ID_JZ4780) {
+		ingenic_config_pin(jzpc, pin, JZ4780_GPIO_INT, false);
+		ingenic_config_pin(jzpc, pin, JZ4780_GPIO_MSK, true);
+		ingenic_config_pin(jzpc, pin, JZ4780_GPIO_PAT1, input);
+	} else {
+		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false);
+		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, input);
+		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, false);
+	}
+
+	return 0;
+}
+
+static struct pinmux_ops ingenic_pmxops = {
+	.get_functions_count = pinmux_generic_get_function_count,
+	.get_function_name = pinmux_generic_get_function_name,
+	.get_function_groups = pinmux_generic_get_function_groups,
+	.set_mux = ingenic_pinmux_set_mux,
+	.gpio_set_direction = ingenic_pinmux_gpio_set_direction,
+};
+
+static int ingenic_pinconf_get(struct pinctrl_dev *pctldev,
+		unsigned int pin, unsigned long *config)
+{
+	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
+	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
+	bool pull;
+
+	if (jzpc->version >= ID_JZ4780)
+		pull = !ingenic_get_pin_config(jzpc, pin, JZ4780_GPIO_PEN);
+	else
+		pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		if (pull)
+			return -EINVAL;
+		break;
+
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (!pull || !(jzpc->pull_ups[offt] & BIT(idx)))
+			return -EINVAL;
+		break;
+
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (!pull || !(jzpc->pull_downs[offt] & BIT(idx)))
+			return -EINVAL;
+		break;
+
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, 1);
+	return 0;
+}
+
+static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
+		unsigned int pin, bool enabled)
+{
+	if (jzpc->version >= ID_JZ4780)
+		ingenic_config_pin(jzpc, pin, JZ4780_GPIO_PEN, !enabled);
+	else
+		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_PULL_DIS, !enabled);
+}
+
+static int ingenic_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+		unsigned long *configs, unsigned int num_configs)
+{
+	struct ingenic_pinctrl *jzpc = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int idx = pin % PINS_PER_GPIO_CHIP;
+	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
+	unsigned int cfg;
+
+	for (cfg = 0; cfg < num_configs; cfg++) {
+		switch (pinconf_to_config_param(configs[cfg])) {
+		case PIN_CONFIG_BIAS_DISABLE:
+		case PIN_CONFIG_BIAS_PULL_UP:
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			continue;
+		default:
+			return -ENOTSUPP;
+		}
+	}
+
+	for (cfg = 0; cfg < num_configs; cfg++) {
+		switch (pinconf_to_config_param(configs[cfg])) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			dev_dbg(jzpc->dev, "disable pull-over for pin P%c%u\n",
+					'A' + offt, idx);
+			ingenic_set_bias(jzpc, pin, false);
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_UP:
+			if (!(jzpc->pull_ups[offt] & BIT(idx)))
+				return -EINVAL;
+			dev_dbg(jzpc->dev, "set pull-up for pin P%c%u\n",
+					'A' + offt, idx);
+			ingenic_set_bias(jzpc, pin, true);
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			if (!(jzpc->pull_downs[offt] & BIT(idx)))
+				return -EINVAL;
+			dev_dbg(jzpc->dev, "set pull-down for pin P%c%u\n",
+					'A' + offt, idx);
+			ingenic_set_bias(jzpc, pin, true);
+			break;
+
+		default:
+			unreachable();
+		}
+	}
+
+	return 0;
+}
+
+static int ingenic_pinconf_group_get(struct pinctrl_dev *pctldev,
+		unsigned int group, unsigned long *config)
+{
+	const unsigned int *pins;
+	unsigned int i, npins, old = 0;
+	int ret;
+
+	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < npins; i++) {
+		if (ingenic_pinconf_get(pctldev, pins[i], config))
+			return -ENOTSUPP;
+
+		/* configs do not match between two pins */
+		if (i && (old != *config))
+			return -ENOTSUPP;
+
+		old = *config;
+	}
+
+	return 0;
+}
+
+static int ingenic_pinconf_group_set(struct pinctrl_dev *pctldev,
+		unsigned int group, unsigned long *configs,
+		unsigned int num_configs)
+{
+	const unsigned int *pins;
+	unsigned int i, npins;
+	int ret;
+
+	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < npins; i++) {
+		ret = ingenic_pinconf_set(pctldev,
+				pins[i], configs, num_configs);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static struct pinconf_ops ingenic_confops = {
+	.is_generic = true,
+	.pin_config_get = ingenic_pinconf_get,
+	.pin_config_set = ingenic_pinconf_set,
+	.pin_config_group_get = ingenic_pinconf_group_get,
+	.pin_config_group_set = ingenic_pinconf_group_set,
+};
+
+static int ingenic_pinctrl_parse_dt_func(struct ingenic_pinctrl *jzpc,
+		struct device_node *np)
+{
+	unsigned int num_groups;
+	struct device_node *group_node;
+	unsigned int i, j;
+	int err, npins, *pins, *confs;
+	const char **groups;
+
+	num_groups = of_get_child_count(np);
+	groups = devm_kzalloc(jzpc->dev,
+			sizeof(*groups) * num_groups, GFP_KERNEL);
+	if (!groups)
+		return -ENOMEM;
+
+	i = 0;
+	for_each_child_of_node(np, group_node) {
+		groups[i++] = group_node->name;
+
+		npins = of_property_count_elems_of_size(group_node,
+				"ingenic,pins", 8);
+		if (npins < 0)
+			return npins;
+
+		pins = devm_kzalloc(jzpc->dev,
+				sizeof(*pins) * npins, GFP_KERNEL);
+		confs = devm_kzalloc(jzpc->dev,
+				sizeof(*confs) * npins, GFP_KERNEL);
+		if (!pins || !confs)
+			return -ENOMEM;
+
+		for (j = 0; j < npins; j++) {
+			of_property_read_u32_index(group_node,
+					"ingenic,pins", j * 2, &pins[j]);
+
+			of_property_read_u32_index(group_node,
+					"ingenic,pins", j * 2 + 1, &confs[j]);
+		}
+
+		err = pinctrl_generic_add_group(jzpc->pctl, group_node->name,
+				pins, npins, confs);
+		if (err)
+			return err;
+	}
+
+	return pinmux_generic_add_function(jzpc->pctl, np->name,
+			groups, num_groups, NULL);
+}
+
+static const struct of_device_id ingenic_pinctrl_of_match[] = {
+	{ .compatible = "ingenic,jz4740-pinctrl", .data = (void *) ID_JZ4740 },
+	{ .compatible = "ingenic,jz4780-pinctrl", .data = (void *) ID_JZ4780 },
+	{},
+};
+
+int ingenic_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ingenic_pinctrl *jzpc;
+	struct pinctrl_desc *pctl_desc;
+	struct device_node *np, *functions_node;
+	const struct of_device_id *of_id = of_match_device(
+			ingenic_pinctrl_of_match, dev);
+	unsigned int i, num_chips;
+	int err;
+
+	jzpc = devm_kzalloc(dev, sizeof(*jzpc), GFP_KERNEL);
+	if (!jzpc)
+		return -ENOMEM;
+
+	jzpc->base = of_iomap(dev->of_node, 0);
+	if (!jzpc->base) {
+		dev_err(dev, "failed to map IO memory\n");
+		return -ENXIO;
+	}
+
+	jzpc->dev = dev;
+	dev_set_drvdata(dev, jzpc);
+
+	jzpc->version = (enum jz_version)of_id->data;
+
+	if (jzpc->version >= ID_JZ4780)
+		num_chips = 6;
+	else
+		num_chips = 4;
+
+	/*
+	 * Read the ingenic,pull-ups and ingenic,pull-downs arrays if present in
+	 * the devicetree. Otherwise set all bits to 0xff to consider that
+	 * pull-over resistors are available on all pins.
+	 */
+	err = of_property_read_u32_array(dev->of_node, "ingenic,pull-ups",
+			jzpc->pull_ups, num_chips);
+	if (err)
+		memset(jzpc->pull_ups, 0xff, sizeof(jzpc->pull_ups));
+
+	err = of_property_read_u32_array(dev->of_node, "ingenic,pull-downs",
+			jzpc->pull_downs, num_chips);
+	if (err)
+		memset(jzpc->pull_downs, 0xff, sizeof(jzpc->pull_downs));
+
+	functions_node = of_find_node_by_name(dev->of_node, "functions");
+	if (!functions_node) {
+		dev_err(dev, "Missing \"functions\" devicetree node\n");
+		return -EINVAL;
+	}
+
+	pctl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctl_desc), GFP_KERNEL);
+	if (!pctl_desc)
+		return -ENOMEM;
+
+	/* fill in pinctrl_desc structure */
+	pctl_desc->name = dev_name(dev);
+	pctl_desc->owner = THIS_MODULE;
+	pctl_desc->pctlops = &ingenic_pctlops;
+	pctl_desc->pmxops = &ingenic_pmxops;
+	pctl_desc->confops = &ingenic_confops;
+	pctl_desc->npins = num_chips * PINS_PER_GPIO_CHIP;
+	pctl_desc->pins = jzpc->pdesc = devm_kzalloc(&pdev->dev,
+			sizeof(*jzpc->pdesc) * pctl_desc->npins, GFP_KERNEL);
+	if (!jzpc->pdesc)
+		return -ENOMEM;
+
+	for (i = 0; i < pctl_desc->npins; i++) {
+		jzpc->pdesc[i].number = i;
+		jzpc->pdesc[i].name = kasprintf(GFP_KERNEL, "P%c%d",
+						'A' + (i / PINS_PER_GPIO_CHIP),
+						i % PINS_PER_GPIO_CHIP);
+	}
+
+	jzpc->pctl = devm_pinctrl_register(dev, pctl_desc, jzpc);
+	if (!jzpc->pctl) {
+		dev_err(dev, "Failed pinctrl registration\n");
+		return -EINVAL;
+	}
+
+	for_each_child_of_node(functions_node, np) {
+		err = ingenic_pinctrl_parse_dt_func(jzpc, np);
+		if (err) {
+			dev_err(dev, "failed to parse function %s\n",
+					np->full_name);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+static struct platform_driver ingenic_pinctrl_driver = {
+	.driver = {
+		.name = "pinctrl-ingenic",
+		.of_match_table = of_match_ptr(ingenic_pinctrl_of_match),
+		.suppress_bind_attrs = true,
+	},
+	.probe = ingenic_pinctrl_probe,
+};
+
+static int __init ingenic_pinctrl_drv_register(void)
+{
+	return platform_driver_register(&ingenic_pinctrl_driver);
+}
+postcore_initcall(ingenic_pinctrl_drv_register);
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1570769 — Re: [PATCH v3 03/14] pinctrl-ingenic: add a pinctrl driver for the Ingenic jz47xx SoCs

FromLinus Walleij <linus.walleij@linaro.org>
Date2017-01-31 15:10 +0100
SubjectRe: [PATCH v3 03/14] pinctrl-ingenic: add a pinctrl driver for the Ingenic jz47xx SoCs
Message-ID<t5Hia-1EP-23@gated-at.bofh.it>
In reply to#1566863
On Wed, Jan 25, 2017 at 7:51 PM, Paul Cercueil <paul@crapouillou.net> wrote:

> This driver handles pin configuration and pin muxing for the
> JZ4740 and JZ4780 SoCs from Ingenic.
>
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>

This is starting to look very nice.

> +#include <linux/compiler.h>
> +#include <linux/gpio.h>

Use <linux/gpio/driver.h> if it is a GPIO driver. I should
be enough ... I think.

> +static int ingenic_pinctrl_parse_dt_func(struct ingenic_pinctrl *jzpc,
> +               struct device_node *np)
> +{
> +       unsigned int num_groups;
> +       struct device_node *group_node;
> +       unsigned int i, j;
> +       int err, npins, *pins, *confs;
> +       const char **groups;
> +
> +       num_groups = of_get_child_count(np);
> +       groups = devm_kzalloc(jzpc->dev,
> +                       sizeof(*groups) * num_groups, GFP_KERNEL);
> +       if (!groups)
> +               return -ENOMEM;
> +
> +       i = 0;
> +       for_each_child_of_node(np, group_node) {
> +               groups[i++] = group_node->name;
> +
> +               npins = of_property_count_elems_of_size(group_node,
> +                               "ingenic,pins", 8);
> +               if (npins < 0)
> +                       return npins;
> +
> +               pins = devm_kzalloc(jzpc->dev,
> +                               sizeof(*pins) * npins, GFP_KERNEL);
> +               confs = devm_kzalloc(jzpc->dev,
> +                               sizeof(*confs) * npins, GFP_KERNEL);
> +               if (!pins || !confs)
> +                       return -ENOMEM;
> +
> +               for (j = 0; j < npins; j++) {
> +                       of_property_read_u32_index(group_node,
> +                                       "ingenic,pins", j * 2, &pins[j]);
> +
> +                       of_property_read_u32_index(group_node,
> +                                       "ingenic,pins", j * 2 + 1, &confs[j]);

If I didn't mention before this could pperhaps just use "pins"?

Or does these DT entries not match the generic bindings?

> +               }
> +
> +               err = pinctrl_generic_add_group(jzpc->pctl, group_node->name,
> +                               pins, npins, confs);
> +               if (err)
> +                       return err;
> +       }
> +
> +       return pinmux_generic_add_function(jzpc->pctl, np->name,
> +                       groups, num_groups, NULL);
> +}

If you just use "pins" can this even be parsed by a generic parser function
pinconf_generic_dt_subnode_to_map()?

Yours,
Linus Walleij

[toc] | [prev] | [next] | [standalone]


#1570774 — Re: [PATCH v3 03/14] pinctrl-ingenic: add a pinctrl driver for the Ingenic jz47xx SoCs

FromPaul Cercueil <paul@crapouillou.net>
Date2017-01-31 15:20 +0100
SubjectRe: [PATCH v3 03/14] pinctrl-ingenic: add a pinctrl driver for the Ingenic jz47xx SoCs
Message-ID<t5HrP-1HV-13@gated-at.bofh.it>
In reply to#1570769
Le 2017-01-31 15:05, Linus Walleij a écrit :

> If I didn't mention before this could pperhaps just use "pins"?

You commented this on v2 after I sent the v3 :)
I will fix it for v4.

> If you just use "pins" can this even be parsed by a generic parser 
> function
> pinconf_generic_dt_subnode_to_map()?

I'll take a look. Thanks.

Regards,
-Paul

[toc] | [prev] | [next] | [standalone]


#1562437

FromLinus Walleij <linus.walleij@linaro.org>
Date2017-01-19 07:50 +0100
Message-ID<t1eHM-6qK-11@gated-at.bofh.it>
In reply to#1561092
On Wed, Jan 18, 2017 at 12:14 AM, Paul Cercueil <paul@crapouillou.net> wrote:

> One problem still unresolved: the pinctrl framework does not allow us to
> configure each pin on demand (someone please prove me wrong), when the
> various PWM channels are requested or released. For instance, the PWM
> channels can be configured from sysfs, which would require all PWM pins
> to be configured properly beforehand for the PWM function, eventually
> causing conflicts with other platform or board drivers.

Why do you think this?

- Pincontrol handles can be obtained at runtime.
- Pincontrol states can be changed at runtime.

The fact that a the handle is retrived by the device core and set to
the states named "init" or "default" during boot is just a convenience.

You can have as many and as fine-grained states as you want. They
can pertain to just one pin too.

Linus Walleij

[toc] | [prev] | [standalone]


Page 4 of 4 — ← Prev page 1 2 3 [4]

Back to top | Article view | linux.kernel


csiph-web