From 660549e05d6bf7ed7160de51da2948c2f1646f7e Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Tue, 10 Jan 2017 13:51:06 -0500 Subject: gpio: pc104: Mask PC/104 drivers via PC104 Kconfig option PC/104 drivers should be hidden on machines which do not support PC/104 devices. This patch adds the PC104 Kconfig option as a dependency for the relevant PC/104 device driver Kconfig options. Cc: Linus Walleij Cc: Alexandre Courbot Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpio/Kconfig') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 05043071fc98..a3b07702de88 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -557,7 +557,7 @@ menu "Port-mapped I/O GPIO drivers" config GPIO_104_DIO_48E tristate "ACCES 104-DIO-48E GPIO support" - depends on ISA_BUS_API + depends on PC104 && ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E, @@ -567,7 +567,7 @@ config GPIO_104_DIO_48E config GPIO_104_IDIO_16 tristate "ACCES 104-IDIO-16 GPIO support" - depends on ISA_BUS_API + depends on PC104 && ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16, @@ -578,7 +578,7 @@ config GPIO_104_IDIO_16 config GPIO_104_IDI_48 tristate "ACCES 104-IDI-48 GPIO support" - depends on ISA_BUS_API + depends on PC104 && ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A, @@ -598,7 +598,7 @@ config GPIO_F7188X config GPIO_GPIO_MM tristate "Diamond Systems GPIO-MM GPIO support" - depends on ISA_BUS_API + depends on PC104 && ISA_BUS_API help Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12. -- cgit v1.2.3 From 529f75d8ca214aa52ed609d1a909bbe3a71504bf Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Sun, 12 Mar 2017 11:14:28 +0000 Subject: gpio: xlp: Update for ARCH_THUNDER2 ARCH_VULCAN arm64 platform (for Broadcom Vulcan ARM64 processors) has been discontinued. Cavium's ThunderX2 CN99XX (ARCH_THUNDER2) will be the next revision of this platform. Update compile dependencies and ACPI ID to reflect this change. Signed-off-by: Jayachandran C [Drop depreciation of ARCH_VULCAN] Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-xlp.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpio/Kconfig') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a3b07702de88..a386240c5921 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -505,7 +505,7 @@ config GPIO_XILINX config GPIO_XLP tristate "Netlogic XLP GPIO support" - depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || COMPILE_TEST) + depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || ARCH_THUNDER2 || COMPILE_TEST) select GPIOLIB_IRQCHIP help This driver provides support for GPIO interface on Netlogic XLP MIPS64 diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index 7cc82cf82b82..d857e1d8e731 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -441,6 +441,7 @@ out_gpio_remove: #ifdef CONFIG_ACPI static const struct acpi_device_id xlp_gpio_acpi_match[] = { { "BRCM9006", GPIO_VARIANT_VULCAN }, + { "CAV9006", GPIO_VARIANT_VULCAN }, {}, }; MODULE_DEVICE_TABLE(acpi, xlp_gpio_acpi_match); -- cgit v1.2.3 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 (limited to 'drivers/gpio/Kconfig') 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 From d8307c09206b35a9526bfdf076c9f516c0b5e6f1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Mar 2017 00:28:17 +0100 Subject: gpio: moxart: Switch to using the FTGPIO010 driver This just deletes the Moxa ART driver and replaces it with the more versatile Faraday FTGPIO010 driver. Make this default on for ARCH_GEMINI and ARCH_MOXART so we do not get Kconfig glitches. Tested-by: Jonas Jensen Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 10 +----- drivers/gpio/Makefile | 1 - drivers/gpio/gpio-moxart.c | 84 ---------------------------------------------- 3 files changed, 1 insertion(+), 94 deletions(-) delete mode 100644 drivers/gpio/gpio-moxart.c (limited to 'drivers/gpio/Kconfig') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2c3f6390b44b..d6e3cfd54848 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -206,10 +206,10 @@ config GPIO_GE_FPGA config GPIO_FTGPIO010 bool "Faraday FTGPIO010 GPIO" - depends on ARCH_GEMINI depends on OF_GPIO select GPIO_GENERIC select GPIOLIB_IRQCHIP + default (ARCH_GEMINI || ARCH_MOXART) help Support for common GPIOs from the Faraday FTGPIO010 IP core, found in Cortina systems Gemini platforms, Moxa ART and others. @@ -309,14 +309,6 @@ config GPIO_MOCKUP tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in it. -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 4b904fec8273..bd995dc2a84a 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -80,7 +80,6 @@ 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_MOCKUP) += gpio-mockup.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-moxart.c b/drivers/gpio/gpio-moxart.c deleted file mode 100644 index d58d38906ba6..000000000000 --- a/drivers/gpio/gpio-moxart.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * MOXA ART SoCs GPIO driver. - * - * Copyright (C) 2013 Jonas Jensen - * - * Jonas Jensen - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GPIO_DATA_OUT 0x00 -#define GPIO_DATA_IN 0x04 -#define GPIO_PIN_DIRECTION 0x08 - -static int moxart_gpio_probe(struct platform_device *pdev) -{ - 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; - - 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; -} - -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); -- cgit v1.2.3 From 380639c7cc786ec663e43eb3896ccf9172a46900 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 31 Aug 2016 08:49:44 +0100 Subject: gpio: add generic single-register fixed-direction GPIO driver Add a simple, generic, single register fixed-direction GPIO driver. This is able to support a single register with a mixture of inputs and outputs. This is different from gpio-mmio and gpio-74xx-mmio: * gpio-mmio doesn't allow a fixed direction, it assumes there is always a direction register. * gpio-74xx-mmio only supports all-in or all-out setups * gpio-74xx-mmio is DT only, this needs to support legacy too * they don't double-read when getting the GPIO value, as required by some implementations that this driver supports * we need to always do 32-bit reads, which bgpio doesn't guarantee * the current output state may not be readable from the hardware register - reading may reflect input status but not output status. Signed-off-by: Russell King Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-reg.c | 164 ++++++++++++++++++++++++++++++++++++++++++ include/linux/gpio/gpio-reg.h | 12 ++++ 4 files changed, 183 insertions(+) create mode 100644 drivers/gpio/gpio-reg.c create mode 100644 include/linux/gpio/gpio-reg.h (limited to 'drivers/gpio/Kconfig') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d6e3cfd54848..63ceed246b6f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -380,6 +380,12 @@ config GPIO_RCAR help Say yes here to support GPIO on Renesas R-Car SoCs. +config GPIO_REG + bool + help + A 32-bit single register GPIO fixed in/out implementation. This + can be used to represent any register as a set of GPIO signals. + config GPIO_SPEAR_SPICS bool "ST SPEAr13xx SPI Chip Select as GPIO support" depends on PLAT_SPEAR diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index bd995dc2a84a..095598e856ca 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o +obj-$(CONFIG_GPIO_REG) += gpio-reg.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o diff --git a/drivers/gpio/gpio-reg.c b/drivers/gpio/gpio-reg.c new file mode 100644 index 000000000000..209f73695a47 --- /dev/null +++ b/drivers/gpio/gpio-reg.c @@ -0,0 +1,164 @@ +/* + * gpio-reg: single register individually fixed-direction GPIOs + * + * Copyright (C) 2016 Russell King + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + */ +#include +#include +#include +#include +#include + +struct gpio_reg { + struct gpio_chip gc; + spinlock_t lock; + u32 direction; + u32 out; + void __iomem *reg; +}; + +#define to_gpio_reg(x) container_of(x, struct gpio_reg, gc) + +static int gpio_reg_get_direction(struct gpio_chip *gc, unsigned offset) +{ + struct gpio_reg *r = to_gpio_reg(gc); + + return r->direction & BIT(offset) ? 1 : 0; +} + +static int gpio_reg_direction_output(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct gpio_reg *r = to_gpio_reg(gc); + + if (r->direction & BIT(offset)) + return -ENOTSUPP; + + gc->set(gc, offset, value); + return 0; +} + +static int gpio_reg_direction_input(struct gpio_chip *gc, unsigned offset) +{ + struct gpio_reg *r = to_gpio_reg(gc); + + return r->direction & BIT(offset) ? 0 : -ENOTSUPP; +} + +static void gpio_reg_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct gpio_reg *r = to_gpio_reg(gc); + unsigned long flags; + u32 val, mask = BIT(offset); + + spin_lock_irqsave(&r->lock, flags); + val = r->out; + if (value) + val |= mask; + else + val &= ~mask; + r->out = val; + writel_relaxed(val, r->reg); + spin_unlock_irqrestore(&r->lock, flags); +} + +static int gpio_reg_get(struct gpio_chip *gc, unsigned offset) +{ + struct gpio_reg *r = to_gpio_reg(gc); + u32 val, mask = BIT(offset); + + if (r->direction & mask) { + /* + * double-read the value, some registers latch after the + * first read. + */ + readl_relaxed(r->reg); + val = readl_relaxed(r->reg); + } else { + val = r->out; + } + return !!(val & mask); +} + +static void gpio_reg_set_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + struct gpio_reg *r = to_gpio_reg(gc); + unsigned long flags; + + spin_lock_irqsave(&r->lock, flags); + r->out = (r->out & ~*mask) | (*bits & *mask); + writel_relaxed(r->out, r->reg); + spin_unlock_irqrestore(&r->lock, flags); +} + +/** + * gpio_reg_init - add a fixed in/out register as gpio + * @dev: optional struct device associated with this register + * @base: start gpio number, or -1 to allocate + * @num: number of GPIOs, maximum 32 + * @label: GPIO chip label + * @direction: bitmask of fixed direction, one per GPIO signal, 1 = in + * @def_out: initial GPIO output value + * @names: array of %num strings describing each GPIO signal + * + * Add a single-register GPIO device containing up to 32 GPIO signals, + * where each GPIO has a fixed input or output configuration. Only + * input GPIOs are assumed to be readable from the register, and only + * then after a double-read. Output values are assumed not to be + * readable. + */ +struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg, + int base, int num, const char *label, u32 direction, u32 def_out, + const char *const *names) +{ + struct gpio_reg *r; + int ret; + + if (dev) + r = devm_kzalloc(dev, sizeof(*r), GFP_KERNEL); + else + r = kzalloc(sizeof(*r), GFP_KERNEL); + + if (!r) + return ERR_PTR(-ENOMEM); + + spin_lock_init(&r->lock); + + r->gc.label = label; + r->gc.get_direction = gpio_reg_get_direction; + r->gc.direction_input = gpio_reg_direction_input; + r->gc.direction_output = gpio_reg_direction_output; + r->gc.set = gpio_reg_set; + r->gc.get = gpio_reg_get; + r->gc.set_multiple = gpio_reg_set_multiple; + r->gc.base = base; + r->gc.ngpio = num; + r->gc.names = names; + r->direction = direction; + r->out = def_out; + r->reg = reg; + + if (dev) + ret = devm_gpiochip_add_data(dev, &r->gc, r); + else + ret = gpiochip_add_data(&r->gc, r); + + return ret ? ERR_PTR(ret) : &r->gc; +} + +int gpio_reg_resume(struct gpio_chip *gc) +{ + struct gpio_reg *r = to_gpio_reg(gc); + unsigned long flags; + + spin_lock_irqsave(&r->lock, flags); + writel_relaxed(r->out, r->reg); + spin_unlock_irqrestore(&r->lock, flags); + + return 0; +} diff --git a/include/linux/gpio/gpio-reg.h b/include/linux/gpio/gpio-reg.h new file mode 100644 index 000000000000..0352bec7319a --- /dev/null +++ b/include/linux/gpio/gpio-reg.h @@ -0,0 +1,12 @@ +#ifndef GPIO_REG_H +#define GPIO_REG_H + +struct device; + +struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg, + int base, int num, const char *label, u32 direction, u32 def_out, + const char *const *names); + +int gpio_reg_resume(struct gpio_chip *gc); + +#endif -- cgit v1.2.3 From 1b9a0c25065c174134494d1ca91f4da8430e6902 Mon Sep 17 00:00:00 2001 From: Anders Darander Date: Fri, 21 Apr 2017 14:46:30 +0200 Subject: gpio: move tca9554 from pcf857x to pca953x The TCA9554 doesn't work with the pcf857x driver, trying to change the direction gives a NAK bailout error. TCA9554 is similar to the PCA9554, thus change the driver. Signed-off-by: Anders Darander Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-pca953x.c | 1 + drivers/gpio/gpio-pcf857x.c | 2 -- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpio/Kconfig') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 63ceed246b6f..c0629e6639fa 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -752,7 +752,7 @@ config GPIO_PCA953X 4 bits: pca9536, pca9537 8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554, - pca9556, pca9557, pca9574, tca6408, xra1202 + pca9556, pca9557, pca9574, tca6408, tca9554, xra1202 16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575, tca6416 diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index b9373785ccf5..4c9e21300a26 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -82,6 +82,7 @@ static const struct i2c_device_id pca953x_id[] = { { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, { "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, { "tca9539", 16 | PCA953X_TYPE | PCA_INT, }, + { "tca9554", 8 | PCA953X_TYPE | PCA_INT, }, { "xra1202", 8 | PCA953X_TYPE }, { } }; diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 895af42a4513..8ddf9302ce3b 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -46,7 +46,6 @@ static const struct i2c_device_id pcf857x_id[] = { { "pca9675", 16 }, { "max7328", 8 }, { "max7329", 8 }, - { "tca9554", 8 }, { } }; MODULE_DEVICE_TABLE(i2c, pcf857x_id); @@ -66,7 +65,6 @@ static const struct of_device_id pcf857x_of_table[] = { { .compatible = "nxp,pca9675" }, { .compatible = "maxim,max7328" }, { .compatible = "maxim,max7329" }, - { .compatible = "ti,tca9554" }, { } }; MODULE_DEVICE_TABLE(of, pcf857x_of_table); -- cgit v1.2.3 From 9384793036afb7529c1c564e839ef4356271d68e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 25 Apr 2017 20:32:09 +0200 Subject: gpio: Add ROHM BD9571MWV-M PMIC GPIO driver Add driver for the GPIO block in the ROHM BD9571MWV-W MFD PMIC. This block is pretty trivial and supports setting GPIO direction as Input/Output and in case of Output, supports setting value. Signed-off-by: Marek Vasut Cc: linux-gpio@vger.kernel.org Cc: Geert Uytterhoeven Cc: Linus Walleij Reviewed-by: Linus Walleij Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 11 ++++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-bd9571mwv.c | 144 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 drivers/gpio/gpio-bd9571mwv.c (limited to 'drivers/gpio/Kconfig') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c0629e6639fa..5662b0580777 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -844,6 +844,17 @@ config GPIO_ARIZONA help Support for GPIOs on Wolfson Arizona class devices. +config GPIO_BD9571MWV + tristate "ROHM BD9571 GPIO support" + depends on MFD_BD9571MWV + help + Support for GPIOs on ROHM BD9571 PMIC. There are two GPIOs + available on the ROHM PMIC in total, both of which can also + generate interrupts. + + This driver can also be built as a module. If so, the module + will be called gpio-bd9571mwv. + config GPIO_CRYSTAL_COVE tristate "GPIO support for Crystal Cove PMIC" depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 095598e856ca..68b96277d9fa 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o +obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o diff --git a/drivers/gpio/gpio-bd9571mwv.c b/drivers/gpio/gpio-bd9571mwv.c new file mode 100644 index 000000000000..5224a946e8ab --- /dev/null +++ b/drivers/gpio/gpio-bd9571mwv.c @@ -0,0 +1,144 @@ +/* + * ROHM BD9571MWV-M GPIO driver + * + * Copyright (C) 2017 Marek Vasut + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65086 driver + * + * NOTE: Interrupts are not supported yet. + */ + +#include +#include +#include + +#include + +struct bd9571mwv_gpio { + struct gpio_chip chip; + struct bd9571mwv *bd; +}; + +static int bd9571mwv_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + int ret, val; + + ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_DIR, &val); + if (ret < 0) + return ret; + + return val & BIT(offset); +} + +static int bd9571mwv_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + + regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR, + BIT(offset), 0); + + return 0; +} + +static int bd9571mwv_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + + /* Set the initial value */ + regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT, + BIT(offset), value ? BIT(offset) : 0); + regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR, + BIT(offset), BIT(offset)); + + return 0; +} + +static int bd9571mwv_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + int ret, val; + + ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_IN, &val); + if (ret < 0) + return ret; + + return val & BIT(offset); +} + +static void bd9571mwv_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + + regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT, + BIT(offset), value ? BIT(offset) : 0); +} + +static const struct gpio_chip template_chip = { + .label = "bd9571mwv-gpio", + .owner = THIS_MODULE, + .get_direction = bd9571mwv_gpio_get_direction, + .direction_input = bd9571mwv_gpio_direction_input, + .direction_output = bd9571mwv_gpio_direction_output, + .get = bd9571mwv_gpio_get, + .set = bd9571mwv_gpio_set, + .base = -1, + .ngpio = 2, + .can_sleep = true, +}; + +static int bd9571mwv_gpio_probe(struct platform_device *pdev) +{ + struct bd9571mwv_gpio *gpio; + int ret; + + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + platform_set_drvdata(pdev, gpio); + + gpio->bd = dev_get_drvdata(pdev->dev.parent); + gpio->chip = template_chip; + gpio->chip.parent = gpio->bd->dev; + + ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); + return ret; + } + + return 0; +} + +static const struct platform_device_id bd9571mwv_gpio_id_table[] = { + { "bd9571mwv-gpio", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, bd9571mwv_gpio_id_table); + +static struct platform_driver bd9571mwv_gpio_driver = { + .driver = { + .name = "bd9571mwv-gpio", + }, + .probe = bd9571mwv_gpio_probe, + .id_table = bd9571mwv_gpio_id_table, +}; +module_platform_driver(bd9571mwv_gpio_driver); + +MODULE_AUTHOR("Marek Vasut "); +MODULE_DESCRIPTION("BD9571MWV GPIO driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3