gpio-siox.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2015-2018 Pengutronix, Uwe Kleine-König <kernel@pengutronix.de>
  4. */
  5. #include <linux/module.h>
  6. #include <linux/siox.h>
  7. #include <linux/gpio/driver.h>
  8. #include <linux/of.h>
  9. struct gpio_siox_ddata {
  10. struct gpio_chip gchip;
  11. struct irq_chip ichip;
  12. struct mutex lock;
  13. u8 setdata[1];
  14. u8 getdata[3];
  15. raw_spinlock_t irqlock;
  16. u32 irq_enable;
  17. u32 irq_status;
  18. u32 irq_type[20];
  19. };
  20. /*
  21. * Note that this callback only sets the value that is clocked out in the next
  22. * cycle.
  23. */
  24. static int gpio_siox_set_data(struct siox_device *sdevice, u8 status, u8 buf[])
  25. {
  26. struct gpio_siox_ddata *ddata = dev_get_drvdata(&sdevice->dev);
  27. mutex_lock(&ddata->lock);
  28. buf[0] = ddata->setdata[0];
  29. mutex_unlock(&ddata->lock);
  30. return 0;
  31. }
  32. static int gpio_siox_get_data(struct siox_device *sdevice, const u8 buf[])
  33. {
  34. struct gpio_siox_ddata *ddata = dev_get_drvdata(&sdevice->dev);
  35. size_t offset;
  36. u32 trigger;
  37. mutex_lock(&ddata->lock);
  38. raw_spin_lock_irq(&ddata->irqlock);
  39. for (offset = 0; offset < 12; ++offset) {
  40. unsigned int bitpos = 11 - offset;
  41. unsigned int gpiolevel = buf[bitpos / 8] & (1 << bitpos % 8);
  42. unsigned int prev_level =
  43. ddata->getdata[bitpos / 8] & (1 << (bitpos % 8));
  44. u32 irq_type = ddata->irq_type[offset];
  45. if (gpiolevel) {
  46. if ((irq_type & IRQ_TYPE_LEVEL_HIGH) ||
  47. ((irq_type & IRQ_TYPE_EDGE_RISING) && !prev_level))
  48. ddata->irq_status |= 1 << offset;
  49. } else {
  50. if ((irq_type & IRQ_TYPE_LEVEL_LOW) ||
  51. ((irq_type & IRQ_TYPE_EDGE_FALLING) && prev_level))
  52. ddata->irq_status |= 1 << offset;
  53. }
  54. }
  55. trigger = ddata->irq_status & ddata->irq_enable;
  56. raw_spin_unlock_irq(&ddata->irqlock);
  57. ddata->getdata[0] = buf[0];
  58. ddata->getdata[1] = buf[1];
  59. ddata->getdata[2] = buf[2];
  60. mutex_unlock(&ddata->lock);
  61. for (offset = 0; offset < 12; ++offset) {
  62. if (trigger & (1 << offset)) {
  63. struct irq_domain *irqdomain = ddata->gchip.irq.domain;
  64. unsigned int irq = irq_find_mapping(irqdomain, offset);
  65. /*
  66. * Conceptually handle_nested_irq should call the flow
  67. * handler of the irq chip. But it doesn't, so we have
  68. * to clean the irq_status here.
  69. */
  70. raw_spin_lock_irq(&ddata->irqlock);
  71. ddata->irq_status &= ~(1 << offset);
  72. raw_spin_unlock_irq(&ddata->irqlock);
  73. handle_nested_irq(irq);
  74. }
  75. }
  76. return 0;
  77. }
  78. static void gpio_siox_irq_ack(struct irq_data *d)
  79. {
  80. struct irq_chip *ic = irq_data_get_irq_chip(d);
  81. struct gpio_siox_ddata *ddata =
  82. container_of(ic, struct gpio_siox_ddata, ichip);
  83. raw_spin_lock(&ddata->irqlock);
  84. ddata->irq_status &= ~(1 << d->hwirq);
  85. raw_spin_unlock(&ddata->irqlock);
  86. }
  87. static void gpio_siox_irq_mask(struct irq_data *d)
  88. {
  89. struct irq_chip *ic = irq_data_get_irq_chip(d);
  90. struct gpio_siox_ddata *ddata =
  91. container_of(ic, struct gpio_siox_ddata, ichip);
  92. raw_spin_lock(&ddata->irqlock);
  93. ddata->irq_enable &= ~(1 << d->hwirq);
  94. raw_spin_unlock(&ddata->irqlock);
  95. }
  96. static void gpio_siox_irq_unmask(struct irq_data *d)
  97. {
  98. struct irq_chip *ic = irq_data_get_irq_chip(d);
  99. struct gpio_siox_ddata *ddata =
  100. container_of(ic, struct gpio_siox_ddata, ichip);
  101. raw_spin_lock(&ddata->irqlock);
  102. ddata->irq_enable |= 1 << d->hwirq;
  103. raw_spin_unlock(&ddata->irqlock);
  104. }
  105. static int gpio_siox_irq_set_type(struct irq_data *d, u32 type)
  106. {
  107. struct irq_chip *ic = irq_data_get_irq_chip(d);
  108. struct gpio_siox_ddata *ddata =
  109. container_of(ic, struct gpio_siox_ddata, ichip);
  110. raw_spin_lock(&ddata->irqlock);
  111. ddata->irq_type[d->hwirq] = type;
  112. raw_spin_unlock(&ddata->irqlock);
  113. return 0;
  114. }
  115. static int gpio_siox_get(struct gpio_chip *chip, unsigned int offset)
  116. {
  117. struct gpio_siox_ddata *ddata =
  118. container_of(chip, struct gpio_siox_ddata, gchip);
  119. int ret;
  120. mutex_lock(&ddata->lock);
  121. if (offset >= 12) {
  122. unsigned int bitpos = 19 - offset;
  123. ret = ddata->setdata[0] & (1 << bitpos);
  124. } else {
  125. unsigned int bitpos = 11 - offset;
  126. ret = ddata->getdata[bitpos / 8] & (1 << (bitpos % 8));
  127. }
  128. mutex_unlock(&ddata->lock);
  129. return ret;
  130. }
  131. static void gpio_siox_set(struct gpio_chip *chip,
  132. unsigned int offset, int value)
  133. {
  134. struct gpio_siox_ddata *ddata =
  135. container_of(chip, struct gpio_siox_ddata, gchip);
  136. u8 mask = 1 << (19 - offset);
  137. mutex_lock(&ddata->lock);
  138. if (value)
  139. ddata->setdata[0] |= mask;
  140. else
  141. ddata->setdata[0] &= ~mask;
  142. mutex_unlock(&ddata->lock);
  143. }
  144. static int gpio_siox_direction_input(struct gpio_chip *chip,
  145. unsigned int offset)
  146. {
  147. if (offset >= 12)
  148. return -EINVAL;
  149. return 0;
  150. }
  151. static int gpio_siox_direction_output(struct gpio_chip *chip,
  152. unsigned int offset, int value)
  153. {
  154. if (offset < 12)
  155. return -EINVAL;
  156. gpio_siox_set(chip, offset, value);
  157. return 0;
  158. }
  159. static int gpio_siox_get_direction(struct gpio_chip *chip, unsigned int offset)
  160. {
  161. if (offset < 12)
  162. return GPIO_LINE_DIRECTION_IN;
  163. else
  164. return GPIO_LINE_DIRECTION_OUT;
  165. }
  166. static int gpio_siox_probe(struct siox_device *sdevice)
  167. {
  168. struct gpio_siox_ddata *ddata;
  169. struct gpio_irq_chip *girq;
  170. struct device *dev = &sdevice->dev;
  171. int ret;
  172. ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
  173. if (!ddata)
  174. return -ENOMEM;
  175. dev_set_drvdata(dev, ddata);
  176. mutex_init(&ddata->lock);
  177. raw_spin_lock_init(&ddata->irqlock);
  178. ddata->gchip.base = -1;
  179. ddata->gchip.can_sleep = 1;
  180. ddata->gchip.parent = dev;
  181. ddata->gchip.owner = THIS_MODULE;
  182. ddata->gchip.get = gpio_siox_get;
  183. ddata->gchip.set = gpio_siox_set;
  184. ddata->gchip.direction_input = gpio_siox_direction_input;
  185. ddata->gchip.direction_output = gpio_siox_direction_output;
  186. ddata->gchip.get_direction = gpio_siox_get_direction;
  187. ddata->gchip.ngpio = 20;
  188. ddata->ichip.name = "siox-gpio";
  189. ddata->ichip.irq_ack = gpio_siox_irq_ack;
  190. ddata->ichip.irq_mask = gpio_siox_irq_mask;
  191. ddata->ichip.irq_unmask = gpio_siox_irq_unmask;
  192. ddata->ichip.irq_set_type = gpio_siox_irq_set_type;
  193. girq = &ddata->gchip.irq;
  194. girq->chip = &ddata->ichip;
  195. girq->default_type = IRQ_TYPE_NONE;
  196. girq->handler = handle_level_irq;
  197. girq->threaded = true;
  198. ret = devm_gpiochip_add_data(dev, &ddata->gchip, NULL);
  199. if (ret)
  200. dev_err(dev, "Failed to register gpio chip (%d)\n", ret);
  201. return ret;
  202. }
  203. static struct siox_driver gpio_siox_driver = {
  204. .probe = gpio_siox_probe,
  205. .set_data = gpio_siox_set_data,
  206. .get_data = gpio_siox_get_data,
  207. .driver = {
  208. .name = "gpio-siox",
  209. },
  210. };
  211. module_siox_driver(gpio_siox_driver);
  212. MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
  213. MODULE_DESCRIPTION("SIOX gpio driver");
  214. MODULE_LICENSE("GPL v2");