From: John Crispin Date: Mon, 4 Aug 2014 20:36:29 +0200 Subject: [PATCH 2/2] GPIO: MIPS: ralink: add gpio driver for ralink SoC Add gpio driver for Ralink SoC. This driver makes the gpio core on RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work. Signed-off-by: John Crispin --- drivers/gpio/Kconfig | 8 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-ralink.c | 230 +++++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 drivers/gpio/gpio-ralink.c --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -509,6 +509,14 @@ config GPIO_PXA help Say yes here to support the PXA GPIO device. +config GPIO_RALINK + bool "Ralink GPIO Support" + depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620 + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Say yes here to support the Ralink SoC GPIO device + config GPIO_RCAR tristate "Renesas R-Car and RZ/G GPIO support" depends on ARCH_RENESAS || COMPILE_TEST --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -130,6 +130,7 @@ obj-$(CONFIG_GPIO_PISOSR) += gpio-pisos obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o +obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o --- /dev/null +++ b/drivers/gpio/gpio-ralink.c @@ -0,0 +1,230 @@ +/* + * 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. + * + * Copyright (C) 2009-2011 Gabor Juhos + * Copyright (C) 2013 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include + +enum ralink_gpio_reg { + GPIO_REG_INT = 0, + GPIO_REG_EDGE, + GPIO_REG_RENA, + GPIO_REG_FENA, + GPIO_REG_DATA, + GPIO_REG_DIR, + GPIO_REG_POL, + GPIO_REG_SET, + GPIO_REG_RESET, + GPIO_REG_TOGGLE, + GPIO_REG_MAX +}; + +struct ralink_gpio_chip { + struct gpio_chip chip; + u8 regs[GPIO_REG_MAX]; + + spinlock_t lock; + void __iomem *membase; + int gpio_irq; + + u32 rising; + u32 falling; +}; + +static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val) +{ + iowrite32(val, rg->membase + rg->regs[reg]); +} + +static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg) +{ + return ioread32(rg->membase + rg->regs[reg]); +} + +static irqreturn_t ralink_gpio_irq_handler(int irq, void *data) +{ + struct gpio_chip *gc = data; + struct ralink_gpio_chip *rg = gpiochip_get_data(gc); + irqreturn_t ret = IRQ_NONE; + unsigned long pending; + int bit; + + pending = rt_gpio_r32(rg, GPIO_REG_INT); + for_each_set_bit(bit, &pending, rg->chip.ngpio) { + generic_handle_domain_irq(gc->irq.domain, bit); + rt_gpio_w32(rg, GPIO_REG_INT, BIT(bit)); + ret |= IRQ_HANDLED; + } + + return ret; +} + +static void ralink_gpio_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ralink_gpio_chip *rg = gpiochip_get_data(gc); + unsigned long flags; + u32 rise, fall; + + rise = rt_gpio_r32(rg, GPIO_REG_RENA); + fall = rt_gpio_r32(rg, GPIO_REG_FENA); + + spin_lock_irqsave(&rg->lock, flags); + rt_gpio_w32(rg, GPIO_REG_RENA, rise | (BIT(d->hwirq) & rg->rising)); + rt_gpio_w32(rg, GPIO_REG_FENA, fall | (BIT(d->hwirq) & rg->falling)); + spin_unlock_irqrestore(&rg->lock, flags); +} + +static void ralink_gpio_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ralink_gpio_chip *rg = gpiochip_get_data(gc); + unsigned long flags; + u32 rise, fall; + + rise = rt_gpio_r32(rg, GPIO_REG_RENA); + fall = rt_gpio_r32(rg, GPIO_REG_FENA); + + spin_lock_irqsave(&rg->lock, flags); + rt_gpio_w32(rg, GPIO_REG_FENA, fall & ~BIT(d->hwirq)); + rt_gpio_w32(rg, GPIO_REG_RENA, rise & ~BIT(d->hwirq)); + spin_unlock_irqrestore(&rg->lock, flags); +} + +static int ralink_gpio_irq_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ralink_gpio_chip *rg = gpiochip_get_data(gc); + u32 mask = BIT(d->hwirq); + + if (type == IRQ_TYPE_PROBE) { + if ((rg->rising | rg->falling) & mask) + return 0; + + type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; + } + + if (type & IRQ_TYPE_EDGE_RISING) + rg->rising |= mask; + else + rg->rising &= ~mask; + + if (type & IRQ_TYPE_EDGE_FALLING) + rg->falling |= mask; + else + rg->falling &= ~mask; + + return 0; +} + +static struct irq_chip ralink_gpio_irq_chip = { + .name = "gpio-ralink", + .irq_unmask = ralink_gpio_irq_unmask, + .irq_mask = ralink_gpio_irq_mask, + .irq_mask_ack = ralink_gpio_irq_mask, + .irq_set_type = ralink_gpio_irq_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static int ralink_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct ralink_gpio_chip *rg; + int ret; + + rg = devm_kzalloc(dev, sizeof(struct ralink_gpio_chip), GFP_KERNEL); + if (!rg) + return -ENOMEM; + + rg->membase = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(rg->membase)) + return PTR_ERR(rg->membase); + + if (of_property_read_u8_array(np, "ralink,register-map", + rg->regs, GPIO_REG_MAX)) { + dev_err(dev, "failed to read register definition\n"); + return -EINVAL; + } + + spin_lock_init(&rg->lock); + + ret = bgpio_init(&rg->chip, dev, 4, + rg->membase + rg->regs[GPIO_REG_DATA], + rg->membase + rg->regs[GPIO_REG_SET], + rg->membase + rg->regs[GPIO_REG_RESET], + rg->membase + rg->regs[GPIO_REG_DIR], + NULL, 0); + if (ret) + return dev_err_probe(dev, ret, "bgpio_init() failed\n"); + + /* set polarity to low for all lines */ + rt_gpio_w32(rg, GPIO_REG_POL, 0); + + rg->gpio_irq = platform_get_irq(pdev, 0); + if (rg->gpio_irq < 0) + return rg->gpio_irq; + + if (rg->gpio_irq) { + struct gpio_irq_chip *girq; + + /* + * Directly request the irq here instead of passing + * a flow-handler because the irq is shared. + */ + ret = devm_request_irq(dev, rg->gpio_irq, + ralink_gpio_irq_handler, IRQF_SHARED, + NULL, &rg->chip); + if (ret) { + dev_err(dev, "Error requesting IRQ %d: %d\n", + rg->gpio_irq, ret); + return ret; + } + + girq = &rg->chip.irq; + gpio_irq_chip_set_chip(girq, &ralink_gpio_irq_chip); + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + + rt_gpio_w32(rg, GPIO_REG_RENA, 0); + rt_gpio_w32(rg, GPIO_REG_FENA, 0); + } + + return devm_gpiochip_add_data(dev, &rg->chip, rg); +} + +static const struct of_device_id ralink_gpio_match[] = { + { .compatible = "ralink,rt2880-gpio" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ralink_gpio_match); + +static struct platform_driver ralink_gpio_driver = { + .probe = ralink_gpio_probe, + .driver = { + .name = "ralink_gpio", + .of_match_table = ralink_gpio_match, + }, +}; + +static int __init ralink_gpio_init(void) +{ + return platform_driver_register(&ralink_gpio_driver); +} + +subsys_initcall(ralink_gpio_init);