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

MIPS: Update VR41xx GPIO driver to use gpiolib

Signed-off-by: Yoichi Yuasa <yyuasa@linux.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Yoichi Yuasa and committed by
Ralf Baechle
27fdd325 69f16c9a

+597 -704
+1
arch/mips/Kconfig
··· 267 267 select CEVT_R4K 268 268 select CSRC_R4K 269 269 select SYS_HAS_CPU_VR41XX 270 + select ARCH_REQUIRE_GPIOLIB 270 271 271 272 config NXP_STB220 272 273 bool "NXP STB220 board"
+3 -19
arch/mips/include/asm/vr41xx/giu.h
··· 1 1 /* 2 2 * Include file for NEC VR4100 series General-purpose I/O Unit. 3 3 * 4 - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 4 + * Copyright (C) 2005-2009 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 5 5 * 6 6 * This program is free software; you can redistribute it and/or modify 7 7 * it under the terms of the GNU General Public License as published by ··· 41 41 IRQ_SIGNAL_HOLD, 42 42 } irq_signal_t; 43 43 44 - extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal); 44 + extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, 45 + irq_signal_t signal); 45 46 46 47 typedef enum { 47 48 IRQ_LEVEL_LOW, ··· 50 49 } irq_level_t; 51 50 52 51 extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level); 53 - 54 - typedef enum { 55 - GPIO_DATA_LOW, 56 - GPIO_DATA_HIGH, 57 - GPIO_DATA_INVAL, 58 - } gpio_data_t; 59 - 60 - extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin); 61 - extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data); 62 - 63 - typedef enum { 64 - GPIO_INPUT, 65 - GPIO_OUTPUT, 66 - GPIO_OUTPUT_DISABLE, 67 - } gpio_direction_t; 68 - 69 - extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir); 70 52 71 53 typedef enum { 72 54 GPIO_PULL_DOWN,
-4
drivers/char/Kconfig
··· 1029 1029 1030 1030 If compiled as a module, it will be called cs5535_gpio. 1031 1031 1032 - config GPIO_VR41XX 1033 - tristate "NEC VR4100 series General-purpose I/O Unit support" 1034 - depends on CPU_VR41XX 1035 - 1036 1032 config RAW_DRIVER 1037 1033 tristate "RAW driver (/dev/raw/rawN)" 1038 1034 depends on BLOCK
-1
drivers/char/Makefile
··· 95 95 obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o 96 96 obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o 97 97 obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o 98 - obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o 99 98 obj-$(CONFIG_GPIO_TB0219) += tb0219.o 100 99 obj-$(CONFIG_TELCLOCK) += tlclk.o 101 100
-680
drivers/char/vr41xx_giu.c
··· 1 - /* 2 - * Driver for NEC VR4100 series General-purpose I/O Unit. 3 - * 4 - * Copyright (C) 2002 MontaVista Software Inc. 5 - * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> 6 - * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 7 - * 8 - * This program is free software; you can redistribute it and/or modify 9 - * it under the terms of the GNU General Public License as published by 10 - * the Free Software Foundation; either version 2 of the License, or 11 - * (at your option) any later version. 12 - * 13 - * This program is distributed in the hope that it will be useful, 14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 - * GNU General Public License for more details. 17 - * 18 - * You should have received a copy of the GNU General Public License 19 - * along with this program; if not, write to the Free Software 20 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 - */ 22 - #include <linux/errno.h> 23 - #include <linux/fs.h> 24 - #include <linux/init.h> 25 - #include <linux/interrupt.h> 26 - #include <linux/irq.h> 27 - #include <linux/kernel.h> 28 - #include <linux/module.h> 29 - #include <linux/platform_device.h> 30 - #include <linux/smp_lock.h> 31 - #include <linux/spinlock.h> 32 - #include <linux/types.h> 33 - 34 - #include <asm/io.h> 35 - #include <asm/vr41xx/giu.h> 36 - #include <asm/vr41xx/irq.h> 37 - #include <asm/vr41xx/vr41xx.h> 38 - 39 - MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); 40 - MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); 41 - MODULE_LICENSE("GPL"); 42 - 43 - static int major; /* default is dynamic major device number */ 44 - module_param(major, int, 0); 45 - MODULE_PARM_DESC(major, "Major device number"); 46 - 47 - #define GIUIOSELL 0x00 48 - #define GIUIOSELH 0x02 49 - #define GIUPIODL 0x04 50 - #define GIUPIODH 0x06 51 - #define GIUINTSTATL 0x08 52 - #define GIUINTSTATH 0x0a 53 - #define GIUINTENL 0x0c 54 - #define GIUINTENH 0x0e 55 - #define GIUINTTYPL 0x10 56 - #define GIUINTTYPH 0x12 57 - #define GIUINTALSELL 0x14 58 - #define GIUINTALSELH 0x16 59 - #define GIUINTHTSELL 0x18 60 - #define GIUINTHTSELH 0x1a 61 - #define GIUPODATL 0x1c 62 - #define GIUPODATEN 0x1c 63 - #define GIUPODATH 0x1e 64 - #define PIOEN0 0x0100 65 - #define PIOEN1 0x0200 66 - #define GIUPODAT 0x1e 67 - #define GIUFEDGEINHL 0x20 68 - #define GIUFEDGEINHH 0x22 69 - #define GIUREDGEINHL 0x24 70 - #define GIUREDGEINHH 0x26 71 - 72 - #define GIUUSEUPDN 0x1e0 73 - #define GIUTERMUPDN 0x1e2 74 - 75 - #define GPIO_HAS_PULLUPDOWN_IO 0x0001 76 - #define GPIO_HAS_OUTPUT_ENABLE 0x0002 77 - #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 78 - 79 - static spinlock_t giu_lock; 80 - static unsigned long giu_flags; 81 - static unsigned int giu_nr_pins; 82 - 83 - static void __iomem *giu_base; 84 - 85 - #define giu_read(offset) readw(giu_base + (offset)) 86 - #define giu_write(offset, value) writew((value), giu_base + (offset)) 87 - 88 - #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) 89 - #define GIUINT_HIGH_OFFSET 16 90 - #define GIUINT_HIGH_MAX 32 91 - 92 - static inline uint16_t giu_set(uint16_t offset, uint16_t set) 93 - { 94 - uint16_t data; 95 - 96 - data = giu_read(offset); 97 - data |= set; 98 - giu_write(offset, data); 99 - 100 - return data; 101 - } 102 - 103 - static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) 104 - { 105 - uint16_t data; 106 - 107 - data = giu_read(offset); 108 - data &= ~clear; 109 - giu_write(offset, data); 110 - 111 - return data; 112 - } 113 - 114 - static void ack_giuint_low(unsigned int irq) 115 - { 116 - giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); 117 - } 118 - 119 - static void mask_giuint_low(unsigned int irq) 120 - { 121 - giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); 122 - } 123 - 124 - static void mask_ack_giuint_low(unsigned int irq) 125 - { 126 - unsigned int pin; 127 - 128 - pin = GPIO_PIN_OF_IRQ(irq); 129 - giu_clear(GIUINTENL, 1 << pin); 130 - giu_write(GIUINTSTATL, 1 << pin); 131 - } 132 - 133 - static void unmask_giuint_low(unsigned int irq) 134 - { 135 - giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); 136 - } 137 - 138 - static struct irq_chip giuint_low_irq_chip = { 139 - .name = "GIUINTL", 140 - .ack = ack_giuint_low, 141 - .mask = mask_giuint_low, 142 - .mask_ack = mask_ack_giuint_low, 143 - .unmask = unmask_giuint_low, 144 - }; 145 - 146 - static void ack_giuint_high(unsigned int irq) 147 - { 148 - giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 149 - } 150 - 151 - static void mask_giuint_high(unsigned int irq) 152 - { 153 - giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 154 - } 155 - 156 - static void mask_ack_giuint_high(unsigned int irq) 157 - { 158 - unsigned int pin; 159 - 160 - pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; 161 - giu_clear(GIUINTENH, 1 << pin); 162 - giu_write(GIUINTSTATH, 1 << pin); 163 - } 164 - 165 - static void unmask_giuint_high(unsigned int irq) 166 - { 167 - giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 168 - } 169 - 170 - static struct irq_chip giuint_high_irq_chip = { 171 - .name = "GIUINTH", 172 - .ack = ack_giuint_high, 173 - .mask = mask_giuint_high, 174 - .mask_ack = mask_ack_giuint_high, 175 - .unmask = unmask_giuint_high, 176 - }; 177 - 178 - static int giu_get_irq(unsigned int irq) 179 - { 180 - uint16_t pendl, pendh, maskl, maskh; 181 - int i; 182 - 183 - pendl = giu_read(GIUINTSTATL); 184 - pendh = giu_read(GIUINTSTATH); 185 - maskl = giu_read(GIUINTENL); 186 - maskh = giu_read(GIUINTENH); 187 - 188 - maskl &= pendl; 189 - maskh &= pendh; 190 - 191 - if (maskl) { 192 - for (i = 0; i < 16; i++) { 193 - if (maskl & (1 << i)) 194 - return GIU_IRQ(i); 195 - } 196 - } else if (maskh) { 197 - for (i = 0; i < 16; i++) { 198 - if (maskh & (1 << i)) 199 - return GIU_IRQ(i + GIUINT_HIGH_OFFSET); 200 - } 201 - } 202 - 203 - printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", 204 - maskl, pendl, maskh, pendh); 205 - 206 - atomic_inc(&irq_err_count); 207 - 208 - return -EINVAL; 209 - } 210 - 211 - void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal) 212 - { 213 - uint16_t mask; 214 - 215 - if (pin < GIUINT_HIGH_OFFSET) { 216 - mask = 1 << pin; 217 - if (trigger != IRQ_TRIGGER_LEVEL) { 218 - giu_set(GIUINTTYPL, mask); 219 - if (signal == IRQ_SIGNAL_HOLD) 220 - giu_set(GIUINTHTSELL, mask); 221 - else 222 - giu_clear(GIUINTHTSELL, mask); 223 - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 224 - switch (trigger) { 225 - case IRQ_TRIGGER_EDGE_FALLING: 226 - giu_set(GIUFEDGEINHL, mask); 227 - giu_clear(GIUREDGEINHL, mask); 228 - break; 229 - case IRQ_TRIGGER_EDGE_RISING: 230 - giu_clear(GIUFEDGEINHL, mask); 231 - giu_set(GIUREDGEINHL, mask); 232 - break; 233 - default: 234 - giu_set(GIUFEDGEINHL, mask); 235 - giu_set(GIUREDGEINHL, mask); 236 - break; 237 - } 238 - } 239 - set_irq_chip_and_handler(GIU_IRQ(pin), 240 - &giuint_low_irq_chip, 241 - handle_edge_irq); 242 - } else { 243 - giu_clear(GIUINTTYPL, mask); 244 - giu_clear(GIUINTHTSELL, mask); 245 - set_irq_chip_and_handler(GIU_IRQ(pin), 246 - &giuint_low_irq_chip, 247 - handle_level_irq); 248 - } 249 - giu_write(GIUINTSTATL, mask); 250 - } else if (pin < GIUINT_HIGH_MAX) { 251 - mask = 1 << (pin - GIUINT_HIGH_OFFSET); 252 - if (trigger != IRQ_TRIGGER_LEVEL) { 253 - giu_set(GIUINTTYPH, mask); 254 - if (signal == IRQ_SIGNAL_HOLD) 255 - giu_set(GIUINTHTSELH, mask); 256 - else 257 - giu_clear(GIUINTHTSELH, mask); 258 - if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 259 - switch (trigger) { 260 - case IRQ_TRIGGER_EDGE_FALLING: 261 - giu_set(GIUFEDGEINHH, mask); 262 - giu_clear(GIUREDGEINHH, mask); 263 - break; 264 - case IRQ_TRIGGER_EDGE_RISING: 265 - giu_clear(GIUFEDGEINHH, mask); 266 - giu_set(GIUREDGEINHH, mask); 267 - break; 268 - default: 269 - giu_set(GIUFEDGEINHH, mask); 270 - giu_set(GIUREDGEINHH, mask); 271 - break; 272 - } 273 - } 274 - set_irq_chip_and_handler(GIU_IRQ(pin), 275 - &giuint_high_irq_chip, 276 - handle_edge_irq); 277 - } else { 278 - giu_clear(GIUINTTYPH, mask); 279 - giu_clear(GIUINTHTSELH, mask); 280 - set_irq_chip_and_handler(GIU_IRQ(pin), 281 - &giuint_high_irq_chip, 282 - handle_level_irq); 283 - } 284 - giu_write(GIUINTSTATH, mask); 285 - } 286 - } 287 - EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); 288 - 289 - void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) 290 - { 291 - uint16_t mask; 292 - 293 - if (pin < GIUINT_HIGH_OFFSET) { 294 - mask = 1 << pin; 295 - if (level == IRQ_LEVEL_HIGH) 296 - giu_set(GIUINTALSELL, mask); 297 - else 298 - giu_clear(GIUINTALSELL, mask); 299 - giu_write(GIUINTSTATL, mask); 300 - } else if (pin < GIUINT_HIGH_MAX) { 301 - mask = 1 << (pin - GIUINT_HIGH_OFFSET); 302 - if (level == IRQ_LEVEL_HIGH) 303 - giu_set(GIUINTALSELH, mask); 304 - else 305 - giu_clear(GIUINTALSELH, mask); 306 - giu_write(GIUINTSTATH, mask); 307 - } 308 - } 309 - EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); 310 - 311 - gpio_data_t vr41xx_gpio_get_pin(unsigned int pin) 312 - { 313 - uint16_t reg, mask; 314 - 315 - if (pin >= giu_nr_pins) 316 - return GPIO_DATA_INVAL; 317 - 318 - if (pin < 16) { 319 - reg = giu_read(GIUPIODL); 320 - mask = (uint16_t)1 << pin; 321 - } else if (pin < 32) { 322 - reg = giu_read(GIUPIODH); 323 - mask = (uint16_t)1 << (pin - 16); 324 - } else if (pin < 48) { 325 - reg = giu_read(GIUPODATL); 326 - mask = (uint16_t)1 << (pin - 32); 327 - } else { 328 - reg = giu_read(GIUPODATH); 329 - mask = (uint16_t)1 << (pin - 48); 330 - } 331 - 332 - if (reg & mask) 333 - return GPIO_DATA_HIGH; 334 - 335 - return GPIO_DATA_LOW; 336 - } 337 - EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); 338 - 339 - int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data) 340 - { 341 - uint16_t offset, mask, reg; 342 - unsigned long flags; 343 - 344 - if (pin >= giu_nr_pins) 345 - return -EINVAL; 346 - 347 - if (pin < 16) { 348 - offset = GIUPIODL; 349 - mask = (uint16_t)1 << pin; 350 - } else if (pin < 32) { 351 - offset = GIUPIODH; 352 - mask = (uint16_t)1 << (pin - 16); 353 - } else if (pin < 48) { 354 - offset = GIUPODATL; 355 - mask = (uint16_t)1 << (pin - 32); 356 - } else { 357 - offset = GIUPODATH; 358 - mask = (uint16_t)1 << (pin - 48); 359 - } 360 - 361 - spin_lock_irqsave(&giu_lock, flags); 362 - 363 - reg = giu_read(offset); 364 - if (data == GPIO_DATA_HIGH) 365 - reg |= mask; 366 - else 367 - reg &= ~mask; 368 - giu_write(offset, reg); 369 - 370 - spin_unlock_irqrestore(&giu_lock, flags); 371 - 372 - return 0; 373 - } 374 - EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); 375 - 376 - int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir) 377 - { 378 - uint16_t offset, mask, reg; 379 - unsigned long flags; 380 - 381 - if (pin >= giu_nr_pins) 382 - return -EINVAL; 383 - 384 - if (pin < 16) { 385 - offset = GIUIOSELL; 386 - mask = (uint16_t)1 << pin; 387 - } else if (pin < 32) { 388 - offset = GIUIOSELH; 389 - mask = (uint16_t)1 << (pin - 16); 390 - } else { 391 - if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { 392 - offset = GIUPODATEN; 393 - mask = (uint16_t)1 << (pin - 32); 394 - } else { 395 - switch (pin) { 396 - case 48: 397 - offset = GIUPODATH; 398 - mask = PIOEN0; 399 - break; 400 - case 49: 401 - offset = GIUPODATH; 402 - mask = PIOEN1; 403 - break; 404 - default: 405 - return -EINVAL; 406 - } 407 - } 408 - } 409 - 410 - spin_lock_irqsave(&giu_lock, flags); 411 - 412 - reg = giu_read(offset); 413 - if (dir == GPIO_OUTPUT) 414 - reg |= mask; 415 - else 416 - reg &= ~mask; 417 - giu_write(offset, reg); 418 - 419 - spin_unlock_irqrestore(&giu_lock, flags); 420 - 421 - return 0; 422 - } 423 - EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); 424 - 425 - int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) 426 - { 427 - uint16_t reg, mask; 428 - unsigned long flags; 429 - 430 - if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) 431 - return -EPERM; 432 - 433 - if (pin >= 15) 434 - return -EINVAL; 435 - 436 - mask = (uint16_t)1 << pin; 437 - 438 - spin_lock_irqsave(&giu_lock, flags); 439 - 440 - if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { 441 - reg = giu_read(GIUTERMUPDN); 442 - if (pull == GPIO_PULL_UP) 443 - reg |= mask; 444 - else 445 - reg &= ~mask; 446 - giu_write(GIUTERMUPDN, reg); 447 - 448 - reg = giu_read(GIUUSEUPDN); 449 - reg |= mask; 450 - giu_write(GIUUSEUPDN, reg); 451 - } else { 452 - reg = giu_read(GIUUSEUPDN); 453 - reg &= ~mask; 454 - giu_write(GIUUSEUPDN, reg); 455 - } 456 - 457 - spin_unlock_irqrestore(&giu_lock, flags); 458 - 459 - return 0; 460 - } 461 - EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); 462 - 463 - static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, 464 - loff_t *ppos) 465 - { 466 - unsigned int pin; 467 - char value = '0'; 468 - 469 - pin = iminor(file->f_path.dentry->d_inode); 470 - if (pin >= giu_nr_pins) 471 - return -EBADF; 472 - 473 - if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH) 474 - value = '1'; 475 - 476 - if (len <= 0) 477 - return -EFAULT; 478 - 479 - if (put_user(value, buf)) 480 - return -EFAULT; 481 - 482 - return 1; 483 - } 484 - 485 - static ssize_t gpio_write(struct file *file, const char __user *data, 486 - size_t len, loff_t *ppos) 487 - { 488 - unsigned int pin; 489 - size_t i; 490 - char c; 491 - int retval = 0; 492 - 493 - pin = iminor(file->f_path.dentry->d_inode); 494 - if (pin >= giu_nr_pins) 495 - return -EBADF; 496 - 497 - for (i = 0; i < len; i++) { 498 - if (get_user(c, data + i)) 499 - return -EFAULT; 500 - 501 - switch (c) { 502 - case '0': 503 - retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW); 504 - break; 505 - case '1': 506 - retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH); 507 - break; 508 - case 'D': 509 - printk(KERN_INFO "GPIO%d: pull down\n", pin); 510 - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN); 511 - break; 512 - case 'd': 513 - printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); 514 - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); 515 - break; 516 - case 'I': 517 - printk(KERN_INFO "GPIO%d: input\n", pin); 518 - retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT); 519 - break; 520 - case 'O': 521 - printk(KERN_INFO "GPIO%d: output\n", pin); 522 - retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT); 523 - break; 524 - case 'o': 525 - printk(KERN_INFO "GPIO%d: output disable\n", pin); 526 - retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE); 527 - break; 528 - case 'P': 529 - printk(KERN_INFO "GPIO%d: pull up\n", pin); 530 - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP); 531 - break; 532 - case 'p': 533 - printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin); 534 - retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE); 535 - break; 536 - default: 537 - break; 538 - } 539 - 540 - if (retval < 0) 541 - break; 542 - } 543 - 544 - return i; 545 - } 546 - 547 - static int gpio_open(struct inode *inode, struct file *file) 548 - { 549 - unsigned int pin; 550 - 551 - cycle_kernel_lock(); 552 - pin = iminor(inode); 553 - if (pin >= giu_nr_pins) 554 - return -EBADF; 555 - 556 - return nonseekable_open(inode, file); 557 - } 558 - 559 - static int gpio_release(struct inode *inode, struct file *file) 560 - { 561 - unsigned int pin; 562 - 563 - pin = iminor(inode); 564 - if (pin >= giu_nr_pins) 565 - return -EBADF; 566 - 567 - return 0; 568 - } 569 - 570 - static const struct file_operations gpio_fops = { 571 - .owner = THIS_MODULE, 572 - .read = gpio_read, 573 - .write = gpio_write, 574 - .open = gpio_open, 575 - .release = gpio_release, 576 - }; 577 - 578 - static int __devinit giu_probe(struct platform_device *dev) 579 - { 580 - struct resource *res; 581 - unsigned int trigger, i, pin; 582 - struct irq_chip *chip; 583 - int irq, retval; 584 - 585 - switch (dev->id) { 586 - case GPIO_50PINS_PULLUPDOWN: 587 - giu_flags = GPIO_HAS_PULLUPDOWN_IO; 588 - giu_nr_pins = 50; 589 - break; 590 - case GPIO_36PINS: 591 - giu_nr_pins = 36; 592 - break; 593 - case GPIO_48PINS_EDGE_SELECT: 594 - giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; 595 - giu_nr_pins = 48; 596 - break; 597 - default: 598 - printk(KERN_ERR "GIU: unknown ID %d\n", dev->id); 599 - return -ENODEV; 600 - } 601 - 602 - res = platform_get_resource(dev, IORESOURCE_MEM, 0); 603 - if (!res) 604 - return -EBUSY; 605 - 606 - giu_base = ioremap(res->start, res->end - res->start + 1); 607 - if (!giu_base) 608 - return -ENOMEM; 609 - 610 - retval = register_chrdev(major, "GIU", &gpio_fops); 611 - if (retval < 0) { 612 - iounmap(giu_base); 613 - giu_base = NULL; 614 - return retval; 615 - } 616 - 617 - if (major == 0) { 618 - major = retval; 619 - printk(KERN_INFO "GIU: major number %d\n", major); 620 - } 621 - 622 - spin_lock_init(&giu_lock); 623 - 624 - giu_write(GIUINTENL, 0); 625 - giu_write(GIUINTENH, 0); 626 - 627 - trigger = giu_read(GIUINTTYPH) << 16; 628 - trigger |= giu_read(GIUINTTYPL); 629 - for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { 630 - pin = GPIO_PIN_OF_IRQ(i); 631 - if (pin < GIUINT_HIGH_OFFSET) 632 - chip = &giuint_low_irq_chip; 633 - else 634 - chip = &giuint_high_irq_chip; 635 - 636 - if (trigger & (1 << pin)) 637 - set_irq_chip_and_handler(i, chip, handle_edge_irq); 638 - else 639 - set_irq_chip_and_handler(i, chip, handle_level_irq); 640 - 641 - } 642 - 643 - irq = platform_get_irq(dev, 0); 644 - if (irq < 0 || irq >= nr_irqs) 645 - return -EBUSY; 646 - 647 - return cascade_irq(irq, giu_get_irq); 648 - } 649 - 650 - static int __devexit giu_remove(struct platform_device *dev) 651 - { 652 - if (giu_base) { 653 - iounmap(giu_base); 654 - giu_base = NULL; 655 - } 656 - 657 - return 0; 658 - } 659 - 660 - static struct platform_driver giu_device_driver = { 661 - .probe = giu_probe, 662 - .remove = __devexit_p(giu_remove), 663 - .driver = { 664 - .name = "GIU", 665 - .owner = THIS_MODULE, 666 - }, 667 - }; 668 - 669 - static int __init vr41xx_giu_init(void) 670 - { 671 - return platform_driver_register(&giu_device_driver); 672 - } 673 - 674 - static void __exit vr41xx_giu_exit(void) 675 - { 676 - platform_driver_unregister(&giu_device_driver); 677 - } 678 - 679 - module_init(vr41xx_giu_init); 680 - module_exit(vr41xx_giu_exit);
+6
drivers/gpio/Kconfig
··· 79 79 help 80 80 Say yes here to support the Xilinx FPGA GPIO device 81 81 82 + config GPIO_VR41XX 83 + tristate "NEC VR4100 series General-purpose I/O Uint support" 84 + depends on CPU_VR41XX 85 + help 86 + Say yes here to support the NEC VR4100 series General-purpose I/O Uint 87 + 82 88 comment "I2C GPIO expanders:" 83 89 84 90 config GPIO_MAX732X
+1
drivers/gpio/Makefile
··· 13 13 obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o 14 14 obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o 15 15 obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o 16 + obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
+586
drivers/gpio/vr41xx_giu.c
··· 1 + /* 2 + * Driver for NEC VR4100 series General-purpose I/O Unit. 3 + * 4 + * Copyright (C) 2002 MontaVista Software Inc. 5 + * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> 6 + * Copyright (C) 2003-2009 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to the Free Software 20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 + */ 22 + #include <linux/errno.h> 23 + #include <linux/fs.h> 24 + #include <linux/gpio.h> 25 + #include <linux/init.h> 26 + #include <linux/interrupt.h> 27 + #include <linux/io.h> 28 + #include <linux/irq.h> 29 + #include <linux/kernel.h> 30 + #include <linux/module.h> 31 + #include <linux/platform_device.h> 32 + #include <linux/smp_lock.h> 33 + #include <linux/spinlock.h> 34 + #include <linux/types.h> 35 + 36 + #include <asm/vr41xx/giu.h> 37 + #include <asm/vr41xx/irq.h> 38 + #include <asm/vr41xx/vr41xx.h> 39 + 40 + MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); 41 + MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); 42 + MODULE_LICENSE("GPL"); 43 + 44 + #define GIUIOSELL 0x00 45 + #define GIUIOSELH 0x02 46 + #define GIUPIODL 0x04 47 + #define GIUPIODH 0x06 48 + #define GIUINTSTATL 0x08 49 + #define GIUINTSTATH 0x0a 50 + #define GIUINTENL 0x0c 51 + #define GIUINTENH 0x0e 52 + #define GIUINTTYPL 0x10 53 + #define GIUINTTYPH 0x12 54 + #define GIUINTALSELL 0x14 55 + #define GIUINTALSELH 0x16 56 + #define GIUINTHTSELL 0x18 57 + #define GIUINTHTSELH 0x1a 58 + #define GIUPODATL 0x1c 59 + #define GIUPODATEN 0x1c 60 + #define GIUPODATH 0x1e 61 + #define PIOEN0 0x0100 62 + #define PIOEN1 0x0200 63 + #define GIUPODAT 0x1e 64 + #define GIUFEDGEINHL 0x20 65 + #define GIUFEDGEINHH 0x22 66 + #define GIUREDGEINHL 0x24 67 + #define GIUREDGEINHH 0x26 68 + 69 + #define GIUUSEUPDN 0x1e0 70 + #define GIUTERMUPDN 0x1e2 71 + 72 + #define GPIO_HAS_PULLUPDOWN_IO 0x0001 73 + #define GPIO_HAS_OUTPUT_ENABLE 0x0002 74 + #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100 75 + 76 + enum { 77 + GPIO_INPUT, 78 + GPIO_OUTPUT, 79 + }; 80 + 81 + static DEFINE_SPINLOCK(giu_lock); 82 + static unsigned long giu_flags; 83 + 84 + static void __iomem *giu_base; 85 + 86 + #define giu_read(offset) readw(giu_base + (offset)) 87 + #define giu_write(offset, value) writew((value), giu_base + (offset)) 88 + 89 + #define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE) 90 + #define GIUINT_HIGH_OFFSET 16 91 + #define GIUINT_HIGH_MAX 32 92 + 93 + static inline u16 giu_set(u16 offset, u16 set) 94 + { 95 + u16 data; 96 + 97 + data = giu_read(offset); 98 + data |= set; 99 + giu_write(offset, data); 100 + 101 + return data; 102 + } 103 + 104 + static inline u16 giu_clear(u16 offset, u16 clear) 105 + { 106 + u16 data; 107 + 108 + data = giu_read(offset); 109 + data &= ~clear; 110 + giu_write(offset, data); 111 + 112 + return data; 113 + } 114 + 115 + static void ack_giuint_low(unsigned int irq) 116 + { 117 + giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); 118 + } 119 + 120 + static void mask_giuint_low(unsigned int irq) 121 + { 122 + giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); 123 + } 124 + 125 + static void mask_ack_giuint_low(unsigned int irq) 126 + { 127 + unsigned int pin; 128 + 129 + pin = GPIO_PIN_OF_IRQ(irq); 130 + giu_clear(GIUINTENL, 1 << pin); 131 + giu_write(GIUINTSTATL, 1 << pin); 132 + } 133 + 134 + static void unmask_giuint_low(unsigned int irq) 135 + { 136 + giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); 137 + } 138 + 139 + static struct irq_chip giuint_low_irq_chip = { 140 + .name = "GIUINTL", 141 + .ack = ack_giuint_low, 142 + .mask = mask_giuint_low, 143 + .mask_ack = mask_ack_giuint_low, 144 + .unmask = unmask_giuint_low, 145 + }; 146 + 147 + static void ack_giuint_high(unsigned int irq) 148 + { 149 + giu_write(GIUINTSTATH, 150 + 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 151 + } 152 + 153 + static void mask_giuint_high(unsigned int irq) 154 + { 155 + giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 156 + } 157 + 158 + static void mask_ack_giuint_high(unsigned int irq) 159 + { 160 + unsigned int pin; 161 + 162 + pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; 163 + giu_clear(GIUINTENH, 1 << pin); 164 + giu_write(GIUINTSTATH, 1 << pin); 165 + } 166 + 167 + static void unmask_giuint_high(unsigned int irq) 168 + { 169 + giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 170 + } 171 + 172 + static struct irq_chip giuint_high_irq_chip = { 173 + .name = "GIUINTH", 174 + .ack = ack_giuint_high, 175 + .mask = mask_giuint_high, 176 + .mask_ack = mask_ack_giuint_high, 177 + .unmask = unmask_giuint_high, 178 + }; 179 + 180 + static int giu_get_irq(unsigned int irq) 181 + { 182 + u16 pendl, pendh, maskl, maskh; 183 + int i; 184 + 185 + pendl = giu_read(GIUINTSTATL); 186 + pendh = giu_read(GIUINTSTATH); 187 + maskl = giu_read(GIUINTENL); 188 + maskh = giu_read(GIUINTENH); 189 + 190 + maskl &= pendl; 191 + maskh &= pendh; 192 + 193 + if (maskl) { 194 + for (i = 0; i < 16; i++) { 195 + if (maskl & (1 << i)) 196 + return GIU_IRQ(i); 197 + } 198 + } else if (maskh) { 199 + for (i = 0; i < 16; i++) { 200 + if (maskh & (1 << i)) 201 + return GIU_IRQ(i + GIUINT_HIGH_OFFSET); 202 + } 203 + } 204 + 205 + printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n", 206 + maskl, pendl, maskh, pendh); 207 + 208 + atomic_inc(&irq_err_count); 209 + 210 + return -EINVAL; 211 + } 212 + 213 + void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, 214 + irq_signal_t signal) 215 + { 216 + u16 mask; 217 + 218 + if (pin < GIUINT_HIGH_OFFSET) { 219 + mask = 1 << pin; 220 + if (trigger != IRQ_TRIGGER_LEVEL) { 221 + giu_set(GIUINTTYPL, mask); 222 + if (signal == IRQ_SIGNAL_HOLD) 223 + giu_set(GIUINTHTSELL, mask); 224 + else 225 + giu_clear(GIUINTHTSELL, mask); 226 + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 227 + switch (trigger) { 228 + case IRQ_TRIGGER_EDGE_FALLING: 229 + giu_set(GIUFEDGEINHL, mask); 230 + giu_clear(GIUREDGEINHL, mask); 231 + break; 232 + case IRQ_TRIGGER_EDGE_RISING: 233 + giu_clear(GIUFEDGEINHL, mask); 234 + giu_set(GIUREDGEINHL, mask); 235 + break; 236 + default: 237 + giu_set(GIUFEDGEINHL, mask); 238 + giu_set(GIUREDGEINHL, mask); 239 + break; 240 + } 241 + } 242 + set_irq_chip_and_handler(GIU_IRQ(pin), 243 + &giuint_low_irq_chip, 244 + handle_edge_irq); 245 + } else { 246 + giu_clear(GIUINTTYPL, mask); 247 + giu_clear(GIUINTHTSELL, mask); 248 + set_irq_chip_and_handler(GIU_IRQ(pin), 249 + &giuint_low_irq_chip, 250 + handle_level_irq); 251 + } 252 + giu_write(GIUINTSTATL, mask); 253 + } else if (pin < GIUINT_HIGH_MAX) { 254 + mask = 1 << (pin - GIUINT_HIGH_OFFSET); 255 + if (trigger != IRQ_TRIGGER_LEVEL) { 256 + giu_set(GIUINTTYPH, mask); 257 + if (signal == IRQ_SIGNAL_HOLD) 258 + giu_set(GIUINTHTSELH, mask); 259 + else 260 + giu_clear(GIUINTHTSELH, mask); 261 + if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) { 262 + switch (trigger) { 263 + case IRQ_TRIGGER_EDGE_FALLING: 264 + giu_set(GIUFEDGEINHH, mask); 265 + giu_clear(GIUREDGEINHH, mask); 266 + break; 267 + case IRQ_TRIGGER_EDGE_RISING: 268 + giu_clear(GIUFEDGEINHH, mask); 269 + giu_set(GIUREDGEINHH, mask); 270 + break; 271 + default: 272 + giu_set(GIUFEDGEINHH, mask); 273 + giu_set(GIUREDGEINHH, mask); 274 + break; 275 + } 276 + } 277 + set_irq_chip_and_handler(GIU_IRQ(pin), 278 + &giuint_high_irq_chip, 279 + handle_edge_irq); 280 + } else { 281 + giu_clear(GIUINTTYPH, mask); 282 + giu_clear(GIUINTHTSELH, mask); 283 + set_irq_chip_and_handler(GIU_IRQ(pin), 284 + &giuint_high_irq_chip, 285 + handle_level_irq); 286 + } 287 + giu_write(GIUINTSTATH, mask); 288 + } 289 + } 290 + EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); 291 + 292 + void vr41xx_set_irq_level(unsigned int pin, irq_level_t level) 293 + { 294 + u16 mask; 295 + 296 + if (pin < GIUINT_HIGH_OFFSET) { 297 + mask = 1 << pin; 298 + if (level == IRQ_LEVEL_HIGH) 299 + giu_set(GIUINTALSELL, mask); 300 + else 301 + giu_clear(GIUINTALSELL, mask); 302 + giu_write(GIUINTSTATL, mask); 303 + } else if (pin < GIUINT_HIGH_MAX) { 304 + mask = 1 << (pin - GIUINT_HIGH_OFFSET); 305 + if (level == IRQ_LEVEL_HIGH) 306 + giu_set(GIUINTALSELH, mask); 307 + else 308 + giu_clear(GIUINTALSELH, mask); 309 + giu_write(GIUINTSTATH, mask); 310 + } 311 + } 312 + EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); 313 + 314 + static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir) 315 + { 316 + u16 offset, mask, reg; 317 + unsigned long flags; 318 + 319 + if (pin >= chip->ngpio) 320 + return -EINVAL; 321 + 322 + if (pin < 16) { 323 + offset = GIUIOSELL; 324 + mask = 1 << pin; 325 + } else if (pin < 32) { 326 + offset = GIUIOSELH; 327 + mask = 1 << (pin - 16); 328 + } else { 329 + if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) { 330 + offset = GIUPODATEN; 331 + mask = 1 << (pin - 32); 332 + } else { 333 + switch (pin) { 334 + case 48: 335 + offset = GIUPODATH; 336 + mask = PIOEN0; 337 + break; 338 + case 49: 339 + offset = GIUPODATH; 340 + mask = PIOEN1; 341 + break; 342 + default: 343 + return -EINVAL; 344 + } 345 + } 346 + } 347 + 348 + spin_lock_irqsave(&giu_lock, flags); 349 + 350 + reg = giu_read(offset); 351 + if (dir == GPIO_OUTPUT) 352 + reg |= mask; 353 + else 354 + reg &= ~mask; 355 + giu_write(offset, reg); 356 + 357 + spin_unlock_irqrestore(&giu_lock, flags); 358 + 359 + return 0; 360 + } 361 + 362 + int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull) 363 + { 364 + u16 reg, mask; 365 + unsigned long flags; 366 + 367 + if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO) 368 + return -EPERM; 369 + 370 + if (pin >= 15) 371 + return -EINVAL; 372 + 373 + mask = 1 << pin; 374 + 375 + spin_lock_irqsave(&giu_lock, flags); 376 + 377 + if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) { 378 + reg = giu_read(GIUTERMUPDN); 379 + if (pull == GPIO_PULL_UP) 380 + reg |= mask; 381 + else 382 + reg &= ~mask; 383 + giu_write(GIUTERMUPDN, reg); 384 + 385 + reg = giu_read(GIUUSEUPDN); 386 + reg |= mask; 387 + giu_write(GIUUSEUPDN, reg); 388 + } else { 389 + reg = giu_read(GIUUSEUPDN); 390 + reg &= ~mask; 391 + giu_write(GIUUSEUPDN, reg); 392 + } 393 + 394 + spin_unlock_irqrestore(&giu_lock, flags); 395 + 396 + return 0; 397 + } 398 + EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); 399 + 400 + static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin) 401 + { 402 + u16 reg, mask; 403 + 404 + if (pin >= chip->ngpio) 405 + return -EINVAL; 406 + 407 + if (pin < 16) { 408 + reg = giu_read(GIUPIODL); 409 + mask = 1 << pin; 410 + } else if (pin < 32) { 411 + reg = giu_read(GIUPIODH); 412 + mask = 1 << (pin - 16); 413 + } else if (pin < 48) { 414 + reg = giu_read(GIUPODATL); 415 + mask = 1 << (pin - 32); 416 + } else { 417 + reg = giu_read(GIUPODATH); 418 + mask = 1 << (pin - 48); 419 + } 420 + 421 + if (reg & mask) 422 + return 1; 423 + 424 + return 0; 425 + } 426 + 427 + static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin, 428 + int value) 429 + { 430 + u16 offset, mask, reg; 431 + unsigned long flags; 432 + 433 + if (pin >= chip->ngpio) 434 + return; 435 + 436 + if (pin < 16) { 437 + offset = GIUPIODL; 438 + mask = 1 << pin; 439 + } else if (pin < 32) { 440 + offset = GIUPIODH; 441 + mask = 1 << (pin - 16); 442 + } else if (pin < 48) { 443 + offset = GIUPODATL; 444 + mask = 1 << (pin - 32); 445 + } else { 446 + offset = GIUPODATH; 447 + mask = 1 << (pin - 48); 448 + } 449 + 450 + spin_lock_irqsave(&giu_lock, flags); 451 + 452 + reg = giu_read(offset); 453 + if (value) 454 + reg |= mask; 455 + else 456 + reg &= ~mask; 457 + giu_write(offset, reg); 458 + 459 + spin_unlock_irqrestore(&giu_lock, flags); 460 + } 461 + 462 + 463 + static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 464 + { 465 + return giu_set_direction(chip, offset, GPIO_INPUT); 466 + } 467 + 468 + static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 469 + int value) 470 + { 471 + vr41xx_gpio_set(chip, offset, value); 472 + 473 + return giu_set_direction(chip, offset, GPIO_OUTPUT); 474 + } 475 + 476 + static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 477 + { 478 + if (offset >= chip->ngpio) 479 + return -EINVAL; 480 + 481 + return GIU_IRQ_BASE + offset; 482 + } 483 + 484 + static struct gpio_chip vr41xx_gpio_chip = { 485 + .label = "vr41xx", 486 + .owner = THIS_MODULE, 487 + .direction_input = vr41xx_gpio_direction_input, 488 + .get = vr41xx_gpio_get, 489 + .direction_output = vr41xx_gpio_direction_output, 490 + .set = vr41xx_gpio_set, 491 + .to_irq = vr41xx_gpio_to_irq, 492 + }; 493 + 494 + static int __devinit giu_probe(struct platform_device *pdev) 495 + { 496 + struct resource *res; 497 + unsigned int trigger, i, pin; 498 + struct irq_chip *chip; 499 + int irq, retval; 500 + 501 + switch (pdev->id) { 502 + case GPIO_50PINS_PULLUPDOWN: 503 + giu_flags = GPIO_HAS_PULLUPDOWN_IO; 504 + vr41xx_gpio_chip.ngpio = 50; 505 + break; 506 + case GPIO_36PINS: 507 + vr41xx_gpio_chip.ngpio = 36; 508 + break; 509 + case GPIO_48PINS_EDGE_SELECT: 510 + giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT; 511 + vr41xx_gpio_chip.ngpio = 48; 512 + break; 513 + default: 514 + dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id); 515 + return -ENODEV; 516 + } 517 + 518 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 519 + if (!res) 520 + return -EBUSY; 521 + 522 + giu_base = ioremap(res->start, res->end - res->start + 1); 523 + if (!giu_base) 524 + return -ENOMEM; 525 + 526 + vr41xx_gpio_chip.dev = &pdev->dev; 527 + 528 + retval = gpiochip_add(&vr41xx_gpio_chip); 529 + 530 + giu_write(GIUINTENL, 0); 531 + giu_write(GIUINTENH, 0); 532 + 533 + trigger = giu_read(GIUINTTYPH) << 16; 534 + trigger |= giu_read(GIUINTTYPL); 535 + for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { 536 + pin = GPIO_PIN_OF_IRQ(i); 537 + if (pin < GIUINT_HIGH_OFFSET) 538 + chip = &giuint_low_irq_chip; 539 + else 540 + chip = &giuint_high_irq_chip; 541 + 542 + if (trigger & (1 << pin)) 543 + set_irq_chip_and_handler(i, chip, handle_edge_irq); 544 + else 545 + set_irq_chip_and_handler(i, chip, handle_level_irq); 546 + 547 + } 548 + 549 + irq = platform_get_irq(pdev, 0); 550 + if (irq < 0 || irq >= nr_irqs) 551 + return -EBUSY; 552 + 553 + return cascade_irq(irq, giu_get_irq); 554 + } 555 + 556 + static int __devexit giu_remove(struct platform_device *pdev) 557 + { 558 + if (giu_base) { 559 + iounmap(giu_base); 560 + giu_base = NULL; 561 + } 562 + 563 + return 0; 564 + } 565 + 566 + static struct platform_driver giu_device_driver = { 567 + .probe = giu_probe, 568 + .remove = __devexit_p(giu_remove), 569 + .driver = { 570 + .name = "GIU", 571 + .owner = THIS_MODULE, 572 + }, 573 + }; 574 + 575 + static int __init vr41xx_giu_init(void) 576 + { 577 + return platform_driver_register(&giu_device_driver); 578 + } 579 + 580 + static void __exit vr41xx_giu_exit(void) 581 + { 582 + platform_driver_unregister(&giu_device_driver); 583 + } 584 + 585 + module_init(vr41xx_giu_init); 586 + module_exit(vr41xx_giu_exit);