From e9004f5039b3840089cb1cb0fe558a81e2bb55f0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Sep 2013 11:59:51 +0200 Subject: ARM: plat-iop: move the GPIO driver to drivers/gpio Move the IOP GPIO driver to live with its siblings in the GPIO subsystem. Cc: Lennert Buytenhek Cc: Dan Williams Cc: Mikael Pettersson Tested-by: Aaro Koskinen Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 9 +++++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-iop.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 drivers/gpio/gpio-iop.c (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b6ed304863eb..cc30426d31ec 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -320,6 +320,15 @@ config GPIO_ICH If unsure, say N. +config GPIO_IOP + tristate "Intel IOP GPIO" + depends on ARM && (ARCH_IOP32X || ARCH_IOP33X) + help + Say yes here to support the GPIO functionality of a number of Intel + IOP32X or IOP33X. + + If unsure, say N. + config GPIO_VX855 tristate "VIA VX855/VX875 GPIO" depends on PCI diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 98e23ebba2cf..06e5662aa4ec 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -28,6 +28,7 @@ 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 obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c new file mode 100644 index 000000000000..697de6dc4936 --- /dev/null +++ b/drivers/gpio/gpio-iop.c @@ -0,0 +1,93 @@ +/* + * arch/arm/plat-iop/gpio.c + * GPIO handling for Intel IOP3xx processors. + * + * Copyright (C) 2006 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void gpio_line_config(int line, int direction) +{ + unsigned long flags; + + local_irq_save(flags); + if (direction == GPIO_IN) { + *IOP3XX_GPOE |= 1 << line; + } else if (direction == GPIO_OUT) { + *IOP3XX_GPOE &= ~(1 << line); + } + local_irq_restore(flags); +} +EXPORT_SYMBOL(gpio_line_config); + +int gpio_line_get(int line) +{ + return !!(*IOP3XX_GPID & (1 << line)); +} +EXPORT_SYMBOL(gpio_line_get); + +void gpio_line_set(int line, int value) +{ + unsigned long flags; + + local_irq_save(flags); + if (value == GPIO_LOW) { + *IOP3XX_GPOD &= ~(1 << line); + } else if (value == GPIO_HIGH) { + *IOP3XX_GPOD |= 1 << line; + } + local_irq_restore(flags); +} +EXPORT_SYMBOL(gpio_line_set); + +static int iop3xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ + gpio_line_config(gpio, GPIO_IN); + return 0; +} + +static int iop3xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level) +{ + gpio_line_set(gpio, level); + gpio_line_config(gpio, GPIO_OUT); + return 0; +} + +static int iop3xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio) +{ + return gpio_line_get(gpio); +} + +static void iop3xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) +{ + gpio_line_set(gpio, value); +} + +static struct gpio_chip iop3xx_chip = { + .label = "iop3xx", + .direction_input = iop3xx_gpio_direction_input, + .get = iop3xx_gpio_get_value, + .direction_output = iop3xx_gpio_direction_output, + .set = iop3xx_gpio_set_value, + .base = 0, + .ngpio = IOP3XX_N_GPIOS, +}; + +static int __init iop3xx_gpio_setup(void) +{ + return gpiochip_add(&iop3xx_chip); +} +arch_initcall(iop3xx_gpio_setup); -- cgit v1.2.3 From f6ffa5ee039cd0168d82e3edd712ebbb1de93a00 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Sep 2013 15:00:40 +0200 Subject: gpio: decouple the IOP GPIO driver from platform This removes the only dependence between the IOP GPIO driver and the GENERIC_GPIO header in and its common implementation in the namespace by copying the one constant it is using into the driver file. Cc: Lennert Buytenhek Cc: Dan Williams Cc: Mikael Pettersson Tested-by: Aaro Koskinen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-iop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c index 697de6dc4936..d4a170dfe504 100644 --- a/drivers/gpio/gpio-iop.c +++ b/drivers/gpio/gpio-iop.c @@ -16,8 +16,8 @@ #include #include #include -#include -#include + +#define IOP3XX_N_GPIOS 8 void gpio_line_config(int line, int direction) { -- cgit v1.2.3 From 51a97d829e32b7a1b960d3365e4c2546c9c792aa Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Sep 2013 16:07:42 +0200 Subject: ARM: plat-iop: remove custom complex GPIO implementation The kernel will now only use gpiolib to access GPIOs, so remove the complex GPIO flag and the custom implementation. Cc: Lennert Buytenhek Cc: Dan Williams Cc: Mikael Pettersson Tested-by: Aaro Koskinen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-iop.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c index d4a170dfe504..17cc7010cd04 100644 --- a/drivers/gpio/gpio-iop.c +++ b/drivers/gpio/gpio-iop.c @@ -19,7 +19,7 @@ #define IOP3XX_N_GPIOS 8 -void gpio_line_config(int line, int direction) +static void gpio_line_config(int line, int direction) { unsigned long flags; @@ -31,15 +31,13 @@ void gpio_line_config(int line, int direction) } local_irq_restore(flags); } -EXPORT_SYMBOL(gpio_line_config); -int gpio_line_get(int line) +static int gpio_line_get(int line) { return !!(*IOP3XX_GPID & (1 << line)); } -EXPORT_SYMBOL(gpio_line_get); -void gpio_line_set(int line, int value) +static void gpio_line_set(int line, int value) { unsigned long flags; @@ -51,7 +49,6 @@ void gpio_line_set(int line, int value) } local_irq_restore(flags); } -EXPORT_SYMBOL(gpio_line_set); static int iop3xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { -- cgit v1.2.3 From 7b85b867b99044da93f83851c806d1e324d49ed5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Sep 2013 16:39:51 +0200 Subject: ARM: plat-iop: instantiate GPIO from platform device This converts the IOP32x and IOP33x platforms to pass their base address offset by a resource attached to a platform device instead of using static offset macros implicitly passed through including . Delete the local and headers and remove the selection of NEED_MACH_GPIO_H. Pass the virtual address as a resource in the platform device at this point for bisectability, next patch will pass the physical address as is custom. Cc: Lennert Buytenhek Cc: Dan Williams Cc: Mikael Pettersson Tested-by: Aaro Koskinen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-iop.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c index 17cc7010cd04..24a86b05dc8c 100644 --- a/drivers/gpio/gpio-iop.c +++ b/drivers/gpio/gpio-iop.c @@ -16,9 +16,23 @@ #include #include #include +#include #define IOP3XX_N_GPIOS 8 +#define GPIO_IN 0 +#define GPIO_OUT 1 +#define GPIO_LOW 0 +#define GPIO_HIGH 1 + +/* Memory base offset */ +static void __iomem *base; + +#define IOP3XX_GPIO_REG(reg) (base + (reg)) +#define IOP3XX_GPOE (volatile u32 *)IOP3XX_GPIO_REG(0x0000) +#define IOP3XX_GPID (volatile u32 *)IOP3XX_GPIO_REG(0x0004) +#define IOP3XX_GPOD (volatile u32 *)IOP3XX_GPIO_REG(0x0008) + static void gpio_line_config(int line, int direction) { unsigned long flags; @@ -83,8 +97,26 @@ static struct gpio_chip iop3xx_chip = { .ngpio = IOP3XX_N_GPIOS, }; -static int __init iop3xx_gpio_setup(void) +static int iop3xx_gpio_probe(struct platform_device *pdev) { + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = (void *) res->start; + return gpiochip_add(&iop3xx_chip); } -arch_initcall(iop3xx_gpio_setup); + +static struct platform_driver iop3xx_gpio_driver = { + .driver = { + .name = "gpio-iop", + .owner = THIS_MODULE, + }, + .probe = iop3xx_gpio_probe, +}; + +static int __init iop3xx_gpio_init(void) +{ + return platform_driver_register(&iop3xx_gpio_driver); +} +arch_initcall(iop3xx_gpio_init); -- cgit v1.2.3 From e3f94b385748c10b735f392b69f39f33f02ca3a5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Sep 2013 16:54:32 +0200 Subject: gpio: iop: use readl/writel accessors Use the standard 32bit I/O accessors instead of just assigning addresses. Cc: Lennert Buytenhek Cc: Dan Williams Cc: Mikael Pettersson Tested-by: Aaro Koskinen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-iop.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c index 24a86b05dc8c..0d991d732467 100644 --- a/drivers/gpio/gpio-iop.c +++ b/drivers/gpio/gpio-iop.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #define IOP3XX_N_GPIOS 8 @@ -29,38 +31,44 @@ static void __iomem *base; #define IOP3XX_GPIO_REG(reg) (base + (reg)) -#define IOP3XX_GPOE (volatile u32 *)IOP3XX_GPIO_REG(0x0000) -#define IOP3XX_GPID (volatile u32 *)IOP3XX_GPIO_REG(0x0004) -#define IOP3XX_GPOD (volatile u32 *)IOP3XX_GPIO_REG(0x0008) +#define IOP3XX_GPOE IOP3XX_GPIO_REG(0x0000) +#define IOP3XX_GPID IOP3XX_GPIO_REG(0x0004) +#define IOP3XX_GPOD IOP3XX_GPIO_REG(0x0008) static void gpio_line_config(int line, int direction) { unsigned long flags; + u32 val; local_irq_save(flags); + val = readl(IOP3XX_GPOE); if (direction == GPIO_IN) { - *IOP3XX_GPOE |= 1 << line; + val |= BIT(line); } else if (direction == GPIO_OUT) { - *IOP3XX_GPOE &= ~(1 << line); + val &= ~BIT(line); } + writel(val, IOP3XX_GPOE); local_irq_restore(flags); } static int gpio_line_get(int line) { - return !!(*IOP3XX_GPID & (1 << line)); + return !!(readl(IOP3XX_GPID) & BIT(line)); } static void gpio_line_set(int line, int value) { unsigned long flags; + u32 val; local_irq_save(flags); + val = readl(IOP3XX_GPOD); if (value == GPIO_LOW) { - *IOP3XX_GPOD &= ~(1 << line); + val &= ~BIT(line); } else if (value == GPIO_HIGH) { - *IOP3XX_GPOD |= 1 << line; + val |= BIT(line); } + writel(val, IOP3XX_GPOD); local_irq_restore(flags); } -- cgit v1.2.3 From e34ca9de0b3575fc7e94b1f520169fc7024c6dd2 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 9 Sep 2013 16:59:54 +0200 Subject: ARM: plat-iop: pass physical base for GPIO This alters the IOP platforms to pass a physical base for their GPIO blocks and alters the driver to remap it when probing instead of relying on the virtual addresses to be used. Cc: Lennert Buytenhek Cc: Dan Williams Cc: Mikael Pettersson Tested-by: Aaro Koskinen Signed-off-by: Linus Walleij --- drivers/gpio/gpio-iop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c index 0d991d732467..c22a61be3a9c 100644 --- a/drivers/gpio/gpio-iop.c +++ b/drivers/gpio/gpio-iop.c @@ -110,7 +110,7 @@ static int iop3xx_gpio_probe(struct platform_device *pdev) struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = (void *) res->start; + base = devm_ioremap_resource(&pdev->dev, res); return gpiochip_add(&iop3xx_chip); } -- cgit v1.2.3