2016-04-28 09:05:45

by Christian Lamparter

[permalink] [raw]
Subject: [RFC v4 0/8] gpio: add DT support for generic memory-mapped GPIOs

This patch series adds device tree support for generic memory-mapped GPIOs.
The GPIO library already allows drivers and architecture support code to
reuse generic code for managing a GPIO chip. Currently, a developer has
to create a platform device "basic-mmio-gpio" and attach a bgpio_pdata
platform data structure to make use of it. However, for architectures
which rely on the device tree to enumerate devices, creating custom
platform devices is another extra step that can be avoided by having
direct support via a device tree binding.

I initially came across this patch [0] from Álvaro Fernández Rojas,
while looking for an easy way to add support for the GPIO of my
WD MyBook Live [1] (APM82181 - ppc464). This generic approach patch
allowed me to easily get the GPIO (and the connected LEDs,
buttons, gpiohogs, etc.) up and running. Even tought, Mr. Fernandez
initially developed it for his work on the brcm63xx [2].

[0] <https://patchwork.ozlabs.org/patch/422121/>
[1] <https://github.com/chunkeey/MBL-openwrt>
[2] <https://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm63xx>

Currently, the device tree parses for the integrated drivers
(gpio-clps711x, gpio-ge, gpio-moxart and gpio-ts4800) are still
residing in their original driver .c file. This way, these
drivers don't clutter the gpio-generic.c with their own hardware
definitions and MODULE_* statements. I hoped this would make the
transition from the _probe to the parser less painless but the diff
is retty much unreadable. So the next series will consolidate them
into gpio-generic.c and then I can drop the gpio-generic -> gpio-mmio
change. I think this is now mostly a matter of how to organize things
and why not try it just once just so it was tested.

changelog:

v3 -> v4:
- renamed gpio-generic.c to gpio-mmio.c
(The gpio-generic only contains a generic mmio driver,
this confuses and angers people!)
- changed compat. string to "linux,gpio-mmio"
- integrated Cirrus clps711x driver
- integrated GE FGPA gpio-ge driver
- integrated MOXA ART GPIO driver
- integrated TS4800 gpio driver
- reshuffled patches, reworded commits, fixed spelling errors, etc.

Thanks! (Please keep me in the CC)
---
Christian Lamparter (6):
gpio: generic: fix GPIO_GENERIC_PLATFORM is set to module case
gpio: rename gpio-generic.c into gpio-mmio.c
gpio: clps711x: integrate cirrus clps711x into gpio-mmio
gpio: ge: integrate GE's FPGA GPIO into gpio-mmio
gpio: moxart: integrate MOXA ART GPIO driver into gpio-mmio
gpio: ts4800: integrate TS4800 into gpio-mmio

Álvaro Fernández Rojas (2):
gpio: generic: add DT support for generic memory-mapped GPIOs
gpio: dt-bindings: add gpio-mmio bindings

.../devicetree/bindings/gpio/gpio-mmio.txt | 73 +++++++++++++++
drivers/gpio/Kconfig | 57 ++++++------
drivers/gpio/Makefile | 11 ++-
drivers/gpio/gpio-clps711x.c | 84 ++++++-----------
drivers/gpio/gpio-ge.c | 101 ++++++---------------
drivers/gpio/gpio-mmio-compat.h | 65 +++++++++++++
drivers/gpio/{gpio-generic.c => gpio-mmio.c} | 101 ++++++++++++++++++++-
drivers/gpio/gpio-moxart.c | 81 +++++------------
drivers/gpio/gpio-ts4800.c | 76 +++++-----------
9 files changed, 376 insertions(+), 273 deletions(-)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-mmio.txt
create mode 100644 drivers/gpio/gpio-mmio-compat.h
rename drivers/gpio/{gpio-generic.c => gpio-mmio.c} (86%)

--
2.8.1


2016-04-28 09:07:12

by Christian Lamparter

[permalink] [raw]
Subject: [RFC v4 7/8] gpio: ts4800: integrate TS4800 into gpio-mmio

This patch integrates the TS4800 FPGA GPIO driver into
the gpio-mmio framework.

Signed-off-by: Christian Lamparter <[email protected]>
---
drivers/gpio/Kconfig | 17 ++++-----
drivers/gpio/Makefile | 2 +-
drivers/gpio/gpio-mmio-compat.h | 11 ++++++
drivers/gpio/gpio-mmio.c | 1 +
drivers/gpio/gpio-ts4800.c | 76 ++++++++++++++---------------------------
5 files changed, 47 insertions(+), 60 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 487297f..7d88527 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -220,6 +220,15 @@ config GPIO_MOXART
help
Select this option to enable GPIO driver for
MOXA ART SoC devices.
+
+config GPIO_TS4800
+ bool "TS-4800 DIO blocks and compatibles"
+ depends on OF_GPIO
+ depends on SOC_IMX51 || COMPILE_TEST
+ select GPIO_GENERIC
+ help
+ This driver support TS-4800 FPGA GPIO controllers.
+
endif

config GPIO_GRGPIO
@@ -407,14 +416,6 @@ config GPIO_TEGRA
default y
depends on ARCH_TEGRA || COMPILE_TEST

-config GPIO_TS4800
- tristate "TS-4800 DIO blocks and compatibles"
- depends on OF_GPIO
- depends on SOC_IMX51 || COMPILE_TEST
- select GPIO_GENERIC
- help
- This driver support TS-4800 FPGA GPIO controllers.
-
config GPIO_TZ1090
bool "Toumaz Xenif TZ1090 GPIO support"
depends on SOC_TZ1090
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 32ad5fe..f9e5036 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -17,6 +17,7 @@ gpio-generic-$(CONFIG_GPIO_GENERIC) += gpio-mmio.o
gpio-generic-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
gpio-generic-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
gpio-generic-$(CONFIG_GPIO_MOXART) += gpio-moxart.o
+gpio-generic-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o

obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o
obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o
@@ -107,7 +108,6 @@ obj-$(CONFIG_GPIO_TPS65218) += gpio-tps65218.o
obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
-obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o
obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
diff --git a/drivers/gpio/gpio-mmio-compat.h b/drivers/gpio/gpio-mmio-compat.h
index 702a384..a85835b 100644
--- a/drivers/gpio/gpio-mmio-compat.h
+++ b/drivers/gpio/gpio-mmio-compat.h
@@ -42,6 +42,17 @@ int moxart_parse_dt(struct platform_device *pdev,
#define GPIO_MOXART_COMPATIBLE
#endif /* CONFIG_GPIO_MOXART */

+#if IS_ENABLED(CONFIG_GPIO_TS4800)
+int technologic_ts4800_parse_dt(struct platform_device *pdev,
+ struct bgpio_pdata *pdata,
+ unsigned long *flags);
+
+#define GPIO_TS4800_COMPATIBLE \
+ ADD("technologic,ts4800-gpio", technologic_ts4800_parse_dt),
+#else
+#define GPIO_TS4800_COMPATIBLE
+#endif /* CONFIG_GPIO_TS4800 */
+
#undef ADD

static inline void set_resource_address(struct resource *res,
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index fdaf701..9f2cb2c 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -611,6 +611,7 @@ static const struct of_device_id bgpio_of_match[] = {
GPIO_CLPS711X_COMPATIBLE
GPIO_GE_FPGA_COMPATIBLE
GPIO_MOXART_COMPATIBLE
+ GPIO_TS4800_COMPATIBLE

{ }
};
diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c
index 0c144a7..5003655 100644
--- a/drivers/gpio/gpio-ts4800.c
+++ b/drivers/gpio/gpio-ts4800.c
@@ -8,74 +8,48 @@
* warranty of any kind, whether express or implied.
*/

+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
#include <linux/gpio/driver.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include "gpio-mmio-compat.h"

#define DEFAULT_PIN_NUMBER 16
#define INPUT_REG_OFFSET 0x00
#define OUTPUT_REG_OFFSET 0x02
#define DIRECTION_REG_OFFSET 0x04

-static int ts4800_gpio_probe(struct platform_device *pdev)
+int technologic_ts4800_parse_dt(struct platform_device *pdev,
+ struct bgpio_pdata *pdata,
+ unsigned long *flags)
{
- struct device_node *node;
- struct gpio_chip *chip;
+ int err;
struct resource *res;
- void __iomem *base_addr;
- int retval;
- u32 ngpios;
-
- chip = devm_kzalloc(&pdev->dev, sizeof(struct gpio_chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
+ struct resource nres[] = {
+ DEFINE_RES_MEM_NAMED(0, 1, "dat"),
+ DEFINE_RES_MEM_NAMED(0, 1, "set"),
+ DEFINE_RES_MEM_NAMED(0, 1, "dirout"),
+ };

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base_addr = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(base_addr))
- return PTR_ERR(base_addr);
-
- node = pdev->dev.of_node;
- if (!node)
+ if (!res || resource_size(res) != 6)
return -EINVAL;

- retval = of_property_read_u32(node, "ngpios", &ngpios);
- if (retval == -EINVAL)
- ngpios = DEFAULT_PIN_NUMBER;
- else if (retval)
- return retval;
-
- retval = bgpio_init(chip, &pdev->dev, 2, base_addr + INPUT_REG_OFFSET,
- base_addr + OUTPUT_REG_OFFSET, NULL,
- base_addr + DIRECTION_REG_OFFSET, NULL, 0);
- if (retval) {
- dev_err(&pdev->dev, "bgpio_init failed\n");
- return retval;
- }
-
- chip->ngpio = ngpios;
+ set_resource_address(&nres[0], res->start + INPUT_REG_OFFSET, 0x2);
+ set_resource_address(&nres[1], res->start + OUTPUT_REG_OFFSET, 0x2);
+ set_resource_address(&nres[2], res->start + DIRECTION_REG_OFFSET, 0x2);

- platform_set_drvdata(pdev, chip);
+ err = of_property_read_u32(pdev->dev.of_node, "ngpios", &pdata->ngpio);
+ if (err == -EINVAL)
+ pdata->ngpio = DEFAULT_PIN_NUMBER;
+ else if (err)
+ return err;

- return devm_gpiochip_add_data(&pdev->dev, chip, NULL);
+ return platform_device_add_resources(pdev, nres, ARRAY_SIZE(nres));
}

-static const struct of_device_id ts4800_gpio_of_match[] = {
- { .compatible = "technologic,ts4800-gpio", },
- {},
-};
-
-static struct platform_driver ts4800_gpio_driver = {
- .driver = {
- .name = "ts4800-gpio",
- .of_match_table = ts4800_gpio_of_match,
- },
- .probe = ts4800_gpio_probe,
-};
-
-module_platform_driver_probe(ts4800_gpio_driver, ts4800_gpio_probe);
-
MODULE_AUTHOR("Julien Grossholtz <[email protected]>");
MODULE_DESCRIPTION("TS4800 FPGA GPIO driver");
-MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("gpio-ts4800");
--
2.8.1

2016-04-28 09:07:18

by Christian Lamparter

[permalink] [raw]
Subject: [RFC v4 4/8] gpio: clps711x: integrate cirrus clps711x into gpio-mmio

This patch integrates the Cirrus' clps711x driver into the
gpio-mmio framework.

Signed-off-by: Christian Lamparter <[email protected]>
---
drivers/gpio/Kconfig | 14 +++----
drivers/gpio/Makefile | 2 +-
drivers/gpio/gpio-clps711x.c | 84 ++++++++++++++---------------------------
drivers/gpio/gpio-mmio-compat.h | 11 ++++++
drivers/gpio/gpio-mmio.c | 1 +
5 files changed, 48 insertions(+), 64 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d1f124e..ff9ac65 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -152,13 +152,6 @@ config GPIO_BRCMSTB
help
Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs.

-config GPIO_CLPS711X
- tristate "CLPS711X GPIO support"
- depends on ARCH_CLPS711X || COMPILE_TEST
- select GPIO_GENERIC
- help
- Say yes here to support GPIO on CLPS711X SoCs.
-
config GPIO_DAVINCI
bool "TI Davinci/Keystone GPIO support"
default y if ARCH_DAVINCI
@@ -213,6 +206,13 @@ config GPIO_GENERIC_PLATFORM
Say yes here to support basic platform_device memory-mapped GPIO controllers.

if GPIO_GENERIC_PLATFORM
+config GPIO_CLPS711X
+ bool "CLPS711X GPIO support"
+ depends on ARCH_CLPS711X || COMPILE_TEST
+ select GPIO_GENERIC
+ help
+ Say yes here to support GPIO on CLPS711X SoCs.
+
endif

config GPIO_GRGPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 991598e..a1ae48f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o

# directly supported by gpio-generic
gpio-generic-$(CONFIG_GPIO_GENERIC) += gpio-mmio.o
+gpio-generic-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o

obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o
obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o
@@ -31,7 +32,6 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
-obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
index 5a69025..2072d0f 100644
--- a/drivers/gpio/gpio-clps711x.c
+++ b/drivers/gpio/gpio-clps711x.c
@@ -9,83 +9,55 @@
* (at your option) any later version.
*/

-#include <linux/err.h>
+#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
+#include "gpio-mmio-compat.h"

-static int clps711x_gpio_probe(struct platform_device *pdev)
+int cirrus_clps711x_parse_dt(struct platform_device *pdev,
+ struct bgpio_pdata *pdata,
+ unsigned long *flags)
{
struct device_node *np = pdev->dev.of_node;
- void __iomem *dat, *dir;
- struct gpio_chip *gc;
+ int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
struct resource *res;
- int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id;
+ struct resource nres[] = {
+ DEFINE_RES_MEM_NAMED(0, 1, "dat"),
+ DEFINE_RES_MEM_NAMED(0, 1, "dirout"),
+ };

if ((id < 0) || (id > 4))
return -ENODEV;

- gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
- if (!gc)
- return -ENOMEM;
+ if (id == 4) {
+ /* PORTE is 3 lines only */
+ pdata->ngpio = 3;
+ }
+
+ pdata->base = id * 8;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dat = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(dat))
- return PTR_ERR(dat);
+ if (!res || resource_size(res) != 0x1)
+ return -EINVAL;
+ set_resource_address(&nres[0], res->start, 0x1);

res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- dir = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(dir))
- return PTR_ERR(dir);
+ if (!res || resource_size(res) != 0x1)
+ return -EINVAL;
+ set_resource_address(&nres[1], res->start, 0x1);

- switch (id) {
- case 3:
+ if (id == 3) {
/* PORTD is inverted logic for direction register */
- err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
- NULL, dir, 0);
- break;
- default:
- err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
- dir, NULL, 0);
- break;
- }
-
- if (err)
- return err;
-
- switch (id) {
- case 4:
- /* PORTE is 3 lines only */
- gc->ngpio = 3;
- break;
- default:
- break;
+ nres[1].name = "dirin";
}

- gc->base = id * 8;
- gc->owner = THIS_MODULE;
- platform_set_drvdata(pdev, gc);
-
- return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
+ return platform_device_add_resources(pdev, nres, ARRAY_SIZE(nres));
}

-static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {
- { .compatible = "cirrus,clps711x-gpio" },
- { }
-};
-MODULE_DEVICE_TABLE(of, clps711x_gpio_ids);
-
-static struct platform_driver clps711x_gpio_driver = {
- .driver = {
- .name = "clps711x-gpio",
- .of_match_table = of_match_ptr(clps711x_gpio_ids),
- },
- .probe = clps711x_gpio_probe,
-};
-module_platform_driver(clps711x_gpio_driver);
-
-MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Shiyan <[email protected]>");
MODULE_DESCRIPTION("CLPS711X GPIO driver");
MODULE_ALIAS("platform:clps711x-gpio");
+MODULE_ALIAS("clps711x-gpio");
diff --git a/drivers/gpio/gpio-mmio-compat.h b/drivers/gpio/gpio-mmio-compat.h
index 73c48bc..32b5510 100644
--- a/drivers/gpio/gpio-mmio-compat.h
+++ b/drivers/gpio/gpio-mmio-compat.h
@@ -5,6 +5,17 @@

#define ADD(_name, _func) { .compatible = _name, .data = _func }

+#if IS_ENABLED(CONFIG_GPIO_CLPS711X)
+int cirrus_clps711x_parse_dt(struct platform_device *pdev,
+ struct bgpio_pdata *pdata,
+ unsigned long *flags);
+
+#define GPIO_CLPS711X_COMPATIBLE \
+ ADD("cirrus,clps711x-gpio", cirrus_clps711x_parse_dt),
+#else
+#define GPIO_CLPS711X_COMPATIBLE
+#endif /* CONFIG_GPIO_CLPS711X */
+
#undef ADD

static inline void set_resource_address(struct resource *res,
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 4de9846..1be8cb7 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -608,6 +608,7 @@ static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,

static const struct of_device_id bgpio_of_match[] = {
ADD("linux,gpio-mmio", bgpio_basic_mmio_parse_dt),
+ GPIO_CLPS711X_COMPATIBLE

{ }
};
--
2.8.1

2016-04-28 09:05:46

by Christian Lamparter

[permalink] [raw]
Subject: [RFC v4 2/8] gpio: rename gpio-generic.c into gpio-mmio.c

This patch renames the gpio-generic.c into gpio-mmio.c.
This is because currently the file only contains code
for a memory-mapped GPIO driver. There isn't any support
for ioports or other resource type.

Signed-off-by: Christian Lamparter <[email protected]>
---
drivers/gpio/Makefile | 3 +++
drivers/gpio/{gpio-generic.c => gpio-mmio.c} | 0
2 files changed, 3 insertions(+)
rename drivers/gpio/{gpio-generic.c => gpio-mmio.c} (100%)

diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 74eb1a7..991598e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -12,6 +12,9 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
# Device drivers. Generally keep list sorted alphabetically
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o

+# directly supported by gpio-generic
+gpio-generic-$(CONFIG_GPIO_GENERIC) += gpio-mmio.o
+
obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o
obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o
obj-$(CONFIG_GPIO_104_IDI_48) += gpio-104-idi-48.o
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-mmio.c
similarity index 100%
rename from drivers/gpio/gpio-generic.c
rename to drivers/gpio/gpio-mmio.c
--
2.8.1

2016-04-28 09:07:22

by Christian Lamparter

[permalink] [raw]
Subject: [RFC v4 3/8] gpio: generic: add DT support for generic memory-mapped GPIOs

From: Álvaro Fernández Rojas <[email protected]>

This patch adds support for defining memory-mapped GPIOs
which provide a compatible interface for the existing
generic-gpio driver.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
Signed-off-by: Christian Lamparter <[email protected]>
---
drivers/gpio/Kconfig | 3 ++
drivers/gpio/gpio-mmio-compat.h | 17 ++++++++
drivers/gpio/gpio-mmio.c | 95 ++++++++++++++++++++++++++++++++++++++++-
3 files changed, 113 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpio/gpio-mmio-compat.h

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f73f26b..d1f124e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -212,6 +212,9 @@ config GPIO_GENERIC_PLATFORM
help
Say yes here to support basic platform_device memory-mapped GPIO controllers.

+if GPIO_GENERIC_PLATFORM
+endif
+
config GPIO_GRGPIO
tristate "Aeroflex Gaisler GRGPIO support"
depends on OF
diff --git a/drivers/gpio/gpio-mmio-compat.h b/drivers/gpio/gpio-mmio-compat.h
new file mode 100644
index 0000000..73c48bc
--- /dev/null
+++ b/drivers/gpio/gpio-mmio-compat.h
@@ -0,0 +1,17 @@
+#ifndef GPIO_MMIO_COMPAT_H
+#define GPIO_MMIO_COMPAT_H
+
+#include <linux/ioport.h>
+
+#define ADD(_name, _func) { .compatible = _name, .data = _func }
+
+#undef ADD
+
+static inline void set_resource_address(struct resource *res,
+ resource_size_t start,
+ resource_size_t len)
+{
+ res->start = start;
+ res->end = start + len - 1;
+}
+#endif /* GPIO_MMIO_COMPAT_H */
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 6c1cb3b..4de9846 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -61,6 +61,9 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.`
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include "gpio-mmio-compat.h"

static void bgpio_write8(void __iomem *reg, unsigned long data)
{
@@ -569,6 +572,83 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
return devm_ioremap_resource(&pdev->dev, r);
}

+#ifdef CONFIG_OF
+static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
+ struct bgpio_pdata *pdata,
+ unsigned long *flags)
+{
+ struct device *dev = &pdev->dev;
+ int err;
+
+ err = of_property_read_u32(dev->of_node, "ngpio", &pdata->ngpio);
+ if (err && err != -EINVAL)
+ return err;
+
+ if (of_device_is_big_endian(dev->of_node))
+ *flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
+
+ if (of_property_read_bool(dev->of_node, "unreadable-reg-set"))
+ *flags |= BGPIOF_UNREADABLE_REG_SET;
+
+ if (of_property_read_bool(dev->of_node, "unreadable-reg-dir"))
+ *flags |= BGPIOF_UNREADABLE_REG_DIR;
+
+ if (of_property_read_bool(dev->of_node, "big-endian-byte-order"))
+ *flags |= BGPIOF_BIG_ENDIAN;
+
+ if (of_property_read_bool(dev->of_node, "read-output-reg-set"))
+ *flags |= BGPIOF_READ_OUTPUT_REG_SET;
+
+ if (of_property_read_bool(dev->of_node, "no-output"))
+ *flags |= BGPIOF_NO_OUTPUT;
+ return 0;
+}
+
+#define ADD(_name, _func) { .compatible = _name, .data = _func }
+
+static const struct of_device_id bgpio_of_match[] = {
+ ADD("linux,gpio-mmio", bgpio_basic_mmio_parse_dt),
+
+ { }
+};
+#undef ADD
+MODULE_DEVICE_TABLE(of, bgpio_of_match);
+
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+ unsigned long *flags)
+{
+ int (*parse_dt)(struct platform_device *,
+ struct bgpio_pdata *, unsigned long *);
+ const struct device_node *node = pdev->dev.of_node;
+ const struct of_device_id *of_id;
+ struct bgpio_pdata *pdata;
+ int err = -ENODEV;
+
+ of_id = of_match_node(bgpio_of_match, node);
+ if (!of_id)
+ return NULL;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
+ GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ parse_dt = of_id->data;
+ if (parse_dt)
+ err = parse_dt(pdev, pdata, flags);
+ if (err)
+ return ERR_PTR(err);
+
+ return pdata;
+}
+#else
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+ unsigned long *flags)
+{
+ return NULL;
+}
+#endif /* CONFIG_OF */
+
static int bgpio_pdev_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -579,10 +659,18 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
void __iomem *dirout;
void __iomem *dirin;
unsigned long sz;
- unsigned long flags = pdev->id_entry->driver_data;
+ unsigned long flags = 0;
int err;
struct gpio_chip *gc;
- struct bgpio_pdata *pdata = dev_get_platdata(dev);
+ struct bgpio_pdata *pdata;
+
+ pdata = bgpio_parse_dt(pdev, &flags);
+ if (IS_ERR(pdata)) {
+ return PTR_ERR(pdata);
+ } else if (!pdata) {
+ pdata = dev_get_platdata(dev);
+ flags = pdev->id_entry->driver_data;
+ }

r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
if (!r)
@@ -646,6 +734,9 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
static struct platform_driver bgpio_driver = {
.driver = {
.name = "basic-mmio-gpio",
+#ifdef CONFIG_OF
+ .of_match_table = of_match_ptr(bgpio_of_match),
+#endif
},
.id_table = bgpio_id_table,
.probe = bgpio_pdev_probe,
--
2.8.1

2016-04-28 09:58:07

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [RFC v4 3/8] gpio: generic: add DT support for generic memory-mapped GPIOs

On Thu, Apr 28, 2016 at 12:05 PM, Christian Lamparter
<[email protected]> wrote:
> From: Álvaro Fernández Rojas <[email protected]>
>
> This patch adds support for defining memory-mapped GPIOs
> which provide a compatible interface for the existing
> generic-gpio driver.

> +static inline void set_resource_address(struct resource *res,
> + resource_size_t start,
> + resource_size_t len)
> +{
> + res->start = start;
> + res->end = start + len - 1;
> +}

It might make sense to put this in the generic (resource related, e.g.
ioport.h) header. There are plenty users of such already and who knows
how many will come.

> #include <linux/bitops.h>
> #include <linux/platform_device.h>
> #include <linux/mod_devicetable.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>

Perhaps + empty line?

> +#include "gpio-mmio-compat.h"

[]

> +#ifdef CONFIG_OF
> +static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
> + struct bgpio_pdata *pdata,
> + unsigned long *flags)
> +{
> + struct device *dev = &pdev->dev;
> + int err;
> +
> + err = of_property_read_u32(dev->of_node, "ngpio", &pdata->ngpio);
> + if (err && err != -EINVAL)
> + return err;

I think check for -EINVAL needs explanation.

> +}

[]

> + pdata = bgpio_parse_dt(pdev, &flags);
> + if (IS_ERR(pdata)) {
> + return PTR_ERR(pdata);

> + } else if (!pdata) {

Redundant else

> + pdata = dev_get_platdata(dev);
> + flags = pdev->id_entry->driver_data;
> + }
>
> r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
> if (!r)
> @@ -646,6 +734,9 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
> static struct platform_driver bgpio_driver = {
> .driver = {
> .name = "basic-mmio-gpio",

> +#ifdef CONFIG_OF

Doesn't of_match_ptr do this for you?


> + .of_match_table = of_match_ptr(bgpio_of_match),
> +#endif

--
With Best Regards,
Andy Shevchenko

2016-04-28 09:07:14

by Christian Lamparter

[permalink] [raw]
Subject: [RFC v4 5/8] gpio: ge: integrate GE's FPGA GPIO into gpio-mmio

This patch integrates the gpio-ge driver into the
gpio-mmio framework.

Signed-off-by: Christian Lamparter <[email protected]>
---
drivers/gpio/Kconfig | 24 +++++-----
drivers/gpio/Makefile | 2 +-
drivers/gpio/gpio-ge.c | 101 ++++++++++++----------------------------
drivers/gpio/gpio-mmio-compat.h | 14 ++++++
drivers/gpio/gpio-mmio.c | 1 +
5 files changed, 57 insertions(+), 85 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ff9ac65..a0e140d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -187,18 +187,6 @@ config GPIO_ETRAXFS
help
Say yes here to support the GPIO controller on Axis ETRAX FS SoCs.

-config GPIO_GE_FPGA
- bool "GE FPGA based GPIO"
- depends on GE_FPGA
- select GPIO_GENERIC
- help
- Support for common GPIO functionality provided on some GE Single Board
- Computers.
-
- This driver provides basic support (configure as input or output, read
- and write pin state) for GPIO implemented in a number of GE single
- board computers.
-
config GPIO_GENERIC_PLATFORM
tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
select GPIO_GENERIC
@@ -213,6 +201,18 @@ config GPIO_CLPS711X
help
Say yes here to support GPIO on CLPS711X SoCs.

+config GPIO_GE_FPGA
+ bool "GE FPGA based GPIO"
+ depends on GE_FPGA || COMPILE_TEST
+ select GPIO_GENERIC
+ help
+ Support for common GPIO functionality provided on some GE Single Board
+ Computers.
+
+ This driver provides basic support (configure as input or output, read
+ and write pin state) for GPIO implemented in a number of GE single
+ board computers.
+
endif

config GPIO_GRGPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index a1ae48f..a76b13d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
# directly supported by gpio-generic
gpio-generic-$(CONFIG_GPIO_GENERIC) += gpio-mmio.o
gpio-generic-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
+gpio-generic-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o

obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o
obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o
@@ -43,7 +44,6 @@ obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o
obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
-obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
index 8650b29..63cea89 100644
--- a/drivers/gpio/gpio-ge.c
+++ b/drivers/gpio/gpio-ge.c
@@ -18,13 +18,12 @@
*/

#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/of_address.h>
#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+#include "gpio-mmio-compat.h"

#define GEF_GPIO_DIRECT 0x00
#define GEF_GPIO_IN 0x04
@@ -36,79 +35,37 @@
#define GEF_GPIO_OVERRUN 0x1C
#define GEF_GPIO_MODE 0x20

-static const struct of_device_id gef_gpio_ids[] = {
- {
- .compatible = "gef,sbc610-gpio",
- .data = (void *)19,
- }, {
- .compatible = "gef,sbc310-gpio",
- .data = (void *)6,
- }, {
- .compatible = "ge,imp3a-gpio",
- .data = (void *)16,
- },
- { }
-};
-MODULE_DEVICE_TABLE(of, gef_gpio_ids);
-
-static int __init gef_gpio_probe(struct platform_device *pdev)
+int ge_parse_dt(struct platform_device *pdev,
+ struct bgpio_pdata *pdata,
+ unsigned long *flags)
{
- const struct of_device_id *of_id =
- of_match_device(gef_gpio_ids, &pdev->dev);
- struct gpio_chip *gc;
- void __iomem *regs;
- int ret;
-
- gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
- if (!gc)
- return -ENOMEM;
-
- regs = of_iomap(pdev->dev.of_node, 0);
- if (!regs)
- return -ENOMEM;
-
- ret = bgpio_init(gc, &pdev->dev, 4, regs + GEF_GPIO_IN,
- regs + GEF_GPIO_OUT, NULL, NULL,
- regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER);
- if (ret) {
- dev_err(&pdev->dev, "bgpio_init failed\n");
- goto err0;
- }
+ struct device_node *np = pdev->dev.of_node;

- /* Setup pointers to chip functions */
- gc->label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
- GFP_KERNEL);
- if (!gc->label) {
- ret = -ENOMEM;
- goto err0;
- }
+ struct resource *res;
+ struct resource nres[] = {
+ DEFINE_RES_MEM_NAMED(0, 1, "dat"),
+ DEFINE_RES_MEM_NAMED(0, 1, "set"),
+ DEFINE_RES_MEM_NAMED(0, 1, "dirin"),
+ };

- gc->base = -1;
- gc->ngpio = (u16)(uintptr_t)of_id->data;
- gc->of_gpio_n_cells = 2;
- gc->of_node = pdev->dev.of_node;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res || resource_size(res) != 0x24)
+ return -EINVAL;

- /* This function adds a memory mapped GPIO chip */
- ret = devm_gpiochip_add_data(&pdev->dev, gc, NULL);
- if (ret)
- goto err0;
+ set_resource_address(&nres[0], res->start + GEF_GPIO_IN, 0x4);
+ set_resource_address(&nres[1], res->start + GEF_GPIO_OUT, 0x4);
+ set_resource_address(&nres[2], res->start + GEF_GPIO_DIRECT, 0x4);
+ *flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;

- return 0;
-err0:
- iounmap(regs);
- pr_err("%s: GPIO chip registration failed\n",
- pdev->dev.of_node->full_name);
- return ret;
-};
+ if (of_device_is_compatible(np, "ge,imp3a-gpio"))
+ pdata->ngpio = 16;
+ else if (of_device_is_compatible(np, "gef,sbc310-gpio"))
+ pdata->ngpio = 6;
+ else if (of_device_is_compatible(np, "gef,sbc610-gpio"))
+ pdata->ngpio = 19;

-static struct platform_driver gef_gpio_driver = {
- .driver = {
- .name = "gef-gpio",
- .of_match_table = gef_gpio_ids,
- },
-};
-module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
+ return platform_device_add_resources(pdev, nres, ARRAY_SIZE(nres));
+}

MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
MODULE_AUTHOR("Martyn Welch <[email protected]");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mmio-compat.h b/drivers/gpio/gpio-mmio-compat.h
index 32b5510..63863da 100644
--- a/drivers/gpio/gpio-mmio-compat.h
+++ b/drivers/gpio/gpio-mmio-compat.h
@@ -16,6 +16,20 @@ int cirrus_clps711x_parse_dt(struct platform_device *pdev,
#define GPIO_CLPS711X_COMPATIBLE
#endif /* CONFIG_GPIO_CLPS711X */

+#if IS_ENABLED(CONFIG_GPIO_GE_FPGA)
+int ge_parse_dt(struct platform_device *pdev,
+ struct bgpio_pdata *pdata,
+ unsigned long *flags);
+
+#define GPIO_GE_FPGA_COMPATIBLE \
+ ADD("ge,imp3a-gpio", ge_parse_dt), \
+ ADD("gef,sbc310-gpio", ge_parse_dt), \
+ ADD("gef,sbc610-gpio", ge_parse_dt),
+
+#else
+#define GPIO_GE_FPGA_COMPATIBLE
+#endif /* CONFIG_CONFIG_GPIO_GE_FPGA */
+
#undef ADD

static inline void set_resource_address(struct resource *res,
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 1be8cb7..81af498 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -609,6 +609,7 @@ static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
static const struct of_device_id bgpio_of_match[] = {
ADD("linux,gpio-mmio", bgpio_basic_mmio_parse_dt),
GPIO_CLPS711X_COMPATIBLE
+ GPIO_GE_FPGA_COMPATIBLE

{ }
};
--
2.8.1

2016-04-28 09:07:24

by Christian Lamparter

[permalink] [raw]
Subject: [RFC v4 6/8] gpio: moxart: integrate MOXA ART GPIO driver into gpio-mmio

This patch integrates the GPIO driver for the MOXA ART SoC into
the gpio-mmio framework.

Signed-off-by: Christian Lamparter <[email protected]>
---
drivers/gpio/Kconfig | 15 ++++----
drivers/gpio/Makefile | 2 +-
drivers/gpio/gpio-mmio-compat.h | 12 ++++++
drivers/gpio/gpio-mmio.c | 1 +
drivers/gpio/gpio-moxart.c | 81 +++++++++++------------------------------
5 files changed, 42 insertions(+), 69 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a0e140d..487297f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -213,6 +213,13 @@ config GPIO_GE_FPGA
and write pin state) for GPIO implemented in a number of GE single
board computers.

+config GPIO_MOXART
+ bool "MOXART GPIO support"
+ depends on ARCH_MOXART || COMPILE_TEST
+ select GPIO_GENERIC
+ help
+ Select this option to enable GPIO driver for
+ MOXA ART SoC devices.
endif

config GPIO_GRGPIO
@@ -289,14 +296,6 @@ config GPIO_MM_LANTIQ
(EBU) found on Lantiq SoCs. The gpios are output only as they are
created by attaching a 16bit latch to the bus.

-config GPIO_MOXART
- bool "MOXART GPIO support"
- depends on ARCH_MOXART || COMPILE_TEST
- select GPIO_GENERIC
- help
- Select this option to enable GPIO driver for
- MOXA ART SoC devices.
-
config GPIO_MPC5200
def_bool y
depends on PPC_MPC52xx
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index a76b13d..32ad5fe 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
gpio-generic-$(CONFIG_GPIO_GENERIC) += gpio-mmio.o
gpio-generic-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
gpio-generic-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
+gpio-generic-$(CONFIG_GPIO_MOXART) += gpio-moxart.o

obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o
obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o
@@ -68,7 +69,6 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
-obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
diff --git a/drivers/gpio/gpio-mmio-compat.h b/drivers/gpio/gpio-mmio-compat.h
index 63863da..702a384 100644
--- a/drivers/gpio/gpio-mmio-compat.h
+++ b/drivers/gpio/gpio-mmio-compat.h
@@ -30,6 +30,18 @@ int ge_parse_dt(struct platform_device *pdev,
#define GPIO_GE_FPGA_COMPATIBLE
#endif /* CONFIG_CONFIG_GPIO_GE_FPGA */

+#if IS_ENABLED(CONFIG_GPIO_MOXART)
+int moxart_parse_dt(struct platform_device *pdev,
+ struct bgpio_pdata *pdata,
+ unsigned long *flags);
+
+#define GPIO_MOXART_COMPATIBLE \
+ ADD("moxa,moxart-gpio", moxart_parse_dt),
+
+#else
+#define GPIO_MOXART_COMPATIBLE
+#endif /* CONFIG_GPIO_MOXART */
+
#undef ADD

static inline void set_resource_address(struct resource *res,
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 81af498..fdaf701 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -610,6 +610,7 @@ static const struct of_device_id bgpio_of_match[] = {
ADD("linux,gpio-mmio", bgpio_basic_mmio_parse_dt),
GPIO_CLPS711X_COMPATIBLE
GPIO_GE_FPGA_COMPATIBLE
+ GPIO_MOXART_COMPATIBLE

{ }
};
diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c
index d58d389..812b86a 100644
--- a/drivers/gpio/gpio-moxart.c
+++ b/drivers/gpio/gpio-moxart.c
@@ -10,75 +10,36 @@
* warranty of any kind, whether express or implied.
*/

+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of_address.h>
-#include <linux/of_gpio.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/bitops.h>
+#include <linux/ioport.h>
#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+#include "gpio-mmio-compat.h"

#define GPIO_DATA_OUT 0x00
#define GPIO_DATA_IN 0x04
#define GPIO_PIN_DIRECTION 0x08

-static int moxart_gpio_probe(struct platform_device *pdev)
+int moxart_parse_dt(struct platform_device *pdev,
+ struct bgpio_pdata *pdata,
+ unsigned long *flags)
{
- struct device *dev = &pdev->dev;
struct resource *res;
- struct gpio_chip *gc;
- void __iomem *base;
- int ret;
-
- gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
- if (!gc)
- return -ENOMEM;
+ struct resource nres[] = {
+ DEFINE_RES_MEM_NAMED(0, 1, "dat"),
+ DEFINE_RES_MEM_NAMED(0, 1, "set"),
+ DEFINE_RES_MEM_NAMED(0, 1, "dirout"),
+ };

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- ret = bgpio_init(gc, dev, 4, base + GPIO_DATA_IN,
- base + GPIO_DATA_OUT, NULL,
- base + GPIO_PIN_DIRECTION, NULL,
- BGPIOF_READ_OUTPUT_REG_SET);
- if (ret) {
- dev_err(&pdev->dev, "bgpio_init failed\n");
- return ret;
- }
-
- gc->label = "moxart-gpio";
- gc->request = gpiochip_generic_request;
- gc->free = gpiochip_generic_free;
- gc->base = 0;
- gc->owner = THIS_MODULE;
-
- ret = devm_gpiochip_add_data(dev, gc, NULL);
- if (ret) {
- dev_err(dev, "%s: gpiochip_add failed\n",
- dev->of_node->full_name);
- return ret;
- }
-
- return ret;
+ if (!res || resource_size(res) != 12)
+ return -EINVAL;
+
+ *flags |= BGPIOF_READ_OUTPUT_REG_SET;
+ set_resource_address(&nres[0], res->start + GPIO_DATA_IN, 0x4);
+ set_resource_address(&nres[1], res->start + GPIO_DATA_OUT, 0x4);
+ set_resource_address(&nres[2], res->start + GPIO_PIN_DIRECTION, 0x4);
+ return platform_device_add_resources(pdev, nres, ARRAY_SIZE(nres));
}
-
-static const struct of_device_id moxart_gpio_match[] = {
- { .compatible = "moxa,moxart-gpio" },
- { }
-};
-
-static struct platform_driver moxart_gpio_driver = {
- .driver = {
- .name = "moxart-gpio",
- .of_match_table = moxart_gpio_match,
- },
- .probe = moxart_gpio_probe,
-};
-builtin_platform_driver(moxart_gpio_driver);
--
2.8.1

2016-04-28 09:06:46

by Christian Lamparter

[permalink] [raw]
Subject: [RFC v4 8/8] gpio: dt-bindings: add gpio-mmio bindings

From: Álvaro Fernández Rojas <[email protected]>

This patch adds the device tree bindings for the gpio-mmio.
The gpio-mmio is already part of a the GPIO generic library.

Signed-off-by: Álvaro Fernández Rojas <[email protected]>
Signed-off-by: Christian Lamparter <[email protected]>
---
.../devicetree/bindings/gpio/gpio-mmio.txt | 73 ++++++++++++++++++++++
1 file changed, 73 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-mmio.txt

diff --git a/Documentation/devicetree/bindings/gpio/gpio-mmio.txt b/Documentation/devicetree/bindings/gpio/gpio-mmio.txt
new file mode 100644
index 0000000..cc7f0b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-mmio.txt
@@ -0,0 +1,73 @@
+Bindings for the generic driver for memory-mapped GPIO controllers.
+
+Required properties:
+ - compatible: should be "linux,gpio-mmio"
+ - reg-names: must contain
+ "dat" - data register
+ may contain
+ "set" - data set register
+ "clr" - data clear register
+ "dirout" - direction output register
+ "dirin" - direction input register
+ - reg: address + size pairs describing the GPIO register sets;
+ order must correspond with the order of entries in reg-names
+ - #gpio-cells = must be set to 2
+ - gpio-controller: Marks the device node as a gpio controller.
+
+Optional properties:
+ - ngpio: specifies the number of gpio mapped in the register.
+ - big-endian: force big endian register accesses.
+ - big-endian-byte-order: assign GPIOs in reverse order.
+ - unreadable-reg-set: data set register is not readable.
+ - read-output-reg-set: cache value set for reads.
+ - unreadable-reg-dir: dirout/dirin register is not readable.
+ - no-output: GPIOs are read-only.
+
+The GPIO generic library provides support for memory-mapped GPIO
+controllers. The configuration is detected by which resources are present.
+The simplest form of a GPIO controller that the driver support is just a
+single "dat" register, where GPIO state can be read and/or written.
+However, the driver supports far more:
+ - 8/16/32/64 bits registers. The number of GPIOs is automatically
+ determined by the width of the registers.
+ - GPIO controllers with clear/set registers.
+ - GPIO controllers with a single "dat" register.
+ - Big endian bits/GPIOs ordering.
+
+For setting GPIO's there are three configurations:
+ 1. single input/output register resource (named "dat"),
+ 2. set/clear pair (named "set" and "clr"),
+ 3. single output register resource and single input resource
+ ("set" and dat").
+
+For setting the GPIO direction, there are three configurations:
+ a. simple bidirectional GPIOs that requires no configuration.
+ b. an output direction register (named "dirout")
+ where a 1 bit indicates the GPIO is an output.
+ c. an input direction register (named "dirin")
+ where a 1 bit indicates the GPIO is an input.
+
+Examples:
+
+ /* Configuration for single input/output register
+ * for eight simple bidirectional GPIOs.
+ */
+ gpio_a_1 {
+ compatible = "linux,gpio-mmio";
+ reg = <0x18000000 0x1>;
+ reg-names = "dat";
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ /* Configuration for set/clear pair registers with
+ * 32 output direction register GPIOs.
+ */
+ gpio_b_2 {
+ compatible = "linux,gpio-mmio";
+ reg = <0x18000000 0x4>, <0x18000010 0x4>,
+ <0x18000004 0x4>, <0x18000008 0x4>;
+ reg-names = "dat", "set", "clr", "dirout";
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
--
2.8.1

2016-04-28 09:05:42

by Christian Lamparter

[permalink] [raw]
Subject: [RFC v4 1/8] gpio: generic: fix GPIO_GENERIC_PLATFORM is set to module case

GPIO_GENERIC_PLATFORM is a tristate. If the module option is
selected the resulting gpio-generic.ko will lack most of the
module initialzation and probe code.

Signed-off-by: Christian Lamparter <[email protected]>
---
drivers/gpio/gpio-generic.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index 54cddfa..6c1cb3b 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -549,7 +549,7 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,
}
EXPORT_SYMBOL_GPL(bgpio_init);

-#ifdef CONFIG_GPIO_GENERIC_PLATFORM
+#if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM)

static void __iomem *bgpio_map(struct platform_device *pdev,
const char *name,
--
2.8.1

2016-04-28 23:40:05

by Christian Lamparter

[permalink] [raw]
Subject: Re: [RFC v4 3/8] gpio: generic: add DT support for generic memory-mapped GPIOs

On Thursday, April 28, 2016 12:58:03 PM Andy Shevchenko wrote:
> On Thu, Apr 28, 2016 at 12:05 PM, Christian Lamparter
> <[email protected]> wrote:
> > From: ?lvaro Fern?ndez Rojas <[email protected]>
> >
> > This patch adds support for defining memory-mapped GPIOs
> > which provide a compatible interface for the existing
> > generic-gpio driver.

Thanks for your comments! I've prepared a new series which
I'm going to post tomorrow. I've incorporated most of the
remarks, but there's something I have to say about:

> > +static inline void set_resource_address(struct resource *res,
> > + resource_size_t start,
> > + resource_size_t len)
> > +{
> > + res->start = start;
> > + res->end = start + len - 1;
> > +}
>
> It might make sense to put this in the generic (resource related, e.g.
> ioport.h) header. There are plenty users of such already and who knows
> how many will come.

I looked around and found plenty of code in drivers/
alone doing the same song and dance around it:

acpi/pci_root.c acpi/resource.c
bus/mvebu-mbus.c
i2c/busses/i2c-i801.c
irqchip/irq-mips-gic.c
memory/omap-gpmc.c
mfd/janz-cmodio.c mfd/lpc_ich.c mfd/sm501.c mtd/devices/ms02-nv.c
nvdimm/namespace_devs.c
of/address.c
parisc/ccio-dma.c parisc/dino.c parisc/lba_pci.c
pci/hotplug/ibmphp_res.c pci/bus.c pci/iov.c pci/setup-res.c
pci/setup-bus.c pci/hotplug/ibmphp_res.c
pcmcia/rsrc_mgr.c pcmcia/pcmcia_resource.c
pnp/manager.c
platform/x86/intel_pmc_ipc.c
pinctrl/sh-pfc/core.c
etc...

I think arch/ will have a few more. If anything this will require
help from coccinelle and more stuff. For now I'll convert the code
to do the same thing as everybody else. And after the "linux,gpio-mmio"
has been successfully mainlined I can worry about how to write the
perfect set_resource_address or set_resource_range (needs to handle
over- and underflows, etc...) and setup the automatic tools to convert
the whole tree. So, unless someone else beats me to this, this would
be my plan.

Regards,
Christian

2016-04-29 14:15:00

by Linus Walleij

[permalink] [raw]
Subject: Re: [RFC v4 2/8] gpio: rename gpio-generic.c into gpio-mmio.c

On Thu, Apr 28, 2016 at 11:05 AM, Christian Lamparter
<[email protected]> wrote:

> This patch renames the gpio-generic.c into gpio-mmio.c.
> This is because currently the file only contains code
> for a memory-mapped GPIO driver. There isn't any support
> for ioports or other resource type.
>
> Signed-off-by: Christian Lamparter <[email protected]>

Makes perfect sense.

Patch applied.

Yours,
Linus Walleij