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