gpio-vr41xx.c (11831B)
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 return -EINVAL; 221} 222 223void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, 224 irq_signal_t signal) 225{ 226 u16 mask; 227 228 if (pin < GIUINT_HIGH_OFFSET) { 229 mask = 1 << pin; 230 if (trigger != IRQ_TRIGGER_LEVEL) { 231 giu_set(GIUINTTYPL, mask); 232 if (signal == IRQ_SIGNAL_HOLD) 233 giu_set(GIUINTHTSELL, mask); 234 else 235 giu_clear(GIUINTHTSELL, mask); 236 if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 237 switch (trigger) { 238 case IRQ_TRIGGER_EDGE_FALLING: 239 giu_set(GIUFEDGEINHL, mask); 240 giu_clear(GIUREDGEINHL, mask); 241 break; 242 case IRQ_TRIGGER_EDGE_RISING: 243 giu_clear(GIUFEDGEINHL, mask); 244 giu_set(GIUREDGEINHL, mask); 245 break; 246 default: 247 giu_set(GIUFEDGEINHL, mask); 248 giu_set(GIUREDGEINHL, mask); 249 break; 250 } 251 } 252 irq_set_chip_and_handler(GIU_IRQ(pin), 253 &giuint_low_irq_chip, 254 handle_edge_irq); 255 } else { 256 giu_clear(GIUINTTYPL, mask); 257 giu_clear(GIUINTHTSELL, mask); 258 irq_set_chip_and_handler(GIU_IRQ(pin), 259 &giuint_low_irq_chip, 260 handle_level_irq); 261 } 262 giu_write(GIUINTSTATL, mask); 263 } else if (pin < GIUINT_HIGH_MAX) { 264 mask = 1 << (pin - GIUINT_HIGH_OFFSET); 265 if (trigger != IRQ_TRIGGER_LEVEL) { 266 giu_set(GIUINTTYPH, mask); 267 if (signal == IRQ_SIGNAL_HOLD) 268 giu_set(GIUINTHTSELH, mask); 269 else 270 giu_clear(GIUINTHTSELH, mask); 271 if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 272 switch (trigger) { 273 case IRQ_TRIGGER_EDGE_FALLING: 274 giu_set(GIUFEDGEINHH, mask); 275 giu_clear(GIUREDGEINHH, mask); 276 break; 277 case IRQ_TRIGGER_EDGE_RISING: 278 giu_clear(GIUFEDGEINHH, mask); 279 giu_set(GIUREDGEINHH, mask); 280 break; 281 default: 282 giu_set(GIUFEDGEINHH, mask); 283 giu_set(GIUREDGEINHH, mask); 284 break; 285 } 286 } 287 irq_set_chip_and_handler(GIU_IRQ(pin), 288 &giuint_high_irq_chip, 289 handle_edge_irq); 290 } else { 291 giu_clear(GIUINTTYPH, mask); 292 giu_clear(GIUINTHTSELH, mask); 293 irq_set_chip_and_handler(GIU_IRQ(pin), 294 &giuint_high_irq_chip, 295 handle_level_irq); 296 } 297 giu_write(GIUINTSTATH, mask); 298 } 299} 300EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); 301 302void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) 303{ 304 u16 mask; 305 306 if (pin < GIUINT_HIGH_OFFSET) { 307 mask = 1 << pin; 308 if (level == IRQ_LEVEL_HIGH) 309 giu_set(GIUINTALSELL, mask); 310 else 311 giu_clear(GIUINTALSELL, mask); 312 giu_write(GIUINTSTATL, mask); 313 } else if (pin < GIUINT_HIGH_MAX) { 314 mask = 1 << (pin - GIUINT_HIGH_OFFSET); 315 if (level == IRQ_LEVEL_HIGH) 316 giu_set(GIUINTALSELH, mask); 317 else 318 giu_clear(GIUINTALSELH, mask); 319 giu_write(GIUINTSTATH, mask); 320 } 321} 322EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); 323 324static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir) 325{ 326 u16 offset, mask, reg; 327 unsigned long flags; 328 329 if (pin >= chip->ngpio) 330 return -EINVAL; 331 332 if (pin < 16) { 333 offset = GIUIOSELL; 334 mask = 1 << pin; 335 } else if (pin < 32) { 336 offset = GIUIOSELH; 337 mask = 1 << (pin - 16); 338 } else { 339 if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { 340 offset = GIUPODATEN; 341 mask = 1 << (pin - 32); 342 } else { 343 switch (pin) { 344 case 48: 345 offset = GIUPODATH; 346 mask = PIOEN0; 347 break; 348 case 49: 349 offset = GIUPODATH; 350 mask = PIOEN1; 351 break; 352 default: 353 return -EINVAL; 354 } 355 } 356 } 357 358 spin_lock_irqsave(&giu_lock, flags); 359 360 reg = giu_read(offset); 361 if (dir == GPIO_OUTPUT) 362 reg |= mask; 363 else 364 reg &= ~mask; 365 giu_write(offset, reg); 366 367 spin_unlock_irqrestore(&giu_lock, flags); 368 369 return 0; 370} 371 372static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin) 373{ 374 u16 reg, mask; 375 376 if (pin >= chip->ngpio) 377 return -EINVAL; 378 379 if (pin < 16) { 380 reg = giu_read(GIUPIODL); 381 mask = 1 << pin; 382 } else if (pin < 32) { 383 reg = giu_read(GIUPIODH); 384 mask = 1 << (pin - 16); 385 } else if (pin < 48) { 386 reg = giu_read(GIUPODATL); 387 mask = 1 << (pin - 32); 388 } else { 389 reg = giu_read(GIUPODATH); 390 mask = 1 << (pin - 48); 391 } 392 393 if (reg & mask) 394 return 1; 395 396 return 0; 397} 398 399static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin, 400 int value) 401{ 402 u16 offset, mask, reg; 403 unsigned long flags; 404 405 if (pin >= chip->ngpio) 406 return; 407 408 if (pin < 16) { 409 offset = GIUPIODL; 410 mask = 1 << pin; 411 } else if (pin < 32) { 412 offset = GIUPIODH; 413 mask = 1 << (pin - 16); 414 } else if (pin < 48) { 415 offset = GIUPODATL; 416 mask = 1 << (pin - 32); 417 } else { 418 offset = GIUPODATH; 419 mask = 1 << (pin - 48); 420 } 421 422 spin_lock_irqsave(&giu_lock, flags); 423 424 reg = giu_read(offset); 425 if (value) 426 reg |= mask; 427 else 428 reg &= ~mask; 429 giu_write(offset, reg); 430 431 spin_unlock_irqrestore(&giu_lock, flags); 432} 433 434 435static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 436{ 437 return giu_set_direction(chip, offset, GPIO_INPUT); 438} 439 440static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 441 int value) 442{ 443 vr41xx_gpio_set(chip, offset, value); 444 445 return giu_set_direction(chip, offset, GPIO_OUTPUT); 446} 447 448static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 449{ 450 if (offset >= chip->ngpio) 451 return -EINVAL; 452 453 return GIU_IRQ_BASE + offset; 454} 455 456static struct gpio_chip vr41xx_gpio_chip = { 457 .label = "vr41xx", 458 .owner = THIS_MODULE, 459 .direction_input = vr41xx_gpio_direction_input, 460 .get = vr41xx_gpio_get, 461 .direction_output = vr41xx_gpio_direction_output, 462 .set = vr41xx_gpio_set, 463 .to_irq = vr41xx_gpio_to_irq, 464}; 465 466static int giu_probe(struct platform_device *pdev) 467{ 468 unsigned int trigger, i, pin; 469 struct irq_chip *chip; 470 int irq; 471 472 switch (pdev->id) { 473 case GPIO_50PINS_PULLUPDOWN: 474 giu_flags = GPIO_HAS_PULLUPDOWN_IO; 475 vr41xx_gpio_chip.ngpio = 50; 476 break; 477 case GPIO_36PINS: 478 vr41xx_gpio_chip.ngpio = 36; 479 break; 480 case GPIO_48PINS_EDGE_SELECT: 481 giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; 482 vr41xx_gpio_chip.ngpio = 48; 483 break; 484 default: 485 dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id); 486 return -ENODEV; 487 } 488 489 giu_base = devm_platform_ioremap_resource(pdev, 0); 490 if (IS_ERR(giu_base)) 491 return PTR_ERR(giu_base); 492 493 vr41xx_gpio_chip.parent = &pdev->dev; 494 495 if (gpiochip_add_data(&vr41xx_gpio_chip, NULL)) 496 return -ENODEV; 497 498 giu_write(GIUINTENL, 0); 499 giu_write(GIUINTENH, 0); 500 501 trigger = giu_read(GIUINTTYPH) << 16; 502 trigger |= giu_read(GIUINTTYPL); 503 for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { 504 pin = GPIO_PIN_OF_IRQ(i); 505 if (pin < GIUINT_HIGH_OFFSET) 506 chip = &giuint_low_irq_chip; 507 else 508 chip = &giuint_high_irq_chip; 509 510 if (trigger & (1 << pin)) 511 irq_set_chip_and_handler(i, chip, handle_edge_irq); 512 else 513 irq_set_chip_and_handler(i, chip, handle_level_irq); 514 515 } 516 517 irq = platform_get_irq(pdev, 0); 518 if (irq < 0 || irq >= nr_irqs) 519 return -EBUSY; 520 521 return cascade_irq(irq, giu_get_irq); 522} 523 524static int giu_remove(struct platform_device *pdev) 525{ 526 if (giu_base) { 527 giu_base = NULL; 528 } 529 530 return 0; 531} 532 533static struct platform_driver giu_device_driver = { 534 .probe = giu_probe, 535 .remove = giu_remove, 536 .driver = { 537 .name = "GIU", 538 }, 539}; 540 541module_platform_driver(giu_device_driver);