gpio.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * arch/sh/boards/mach-x3proto/gpio.c
  3. *
  4. * Renesas SH-X3 Prototype Baseboard GPIO Support.
  5. *
  6. * Copyright (C) 2010 - 2012 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/driver.h>
  16. #include <linux/irq.h>
  17. #include <linux/kernel.h>
  18. #include <linux/spinlock.h>
  19. #include <linux/irqdomain.h>
  20. #include <linux/io.h>
  21. #include <mach/ilsel.h>
  22. #include <mach/hardware.h>
  23. #define KEYCTLR 0xb81c0000
  24. #define KEYOUTR 0xb81c0002
  25. #define KEYDETR 0xb81c0004
  26. static DEFINE_SPINLOCK(x3proto_gpio_lock);
  27. static struct irq_domain *x3proto_irq_domain;
  28. static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
  29. {
  30. unsigned long flags;
  31. unsigned int data;
  32. spin_lock_irqsave(&x3proto_gpio_lock, flags);
  33. data = __raw_readw(KEYCTLR);
  34. data |= (1 << gpio);
  35. __raw_writew(data, KEYCTLR);
  36. spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
  37. return 0;
  38. }
  39. static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio)
  40. {
  41. return !!(__raw_readw(KEYDETR) & (1 << gpio));
  42. }
  43. static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
  44. {
  45. int virq;
  46. if (gpio < chip->ngpio)
  47. virq = irq_create_mapping(x3proto_irq_domain, gpio);
  48. else
  49. virq = -ENXIO;
  50. return virq;
  51. }
  52. static void x3proto_gpio_irq_handler(struct irq_desc *desc)
  53. {
  54. struct irq_data *data = irq_desc_get_irq_data(desc);
  55. struct irq_chip *chip = irq_data_get_irq_chip(data);
  56. unsigned long mask;
  57. int pin;
  58. chip->irq_mask_ack(data);
  59. mask = __raw_readw(KEYDETR);
  60. for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS)
  61. generic_handle_irq(irq_linear_revmap(x3proto_irq_domain, pin));
  62. chip->irq_unmask(data);
  63. }
  64. struct gpio_chip x3proto_gpio_chip = {
  65. .label = "x3proto-gpio",
  66. .direction_input = x3proto_gpio_direction_input,
  67. .get = x3proto_gpio_get,
  68. .to_irq = x3proto_gpio_to_irq,
  69. .base = -1,
  70. .ngpio = NR_BASEBOARD_GPIOS,
  71. };
  72. static int x3proto_gpio_irq_map(struct irq_domain *domain, unsigned int virq,
  73. irq_hw_number_t hwirq)
  74. {
  75. irq_set_chip_and_handler_name(virq, &dummy_irq_chip, handle_simple_irq,
  76. "gpio");
  77. return 0;
  78. }
  79. static struct irq_domain_ops x3proto_gpio_irq_ops = {
  80. .map = x3proto_gpio_irq_map,
  81. .xlate = irq_domain_xlate_twocell,
  82. };
  83. int __init x3proto_gpio_setup(void)
  84. {
  85. int ilsel, ret;
  86. ilsel = ilsel_enable(ILSEL_KEY);
  87. if (unlikely(ilsel < 0))
  88. return ilsel;
  89. ret = gpiochip_add_data(&x3proto_gpio_chip, NULL);
  90. if (unlikely(ret))
  91. goto err_gpio;
  92. x3proto_irq_domain = irq_domain_add_linear(NULL, NR_BASEBOARD_GPIOS,
  93. &x3proto_gpio_irq_ops, NULL);
  94. if (unlikely(!x3proto_irq_domain))
  95. goto err_irq;
  96. pr_info("registering '%s' support, handling GPIOs %u -> %u, "
  97. "bound to IRQ %u\n",
  98. x3proto_gpio_chip.label, x3proto_gpio_chip.base,
  99. x3proto_gpio_chip.base + x3proto_gpio_chip.ngpio,
  100. ilsel);
  101. irq_set_chained_handler(ilsel, x3proto_gpio_irq_handler);
  102. irq_set_irq_wake(ilsel, 1);
  103. return 0;
  104. err_irq:
  105. gpiochip_remove(&x3proto_gpio_chip);
  106. ret = 0;
  107. err_gpio:
  108. synchronize_irq(ilsel);
  109. ilsel_disable(ILSEL_KEY);
  110. return ret;
  111. }