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 v5.1-rc6 552 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Driver for NEC VR4100 series General-purpose I/O Unit. 4 * 5 * Copyright (C) 2002 MontaVista Software Inc. 6 * Author: Yoichi Yuasa <source@mvista.com> 7 * Copyright (C) 2003-2009 Yoichi Yuasa <yuasa@linux-mips.org> 8 */ 9#include <linux/errno.h> 10#include <linux/fs.h> 11#include <linux/gpio/driver.h> 12#include <linux/init.h> 13#include <linux/interrupt.h> 14#include <linux/io.h> 15#include <linux/irq.h> 16#include <linux/kernel.h> 17#include <linux/module.h> 18#include <linux/platform_device.h> 19#include <linux/spinlock.h> 20#include <linux/types.h> 21 22#include <asm/vr41xx/giu.h> 23#include <asm/vr41xx/irq.h> 24#include <asm/vr41xx/vr41xx.h> 25 26MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); 27MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); 28MODULE_LICENSE("GPL"); 29 30#define GIUIOSELL 0x00 31#define GIUIOSELH 0x02 32#define GIUPIODL 0x04 33#define GIUPIODH 0x06 34#define GIUINTSTATL 0x08 35#define GIUINTSTATH 0x0a 36#define GIUINTENL 0x0c 37#define GIUINTENH 0x0e 38#define GIUINTTYPL 0x10 39#define GIUINTTYPH 0x12 40#define GIUINTALSELL 0x14 41#define GIUINTALSELH 0x16 42#define GIUINTHTSELL 0x18 43#define GIUINTHTSELH 0x1a 44#define GIUPODATL 0x1c 45#define GIUPODATEN 0x1c 46#define GIUPODATH 0x1e 47 #define PIOEN0 0x0100 48 #define PIOEN1 0x0200 49#define GIUPODAT 0x1e 50#define GIUFEDGEINHL 0x20 51#define GIUFEDGEINHH 0x22 52#define GIUREDGEINHL 0x24 53#define GIUREDGEINHH 0x26 54 55#define GIUUSEUPDN 0x1e0 56#define GIUTERMUPDN 0x1e2 57 58#define GPIO_HAS_PULLUPDOWN_IO 0x0001 59#define GPIO_HAS_OUTPUT_ENABLE 0x0002 60#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 61 62enum { 63 GPIO_INPUT, 64 GPIO_OUTPUT, 65}; 66 67static DEFINE_SPINLOCK(giu_lock); 68static unsigned long giu_flags; 69 70static void __iomem *giu_base; 71static struct gpio_chip vr41xx_gpio_chip; 72 73#define giu_read(offset) readw(giu_base + (offset)) 74#define giu_write(offset, value) writew((value), giu_base + (offset)) 75 76#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) 77#define GIUINT_HIGH_OFFSET 16 78#define GIUINT_HIGH_MAX 32 79 80static inline u16 giu_set(u16 offset, u16 set) 81{ 82 u16 data; 83 84 data = giu_read(offset); 85 data |= set; 86 giu_write(offset, data); 87 88 return data; 89} 90 91static inline u16 giu_clear(u16 offset, u16 clear) 92{ 93 u16 data; 94 95 data = giu_read(offset); 96 data &= ~clear; 97 giu_write(offset, data); 98 99 return data; 100} 101 102static void ack_giuint_low(struct irq_data *d) 103{ 104 giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq)); 105} 106 107static void mask_giuint_low(struct irq_data *d) 108{ 109 giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq)); 110} 111 112static void mask_ack_giuint_low(struct irq_data *d) 113{ 114 unsigned int pin; 115 116 pin = GPIO_PIN_OF_IRQ(d->irq); 117 giu_clear(GIUINTENL, 1 << pin); 118 giu_write(GIUINTSTATL, 1 << pin); 119} 120 121static void unmask_giuint_low(struct irq_data *d) 122{ 123 giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq)); 124} 125 126static unsigned int startup_giuint(struct irq_data *data) 127{ 128 int ret; 129 130 ret = gpiochip_lock_as_irq(&vr41xx_gpio_chip, irqd_to_hwirq(data)); 131 if (ret) { 132 dev_err(vr41xx_gpio_chip.parent, 133 "unable to lock HW IRQ %lu for IRQ\n", 134 data->hwirq); 135 return ret; 136 } 137 138 /* Satisfy the .enable semantics by unmasking the line */ 139 unmask_giuint_low(data); 140 return 0; 141} 142 143static void shutdown_giuint(struct irq_data *data) 144{ 145 mask_giuint_low(data); 146 gpiochip_unlock_as_irq(&vr41xx_gpio_chip, data->hwirq); 147} 148 149static struct irq_chip giuint_low_irq_chip = { 150 .name = "GIUINTL", 151 .irq_ack = ack_giuint_low, 152 .irq_mask = mask_giuint_low, 153 .irq_mask_ack = mask_ack_giuint_low, 154 .irq_unmask = unmask_giuint_low, 155 .irq_startup = startup_giuint, 156 .irq_shutdown = shutdown_giuint, 157}; 158 159static void ack_giuint_high(struct irq_data *d) 160{ 161 giu_write(GIUINTSTATH, 162 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET)); 163} 164 165static void mask_giuint_high(struct irq_data *d) 166{ 167 giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET)); 168} 169 170static void mask_ack_giuint_high(struct irq_data *d) 171{ 172 unsigned int pin; 173 174 pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET; 175 giu_clear(GIUINTENH, 1 << pin); 176 giu_write(GIUINTSTATH, 1 << pin); 177} 178 179static void unmask_giuint_high(struct irq_data *d) 180{ 181 giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET)); 182} 183 184static struct irq_chip giuint_high_irq_chip = { 185 .name = "GIUINTH", 186 .irq_ack = ack_giuint_high, 187 .irq_mask = mask_giuint_high, 188 .irq_mask_ack = mask_ack_giuint_high, 189 .irq_unmask = unmask_giuint_high, 190}; 191 192static int giu_get_irq(unsigned int irq) 193{ 194 u16 pendl, pendh, maskl, maskh; 195 int i; 196 197 pendl = giu_read(GIUINTSTATL); 198 pendh = giu_read(GIUINTSTATH); 199 maskl = giu_read(GIUINTENL); 200 maskh = giu_read(GIUINTENH); 201 202 maskl &= pendl; 203 maskh &= pendh; 204 205 if (maskl) { 206 for (i = 0; i < 16; i++) { 207 if (maskl & (1 << i)) 208 return GIU_IRQ(i); 209 } 210 } else if (maskh) { 211 for (i = 0; i < 16; i++) { 212 if (maskh & (1 << i)) 213 return GIU_IRQ(i + GIUINT_HIGH_OFFSET); 214 } 215 } 216 217 printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", 218 maskl, pendl, maskh, pendh); 219 220 atomic_inc(&irq_err_count); 221 222 return -EINVAL; 223} 224 225void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, 226 irq_signal_t signal) 227{ 228 u16 mask; 229 230 if (pin < GIUINT_HIGH_OFFSET) { 231 mask = 1 << pin; 232 if (trigger != IRQ_TRIGGER_LEVEL) { 233 giu_set(GIUINTTYPL, mask); 234 if (signal == IRQ_SIGNAL_HOLD) 235 giu_set(GIUINTHTSELL, mask); 236 else 237 giu_clear(GIUINTHTSELL, mask); 238 if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 239 switch (trigger) { 240 case IRQ_TRIGGER_EDGE_FALLING: 241 giu_set(GIUFEDGEINHL, mask); 242 giu_clear(GIUREDGEINHL, mask); 243 break; 244 case IRQ_TRIGGER_EDGE_RISING: 245 giu_clear(GIUFEDGEINHL, mask); 246 giu_set(GIUREDGEINHL, mask); 247 break; 248 default: 249 giu_set(GIUFEDGEINHL, mask); 250 giu_set(GIUREDGEINHL, mask); 251 break; 252 } 253 } 254 irq_set_chip_and_handler(GIU_IRQ(pin), 255 &giuint_low_irq_chip, 256 handle_edge_irq); 257 } else { 258 giu_clear(GIUINTTYPL, mask); 259 giu_clear(GIUINTHTSELL, mask); 260 irq_set_chip_and_handler(GIU_IRQ(pin), 261 &giuint_low_irq_chip, 262 handle_level_irq); 263 } 264 giu_write(GIUINTSTATL, mask); 265 } else if (pin < GIUINT_HIGH_MAX) { 266 mask = 1 << (pin - GIUINT_HIGH_OFFSET); 267 if (trigger != IRQ_TRIGGER_LEVEL) { 268 giu_set(GIUINTTYPH, mask); 269 if (signal == IRQ_SIGNAL_HOLD) 270 giu_set(GIUINTHTSELH, mask); 271 else 272 giu_clear(GIUINTHTSELH, mask); 273 if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 274 switch (trigger) { 275 case IRQ_TRIGGER_EDGE_FALLING: 276 giu_set(GIUFEDGEINHH, mask); 277 giu_clear(GIUREDGEINHH, mask); 278 break; 279 case IRQ_TRIGGER_EDGE_RISING: 280 giu_clear(GIUFEDGEINHH, mask); 281 giu_set(GIUREDGEINHH, mask); 282 break; 283 default: 284 giu_set(GIUFEDGEINHH, mask); 285 giu_set(GIUREDGEINHH, mask); 286 break; 287 } 288 } 289 irq_set_chip_and_handler(GIU_IRQ(pin), 290 &giuint_high_irq_chip, 291 handle_edge_irq); 292 } else { 293 giu_clear(GIUINTTYPH, mask); 294 giu_clear(GIUINTHTSELH, mask); 295 irq_set_chip_and_handler(GIU_IRQ(pin), 296 &giuint_high_irq_chip, 297 handle_level_irq); 298 } 299 giu_write(GIUINTSTATH, mask); 300 } 301} 302EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); 303 304void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) 305{ 306 u16 mask; 307 308 if (pin < GIUINT_HIGH_OFFSET) { 309 mask = 1 << pin; 310 if (level == IRQ_LEVEL_HIGH) 311 giu_set(GIUINTALSELL, mask); 312 else 313 giu_clear(GIUINTALSELL, mask); 314 giu_write(GIUINTSTATL, mask); 315 } else if (pin < GIUINT_HIGH_MAX) { 316 mask = 1 << (pin - GIUINT_HIGH_OFFSET); 317 if (level == IRQ_LEVEL_HIGH) 318 giu_set(GIUINTALSELH, mask); 319 else 320 giu_clear(GIUINTALSELH, mask); 321 giu_write(GIUINTSTATH, mask); 322 } 323} 324EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); 325 326static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir) 327{ 328 u16 offset, mask, reg; 329 unsigned long flags; 330 331 if (pin >= chip->ngpio) 332 return -EINVAL; 333 334 if (pin < 16) { 335 offset = GIUIOSELL; 336 mask = 1 << pin; 337 } else if (pin < 32) { 338 offset = GIUIOSELH; 339 mask = 1 << (pin - 16); 340 } else { 341 if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { 342 offset = GIUPODATEN; 343 mask = 1 << (pin - 32); 344 } else { 345 switch (pin) { 346 case 48: 347 offset = GIUPODATH; 348 mask = PIOEN0; 349 break; 350 case 49: 351 offset = GIUPODATH; 352 mask = PIOEN1; 353 break; 354 default: 355 return -EINVAL; 356 } 357 } 358 } 359 360 spin_lock_irqsave(&giu_lock, flags); 361 362 reg = giu_read(offset); 363 if (dir == GPIO_OUTPUT) 364 reg |= mask; 365 else 366 reg &= ~mask; 367 giu_write(offset, reg); 368 369 spin_unlock_irqrestore(&giu_lock, flags); 370 371 return 0; 372} 373 374static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin) 375{ 376 u16 reg, mask; 377 378 if (pin >= chip->ngpio) 379 return -EINVAL; 380 381 if (pin < 16) { 382 reg = giu_read(GIUPIODL); 383 mask = 1 << pin; 384 } else if (pin < 32) { 385 reg = giu_read(GIUPIODH); 386 mask = 1 << (pin - 16); 387 } else if (pin < 48) { 388 reg = giu_read(GIUPODATL); 389 mask = 1 << (pin - 32); 390 } else { 391 reg = giu_read(GIUPODATH); 392 mask = 1 << (pin - 48); 393 } 394 395 if (reg & mask) 396 return 1; 397 398 return 0; 399} 400 401static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin, 402 int value) 403{ 404 u16 offset, mask, reg; 405 unsigned long flags; 406 407 if (pin >= chip->ngpio) 408 return; 409 410 if (pin < 16) { 411 offset = GIUPIODL; 412 mask = 1 << pin; 413 } else if (pin < 32) { 414 offset = GIUPIODH; 415 mask = 1 << (pin - 16); 416 } else if (pin < 48) { 417 offset = GIUPODATL; 418 mask = 1 << (pin - 32); 419 } else { 420 offset = GIUPODATH; 421 mask = 1 << (pin - 48); 422 } 423 424 spin_lock_irqsave(&giu_lock, flags); 425 426 reg = giu_read(offset); 427 if (value) 428 reg |= mask; 429 else 430 reg &= ~mask; 431 giu_write(offset, reg); 432 433 spin_unlock_irqrestore(&giu_lock, flags); 434} 435 436 437static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 438{ 439 return giu_set_direction(chip, offset, GPIO_INPUT); 440} 441 442static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 443 int value) 444{ 445 vr41xx_gpio_set(chip, offset, value); 446 447 return giu_set_direction(chip, offset, GPIO_OUTPUT); 448} 449 450static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 451{ 452 if (offset >= chip->ngpio) 453 return -EINVAL; 454 455 return GIU_IRQ_BASE + offset; 456} 457 458static struct gpio_chip vr41xx_gpio_chip = { 459 .label = "vr41xx", 460 .owner = THIS_MODULE, 461 .direction_input = vr41xx_gpio_direction_input, 462 .get = vr41xx_gpio_get, 463 .direction_output = vr41xx_gpio_direction_output, 464 .set = vr41xx_gpio_set, 465 .to_irq = vr41xx_gpio_to_irq, 466}; 467 468static int giu_probe(struct platform_device *pdev) 469{ 470 struct resource *res; 471 unsigned int trigger, i, pin; 472 struct irq_chip *chip; 473 int irq, ret; 474 475 switch (pdev->id) { 476 case GPIO_50PINS_PULLUPDOWN: 477 giu_flags = GPIO_HAS_PULLUPDOWN_IO; 478 vr41xx_gpio_chip.ngpio = 50; 479 break; 480 case GPIO_36PINS: 481 vr41xx_gpio_chip.ngpio = 36; 482 break; 483 case GPIO_48PINS_EDGE_SELECT: 484 giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; 485 vr41xx_gpio_chip.ngpio = 48; 486 break; 487 default: 488 dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id); 489 return -ENODEV; 490 } 491 492 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 493 if (!res) 494 return -EBUSY; 495 496 giu_base = ioremap(res->start, resource_size(res)); 497 if (!giu_base) 498 return -ENOMEM; 499 500 vr41xx_gpio_chip.parent = &pdev->dev; 501 502 ret = gpiochip_add_data(&vr41xx_gpio_chip, NULL); 503 if (!ret) { 504 iounmap(giu_base); 505 return -ENODEV; 506 } 507 508 giu_write(GIUINTENL, 0); 509 giu_write(GIUINTENH, 0); 510 511 trigger = giu_read(GIUINTTYPH) << 16; 512 trigger |= giu_read(GIUINTTYPL); 513 for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { 514 pin = GPIO_PIN_OF_IRQ(i); 515 if (pin < GIUINT_HIGH_OFFSET) 516 chip = &giuint_low_irq_chip; 517 else 518 chip = &giuint_high_irq_chip; 519 520 if (trigger & (1 << pin)) 521 irq_set_chip_and_handler(i, chip, handle_edge_irq); 522 else 523 irq_set_chip_and_handler(i, chip, handle_level_irq); 524 525 } 526 527 irq = platform_get_irq(pdev, 0); 528 if (irq < 0 || irq >= nr_irqs) 529 return -EBUSY; 530 531 return cascade_irq(irq, giu_get_irq); 532} 533 534static int giu_remove(struct platform_device *pdev) 535{ 536 if (giu_base) { 537 iounmap(giu_base); 538 giu_base = NULL; 539 } 540 541 return 0; 542} 543 544static struct platform_driver giu_device_driver = { 545 .probe = giu_probe, 546 .remove = giu_remove, 547 .driver = { 548 .name = "GIU", 549 }, 550}; 551 552module_platform_driver(giu_device_driver);