gpio.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * arch/sh/boards/mach-x3proto/gpio.c
  3. *
  4. * Renesas SH-X3 Prototype Baseboard GPIO Support.
  5. *
  6. * Copyright (C) 2010 Paul Mundt
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. */
  12. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13. #include <linux/init.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/gpio.h>
  16. #include <linux/irq.h>
  17. #include <linux/kernel.h>
  18. #include <linux/spinlock.h>
  19. #include <linux/io.h>
  20. #include <mach/ilsel.h>
  21. #include <mach/hardware.h>
  22. #define KEYCTLR 0xb81c0000
  23. #define KEYOUTR 0xb81c0002
  24. #define KEYDETR 0xb81c0004
  25. static DEFINE_SPINLOCK(x3proto_gpio_lock);
  26. static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, };
  27. static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
  28. {
  29. unsigned long flags;
  30. unsigned int data;
  31. spin_lock_irqsave(&x3proto_gpio_lock, flags);
  32. data = __raw_readw(KEYCTLR);
  33. data |= (1 << gpio);
  34. __raw_writew(data, KEYCTLR);
  35. spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
  36. return 0;
  37. }
  38. static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio)
  39. {
  40. return !!(__raw_readw(KEYDETR) & (1 << gpio));
  41. }
  42. static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
  43. {
  44. return x3proto_gpio_irq_map[gpio];
  45. }
  46. static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
  47. {
  48. struct irq_data *data = irq_get_irq_data(irq);
  49. struct irq_chip *chip = irq_data_get_irq_chip(data);
  50. unsigned long mask;
  51. int pin;
  52. chip->irq_mask_ack(data);
  53. mask = __raw_readw(KEYDETR);
  54. for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS)
  55. generic_handle_irq(x3proto_gpio_to_irq(NULL, pin));
  56. chip->irq_unmask(data);
  57. }
  58. struct gpio_chip x3proto_gpio_chip = {
  59. .label = "x3proto-gpio",
  60. .direction_input = x3proto_gpio_direction_input,
  61. .get = x3proto_gpio_get,
  62. .to_irq = x3proto_gpio_to_irq,
  63. .base = -1,
  64. .ngpio = NR_BASEBOARD_GPIOS,
  65. };
  66. int __init x3proto_gpio_setup(void)
  67. {
  68. int ilsel;
  69. int ret, i;
  70. ilsel = ilsel_enable(ILSEL_KEY);
  71. if (unlikely(ilsel < 0))
  72. return ilsel;
  73. ret = gpiochip_add(&x3proto_gpio_chip);
  74. if (unlikely(ret))
  75. goto err_gpio;
  76. for (i = 0; i < NR_BASEBOARD_GPIOS; i++) {
  77. unsigned long flags;
  78. int irq = create_irq();
  79. if (unlikely(irq < 0)) {
  80. ret = -EINVAL;
  81. goto err_irq;
  82. }
  83. spin_lock_irqsave(&x3proto_gpio_lock, flags);
  84. x3proto_gpio_irq_map[i] = irq;
  85. irq_set_chip_and_handler_name(irq, &dummy_irq_chip,
  86. handle_simple_irq, "gpio");
  87. spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
  88. }
  89. pr_info("registering '%s' support, handling GPIOs %u -> %u, "
  90. "bound to IRQ %u\n",
  91. x3proto_gpio_chip.label, x3proto_gpio_chip.base,
  92. x3proto_gpio_chip.base + x3proto_gpio_chip.ngpio,
  93. ilsel);
  94. irq_set_chained_handler(ilsel, x3proto_gpio_irq_handler);
  95. irq_set_irq_wake(ilsel, 1);
  96. return 0;
  97. err_irq:
  98. for (; i >= 0; --i)
  99. if (x3proto_gpio_irq_map[i])
  100. destroy_irq(x3proto_gpio_irq_map[i]);
  101. ret = gpiochip_remove(&x3proto_gpio_chip);
  102. if (unlikely(ret))
  103. pr_err("Failed deregistering GPIO\n");
  104. err_gpio:
  105. synchronize_irq(ilsel);
  106. ilsel_disable(ILSEL_KEY);
  107. return ret;
  108. }