root/drivers/gpio/gpio-vr41xx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. giu_set
  2. giu_clear
  3. ack_giuint_low
  4. mask_giuint_low
  5. mask_ack_giuint_low
  6. unmask_giuint_low
  7. startup_giuint
  8. shutdown_giuint
  9. ack_giuint_high
  10. mask_giuint_high
  11. mask_ack_giuint_high
  12. unmask_giuint_high
  13. giu_get_irq
  14. vr41xx_set_irq_trigger
  15. vr41xx_set_irq_level
  16. giu_set_direction
  17. vr41xx_gpio_get
  18. vr41xx_gpio_set
  19. vr41xx_gpio_direction_input
  20. vr41xx_gpio_direction_output
  21. vr41xx_gpio_to_irq
  22. giu_probe
  23. giu_remove

   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 
  26 MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
  27 MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
  28 MODULE_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 
  62 enum {
  63         GPIO_INPUT,
  64         GPIO_OUTPUT,
  65 };
  66 
  67 static DEFINE_SPINLOCK(giu_lock);
  68 static unsigned long giu_flags;
  69 
  70 static void __iomem *giu_base;
  71 static 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 
  80 static 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 
  91 static 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 
 102 static void ack_giuint_low(struct irq_data *d)
 103 {
 104         giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq));
 105 }
 106 
 107 static void mask_giuint_low(struct irq_data *d)
 108 {
 109         giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
 110 }
 111 
 112 static 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 
 121 static void unmask_giuint_low(struct irq_data *d)
 122 {
 123         giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
 124 }
 125 
 126 static 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 
 143 static 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 
 149 static 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 
 159 static 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 
 165 static 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 
 170 static 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 
 179 static 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 
 184 static 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 
 192 static 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 
 225 void 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 }
 302 EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
 303 
 304 void 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 }
 324 EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
 325 
 326 static 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 
 374 static 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 
 401 static 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 
 437 static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 438 {
 439         return giu_set_direction(chip, offset, GPIO_INPUT);
 440 }
 441 
 442 static 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 
 450 static 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 
 458 static 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 
 468 static int giu_probe(struct platform_device *pdev)
 469 {
 470         unsigned int trigger, i, pin;
 471         struct irq_chip *chip;
 472         int irq;
 473 
 474         switch (pdev->id) {
 475         case GPIO_50PINS_PULLUPDOWN:
 476                 giu_flags = GPIO_HAS_PULLUPDOWN_IO;
 477                 vr41xx_gpio_chip.ngpio = 50;
 478                 break;
 479         case GPIO_36PINS:
 480                 vr41xx_gpio_chip.ngpio = 36;
 481                 break;
 482         case GPIO_48PINS_EDGE_SELECT:
 483                 giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
 484                 vr41xx_gpio_chip.ngpio = 48;
 485                 break;
 486         default:
 487                 dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
 488                 return -ENODEV;
 489         }
 490 
 491         giu_base = devm_platform_ioremap_resource(pdev, 0);
 492         if (IS_ERR(giu_base))
 493                 return PTR_ERR(giu_base);
 494 
 495         vr41xx_gpio_chip.parent = &pdev->dev;
 496 
 497         if (gpiochip_add_data(&vr41xx_gpio_chip, NULL))
 498                 return -ENODEV;
 499 
 500         giu_write(GIUINTENL, 0);
 501         giu_write(GIUINTENH, 0);
 502 
 503         trigger = giu_read(GIUINTTYPH) << 16;
 504         trigger |= giu_read(GIUINTTYPL);
 505         for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
 506                 pin = GPIO_PIN_OF_IRQ(i);
 507                 if (pin < GIUINT_HIGH_OFFSET)
 508                         chip = &giuint_low_irq_chip;
 509                 else
 510                         chip = &giuint_high_irq_chip;
 511 
 512                 if (trigger & (1 << pin))
 513                         irq_set_chip_and_handler(i, chip, handle_edge_irq);
 514                 else
 515                         irq_set_chip_and_handler(i, chip, handle_level_irq);
 516 
 517         }
 518 
 519         irq = platform_get_irq(pdev, 0);
 520         if (irq < 0 || irq >= nr_irqs)
 521                 return -EBUSY;
 522 
 523         return cascade_irq(irq, giu_get_irq);
 524 }
 525 
 526 static int giu_remove(struct platform_device *pdev)
 527 {
 528         if (giu_base) {
 529                 giu_base = NULL;
 530         }
 531 
 532         return 0;
 533 }
 534 
 535 static struct platform_driver giu_device_driver = {
 536         .probe          = giu_probe,
 537         .remove         = giu_remove,
 538         .driver         = {
 539                 .name   = "GIU",
 540         },
 541 };
 542 
 543 module_platform_driver(giu_device_driver);

/* [<][>][^][v][top][bottom][index][help] */