Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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