driver_gpio.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * Broadcom specific AMBA
  3. * GPIO driver
  4. *
  5. * Copyright 2011, Broadcom Corporation
  6. * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
  7. *
  8. * Licensed under the GNU/GPL. See COPYING for details.
  9. */
  10. #include <linux/gpio.h>
  11. #include <linux/irq.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/irqdomain.h>
  14. #include <linux/export.h>
  15. #include <linux/bcma/bcma.h>
  16. #include "bcma_private.h"
  17. #define BCMA_GPIO_MAX_PINS 32
  18. static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip)
  19. {
  20. return container_of(chip, struct bcma_drv_cc, gpio);
  21. }
  22. static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
  23. {
  24. struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
  25. return !!bcma_chipco_gpio_in(cc, 1 << gpio);
  26. }
  27. static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
  28. int value)
  29. {
  30. struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
  31. bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
  32. }
  33. static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
  34. {
  35. struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
  36. bcma_chipco_gpio_outen(cc, 1 << gpio, 0);
  37. return 0;
  38. }
  39. static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
  40. int value)
  41. {
  42. struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
  43. bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio);
  44. bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0);
  45. return 0;
  46. }
  47. static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio)
  48. {
  49. struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
  50. bcma_chipco_gpio_control(cc, 1 << gpio, 0);
  51. /* clear pulldown */
  52. bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0);
  53. /* Set pullup */
  54. bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio);
  55. return 0;
  56. }
  57. static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
  58. {
  59. struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
  60. /* clear pullup */
  61. bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
  62. }
  63. #if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X)
  64. static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
  65. {
  66. struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
  67. if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
  68. return irq_find_mapping(cc->irq_domain, gpio);
  69. else
  70. return -EINVAL;
  71. }
  72. static void bcma_gpio_irq_unmask(struct irq_data *d)
  73. {
  74. struct bcma_drv_cc *cc = irq_data_get_irq_chip_data(d);
  75. int gpio = irqd_to_hwirq(d);
  76. u32 val = bcma_chipco_gpio_in(cc, BIT(gpio));
  77. bcma_chipco_gpio_polarity(cc, BIT(gpio), val);
  78. bcma_chipco_gpio_intmask(cc, BIT(gpio), BIT(gpio));
  79. }
  80. static void bcma_gpio_irq_mask(struct irq_data *d)
  81. {
  82. struct bcma_drv_cc *cc = irq_data_get_irq_chip_data(d);
  83. int gpio = irqd_to_hwirq(d);
  84. bcma_chipco_gpio_intmask(cc, BIT(gpio), 0);
  85. }
  86. static struct irq_chip bcma_gpio_irq_chip = {
  87. .name = "BCMA-GPIO",
  88. .irq_mask = bcma_gpio_irq_mask,
  89. .irq_unmask = bcma_gpio_irq_unmask,
  90. };
  91. static irqreturn_t bcma_gpio_irq_handler(int irq, void *dev_id)
  92. {
  93. struct bcma_drv_cc *cc = dev_id;
  94. u32 val = bcma_cc_read32(cc, BCMA_CC_GPIOIN);
  95. u32 mask = bcma_cc_read32(cc, BCMA_CC_GPIOIRQ);
  96. u32 pol = bcma_cc_read32(cc, BCMA_CC_GPIOPOL);
  97. unsigned long irqs = (val ^ pol) & mask;
  98. int gpio;
  99. if (!irqs)
  100. return IRQ_NONE;
  101. for_each_set_bit(gpio, &irqs, cc->gpio.ngpio)
  102. generic_handle_irq(bcma_gpio_to_irq(&cc->gpio, gpio));
  103. bcma_chipco_gpio_polarity(cc, irqs, val & irqs);
  104. return IRQ_HANDLED;
  105. }
  106. static int bcma_gpio_irq_domain_init(struct bcma_drv_cc *cc)
  107. {
  108. struct gpio_chip *chip = &cc->gpio;
  109. int gpio, hwirq, err;
  110. if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC)
  111. return 0;
  112. cc->irq_domain = irq_domain_add_linear(NULL, chip->ngpio,
  113. &irq_domain_simple_ops, cc);
  114. if (!cc->irq_domain) {
  115. err = -ENODEV;
  116. goto err_irq_domain;
  117. }
  118. for (gpio = 0; gpio < chip->ngpio; gpio++) {
  119. int irq = irq_create_mapping(cc->irq_domain, gpio);
  120. irq_set_chip_data(irq, cc);
  121. irq_set_chip_and_handler(irq, &bcma_gpio_irq_chip,
  122. handle_simple_irq);
  123. }
  124. hwirq = bcma_core_irq(cc->core, 0);
  125. err = request_irq(hwirq, bcma_gpio_irq_handler, IRQF_SHARED, "gpio",
  126. cc);
  127. if (err)
  128. goto err_req_irq;
  129. bcma_chipco_gpio_intmask(cc, ~0, 0);
  130. bcma_cc_set32(cc, BCMA_CC_IRQMASK, BCMA_CC_IRQ_GPIO);
  131. return 0;
  132. err_req_irq:
  133. for (gpio = 0; gpio < chip->ngpio; gpio++) {
  134. int irq = irq_find_mapping(cc->irq_domain, gpio);
  135. irq_dispose_mapping(irq);
  136. }
  137. irq_domain_remove(cc->irq_domain);
  138. err_irq_domain:
  139. return err;
  140. }
  141. static void bcma_gpio_irq_domain_exit(struct bcma_drv_cc *cc)
  142. {
  143. struct gpio_chip *chip = &cc->gpio;
  144. int gpio;
  145. if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC)
  146. return;
  147. bcma_cc_mask32(cc, BCMA_CC_IRQMASK, ~BCMA_CC_IRQ_GPIO);
  148. free_irq(bcma_core_irq(cc->core, 0), cc);
  149. for (gpio = 0; gpio < chip->ngpio; gpio++) {
  150. int irq = irq_find_mapping(cc->irq_domain, gpio);
  151. irq_dispose_mapping(irq);
  152. }
  153. irq_domain_remove(cc->irq_domain);
  154. }
  155. #else
  156. static int bcma_gpio_irq_domain_init(struct bcma_drv_cc *cc)
  157. {
  158. return 0;
  159. }
  160. static void bcma_gpio_irq_domain_exit(struct bcma_drv_cc *cc)
  161. {
  162. }
  163. #endif
  164. int bcma_gpio_init(struct bcma_drv_cc *cc)
  165. {
  166. struct bcma_bus *bus = cc->core->bus;
  167. struct gpio_chip *chip = &cc->gpio;
  168. int err;
  169. chip->label = "bcma_gpio";
  170. chip->owner = THIS_MODULE;
  171. chip->request = bcma_gpio_request;
  172. chip->free = bcma_gpio_free;
  173. chip->get = bcma_gpio_get_value;
  174. chip->set = bcma_gpio_set_value;
  175. chip->direction_input = bcma_gpio_direction_input;
  176. chip->direction_output = bcma_gpio_direction_output;
  177. #if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X)
  178. chip->to_irq = bcma_gpio_to_irq;
  179. #endif
  180. #if IS_BUILTIN(CONFIG_OF)
  181. if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
  182. chip->of_node = cc->core->dev.of_node;
  183. #endif
  184. switch (bus->chipinfo.id) {
  185. case BCMA_CHIP_ID_BCM4707:
  186. case BCMA_CHIP_ID_BCM5357:
  187. case BCMA_CHIP_ID_BCM53572:
  188. chip->ngpio = 32;
  189. break;
  190. default:
  191. chip->ngpio = 16;
  192. }
  193. /*
  194. * Register SoC GPIO devices with absolute GPIO pin base.
  195. * On MIPS, we don't have Device Tree and we can't use relative (per chip)
  196. * GPIO numbers.
  197. * On some ARM devices, user space may want to access some system GPIO
  198. * pins directly, which is easier to do with a predictable GPIO base.
  199. */
  200. if (IS_BUILTIN(CONFIG_BCM47XX) ||
  201. cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
  202. chip->base = bus->num * BCMA_GPIO_MAX_PINS;
  203. else
  204. chip->base = -1;
  205. err = bcma_gpio_irq_domain_init(cc);
  206. if (err)
  207. return err;
  208. err = gpiochip_add(chip);
  209. if (err) {
  210. bcma_gpio_irq_domain_exit(cc);
  211. return err;
  212. }
  213. return 0;
  214. }
  215. int bcma_gpio_unregister(struct bcma_drv_cc *cc)
  216. {
  217. bcma_gpio_irq_domain_exit(cc);
  218. gpiochip_remove(&cc->gpio);
  219. return 0;
  220. }