1 /* 2 * Copyright (C) 2013 Altera Corporation 3 * Based on gpio-mpc8xxx.c 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 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, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <linux/io.h> 20 #include <linux/module.h> 21 #include <linux/of_gpio.h> 22 #include <linux/platform_device.h> 23 24 #define ALTERA_GPIO_MAX_NGPIO 32 25 #define ALTERA_GPIO_DATA 0x0 26 #define ALTERA_GPIO_DIR 0x4 27 #define ALTERA_GPIO_IRQ_MASK 0x8 28 #define ALTERA_GPIO_EDGE_CAP 0xc 29 30 /** 31 * struct altera_gpio_chip 32 * @mmchip : memory mapped chip structure. 33 * @gpio_lock : synchronization lock so that new irq/set/get requests 34 will be blocked until the current one completes. 35 * @interrupt_trigger : specifies the hardware configured IRQ trigger type 36 (rising, falling, both, high) 37 * @mapped_irq : kernel mapped irq number. 38 */ 39 struct altera_gpio_chip { 40 struct of_mm_gpio_chip mmchip; 41 raw_spinlock_t gpio_lock; 42 int interrupt_trigger; 43 int mapped_irq; 44 }; 45 46 static void altera_gpio_irq_unmask(struct irq_data *d) 47 { 48 struct altera_gpio_chip *altera_gc; 49 struct of_mm_gpio_chip *mm_gc; 50 unsigned long flags; 51 u32 intmask; 52 53 altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d)); 54 mm_gc = &altera_gc->mmchip; 55 56 raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags); 57 intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK); 58 /* Set ALTERA_GPIO_IRQ_MASK bit to unmask */ 59 intmask |= BIT(irqd_to_hwirq(d)); 60 writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK); 61 raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags); 62 } 63 64 static void altera_gpio_irq_mask(struct irq_data *d) 65 { 66 struct altera_gpio_chip *altera_gc; 67 struct of_mm_gpio_chip *mm_gc; 68 unsigned long flags; 69 u32 intmask; 70 71 altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d)); 72 mm_gc = &altera_gc->mmchip; 73 74 raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags); 75 intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK); 76 /* Clear ALTERA_GPIO_IRQ_MASK bit to mask */ 77 intmask &= ~BIT(irqd_to_hwirq(d)); 78 writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK); 79 raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags); 80 } 81 82 /** 83 * This controller's IRQ type is synthesized in hardware, so this function 84 * just checks if the requested set_type matches the synthesized IRQ type 85 */ 86 static int altera_gpio_irq_set_type(struct irq_data *d, 87 unsigned int type) 88 { 89 struct altera_gpio_chip *altera_gc; 90 91 altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d)); 92 93 if (type == IRQ_TYPE_NONE) { 94 irq_set_handler_locked(d, handle_bad_irq); 95 return 0; 96 } 97 if (type == altera_gc->interrupt_trigger) { 98 if (type == IRQ_TYPE_LEVEL_HIGH) 99 irq_set_handler_locked(d, handle_level_irq); 100 else 101 irq_set_handler_locked(d, handle_simple_irq); 102 return 0; 103 } 104 irq_set_handler_locked(d, handle_bad_irq); 105 return -EINVAL; 106 } 107 108 static unsigned int altera_gpio_irq_startup(struct irq_data *d) 109 { 110 altera_gpio_irq_unmask(d); 111 112 return 0; 113 } 114 115 static struct irq_chip altera_irq_chip = { 116 .name = "altera-gpio", 117 .irq_mask = altera_gpio_irq_mask, 118 .irq_unmask = altera_gpio_irq_unmask, 119 .irq_set_type = altera_gpio_irq_set_type, 120 .irq_startup = altera_gpio_irq_startup, 121 .irq_shutdown = altera_gpio_irq_mask, 122 }; 123 124 static int altera_gpio_get(struct gpio_chip *gc, unsigned offset) 125 { 126 struct of_mm_gpio_chip *mm_gc; 127 128 mm_gc = to_of_mm_gpio_chip(gc); 129 130 return !!(readl(mm_gc->regs + ALTERA_GPIO_DATA) & BIT(offset)); 131 } 132 133 static void altera_gpio_set(struct gpio_chip *gc, unsigned offset, int value) 134 { 135 struct of_mm_gpio_chip *mm_gc; 136 struct altera_gpio_chip *chip; 137 unsigned long flags; 138 unsigned int data_reg; 139 140 mm_gc = to_of_mm_gpio_chip(gc); 141 chip = gpiochip_get_data(gc); 142 143 raw_spin_lock_irqsave(&chip->gpio_lock, flags); 144 data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA); 145 if (value) 146 data_reg |= BIT(offset); 147 else 148 data_reg &= ~BIT(offset); 149 writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA); 150 raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); 151 } 152 153 static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset) 154 { 155 struct of_mm_gpio_chip *mm_gc; 156 struct altera_gpio_chip *chip; 157 unsigned long flags; 158 unsigned int gpio_ddr; 159 160 mm_gc = to_of_mm_gpio_chip(gc); 161 chip = gpiochip_get_data(gc); 162 163 raw_spin_lock_irqsave(&chip->gpio_lock, flags); 164 /* Set pin as input, assumes software controlled IP */ 165 gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR); 166 gpio_ddr &= ~BIT(offset); 167 writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR); 168 raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); 169 170 return 0; 171 } 172 173 static int altera_gpio_direction_output(struct gpio_chip *gc, 174 unsigned offset, int value) 175 { 176 struct of_mm_gpio_chip *mm_gc; 177 struct altera_gpio_chip *chip; 178 unsigned long flags; 179 unsigned int data_reg, gpio_ddr; 180 181 mm_gc = to_of_mm_gpio_chip(gc); 182 chip = gpiochip_get_data(gc); 183 184 raw_spin_lock_irqsave(&chip->gpio_lock, flags); 185 /* Sets the GPIO value */ 186 data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA); 187 if (value) 188 data_reg |= BIT(offset); 189 else 190 data_reg &= ~BIT(offset); 191 writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA); 192 193 /* Set pin as output, assumes software controlled IP */ 194 gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR); 195 gpio_ddr |= BIT(offset); 196 writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR); 197 raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); 198 199 return 0; 200 } 201 202 static void altera_gpio_irq_edge_handler(struct irq_desc *desc) 203 { 204 struct altera_gpio_chip *altera_gc; 205 struct irq_chip *chip; 206 struct of_mm_gpio_chip *mm_gc; 207 struct irq_domain *irqdomain; 208 unsigned long status; 209 int i; 210 211 altera_gc = gpiochip_get_data(irq_desc_get_handler_data(desc)); 212 chip = irq_desc_get_chip(desc); 213 mm_gc = &altera_gc->mmchip; 214 irqdomain = altera_gc->mmchip.gc.irqdomain; 215 216 chained_irq_enter(chip, desc); 217 218 while ((status = 219 (readl(mm_gc->regs + ALTERA_GPIO_EDGE_CAP) & 220 readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK)))) { 221 writel(status, mm_gc->regs + ALTERA_GPIO_EDGE_CAP); 222 for_each_set_bit(i, &status, mm_gc->gc.ngpio) { 223 generic_handle_irq(irq_find_mapping(irqdomain, i)); 224 } 225 } 226 227 chained_irq_exit(chip, desc); 228 } 229 230 static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc) 231 { 232 struct altera_gpio_chip *altera_gc; 233 struct irq_chip *chip; 234 struct of_mm_gpio_chip *mm_gc; 235 struct irq_domain *irqdomain; 236 unsigned long status; 237 int i; 238 239 altera_gc = gpiochip_get_data(irq_desc_get_handler_data(desc)); 240 chip = irq_desc_get_chip(desc); 241 mm_gc = &altera_gc->mmchip; 242 irqdomain = altera_gc->mmchip.gc.irqdomain; 243 244 chained_irq_enter(chip, desc); 245 246 status = readl(mm_gc->regs + ALTERA_GPIO_DATA); 247 status &= readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK); 248 249 for_each_set_bit(i, &status, mm_gc->gc.ngpio) { 250 generic_handle_irq(irq_find_mapping(irqdomain, i)); 251 } 252 chained_irq_exit(chip, desc); 253 } 254 255 static int altera_gpio_probe(struct platform_device *pdev) 256 { 257 struct device_node *node = pdev->dev.of_node; 258 int reg, ret; 259 struct altera_gpio_chip *altera_gc; 260 261 altera_gc = devm_kzalloc(&pdev->dev, sizeof(*altera_gc), GFP_KERNEL); 262 if (!altera_gc) 263 return -ENOMEM; 264 265 raw_spin_lock_init(&altera_gc->gpio_lock); 266 267 if (of_property_read_u32(node, "altr,ngpio", ®)) 268 /* By default assume maximum ngpio */ 269 altera_gc->mmchip.gc.ngpio = ALTERA_GPIO_MAX_NGPIO; 270 else 271 altera_gc->mmchip.gc.ngpio = reg; 272 273 if (altera_gc->mmchip.gc.ngpio > ALTERA_GPIO_MAX_NGPIO) { 274 dev_warn(&pdev->dev, 275 "ngpio is greater than %d, defaulting to %d\n", 276 ALTERA_GPIO_MAX_NGPIO, ALTERA_GPIO_MAX_NGPIO); 277 altera_gc->mmchip.gc.ngpio = ALTERA_GPIO_MAX_NGPIO; 278 } 279 280 altera_gc->mmchip.gc.direction_input = altera_gpio_direction_input; 281 altera_gc->mmchip.gc.direction_output = altera_gpio_direction_output; 282 altera_gc->mmchip.gc.get = altera_gpio_get; 283 altera_gc->mmchip.gc.set = altera_gpio_set; 284 altera_gc->mmchip.gc.owner = THIS_MODULE; 285 altera_gc->mmchip.gc.parent = &pdev->dev; 286 287 ret = of_mm_gpiochip_add_data(node, &altera_gc->mmchip, altera_gc); 288 if (ret) { 289 dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n"); 290 return ret; 291 } 292 293 platform_set_drvdata(pdev, altera_gc); 294 295 altera_gc->mapped_irq = platform_get_irq(pdev, 0); 296 297 if (altera_gc->mapped_irq < 0) 298 goto skip_irq; 299 300 if (of_property_read_u32(node, "altr,interrupt-type", ®)) { 301 ret = -EINVAL; 302 dev_err(&pdev->dev, 303 "altr,interrupt-type value not set in device tree\n"); 304 goto teardown; 305 } 306 altera_gc->interrupt_trigger = reg; 307 308 ret = gpiochip_irqchip_add(&altera_gc->mmchip.gc, &altera_irq_chip, 0, 309 handle_bad_irq, IRQ_TYPE_NONE); 310 311 if (ret) { 312 dev_err(&pdev->dev, "could not add irqchip\n"); 313 goto teardown; 314 } 315 316 gpiochip_set_chained_irqchip(&altera_gc->mmchip.gc, 317 &altera_irq_chip, 318 altera_gc->mapped_irq, 319 altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH ? 320 altera_gpio_irq_leveL_high_handler : 321 altera_gpio_irq_edge_handler); 322 323 skip_irq: 324 return 0; 325 teardown: 326 of_mm_gpiochip_remove(&altera_gc->mmchip); 327 pr_err("%s: registration failed with status %d\n", 328 node->full_name, ret); 329 330 return ret; 331 } 332 333 static int altera_gpio_remove(struct platform_device *pdev) 334 { 335 struct altera_gpio_chip *altera_gc = platform_get_drvdata(pdev); 336 337 of_mm_gpiochip_remove(&altera_gc->mmchip); 338 339 return 0; 340 } 341 342 static const struct of_device_id altera_gpio_of_match[] = { 343 { .compatible = "altr,pio-1.0", }, 344 {}, 345 }; 346 MODULE_DEVICE_TABLE(of, altera_gpio_of_match); 347 348 static struct platform_driver altera_gpio_driver = { 349 .driver = { 350 .name = "altera_gpio", 351 .of_match_table = of_match_ptr(altera_gpio_of_match), 352 }, 353 .probe = altera_gpio_probe, 354 .remove = altera_gpio_remove, 355 }; 356 357 static int __init altera_gpio_init(void) 358 { 359 return platform_driver_register(&altera_gpio_driver); 360 } 361 subsys_initcall(altera_gpio_init); 362 363 static void __exit altera_gpio_exit(void) 364 { 365 platform_driver_unregister(&altera_gpio_driver); 366 } 367 module_exit(altera_gpio_exit); 368 369 MODULE_AUTHOR("Tien Hock Loh <thloh@altera.com>"); 370 MODULE_DESCRIPTION("Altera GPIO driver"); 371 MODULE_LICENSE("GPL"); 372