1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Faraday Technolog FTGPIO010 gpiochip and interrupt routines 4 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> 5 * 6 * Based on arch/arm/mach-gemini/gpio.c: 7 * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> 8 * 9 * Based on plat-mxc/gpio.c: 10 * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de> 11 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de 12 */ 13 #include <linux/gpio/driver.h> 14 #include <linux/io.h> 15 #include <linux/interrupt.h> 16 #include <linux/platform_device.h> 17 #include <linux/of_gpio.h> 18 #include <linux/bitops.h> 19 20 /* GPIO registers definition */ 21 #define GPIO_DATA_OUT 0x00 22 #define GPIO_DATA_IN 0x04 23 #define GPIO_DIR 0x08 24 #define GPIO_DATA_SET 0x10 25 #define GPIO_DATA_CLR 0x14 26 #define GPIO_PULL_EN 0x18 27 #define GPIO_PULL_TYPE 0x1C 28 #define GPIO_INT_EN 0x20 29 #define GPIO_INT_STAT 0x24 30 #define GPIO_INT_MASK 0x2C 31 #define GPIO_INT_CLR 0x30 32 #define GPIO_INT_TYPE 0x34 33 #define GPIO_INT_BOTH_EDGE 0x38 34 #define GPIO_INT_LEVEL 0x3C 35 #define GPIO_DEBOUNCE_EN 0x40 36 #define GPIO_DEBOUNCE_PRESCALE 0x44 37 38 /** 39 * struct ftgpio_gpio - Gemini GPIO state container 40 * @dev: containing device for this instance 41 * @gc: gpiochip for this instance 42 */ 43 struct ftgpio_gpio { 44 struct device *dev; 45 struct gpio_chip gc; 46 void __iomem *base; 47 }; 48 49 static void ftgpio_gpio_ack_irq(struct irq_data *d) 50 { 51 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 52 struct ftgpio_gpio *g = gpiochip_get_data(gc); 53 54 writel(BIT(irqd_to_hwirq(d)), g->base + GPIO_INT_CLR); 55 } 56 57 static void ftgpio_gpio_mask_irq(struct irq_data *d) 58 { 59 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 60 struct ftgpio_gpio *g = gpiochip_get_data(gc); 61 u32 val; 62 63 val = readl(g->base + GPIO_INT_EN); 64 val &= ~BIT(irqd_to_hwirq(d)); 65 writel(val, g->base + GPIO_INT_EN); 66 } 67 68 static void ftgpio_gpio_unmask_irq(struct irq_data *d) 69 { 70 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 71 struct ftgpio_gpio *g = gpiochip_get_data(gc); 72 u32 val; 73 74 val = readl(g->base + GPIO_INT_EN); 75 val |= BIT(irqd_to_hwirq(d)); 76 writel(val, g->base + GPIO_INT_EN); 77 } 78 79 static int ftgpio_gpio_set_irq_type(struct irq_data *d, unsigned int type) 80 { 81 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 82 struct ftgpio_gpio *g = gpiochip_get_data(gc); 83 u32 mask = BIT(irqd_to_hwirq(d)); 84 u32 reg_both, reg_level, reg_type; 85 86 reg_type = readl(g->base + GPIO_INT_TYPE); 87 reg_level = readl(g->base + GPIO_INT_LEVEL); 88 reg_both = readl(g->base + GPIO_INT_BOTH_EDGE); 89 90 switch (type) { 91 case IRQ_TYPE_EDGE_BOTH: 92 irq_set_handler_locked(d, handle_edge_irq); 93 reg_type &= ~mask; 94 reg_both |= mask; 95 break; 96 case IRQ_TYPE_EDGE_RISING: 97 irq_set_handler_locked(d, handle_edge_irq); 98 reg_type &= ~mask; 99 reg_both &= ~mask; 100 reg_level &= ~mask; 101 break; 102 case IRQ_TYPE_EDGE_FALLING: 103 irq_set_handler_locked(d, handle_edge_irq); 104 reg_type &= ~mask; 105 reg_both &= ~mask; 106 reg_level |= mask; 107 break; 108 case IRQ_TYPE_LEVEL_HIGH: 109 irq_set_handler_locked(d, handle_level_irq); 110 reg_type |= mask; 111 reg_level &= ~mask; 112 break; 113 case IRQ_TYPE_LEVEL_LOW: 114 irq_set_handler_locked(d, handle_level_irq); 115 reg_type |= mask; 116 reg_level |= mask; 117 break; 118 default: 119 irq_set_handler_locked(d, handle_bad_irq); 120 return -EINVAL; 121 } 122 123 writel(reg_type, g->base + GPIO_INT_TYPE); 124 writel(reg_level, g->base + GPIO_INT_LEVEL); 125 writel(reg_both, g->base + GPIO_INT_BOTH_EDGE); 126 127 ftgpio_gpio_ack_irq(d); 128 129 return 0; 130 } 131 132 static struct irq_chip ftgpio_gpio_irqchip = { 133 .name = "FTGPIO010", 134 .irq_ack = ftgpio_gpio_ack_irq, 135 .irq_mask = ftgpio_gpio_mask_irq, 136 .irq_unmask = ftgpio_gpio_unmask_irq, 137 .irq_set_type = ftgpio_gpio_set_irq_type, 138 }; 139 140 static void ftgpio_gpio_irq_handler(struct irq_desc *desc) 141 { 142 struct gpio_chip *gc = irq_desc_get_handler_data(desc); 143 struct ftgpio_gpio *g = gpiochip_get_data(gc); 144 struct irq_chip *irqchip = irq_desc_get_chip(desc); 145 int offset; 146 unsigned long stat; 147 148 chained_irq_enter(irqchip, desc); 149 150 stat = readl(g->base + GPIO_INT_STAT); 151 if (stat) 152 for_each_set_bit(offset, &stat, gc->ngpio) 153 generic_handle_irq(irq_find_mapping(gc->irq.domain, 154 offset)); 155 156 chained_irq_exit(irqchip, desc); 157 } 158 159 static int ftgpio_gpio_probe(struct platform_device *pdev) 160 { 161 struct device *dev = &pdev->dev; 162 struct resource *res; 163 struct ftgpio_gpio *g; 164 int irq; 165 int ret; 166 167 g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL); 168 if (!g) 169 return -ENOMEM; 170 171 g->dev = dev; 172 173 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 174 g->base = devm_ioremap_resource(dev, res); 175 if (IS_ERR(g->base)) 176 return PTR_ERR(g->base); 177 178 irq = platform_get_irq(pdev, 0); 179 if (irq <= 0) 180 return irq ? irq : -EINVAL; 181 182 ret = bgpio_init(&g->gc, dev, 4, 183 g->base + GPIO_DATA_IN, 184 g->base + GPIO_DATA_SET, 185 g->base + GPIO_DATA_CLR, 186 g->base + GPIO_DIR, 187 NULL, 188 0); 189 if (ret) { 190 dev_err(dev, "unable to init generic GPIO\n"); 191 return ret; 192 } 193 g->gc.label = "FTGPIO010"; 194 g->gc.base = -1; 195 g->gc.parent = dev; 196 g->gc.owner = THIS_MODULE; 197 /* ngpio is set by bgpio_init() */ 198 199 ret = devm_gpiochip_add_data(dev, &g->gc, g); 200 if (ret) 201 return ret; 202 203 /* Disable, unmask and clear all interrupts */ 204 writel(0x0, g->base + GPIO_INT_EN); 205 writel(0x0, g->base + GPIO_INT_MASK); 206 writel(~0x0, g->base + GPIO_INT_CLR); 207 208 ret = gpiochip_irqchip_add(&g->gc, &ftgpio_gpio_irqchip, 209 0, handle_bad_irq, 210 IRQ_TYPE_NONE); 211 if (ret) { 212 dev_info(dev, "could not add irqchip\n"); 213 return ret; 214 } 215 gpiochip_set_chained_irqchip(&g->gc, &ftgpio_gpio_irqchip, 216 irq, ftgpio_gpio_irq_handler); 217 218 dev_info(dev, "FTGPIO010 @%p registered\n", g->base); 219 220 return 0; 221 } 222 223 static const struct of_device_id ftgpio_gpio_of_match[] = { 224 { 225 .compatible = "cortina,gemini-gpio", 226 }, 227 { 228 .compatible = "moxa,moxart-gpio", 229 }, 230 { 231 .compatible = "faraday,ftgpio010", 232 }, 233 {}, 234 }; 235 236 static struct platform_driver ftgpio_gpio_driver = { 237 .driver = { 238 .name = "ftgpio010-gpio", 239 .of_match_table = of_match_ptr(ftgpio_gpio_of_match), 240 }, 241 .probe = ftgpio_gpio_probe, 242 }; 243 builtin_platform_driver(ftgpio_gpio_driver); 244