1 /* 2 * Timberdale FPGA GPIO driver 3 * Author: Mocean Laboratories 4 * Copyright (c) 2009 Intel Corporation 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 20 /* Supports: 21 * Timberdale FPGA GPIO 22 */ 23 24 #include <linux/init.h> 25 #include <linux/gpio/driver.h> 26 #include <linux/platform_device.h> 27 #include <linux/irq.h> 28 #include <linux/io.h> 29 #include <linux/timb_gpio.h> 30 #include <linux/interrupt.h> 31 #include <linux/slab.h> 32 33 #define DRIVER_NAME "timb-gpio" 34 35 #define TGPIOVAL 0x00 36 #define TGPIODIR 0x04 37 #define TGPIO_IER 0x08 38 #define TGPIO_ISR 0x0c 39 #define TGPIO_IPR 0x10 40 #define TGPIO_ICR 0x14 41 #define TGPIO_FLR 0x18 42 #define TGPIO_LVR 0x1c 43 #define TGPIO_VER 0x20 44 #define TGPIO_BFLR 0x24 45 46 struct timbgpio { 47 void __iomem *membase; 48 spinlock_t lock; /* mutual exclusion */ 49 struct gpio_chip gpio; 50 int irq_base; 51 unsigned long last_ier; 52 }; 53 54 static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, 55 unsigned offset, bool enabled) 56 { 57 struct timbgpio *tgpio = gpiochip_get_data(gpio); 58 u32 reg; 59 60 spin_lock(&tgpio->lock); 61 reg = ioread32(tgpio->membase + offset); 62 63 if (enabled) 64 reg |= (1 << index); 65 else 66 reg &= ~(1 << index); 67 68 iowrite32(reg, tgpio->membase + offset); 69 spin_unlock(&tgpio->lock); 70 71 return 0; 72 } 73 74 static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) 75 { 76 return timbgpio_update_bit(gpio, nr, TGPIODIR, true); 77 } 78 79 static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr) 80 { 81 struct timbgpio *tgpio = gpiochip_get_data(gpio); 82 u32 value; 83 84 value = ioread32(tgpio->membase + TGPIOVAL); 85 return (value & (1 << nr)) ? 1 : 0; 86 } 87 88 static int timbgpio_gpio_direction_output(struct gpio_chip *gpio, 89 unsigned nr, int val) 90 { 91 return timbgpio_update_bit(gpio, nr, TGPIODIR, false); 92 } 93 94 static void timbgpio_gpio_set(struct gpio_chip *gpio, 95 unsigned nr, int val) 96 { 97 timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0); 98 } 99 100 static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset) 101 { 102 struct timbgpio *tgpio = gpiochip_get_data(gpio); 103 104 if (tgpio->irq_base <= 0) 105 return -EINVAL; 106 107 return tgpio->irq_base + offset; 108 } 109 110 /* 111 * GPIO IRQ 112 */ 113 static void timbgpio_irq_disable(struct irq_data *d) 114 { 115 struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); 116 int offset = d->irq - tgpio->irq_base; 117 unsigned long flags; 118 119 spin_lock_irqsave(&tgpio->lock, flags); 120 tgpio->last_ier &= ~(1UL << offset); 121 iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); 122 spin_unlock_irqrestore(&tgpio->lock, flags); 123 } 124 125 static void timbgpio_irq_enable(struct irq_data *d) 126 { 127 struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); 128 int offset = d->irq - tgpio->irq_base; 129 unsigned long flags; 130 131 spin_lock_irqsave(&tgpio->lock, flags); 132 tgpio->last_ier |= 1UL << offset; 133 iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); 134 spin_unlock_irqrestore(&tgpio->lock, flags); 135 } 136 137 static int timbgpio_irq_type(struct irq_data *d, unsigned trigger) 138 { 139 struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); 140 int offset = d->irq - tgpio->irq_base; 141 unsigned long flags; 142 u32 lvr, flr, bflr = 0; 143 u32 ver; 144 int ret = 0; 145 146 if (offset < 0 || offset > tgpio->gpio.ngpio) 147 return -EINVAL; 148 149 ver = ioread32(tgpio->membase + TGPIO_VER); 150 151 spin_lock_irqsave(&tgpio->lock, flags); 152 153 lvr = ioread32(tgpio->membase + TGPIO_LVR); 154 flr = ioread32(tgpio->membase + TGPIO_FLR); 155 if (ver > 2) 156 bflr = ioread32(tgpio->membase + TGPIO_BFLR); 157 158 if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { 159 bflr &= ~(1 << offset); 160 flr &= ~(1 << offset); 161 if (trigger & IRQ_TYPE_LEVEL_HIGH) 162 lvr |= 1 << offset; 163 else 164 lvr &= ~(1 << offset); 165 } 166 167 if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { 168 if (ver < 3) { 169 ret = -EINVAL; 170 goto out; 171 } else { 172 flr |= 1 << offset; 173 bflr |= 1 << offset; 174 } 175 } else { 176 bflr &= ~(1 << offset); 177 flr |= 1 << offset; 178 if (trigger & IRQ_TYPE_EDGE_FALLING) 179 lvr &= ~(1 << offset); 180 else 181 lvr |= 1 << offset; 182 } 183 184 iowrite32(lvr, tgpio->membase + TGPIO_LVR); 185 iowrite32(flr, tgpio->membase + TGPIO_FLR); 186 if (ver > 2) 187 iowrite32(bflr, tgpio->membase + TGPIO_BFLR); 188 189 iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); 190 191 out: 192 spin_unlock_irqrestore(&tgpio->lock, flags); 193 return ret; 194 } 195 196 static void timbgpio_irq(struct irq_desc *desc) 197 { 198 struct timbgpio *tgpio = irq_desc_get_handler_data(desc); 199 struct irq_data *data = irq_desc_get_irq_data(desc); 200 unsigned long ipr; 201 int offset; 202 203 data->chip->irq_ack(data); 204 ipr = ioread32(tgpio->membase + TGPIO_IPR); 205 iowrite32(ipr, tgpio->membase + TGPIO_ICR); 206 207 /* 208 * Some versions of the hardware trash the IER register if more than 209 * one interrupt is received simultaneously. 210 */ 211 iowrite32(0, tgpio->membase + TGPIO_IER); 212 213 for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) 214 generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); 215 216 iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); 217 } 218 219 static struct irq_chip timbgpio_irqchip = { 220 .name = "GPIO", 221 .irq_enable = timbgpio_irq_enable, 222 .irq_disable = timbgpio_irq_disable, 223 .irq_set_type = timbgpio_irq_type, 224 }; 225 226 static int timbgpio_probe(struct platform_device *pdev) 227 { 228 int err, i; 229 struct device *dev = &pdev->dev; 230 struct gpio_chip *gc; 231 struct timbgpio *tgpio; 232 struct resource *iomem; 233 struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev); 234 int irq = platform_get_irq(pdev, 0); 235 236 if (!pdata || pdata->nr_pins > 32) { 237 dev_err(dev, "Invalid platform data\n"); 238 return -EINVAL; 239 } 240 241 tgpio = devm_kzalloc(dev, sizeof(*tgpio), GFP_KERNEL); 242 if (!tgpio) 243 return -EINVAL; 244 245 tgpio->irq_base = pdata->irq_base; 246 247 spin_lock_init(&tgpio->lock); 248 249 iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 250 tgpio->membase = devm_ioremap_resource(dev, iomem); 251 if (IS_ERR(tgpio->membase)) 252 return PTR_ERR(tgpio->membase); 253 254 gc = &tgpio->gpio; 255 256 gc->label = dev_name(&pdev->dev); 257 gc->owner = THIS_MODULE; 258 gc->parent = &pdev->dev; 259 gc->direction_input = timbgpio_gpio_direction_input; 260 gc->get = timbgpio_gpio_get; 261 gc->direction_output = timbgpio_gpio_direction_output; 262 gc->set = timbgpio_gpio_set; 263 gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL; 264 gc->dbg_show = NULL; 265 gc->base = pdata->gpio_base; 266 gc->ngpio = pdata->nr_pins; 267 gc->can_sleep = false; 268 269 err = devm_gpiochip_add_data(&pdev->dev, gc, tgpio); 270 if (err) 271 return err; 272 273 platform_set_drvdata(pdev, tgpio); 274 275 /* make sure to disable interrupts */ 276 iowrite32(0x0, tgpio->membase + TGPIO_IER); 277 278 if (irq < 0 || tgpio->irq_base <= 0) 279 return 0; 280 281 for (i = 0; i < pdata->nr_pins; i++) { 282 irq_set_chip_and_handler(tgpio->irq_base + i, 283 &timbgpio_irqchip, handle_simple_irq); 284 irq_set_chip_data(tgpio->irq_base + i, tgpio); 285 irq_clear_status_flags(tgpio->irq_base + i, IRQ_NOREQUEST | IRQ_NOPROBE); 286 } 287 288 irq_set_chained_handler_and_data(irq, timbgpio_irq, tgpio); 289 290 return 0; 291 } 292 293 static struct platform_driver timbgpio_platform_driver = { 294 .driver = { 295 .name = DRIVER_NAME, 296 .suppress_bind_attrs = true, 297 }, 298 .probe = timbgpio_probe, 299 }; 300 301 /*--------------------------------------------------------------------------*/ 302 303 builtin_platform_driver(timbgpio_platform_driver); 304