From 9d3a15aaaec41252ad7c6592305264e52a801be7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Mar 2017 00:28:16 +0100 Subject: gpio: gemini: rename to match Faraday IP The Gemini driver is actually a driver for the Faraday Technology FTGPIO010 IP block. We rename the driver and the Kconfig symbol and put in a a new compatible string for the Moxa ART SoC that is also using this IP block. Tested-by: Jonas Jensen Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 7 +- drivers/gpio/Makefile | 2 +- drivers/gpio/gpio-ftgpio010.c | 242 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpio/gpio-gemini.c | 236 ---------------------------------------- 4 files changed, 247 insertions(+), 240 deletions(-) create mode 100644 drivers/gpio/gpio-ftgpio010.c delete mode 100644 drivers/gpio/gpio-gemini.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a386240c5921..2c3f6390b44b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -204,14 +204,15 @@ config GPIO_GE_FPGA and write pin state) for GPIO implemented in a number of GE single board computers. -config GPIO_GEMINI - bool "Gemini GPIO" +config GPIO_FTGPIO010 + bool "Faraday FTGPIO010 GPIO" depends on ARCH_GEMINI depends on OF_GPIO select GPIO_GENERIC select GPIOLIB_IRQCHIP help - Support for common GPIOs found in Cortina systems Gemini platforms. + Support for common GPIOs from the Faraday FTGPIO010 IP core, found in + Cortina systems Gemini platforms, Moxa ART and others. config GPIO_GENERIC_PLATFORM tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index becb96c724fe..4b904fec8273 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -48,8 +48,8 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o +obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o -obj-$(CONFIG_GPIO_GEMINI) += gpio-gemini.o obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c new file mode 100644 index 000000000000..e9386f8b67f5 --- /dev/null +++ b/drivers/gpio/gpio-ftgpio010.c @@ -0,0 +1,242 @@ +/* + * Faraday Technolog FTGPIO010 gpiochip and interrupt routines + * Copyright (C) 2017 Linus Walleij + * + * Based on arch/arm/mach-gemini/gpio.c: + * Copyright (C) 2008-2009 Paulius Zaleckas + * + * Based on plat-mxc/gpio.c: + * MXC GPIO support. (c) 2008 Daniel Mack + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de + */ +#include +#include +#include +#include +#include +#include + +/* GPIO registers definition */ +#define GPIO_DATA_OUT 0x00 +#define GPIO_DATA_IN 0x04 +#define GPIO_DIR 0x08 +#define GPIO_DATA_SET 0x10 +#define GPIO_DATA_CLR 0x14 +#define GPIO_PULL_EN 0x18 +#define GPIO_PULL_TYPE 0x1C +#define GPIO_INT_EN 0x20 +#define GPIO_INT_STAT 0x24 +#define GPIO_INT_MASK 0x2C +#define GPIO_INT_CLR 0x30 +#define GPIO_INT_TYPE 0x34 +#define GPIO_INT_BOTH_EDGE 0x38 +#define GPIO_INT_LEVEL 0x3C +#define GPIO_DEBOUNCE_EN 0x40 +#define GPIO_DEBOUNCE_PRESCALE 0x44 + +/** + * struct ftgpio_gpio - Gemini GPIO state container + * @dev: containing device for this instance + * @gc: gpiochip for this instance + */ +struct ftgpio_gpio { + struct device *dev; + struct gpio_chip gc; + void __iomem *base; +}; + +static void ftgpio_gpio_ack_irq(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ftgpio_gpio *g = gpiochip_get_data(gc); + + writel(BIT(irqd_to_hwirq(d)), g->base + GPIO_INT_CLR); +} + +static void ftgpio_gpio_mask_irq(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ftgpio_gpio *g = gpiochip_get_data(gc); + u32 val; + + val = readl(g->base + GPIO_INT_EN); + val &= ~BIT(irqd_to_hwirq(d)); + writel(val, g->base + GPIO_INT_EN); +} + +static void ftgpio_gpio_unmask_irq(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ftgpio_gpio *g = gpiochip_get_data(gc); + u32 val; + + val = readl(g->base + GPIO_INT_EN); + val |= BIT(irqd_to_hwirq(d)); + writel(val, g->base + GPIO_INT_EN); +} + +static int ftgpio_gpio_set_irq_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ftgpio_gpio *g = gpiochip_get_data(gc); + u32 mask = BIT(irqd_to_hwirq(d)); + u32 reg_both, reg_level, reg_type; + + reg_type = readl(g->base + GPIO_INT_TYPE); + reg_level = readl(g->base + GPIO_INT_LEVEL); + reg_both = readl(g->base + GPIO_INT_BOTH_EDGE); + + switch (type) { + case IRQ_TYPE_EDGE_BOTH: + irq_set_handler_locked(d, handle_edge_irq); + reg_type &= ~mask; + reg_both |= mask; + break; + case IRQ_TYPE_EDGE_RISING: + irq_set_handler_locked(d, handle_edge_irq); + reg_type &= ~mask; + reg_both &= ~mask; + reg_level &= ~mask; + break; + case IRQ_TYPE_EDGE_FALLING: + irq_set_handler_locked(d, handle_edge_irq); + reg_type &= ~mask; + reg_both &= ~mask; + reg_level |= mask; + break; + case IRQ_TYPE_LEVEL_HIGH: + irq_set_handler_locked(d, handle_level_irq); + reg_type |= mask; + reg_level &= ~mask; + break; + case IRQ_TYPE_LEVEL_LOW: + irq_set_handler_locked(d, handle_level_irq); + reg_type |= mask; + reg_level |= mask; + break; + default: + irq_set_handler_locked(d, handle_bad_irq); + return -EINVAL; + } + + writel(reg_type, g->base + GPIO_INT_TYPE); + writel(reg_level, g->base + GPIO_INT_LEVEL); + writel(reg_both, g->base + GPIO_INT_BOTH_EDGE); + + ftgpio_gpio_ack_irq(d); + + return 0; +} + +static struct irq_chip ftgpio_gpio_irqchip = { + .name = "FTGPIO010", + .irq_ack = ftgpio_gpio_ack_irq, + .irq_mask = ftgpio_gpio_mask_irq, + .irq_unmask = ftgpio_gpio_unmask_irq, + .irq_set_type = ftgpio_gpio_set_irq_type, +}; + +static void ftgpio_gpio_irq_handler(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct ftgpio_gpio *g = gpiochip_get_data(gc); + struct irq_chip *irqchip = irq_desc_get_chip(desc); + int offset; + unsigned long stat; + + chained_irq_enter(irqchip, desc); + + stat = readl(g->base + GPIO_INT_STAT); + if (stat) + for_each_set_bit(offset, &stat, gc->ngpio) + generic_handle_irq(irq_find_mapping(gc->irqdomain, + offset)); + + chained_irq_exit(irqchip, desc); +} + +static int ftgpio_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct ftgpio_gpio *g; + int irq; + int ret; + + g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL); + if (!g) + return -ENOMEM; + + g->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + g->base = devm_ioremap_resource(dev, res); + if (IS_ERR(g->base)) + return PTR_ERR(g->base); + + irq = platform_get_irq(pdev, 0); + if (!irq) + return -EINVAL; + + ret = bgpio_init(&g->gc, dev, 4, + g->base + GPIO_DATA_IN, + g->base + GPIO_DATA_SET, + g->base + GPIO_DATA_CLR, + g->base + GPIO_DIR, + NULL, + 0); + if (ret) { + dev_err(dev, "unable to init generic GPIO\n"); + return ret; + } + g->gc.label = "FTGPIO010"; + g->gc.base = -1; + g->gc.parent = dev; + g->gc.owner = THIS_MODULE; + /* ngpio is set by bgpio_init() */ + + ret = devm_gpiochip_add_data(dev, &g->gc, g); + if (ret) + return ret; + + /* Disable, unmask and clear all interrupts */ + writel(0x0, g->base + GPIO_INT_EN); + writel(0x0, g->base + GPIO_INT_MASK); + writel(~0x0, g->base + GPIO_INT_CLR); + + ret = gpiochip_irqchip_add(&g->gc, &ftgpio_gpio_irqchip, + 0, handle_bad_irq, + IRQ_TYPE_NONE); + if (ret) { + dev_info(dev, "could not add irqchip\n"); + return ret; + } + gpiochip_set_chained_irqchip(&g->gc, &ftgpio_gpio_irqchip, + irq, ftgpio_gpio_irq_handler); + + dev_info(dev, "FTGPIO010 @%p registered\n", g->base); + + return 0; +} + +static const struct of_device_id ftgpio_gpio_of_match[] = { + { + .compatible = "cortina,gemini-gpio", + }, + { + .compatible = "moxa,moxart-gpio", + }, + { + .compatible = "faraday,ftgpio010", + }, + {}, +}; + +static struct platform_driver ftgpio_gpio_driver = { + .driver = { + .name = "ftgpio010-gpio", + .of_match_table = of_match_ptr(ftgpio_gpio_of_match), + }, + .probe = ftgpio_gpio_probe, +}; +builtin_platform_driver(ftgpio_gpio_driver); diff --git a/drivers/gpio/gpio-gemini.c b/drivers/gpio/gpio-gemini.c deleted file mode 100644 index 962485163b7f..000000000000 --- a/drivers/gpio/gpio-gemini.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Gemini gpiochip and interrupt routines - * Copyright (C) 2017 Linus Walleij - * - * Based on arch/arm/mach-gemini/gpio.c: - * Copyright (C) 2008-2009 Paulius Zaleckas - * - * Based on plat-mxc/gpio.c: - * MXC GPIO support. (c) 2008 Daniel Mack - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - */ -#include -#include -#include -#include -#include -#include - -/* GPIO registers definition */ -#define GPIO_DATA_OUT 0x00 -#define GPIO_DATA_IN 0x04 -#define GPIO_DIR 0x08 -#define GPIO_DATA_SET 0x10 -#define GPIO_DATA_CLR 0x14 -#define GPIO_PULL_EN 0x18 -#define GPIO_PULL_TYPE 0x1C -#define GPIO_INT_EN 0x20 -#define GPIO_INT_STAT 0x24 -#define GPIO_INT_MASK 0x2C -#define GPIO_INT_CLR 0x30 -#define GPIO_INT_TYPE 0x34 -#define GPIO_INT_BOTH_EDGE 0x38 -#define GPIO_INT_LEVEL 0x3C -#define GPIO_DEBOUNCE_EN 0x40 -#define GPIO_DEBOUNCE_PRESCALE 0x44 - -/** - * struct gemini_gpio - Gemini GPIO state container - * @dev: containing device for this instance - * @gc: gpiochip for this instance - */ -struct gemini_gpio { - struct device *dev; - struct gpio_chip gc; - void __iomem *base; -}; - -static void gemini_gpio_ack_irq(struct irq_data *d) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct gemini_gpio *g = gpiochip_get_data(gc); - - writel(BIT(irqd_to_hwirq(d)), g->base + GPIO_INT_CLR); -} - -static void gemini_gpio_mask_irq(struct irq_data *d) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct gemini_gpio *g = gpiochip_get_data(gc); - u32 val; - - val = readl(g->base + GPIO_INT_EN); - val &= ~BIT(irqd_to_hwirq(d)); - writel(val, g->base + GPIO_INT_EN); -} - -static void gemini_gpio_unmask_irq(struct irq_data *d) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct gemini_gpio *g = gpiochip_get_data(gc); - u32 val; - - val = readl(g->base + GPIO_INT_EN); - val |= BIT(irqd_to_hwirq(d)); - writel(val, g->base + GPIO_INT_EN); -} - -static int gemini_gpio_set_irq_type(struct irq_data *d, unsigned int type) -{ - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct gemini_gpio *g = gpiochip_get_data(gc); - u32 mask = BIT(irqd_to_hwirq(d)); - u32 reg_both, reg_level, reg_type; - - reg_type = readl(g->base + GPIO_INT_TYPE); - reg_level = readl(g->base + GPIO_INT_LEVEL); - reg_both = readl(g->base + GPIO_INT_BOTH_EDGE); - - switch (type) { - case IRQ_TYPE_EDGE_BOTH: - irq_set_handler_locked(d, handle_edge_irq); - reg_type &= ~mask; - reg_both |= mask; - break; - case IRQ_TYPE_EDGE_RISING: - irq_set_handler_locked(d, handle_edge_irq); - reg_type &= ~mask; - reg_both &= ~mask; - reg_level &= ~mask; - break; - case IRQ_TYPE_EDGE_FALLING: - irq_set_handler_locked(d, handle_edge_irq); - reg_type &= ~mask; - reg_both &= ~mask; - reg_level |= mask; - break; - case IRQ_TYPE_LEVEL_HIGH: - irq_set_handler_locked(d, handle_level_irq); - reg_type |= mask; - reg_level &= ~mask; - break; - case IRQ_TYPE_LEVEL_LOW: - irq_set_handler_locked(d, handle_level_irq); - reg_type |= mask; - reg_level |= mask; - break; - default: - irq_set_handler_locked(d, handle_bad_irq); - return -EINVAL; - } - - writel(reg_type, g->base + GPIO_INT_TYPE); - writel(reg_level, g->base + GPIO_INT_LEVEL); - writel(reg_both, g->base + GPIO_INT_BOTH_EDGE); - - gemini_gpio_ack_irq(d); - - return 0; -} - -static struct irq_chip gemini_gpio_irqchip = { - .name = "GPIO", - .irq_ack = gemini_gpio_ack_irq, - .irq_mask = gemini_gpio_mask_irq, - .irq_unmask = gemini_gpio_unmask_irq, - .irq_set_type = gemini_gpio_set_irq_type, -}; - -static void gemini_gpio_irq_handler(struct irq_desc *desc) -{ - struct gpio_chip *gc = irq_desc_get_handler_data(desc); - struct gemini_gpio *g = gpiochip_get_data(gc); - struct irq_chip *irqchip = irq_desc_get_chip(desc); - int offset; - unsigned long stat; - - chained_irq_enter(irqchip, desc); - - stat = readl(g->base + GPIO_INT_STAT); - if (stat) - for_each_set_bit(offset, &stat, gc->ngpio) - generic_handle_irq(irq_find_mapping(gc->irqdomain, - offset)); - - chained_irq_exit(irqchip, desc); -} - -static int gemini_gpio_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *res; - struct gemini_gpio *g; - int irq; - int ret; - - g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL); - if (!g) - return -ENOMEM; - - g->dev = dev; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - g->base = devm_ioremap_resource(dev, res); - if (IS_ERR(g->base)) - return PTR_ERR(g->base); - - irq = platform_get_irq(pdev, 0); - if (!irq) - return -EINVAL; - - ret = bgpio_init(&g->gc, dev, 4, - g->base + GPIO_DATA_IN, - g->base + GPIO_DATA_SET, - g->base + GPIO_DATA_CLR, - g->base + GPIO_DIR, - NULL, - 0); - if (ret) { - dev_err(dev, "unable to init generic GPIO\n"); - return ret; - } - g->gc.label = "Gemini"; - g->gc.base = -1; - g->gc.parent = dev; - g->gc.owner = THIS_MODULE; - /* ngpio is set by bgpio_init() */ - - ret = devm_gpiochip_add_data(dev, &g->gc, g); - if (ret) - return ret; - - /* Disable, unmask and clear all interrupts */ - writel(0x0, g->base + GPIO_INT_EN); - writel(0x0, g->base + GPIO_INT_MASK); - writel(~0x0, g->base + GPIO_INT_CLR); - - ret = gpiochip_irqchip_add(&g->gc, &gemini_gpio_irqchip, - 0, handle_bad_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_info(dev, "could not add irqchip\n"); - return ret; - } - gpiochip_set_chained_irqchip(&g->gc, &gemini_gpio_irqchip, - irq, gemini_gpio_irq_handler); - - dev_info(dev, "Gemini GPIO @%p registered\n", g->base); - - return 0; -} - -static const struct of_device_id gemini_gpio_of_match[] = { - { - .compatible = "cortina,gemini-gpio", - }, - {}, -}; - -static struct platform_driver gemini_gpio_driver = { - .driver = { - .name = "gemini-gpio", - .of_match_table = of_match_ptr(gemini_gpio_of_match), - }, - .probe = gemini_gpio_probe, -}; -builtin_platform_driver(gemini_gpio_driver); -- cgit v1.2.3