diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-01-12 13:11:43 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-01-12 13:11:43 +0900 |
commit | b1bdd255661369cb6eb90b6e181169b5e6d0f9b6 (patch) | |
tree | 17d15f3a6dc5bdd6205070dbef0e339421b13d25 /drivers/gpio | |
parent | 9d14070f656addddce3d63fd483de46930b51850 (diff) | |
parent | c1537b4863da620f12f5b42ece61bf65314148ed (diff) | |
download | talos-obmc-linux-b1bdd255661369cb6eb90b6e181169b5e6d0f9b6.tar.gz talos-obmc-linux-b1bdd255661369cb6eb90b6e181169b5e6d0f9b6.zip |
Merge branch 'sh/nommu' into sh-latest
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 15 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 3 | ||||
-rw-r--r-- | drivers/gpio/gpio-pxa.c | 377 | ||||
-rw-r--r-- | drivers/gpio/gpio-samsung.c | 72 | ||||
-rw-r--r-- | drivers/gpio/gpio-u300.c | 917 |
5 files changed, 406 insertions, 978 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5099681cf503..573532f7553e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -141,6 +141,12 @@ config GPIO_PL061 help Say yes here to support the PrimeCell PL061 GPIO device +config GPIO_PXA + bool "PXA GPIO support" + depends on ARCH_PXA || ARCH_MMP + help + Say yes here to support the PXA GPIO device + config GPIO_XILINX bool "Xilinx GPIO support" depends on PPC_OF || MICROBLAZE @@ -170,15 +176,6 @@ config GPIO_SCH The Intel Tunnel Creek processor has 5 GPIOs powered by the core power rail and 9 from suspend power supply. -config GPIO_U300 - bool "ST-Ericsson U300 COH 901 335/571 GPIO" - depends on GPIOLIB && ARCH_U300 - help - Say yes here to support GPIO interface on ST-Ericsson U300. - The names of the two IP block variants supported are - COH 901 335 and COH 901 571/3. They contain 3, 5 or 7 - ports of 8 GPIO pins each. - config GPIO_VX855 tristate "VIA VX855/VX875 GPIO" depends on PCI diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4e018d6a7639..62e641e79e8f 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o obj-$(CONFIG_GPIO_PCH) += gpio-pch.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o -obj-$(CONFIG_PLAT_PXA) += gpio-pxa.o +obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o @@ -54,7 +54,6 @@ obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o -obj-$(CONFIG_MACH_U300) += gpio-u300.o obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index ee137712f9db..b2d3ee1d183a 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -11,14 +11,46 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <linux/clk.h> +#include <linux/err.h> #include <linux/gpio.h> +#include <linux/gpio-pxa.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/platform_device.h> #include <linux/syscore_ops.h> #include <linux/slab.h> -#include <mach/gpio-pxa.h> +/* + * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with + * one set of registers. The register offsets are organized below: + * + * GPLR GPDR GPSR GPCR GRER GFER GEDR + * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 + * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C + * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 + * + * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 + * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C + * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 + * + * NOTE: + * BANK 3 is only available on PXA27x and later processors. + * BANK 4 and 5 are only available on PXA935 + */ + +#define GPLR_OFFSET 0x00 +#define GPDR_OFFSET 0x0C +#define GPSR_OFFSET 0x18 +#define GPCR_OFFSET 0x24 +#define GRER_OFFSET 0x30 +#define GFER_OFFSET 0x3C +#define GEDR_OFFSET 0x48 +#define GAFR_OFFSET 0x54 +#define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */ + +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) int pxa_last_gpio; @@ -39,8 +71,20 @@ struct pxa_gpio_chip { #endif }; +enum { + PXA25X_GPIO = 0, + PXA26X_GPIO, + PXA27X_GPIO, + PXA3XX_GPIO, + PXA93X_GPIO, + MMP_GPIO = 0x10, + MMP2_GPIO, +}; + static DEFINE_SPINLOCK(gpio_lock); static struct pxa_gpio_chip *pxa_gpio_chips; +static int gpio_type; +static void __iomem *gpio_reg_base; #define for_each_gpio_chip(i, c) \ for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) @@ -55,6 +99,122 @@ static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio) return &pxa_gpio_chips[gpio_to_bank(gpio)]; } +static inline int gpio_is_pxa_type(int type) +{ + return (type & MMP_GPIO) == 0; +} + +static inline int gpio_is_mmp_type(int type) +{ + return (type & MMP_GPIO) != 0; +} + +/* GPIO86/87/88/89 on PXA26x have their direction bits in PXA_GPDR(2 inverted, + * as well as their Alternate Function value being '1' for GPIO in GAFRx. + */ +static inline int __gpio_is_inverted(int gpio) +{ + if ((gpio_type == PXA26X_GPIO) && (gpio > 85)) + return 1; + return 0; +} + +/* + * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate + * function of a GPIO, and GPDRx cannot be altered once configured. It + * is attributed as "occupied" here (I know this terminology isn't + * accurate, you are welcome to propose a better one :-) + */ +static inline int __gpio_is_occupied(unsigned gpio) +{ + struct pxa_gpio_chip *pxachip; + void __iomem *base; + unsigned long gafr = 0, gpdr = 0; + int ret, af = 0, dir = 0; + + pxachip = gpio_to_pxachip(gpio); + base = gpio_chip_base(&pxachip->chip); + gpdr = readl_relaxed(base + GPDR_OFFSET); + + switch (gpio_type) { + case PXA25X_GPIO: + case PXA26X_GPIO: + case PXA27X_GPIO: + gafr = readl_relaxed(base + GAFR_OFFSET); + af = (gafr >> ((gpio & 0xf) * 2)) & 0x3; + dir = gpdr & GPIO_bit(gpio); + + if (__gpio_is_inverted(gpio)) + ret = (af != 1) || (dir == 0); + else + ret = (af != 0) || (dir != 0); + break; + default: + ret = gpdr & GPIO_bit(gpio); + break; + } + return ret; +} + +#ifdef CONFIG_ARCH_PXA +static inline int __pxa_gpio_to_irq(int gpio) +{ + if (gpio_is_pxa_type(gpio_type)) + return PXA_GPIO_TO_IRQ(gpio); + return -1; +} + +static inline int __pxa_irq_to_gpio(int irq) +{ + if (gpio_is_pxa_type(gpio_type)) + return irq - PXA_GPIO_TO_IRQ(0); + return -1; +} +#else +static inline int __pxa_gpio_to_irq(int gpio) { return -1; } +static inline int __pxa_irq_to_gpio(int irq) { return -1; } +#endif + +#ifdef CONFIG_ARCH_MMP +static inline int __mmp_gpio_to_irq(int gpio) +{ + if (gpio_is_mmp_type(gpio_type)) + return MMP_GPIO_TO_IRQ(gpio); + return -1; +} + +static inline int __mmp_irq_to_gpio(int irq) +{ + if (gpio_is_mmp_type(gpio_type)) + return irq - MMP_GPIO_TO_IRQ(0); + return -1; +} +#else +static inline int __mmp_gpio_to_irq(int gpio) { return -1; } +static inline int __mmp_irq_to_gpio(int irq) { return -1; } +#endif + +static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + int gpio, ret; + + gpio = chip->base + offset; + ret = __pxa_gpio_to_irq(gpio); + if (ret >= 0) + return ret; + return __mmp_gpio_to_irq(gpio); +} + +int pxa_irq_to_gpio(int irq) +{ + int ret; + + ret = __pxa_irq_to_gpio(irq); + if (ret >= 0) + return ret; + return __mmp_irq_to_gpio(irq); +} + static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { void __iomem *base = gpio_chip_base(chip); @@ -63,12 +223,12 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) spin_lock_irqsave(&gpio_lock, flags); - value = __raw_readl(base + GPDR_OFFSET); + value = readl_relaxed(base + GPDR_OFFSET); if (__gpio_is_inverted(chip->base + offset)) value |= mask; else value &= ~mask; - __raw_writel(value, base + GPDR_OFFSET); + writel_relaxed(value, base + GPDR_OFFSET); spin_unlock_irqrestore(&gpio_lock, flags); return 0; @@ -81,16 +241,16 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, uint32_t tmp, mask = 1 << offset; unsigned long flags; - __raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); + writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); spin_lock_irqsave(&gpio_lock, flags); - tmp = __raw_readl(base + GPDR_OFFSET); + tmp = readl_relaxed(base + GPDR_OFFSET); if (__gpio_is_inverted(chip->base + offset)) tmp &= ~mask; else tmp |= mask; - __raw_writel(tmp, base + GPDR_OFFSET); + writel_relaxed(tmp, base + GPDR_OFFSET); spin_unlock_irqrestore(&gpio_lock, flags); return 0; @@ -98,16 +258,16 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) { - return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); + return readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); } static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - __raw_writel(1 << offset, gpio_chip_base(chip) + + writel_relaxed(1 << offset, gpio_chip_base(chip) + (value ? GPSR_OFFSET : GPCR_OFFSET)); } -static int __init pxa_init_gpio_chip(int gpio_end) +static int __devinit pxa_init_gpio_chip(int gpio_end) { int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; struct pxa_gpio_chip *chips; @@ -122,7 +282,7 @@ static int __init pxa_init_gpio_chip(int gpio_end) struct gpio_chip *c = &chips[i].chip; sprintf(chips[i].label, "gpio-%d", i); - chips[i].regbase = GPIO_BANK(i); + chips[i].regbase = gpio_reg_base + BANK_OFF(i); c->base = gpio; c->label = chips[i].label; @@ -131,6 +291,7 @@ static int __init pxa_init_gpio_chip(int gpio_end) c->direction_output = pxa_gpio_direction_output; c->get = pxa_gpio_get; c->set = pxa_gpio_set; + c->to_irq = pxa_gpio_to_irq; /* number of GPIOs on last bank may be less than 32 */ c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; @@ -147,18 +308,18 @@ static inline void update_edge_detect(struct pxa_gpio_chip *c) { uint32_t grer, gfer; - grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask; - gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask; + grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~c->irq_mask; + gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~c->irq_mask; grer |= c->irq_edge_rise & c->irq_mask; gfer |= c->irq_edge_fall & c->irq_mask; - __raw_writel(grer, c->regbase + GRER_OFFSET); - __raw_writel(gfer, c->regbase + GFER_OFFSET); + writel_relaxed(grer, c->regbase + GRER_OFFSET); + writel_relaxed(gfer, c->regbase + GFER_OFFSET); } static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) { struct pxa_gpio_chip *c; - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); unsigned long gpdr, mask = GPIO_bit(gpio); c = gpio_to_pxachip(gpio); @@ -176,12 +337,12 @@ static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; } - gpdr = __raw_readl(c->regbase + GPDR_OFFSET); + gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); if (__gpio_is_inverted(gpio)) - __raw_writel(gpdr | mask, c->regbase + GPDR_OFFSET); + writel_relaxed(gpdr | mask, c->regbase + GPDR_OFFSET); else - __raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET); + writel_relaxed(gpdr & ~mask, c->regbase + GPDR_OFFSET); if (type & IRQ_TYPE_EDGE_RISING) c->irq_edge_rise |= mask; @@ -212,9 +373,9 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) for_each_gpio_chip(gpio, c) { gpio_base = c->chip.base; - gedr = __raw_readl(c->regbase + GEDR_OFFSET); + gedr = readl_relaxed(c->regbase + GEDR_OFFSET); gedr = gedr & c->irq_mask; - __raw_writel(gedr, c->regbase + GEDR_OFFSET); + writel_relaxed(gedr, c->regbase + GEDR_OFFSET); n = find_first_bit(&gedr, BITS_PER_LONG); while (n < BITS_PER_LONG) { @@ -229,29 +390,29 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) static void pxa_ack_muxed_gpio(struct irq_data *d) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - __raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); + writel_relaxed(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); } static void pxa_mask_muxed_gpio(struct irq_data *d) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); uint32_t grer, gfer; c->irq_mask &= ~GPIO_bit(gpio); - grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); - gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); - __raw_writel(grer, c->regbase + GRER_OFFSET); - __raw_writel(gfer, c->regbase + GFER_OFFSET); + grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); + gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); + writel_relaxed(grer, c->regbase + GRER_OFFSET); + writel_relaxed(gfer, c->regbase + GFER_OFFSET); } static void pxa_unmask_muxed_gpio(struct irq_data *d) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); c->irq_mask |= GPIO_bit(gpio); @@ -266,34 +427,143 @@ static struct irq_chip pxa_muxed_gpio_chip = { .irq_set_type = pxa_gpio_irq_type, }; -void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) +static int pxa_gpio_nums(void) { - struct pxa_gpio_chip *c; - int gpio, irq; + int count = 0; + +#ifdef CONFIG_ARCH_PXA + if (cpu_is_pxa25x()) { +#ifdef CONFIG_CPU_PXA26x + count = 89; + gpio_type = PXA26X_GPIO; +#elif defined(CONFIG_PXA25x) + count = 84; + gpio_type = PXA26X_GPIO; +#endif /* CONFIG_CPU_PXA26x */ + } else if (cpu_is_pxa27x()) { + count = 120; + gpio_type = PXA27X_GPIO; + } else if (cpu_is_pxa93x() || cpu_is_pxa95x()) { + count = 191; + gpio_type = PXA93X_GPIO; + } else if (cpu_is_pxa3xx()) { + count = 127; + gpio_type = PXA3XX_GPIO; + } +#endif /* CONFIG_ARCH_PXA */ + +#ifdef CONFIG_ARCH_MMP + if (cpu_is_pxa168() || cpu_is_pxa910()) { + count = 127; + gpio_type = MMP_GPIO; + } else if (cpu_is_mmp2()) { + count = 191; + gpio_type = MMP2_GPIO; + } +#endif /* CONFIG_ARCH_MMP */ + return count; +} - pxa_last_gpio = end; +static int __devinit pxa_gpio_probe(struct platform_device *pdev) +{ + struct pxa_gpio_chip *c; + struct resource *res; + struct clk *clk; + int gpio, irq, ret; + int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; + + pxa_last_gpio = pxa_gpio_nums(); + if (!pxa_last_gpio) + return -EINVAL; + + irq0 = platform_get_irq_byname(pdev, "gpio0"); + irq1 = platform_get_irq_byname(pdev, "gpio1"); + irq_mux = platform_get_irq_byname(pdev, "gpio_mux"); + if ((irq0 > 0 && irq1 <= 0) || (irq0 <= 0 && irq1 > 0) + || (irq_mux <= 0)) + return -EINVAL; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + gpio_reg_base = ioremap(res->start, resource_size(res)); + if (!gpio_reg_base) + return -EINVAL; + + if (irq0 > 0) + gpio_offset = 2; + + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Error %ld to get gpio clock\n", + PTR_ERR(clk)); + iounmap(gpio_reg_base); + return PTR_ERR(clk); + } + ret = clk_prepare(clk); + if (ret) { + clk_put(clk); + iounmap(gpio_reg_base); + return ret; + } + ret = clk_enable(clk); + if (ret) { + clk_unprepare(clk); + clk_put(clk); + iounmap(gpio_reg_base); + return ret; + } /* Initialize GPIO chips */ - pxa_init_gpio_chip(end); + pxa_init_gpio_chip(pxa_last_gpio); /* clear all GPIO edge detects */ for_each_gpio_chip(gpio, c) { - __raw_writel(0, c->regbase + GFER_OFFSET); - __raw_writel(0, c->regbase + GRER_OFFSET); - __raw_writel(~0,c->regbase + GEDR_OFFSET); + writel_relaxed(0, c->regbase + GFER_OFFSET); + writel_relaxed(0, c->regbase + GRER_OFFSET); + writel_relaxed(~0,c->regbase + GEDR_OFFSET); + /* unmask GPIO edge detect for AP side */ + if (gpio_is_mmp_type(gpio_type)) + writel_relaxed(~0, c->regbase + ED_MASK_OFFSET); } - for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { +#ifdef CONFIG_ARCH_PXA + irq = gpio_to_irq(0); + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); + + irq = gpio_to_irq(1); + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); +#endif + + for (irq = gpio_to_irq(gpio_offset); + irq <= gpio_to_irq(pxa_last_gpio); irq++) { irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - /* Install handler for GPIO>=2 edge detect interrupts */ - irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler); - pxa_muxed_gpio_chip.irq_set_wake = fn; + irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler); + return 0; } +static struct platform_driver pxa_gpio_driver = { + .probe = pxa_gpio_probe, + .driver = { + .name = "pxa-gpio", + }, +}; + +static int __init pxa_gpio_init(void) +{ + return platform_driver_register(&pxa_gpio_driver); +} +postcore_initcall(pxa_gpio_init); + #ifdef CONFIG_PM static int pxa_gpio_suspend(void) { @@ -301,13 +571,13 @@ static int pxa_gpio_suspend(void) int gpio; for_each_gpio_chip(gpio, c) { - c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET); - c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET); - c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET); - c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET); + c->saved_gplr = readl_relaxed(c->regbase + GPLR_OFFSET); + c->saved_gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); + c->saved_grer = readl_relaxed(c->regbase + GRER_OFFSET); + c->saved_gfer = readl_relaxed(c->regbase + GFER_OFFSET); /* Clear GPIO transition detect bits */ - __raw_writel(0xffffffff, c->regbase + GEDR_OFFSET); + writel_relaxed(0xffffffff, c->regbase + GEDR_OFFSET); } return 0; } @@ -319,12 +589,12 @@ static void pxa_gpio_resume(void) for_each_gpio_chip(gpio, c) { /* restore level with set/clear */ - __raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET); - __raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET); + writel_relaxed( c->saved_gplr, c->regbase + GPSR_OFFSET); + writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET); - __raw_writel(c->saved_grer, c->regbase + GRER_OFFSET); - __raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET); - __raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET); + writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET); + writel_relaxed(c->saved_gfer, c->regbase + GFER_OFFSET); + writel_relaxed(c->saved_gpdr, c->regbase + GPDR_OFFSET); } } #else @@ -336,3 +606,10 @@ struct syscore_ops pxa_gpio_syscore_ops = { .suspend = pxa_gpio_suspend, .resume = pxa_gpio_resume, }; + +static int __init pxa_gpio_sysinit(void) +{ + register_syscore_ops(&pxa_gpio_syscore_ops); + return 0; +} +postcore_initcall(pxa_gpio_sysinit); diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index ab098ba9f1dd..a7661773c052 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -24,6 +24,9 @@ #include <linux/interrupt.h> #include <linux/device.h> #include <linux/ioport.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/of_address.h> #include <asm/irq.h> @@ -2383,6 +2386,63 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { #endif }; +#if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) +static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np, + const void *gpio_spec, u32 *flags) +{ + const __be32 *gpio = gpio_spec; + const u32 n = be32_to_cpup(gpio); + unsigned int pin = gc->base + be32_to_cpu(gpio[0]); + + if (WARN_ON(gc->of_gpio_n_cells < 4)) + return -EINVAL; + + if (n > gc->ngpio) + return -EINVAL; + + if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1])))) + pr_warn("gpio_xlate: failed to set pin function\n"); + if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2]))) + pr_warn("gpio_xlate: failed to set pin pull up/down\n"); + if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3]))) + pr_warn("gpio_xlate: failed to set pin drive strength\n"); + + return n; +} + +static const struct of_device_id exynos4_gpio_dt_match[] __initdata = { + { .compatible = "samsung,exynos4-gpio", }, + {} +}; + +static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, + u64 base, u64 offset) +{ + struct gpio_chip *gc = &chip->chip; + u64 address; + + if (!of_have_populated_dt()) + return; + + address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset; + gc->of_node = of_find_matching_node_by_address(NULL, + exynos4_gpio_dt_match, address); + if (!gc->of_node) { + pr_info("gpio: device tree node not found for gpio controller" + " with base address %08llx\n", address); + return; + } + gc->of_gpio_n_cells = 4; + gc->of_xlate = exynos4_gpio_xlate; +} +#elif defined(CONFIG_ARCH_EXYNOS4) +static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, + u64 base, u64 offset) +{ + return; +} +#endif /* defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) */ + /* TODO: cleanup soc_is_* */ static __init int samsung_gpiolib_init(void) { @@ -2464,6 +2524,10 @@ static __init int samsung_gpiolib_init(void) chip->config = &exynos4_gpio_cfg; chip->group = group++; } +#ifdef CONFIG_CPU_EXYNOS4210 + exynos4_gpiolib_attach_ofnode(chip, + EXYNOS4_PA_GPIO1, i * 0x20); +#endif } samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1); @@ -2476,6 +2540,10 @@ static __init int samsung_gpiolib_init(void) chip->config = &exynos4_gpio_cfg; chip->group = group++; } +#ifdef CONFIG_CPU_EXYNOS4210 + exynos4_gpiolib_attach_ofnode(chip, + EXYNOS4_PA_GPIO2, i * 0x20); +#endif } samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2); @@ -2488,6 +2556,10 @@ static __init int samsung_gpiolib_init(void) chip->config = &exynos4_gpio_cfg; chip->group = group++; } +#ifdef CONFIG_CPU_EXYNOS4210 + exynos4_gpiolib_attach_ofnode(chip, + EXYNOS4_PA_GPIO3, i * 0x20); +#endif } samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3); diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c deleted file mode 100644 index 4035778852b0..000000000000 --- a/drivers/gpio/gpio-u300.c +++ /dev/null @@ -1,917 +0,0 @@ -/* - * U300 GPIO module. - * - * Copyright (C) 2007-2011 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * This can driver either of the two basic GPIO cores - * available in the U300 platforms: - * COH 901 335 - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0) - * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0) - * Author: Linus Walleij <linus.walleij@linaro.org> - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> - */ -#include <linux/module.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/list.h> -#include <linux/slab.h> -#include <mach/gpio-u300.h> - -/* - * Bias modes for U300 GPIOs - * - * GPIO_U300_CONFIG_BIAS_UNKNOWN: this bias mode is not known to us - * GPIO_U300_CONFIG_BIAS_FLOAT: no specific bias, the GPIO will float or state - * is not controlled by software - * GPIO_U300_CONFIG_BIAS_PULL_UP: the GPIO will be pulled up (usually with high - * impedance to VDD) - */ -#define GPIO_U300_CONFIG_BIAS_UNKNOWN 0x1000 -#define GPIO_U300_CONFIG_BIAS_FLOAT 0x1001 -#define GPIO_U300_CONFIG_BIAS_PULL_UP 0x1002 - -/* - * Drive modes for U300 GPIOs (output) - * - * GPIO_U300_CONFIG_DRIVE_PUSH_PULL: the GPIO will be driven actively high and - * low, this is the most typical case and is typically achieved with two - * active transistors on the output - * GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: the GPIO will be driven with open drain - * (open collector) which means it is usually wired with other output - * ports which are then pulled up with an external resistor - * GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: the GPIO will be driven with open drain - * (open emitter) which is the same as open drain mutatis mutandis but - * pulled to ground - */ -#define GPIO_U300_CONFIG_DRIVE_PUSH_PULL 0x2000 -#define GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN 0x2001 -#define GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE 0x2002 - -/* - * Register definitions for COH 901 335 variant - */ -#define U300_335_PORT_STRIDE (0x1C) -/* Port X Pin Data Register 32bit, this is both input and output (R/W) */ -#define U300_335_PXPDIR (0x00) -#define U300_335_PXPDOR (0x00) -/* Port X Pin Config Register 32bit (R/W) */ -#define U300_335_PXPCR (0x04) -/* This register layout is the same in both blocks */ -#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) -#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) -#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) -#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) -/* Port X Interrupt Event Register 32bit (R/W) */ -#define U300_335_PXIEV (0x08) -/* Port X Interrupt Enable Register 32bit (R/W) */ -#define U300_335_PXIEN (0x0C) -/* Port X Interrupt Force Register 32bit (R/W) */ -#define U300_335_PXIFR (0x10) -/* Port X Interrupt Config Register 32bit (R/W) */ -#define U300_335_PXICR (0x14) -/* This register layout is the same in both blocks */ -#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) -#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) -#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) -/* Port X Pull-up Enable Register 32bit (R/W) */ -#define U300_335_PXPER (0x18) -/* This register layout is the same in both blocks */ -#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) -#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) -/* Control Register 32bit (R/W) */ -#define U300_335_CR (0x54) -#define U300_335_CR_BLOCK_CLOCK_ENABLE (0x00000001UL) - -/* - * Register definitions for COH 901 571 / 3 variant - */ -#define U300_571_PORT_STRIDE (0x30) -/* - * Control Register 32bit (R/W) - * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores - * gives the number of GPIO pins. - * bit 8-2 (mask 0x000001FC) contains the core version ID. - */ -#define U300_571_CR (0x00) -#define U300_571_CR_SYNC_SEL_ENABLE (0x00000002UL) -#define U300_571_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL) -/* - * These registers have the same layout and function as the corresponding - * COH 901 335 registers, just at different offset. - */ -#define U300_571_PXPDIR (0x04) -#define U300_571_PXPDOR (0x08) -#define U300_571_PXPCR (0x0C) -#define U300_571_PXPER (0x10) -#define U300_571_PXIEV (0x14) -#define U300_571_PXIEN (0x18) -#define U300_571_PXIFR (0x1C) -#define U300_571_PXICR (0x20) - -/* 8 bits per port, no version has more than 7 ports */ -#define U300_GPIO_PINS_PER_PORT 8 -#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * 7) - -struct u300_gpio { - struct gpio_chip chip; - struct list_head port_list; - struct clk *clk; - struct resource *memres; - void __iomem *base; - struct device *dev; - int irq_base; - u32 stride; - /* Register offsets */ - u32 pcr; - u32 dor; - u32 dir; - u32 per; - u32 icr; - u32 ien; - u32 iev; -}; - -struct u300_gpio_port { - struct list_head node; - struct u300_gpio *gpio; - char name[8]; - int irq; - int number; - u8 toggle_edge_mode; -}; - -/* - * Macro to expand to read a specific register found in the "gpio" - * struct. It requires the struct u300_gpio *gpio variable to exist in - * its context. It calculates the port offset from the given pin - * offset, muliplies by the port stride and adds the register offset - * so it provides a pointer to the desired register. - */ -#define U300_PIN_REG(pin, reg) \ - (gpio->base + (pin >> 3) * gpio->stride + gpio->reg) - -/* - * Provides a bitmask for a specific gpio pin inside an 8-bit GPIO - * register. - */ -#define U300_PIN_BIT(pin) \ - (1 << (pin & 0x07)) - -struct u300_gpio_confdata { - u16 bias_mode; - bool output; - int outval; -}; - -/* BS335 has seven ports of 8 bits each = GPIO pins 0..55 */ -#define BS335_GPIO_NUM_PORTS 7 -/* BS365 has five ports of 8 bits each = GPIO pins 0..39 */ -#define BS365_GPIO_NUM_PORTS 5 - -#define U300_FLOATING_INPUT { \ - .bias_mode = GPIO_U300_CONFIG_BIAS_FLOAT, \ - .output = false, \ -} - -#define U300_PULL_UP_INPUT { \ - .bias_mode = GPIO_U300_CONFIG_BIAS_PULL_UP, \ - .output = false, \ -} - -#define U300_OUTPUT_LOW { \ - .output = true, \ - .outval = 0, \ -} - -#define U300_OUTPUT_HIGH { \ - .output = true, \ - .outval = 1, \ -} - - -/* Initial configuration */ -static const struct __initdata u300_gpio_confdata -bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { - /* Port 0, pins 0-7 */ - { - U300_FLOATING_INPUT, - U300_OUTPUT_HIGH, - U300_FLOATING_INPUT, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - }, - /* Port 1, pins 0-7 */ - { - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_PULL_UP_INPUT, - U300_FLOATING_INPUT, - U300_OUTPUT_HIGH, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - }, - /* Port 2, pins 0-7 */ - { - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_OUTPUT_LOW, - U300_PULL_UP_INPUT, - U300_OUTPUT_LOW, - U300_PULL_UP_INPUT, - }, - /* Port 3, pins 0-7 */ - { - U300_PULL_UP_INPUT, - U300_OUTPUT_LOW, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - }, - /* Port 4, pins 0-7 */ - { - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - }, - /* Port 5, pins 0-7 */ - { - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - }, - /* Port 6, pind 0-7 */ - { - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - } -}; - -static const struct __initdata u300_gpio_confdata -bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { - /* Port 0, pins 0-7 */ - { - U300_FLOATING_INPUT, - U300_OUTPUT_LOW, - U300_FLOATING_INPUT, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_PULL_UP_INPUT, - U300_FLOATING_INPUT, - }, - /* Port 1, pins 0-7 */ - { - U300_OUTPUT_LOW, - U300_FLOATING_INPUT, - U300_OUTPUT_LOW, - U300_FLOATING_INPUT, - U300_FLOATING_INPUT, - U300_OUTPUT_HIGH, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - }, - /* Port 2, pins 0-7 */ - { - U300_FLOATING_INPUT, - U300_PULL_UP_INPUT, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - }, - /* Port 3, pins 0-7 */ - { - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - }, - /* Port 4, pins 0-7 */ - { - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - U300_PULL_UP_INPUT, - /* These 4 pins doesn't exist on DB3210 */ - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - U300_OUTPUT_LOW, - } -}; - -/** - * to_u300_gpio() - get the pointer to u300_gpio - * @chip: the gpio chip member of the structure u300_gpio - */ -static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct u300_gpio, chip); -} - -static int u300_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct u300_gpio *gpio = to_u300_gpio(chip); - - return readl(U300_PIN_REG(offset, dir)) & U300_PIN_BIT(offset); -} - -static void u300_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct u300_gpio *gpio = to_u300_gpio(chip); - unsigned long flags; - u32 val; - - local_irq_save(flags); - - val = readl(U300_PIN_REG(offset, dor)); - if (value) - writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, dor)); - else - writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, dor)); - - local_irq_restore(flags); -} - -static int u300_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct u300_gpio *gpio = to_u300_gpio(chip); - unsigned long flags; - u32 val; - - local_irq_save(flags); - val = readl(U300_PIN_REG(offset, pcr)); - /* Mask out this pin, note 2 bits per setting */ - val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1)); - writel(val, U300_PIN_REG(offset, pcr)); - local_irq_restore(flags); - return 0; -} - -static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct u300_gpio *gpio = to_u300_gpio(chip); - unsigned long flags; - u32 oldmode; - u32 val; - - local_irq_save(flags); - val = readl(U300_PIN_REG(offset, pcr)); - /* - * Drive mode must be set by the special mode set function, set - * push/pull mode by default if no mode has been selected. - */ - oldmode = val & (U300_GPIO_PXPCR_PIN_MODE_MASK << - ((offset & 0x07) << 1)); - /* mode = 0 means input, else some mode is already set */ - if (oldmode == 0) { - val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << - ((offset & 0x07) << 1)); - val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL - << ((offset & 0x07) << 1)); - writel(val, U300_PIN_REG(offset, pcr)); - } - u300_gpio_set(chip, offset, value); - local_irq_restore(flags); - return 0; -} - -static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct u300_gpio *gpio = to_u300_gpio(chip); - int retirq = gpio->irq_base + offset; - - dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset, - retirq); - return retirq; -} - -static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, - u16 param, unsigned long *data) -{ - struct u300_gpio *gpio = to_u300_gpio(chip); - unsigned long flags; - u32 val; - - local_irq_save(flags); - switch (param) { - case GPIO_U300_CONFIG_BIAS_UNKNOWN: - case GPIO_U300_CONFIG_BIAS_FLOAT: - val = readl(U300_PIN_REG(offset, per)); - writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); - break; - case GPIO_U300_CONFIG_BIAS_PULL_UP: - val = readl(U300_PIN_REG(offset, per)); - writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); - break; - case GPIO_U300_CONFIG_DRIVE_PUSH_PULL: - val = readl(U300_PIN_REG(offset, pcr)); - val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK - << ((offset & 0x07) << 1)); - val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL - << ((offset & 0x07) << 1)); - writel(val, U300_PIN_REG(offset, pcr)); - break; - case GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: - val = readl(U300_PIN_REG(offset, pcr)); - val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK - << ((offset & 0x07) << 1)); - val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN - << ((offset & 0x07) << 1)); - writel(val, U300_PIN_REG(offset, pcr)); - break; - case GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: - val = readl(U300_PIN_REG(offset, pcr)); - val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK - << ((offset & 0x07) << 1)); - val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE - << ((offset & 0x07) << 1)); - writel(val, U300_PIN_REG(offset, pcr)); - break; - default: - local_irq_restore(flags); - dev_err(gpio->dev, "illegal configuration requested\n"); - return -EINVAL; - } - local_irq_restore(flags); - return 0; -} - -static struct gpio_chip u300_gpio_chip = { - .label = "u300-gpio-chip", - .owner = THIS_MODULE, - .get = u300_gpio_get, - .set = u300_gpio_set, - .direction_input = u300_gpio_direction_input, - .direction_output = u300_gpio_direction_output, - .to_irq = u300_gpio_to_irq, -}; - -static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset) -{ - u32 val; - - val = readl(U300_PIN_REG(offset, icr)); - /* Set mode depending on state */ - if (u300_gpio_get(&gpio->chip, offset)) { - /* High now, let's trigger on falling edge next then */ - writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); - dev_dbg(gpio->dev, "next IRQ on falling edge on pin %d\n", - offset); - } else { - /* Low now, let's trigger on rising edge next then */ - writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); - dev_dbg(gpio->dev, "next IRQ on rising edge on pin %d\n", - offset); - } -} - -static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger) -{ - struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); - struct u300_gpio *gpio = port->gpio; - int offset = d->irq - gpio->irq_base; - u32 val; - - if ((trigger & IRQF_TRIGGER_RISING) && - (trigger & IRQF_TRIGGER_FALLING)) { - /* - * The GPIO block can only trigger on falling OR rising edges, - * not both. So we need to toggle the mode whenever the pin - * goes from one state to the other with a special state flag - */ - dev_dbg(gpio->dev, - "trigger on both rising and falling edge on pin %d\n", - offset); - port->toggle_edge_mode |= U300_PIN_BIT(offset); - u300_toggle_trigger(gpio, offset); - } else if (trigger & IRQF_TRIGGER_RISING) { - dev_dbg(gpio->dev, "trigger on rising edge on pin %d\n", - offset); - val = readl(U300_PIN_REG(offset, icr)); - writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); - port->toggle_edge_mode &= ~U300_PIN_BIT(offset); - } else if (trigger & IRQF_TRIGGER_FALLING) { - dev_dbg(gpio->dev, "trigger on falling edge on pin %d\n", - offset); - val = readl(U300_PIN_REG(offset, icr)); - writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); - port->toggle_edge_mode &= ~U300_PIN_BIT(offset); - } - - return 0; -} - -static void u300_gpio_irq_enable(struct irq_data *d) -{ - struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); - struct u300_gpio *gpio = port->gpio; - int offset = d->irq - gpio->irq_base; - u32 val; - unsigned long flags; - - local_irq_save(flags); - val = readl(U300_PIN_REG(offset, ien)); - writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); - local_irq_restore(flags); -} - -static void u300_gpio_irq_disable(struct irq_data *d) -{ - struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); - struct u300_gpio *gpio = port->gpio; - int offset = d->irq - gpio->irq_base; - u32 val; - unsigned long flags; - - local_irq_save(flags); - val = readl(U300_PIN_REG(offset, ien)); - writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); - local_irq_restore(flags); -} - -static struct irq_chip u300_gpio_irqchip = { - .name = "u300-gpio-irqchip", - .irq_enable = u300_gpio_irq_enable, - .irq_disable = u300_gpio_irq_disable, - .irq_set_type = u300_gpio_irq_type, - -}; - -static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) -{ - struct u300_gpio_port *port = irq_get_handler_data(irq); - struct u300_gpio *gpio = port->gpio; - int pinoffset = port->number << 3; /* get the right stride */ - unsigned long val; - - desc->irq_data.chip->irq_ack(&desc->irq_data); - /* Read event register */ - val = readl(U300_PIN_REG(pinoffset, iev)); - /* Mask relevant bits */ - val &= 0xFFU; /* 8 bits per port */ - /* ACK IRQ (clear event) */ - writel(val, U300_PIN_REG(pinoffset, iev)); - - /* Call IRQ handler */ - if (val != 0) { - int irqoffset; - - for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) { - int pin_irq = gpio->irq_base + (port->number << 3) - + irqoffset; - int offset = pinoffset + irqoffset; - - dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n", - pin_irq, offset); - generic_handle_irq(pin_irq); - /* - * Triggering IRQ on both rising and falling edge - * needs mockery - */ - if (port->toggle_edge_mode & U300_PIN_BIT(offset)) - u300_toggle_trigger(gpio, offset); - } - } - - desc->irq_data.chip->irq_unmask(&desc->irq_data); -} - -static void __init u300_gpio_init_pin(struct u300_gpio *gpio, - int offset, - const struct u300_gpio_confdata *conf) -{ - /* Set mode: input or output */ - if (conf->output) { - u300_gpio_direction_output(&gpio->chip, offset, conf->outval); - - /* Deactivate bias mode for output */ - u300_gpio_config(&gpio->chip, offset, - GPIO_U300_CONFIG_BIAS_FLOAT, - NULL); - - /* Set drive mode for output */ - u300_gpio_config(&gpio->chip, offset, - GPIO_U300_CONFIG_DRIVE_PUSH_PULL, NULL); - - dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n", - offset, conf->outval); - } else { - u300_gpio_direction_input(&gpio->chip, offset); - - /* Always set output low on input pins */ - u300_gpio_set(&gpio->chip, offset, 0); - - /* Set bias mode for input */ - u300_gpio_config(&gpio->chip, offset, conf->bias_mode, NULL); - - dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n", - offset, conf->bias_mode); - } -} - -static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio, - struct u300_gpio_platform *plat) -{ - int i, j; - - /* Write default config and values to all pins */ - for (i = 0; i < plat->ports; i++) { - for (j = 0; j < 8; j++) { - const struct u300_gpio_confdata *conf; - int offset = (i*8) + j; - - if (plat->variant == U300_GPIO_COH901571_3_BS335) - conf = &bs335_gpio_config[i][j]; - else if (plat->variant == U300_GPIO_COH901571_3_BS365) - conf = &bs365_gpio_config[i][j]; - else - break; - - u300_gpio_init_pin(gpio, offset, conf); - } - } -} - -static inline void u300_gpio_free_ports(struct u300_gpio *gpio) -{ - struct u300_gpio_port *port; - struct list_head *p, *n; - - list_for_each_safe(p, n, &gpio->port_list) { - port = list_entry(p, struct u300_gpio_port, node); - list_del(&port->node); - free_irq(port->irq, port); - kfree(port); - } -} - -static int __init u300_gpio_probe(struct platform_device *pdev) -{ - struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev); - struct u300_gpio *gpio; - int err = 0; - int portno; - u32 val; - u32 ifr; - int i; - - gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL); - if (gpio == NULL) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - - gpio->chip = u300_gpio_chip; - gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT; - gpio->irq_base = plat->gpio_irq_base; - gpio->chip.dev = &pdev->dev; - gpio->chip.base = plat->gpio_base; - gpio->dev = &pdev->dev; - - /* Get GPIO clock */ - gpio->clk = clk_get(gpio->dev, NULL); - if (IS_ERR(gpio->clk)) { - err = PTR_ERR(gpio->clk); - dev_err(gpio->dev, "could not get GPIO clock\n"); - goto err_no_clk; - } - err = clk_enable(gpio->clk); - if (err) { - dev_err(gpio->dev, "could not enable GPIO clock\n"); - goto err_no_clk_enable; - } - - gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!gpio->memres) { - dev_err(gpio->dev, "could not get GPIO memory resource\n"); - err = -ENODEV; - goto err_no_resource; - } - - if (!request_mem_region(gpio->memres->start, - resource_size(gpio->memres), - "GPIO Controller")) { - err = -ENODEV; - goto err_no_ioregion; - } - - gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres)); - if (!gpio->base) { - err = -ENOMEM; - goto err_no_ioremap; - } - - if (plat->variant == U300_GPIO_COH901335) { - dev_info(gpio->dev, - "initializing GPIO Controller COH 901 335\n"); - gpio->stride = U300_335_PORT_STRIDE; - gpio->pcr = U300_335_PXPCR; - gpio->dor = U300_335_PXPDOR; - gpio->dir = U300_335_PXPDIR; - gpio->per = U300_335_PXPER; - gpio->icr = U300_335_PXICR; - gpio->ien = U300_335_PXIEN; - gpio->iev = U300_335_PXIEV; - ifr = U300_335_PXIFR; - - /* Turn on the GPIO block */ - writel(U300_335_CR_BLOCK_CLOCK_ENABLE, - gpio->base + U300_335_CR); - } else if (plat->variant == U300_GPIO_COH901571_3_BS335 || - plat->variant == U300_GPIO_COH901571_3_BS365) { - dev_info(gpio->dev, - "initializing GPIO Controller COH 901 571/3\n"); - gpio->stride = U300_571_PORT_STRIDE; - gpio->pcr = U300_571_PXPCR; - gpio->dor = U300_571_PXPDOR; - gpio->dir = U300_571_PXPDIR; - gpio->per = U300_571_PXPER; - gpio->icr = U300_571_PXICR; - gpio->ien = U300_571_PXIEN; - gpio->iev = U300_571_PXIEV; - ifr = U300_571_PXIFR; - - val = readl(gpio->base + U300_571_CR); - dev_info(gpio->dev, "COH901571/3 block version: %d, " \ - "number of cores: %d totalling %d pins\n", - ((val & 0x000001FC) >> 2), - ((val & 0x0000FE00) >> 9), - ((val & 0x0000FE00) >> 9) * 8); - writel(U300_571_CR_BLOCK_CLKRQ_ENABLE, - gpio->base + U300_571_CR); - u300_gpio_init_coh901571(gpio, plat); - } else { - dev_err(gpio->dev, "unknown block variant\n"); - err = -ENODEV; - goto err_unknown_variant; - } - - /* Add each port with its IRQ separately */ - INIT_LIST_HEAD(&gpio->port_list); - for (portno = 0 ; portno < plat->ports; portno++) { - struct u300_gpio_port *port = - kmalloc(sizeof(struct u300_gpio_port), GFP_KERNEL); - - if (!port) { - dev_err(gpio->dev, "out of memory\n"); - err = -ENOMEM; - goto err_no_port; - } - - snprintf(port->name, 8, "gpio%d", portno); - port->number = portno; - port->gpio = gpio; - - port->irq = platform_get_irq_byname(pdev, - port->name); - - dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq, - port->name); - - irq_set_chained_handler(port->irq, u300_gpio_irq_handler); - irq_set_handler_data(port->irq, port); - - /* For each GPIO pin set the unique IRQ handler */ - for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) { - int irqno = gpio->irq_base + (portno << 3) + i; - - dev_dbg(gpio->dev, "handler for IRQ %d on %s\n", - irqno, port->name); - irq_set_chip_and_handler(irqno, &u300_gpio_irqchip, - handle_simple_irq); - set_irq_flags(irqno, IRQF_VALID); - irq_set_chip_data(irqno, port); - } - - /* Turns off irq force (test register) for this port */ - writel(0x0, gpio->base + portno * gpio->stride + ifr); - - list_add_tail(&port->node, &gpio->port_list); - } - dev_dbg(gpio->dev, "initialized %d GPIO ports\n", portno); - - err = gpiochip_add(&gpio->chip); - if (err) { - dev_err(gpio->dev, "unable to add gpiochip: %d\n", err); - goto err_no_chip; - } - - platform_set_drvdata(pdev, gpio); - - return 0; - -err_no_chip: -err_no_port: - u300_gpio_free_ports(gpio); -err_unknown_variant: - iounmap(gpio->base); -err_no_ioremap: - release_mem_region(gpio->memres->start, resource_size(gpio->memres)); -err_no_ioregion: -err_no_resource: - clk_disable(gpio->clk); -err_no_clk_enable: - clk_put(gpio->clk); -err_no_clk: - kfree(gpio); - dev_info(&pdev->dev, "module ERROR:%d\n", err); - return err; -} - -static int __exit u300_gpio_remove(struct platform_device *pdev) -{ - struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev); - struct u300_gpio *gpio = platform_get_drvdata(pdev); - int err; - - /* Turn off the GPIO block */ - if (plat->variant == U300_GPIO_COH901335) - writel(0x00000000U, gpio->base + U300_335_CR); - if (plat->variant == U300_GPIO_COH901571_3_BS335 || - plat->variant == U300_GPIO_COH901571_3_BS365) - writel(0x00000000U, gpio->base + U300_571_CR); - - err = gpiochip_remove(&gpio->chip); - if (err < 0) { - dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err); - return err; - } - u300_gpio_free_ports(gpio); - iounmap(gpio->base); - release_mem_region(gpio->memres->start, - resource_size(gpio->memres)); - clk_disable(gpio->clk); - clk_put(gpio->clk); - platform_set_drvdata(pdev, NULL); - kfree(gpio); - return 0; -} - -static struct platform_driver u300_gpio_driver = { - .driver = { - .name = "u300-gpio", - }, - .remove = __exit_p(u300_gpio_remove), -}; - - -static int __init u300_gpio_init(void) -{ - return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe); -} - -static void __exit u300_gpio_exit(void) -{ - platform_driver_unregister(&u300_gpio_driver); -} - -arch_initcall(u300_gpio_init); -module_exit(u300_gpio_exit); - -MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); -MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335/COH 901 571/3 GPIO driver"); -MODULE_LICENSE("GPL"); |