da9063-irq.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /* Interrupt support for Dialog DA9063
  3. *
  4. * Copyright 2012 Dialog Semiconductor Ltd.
  5. * Copyright 2013 Philipp Zabel, Pengutronix
  6. *
  7. * Author: Michal Hajduk, Dialog Semiconductor
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/irq.h>
  12. #include <linux/mfd/core.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/regmap.h>
  15. #include <linux/mfd/da9063/core.h>
  16. #define DA9063_REG_EVENT_A_OFFSET 0
  17. #define DA9063_REG_EVENT_B_OFFSET 1
  18. #define DA9063_REG_EVENT_C_OFFSET 2
  19. #define DA9063_REG_EVENT_D_OFFSET 3
  20. static const struct regmap_irq da9063_irqs[] = {
  21. /* DA9063 event A register */
  22. REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
  23. DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
  24. REGMAP_IRQ_REG(DA9063_IRQ_ALARM,
  25. DA9063_REG_EVENT_A_OFFSET, DA9063_M_ALARM),
  26. REGMAP_IRQ_REG(DA9063_IRQ_TICK,
  27. DA9063_REG_EVENT_A_OFFSET, DA9063_M_TICK),
  28. REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
  29. DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
  30. REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
  31. DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
  32. /* DA9063 event B register */
  33. REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
  34. DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
  35. REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
  36. DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
  37. REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
  38. DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
  39. REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
  40. DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
  41. REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
  42. DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
  43. REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
  44. DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
  45. REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
  46. DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
  47. REGMAP_IRQ_REG(DA9063_IRQ_WARN,
  48. DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
  49. /* DA9063 event C register */
  50. REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
  51. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
  52. REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
  53. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
  54. REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
  55. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
  56. REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
  57. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
  58. REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
  59. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
  60. REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
  61. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
  62. REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
  63. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
  64. REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
  65. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
  66. /* DA9063 event D register */
  67. REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
  68. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
  69. REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
  70. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
  71. REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
  72. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
  73. REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
  74. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
  75. REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
  76. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
  77. REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
  78. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
  79. REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
  80. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
  81. REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
  82. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
  83. };
  84. static const struct regmap_irq_chip da9063_irq_chip = {
  85. .name = "da9063-irq",
  86. .irqs = da9063_irqs,
  87. .num_irqs = ARRAY_SIZE(da9063_irqs),
  88. .num_regs = 4,
  89. .status_base = DA9063_REG_EVENT_A,
  90. .mask_base = DA9063_REG_IRQ_MASK_A,
  91. .ack_base = DA9063_REG_EVENT_A,
  92. .init_ack_masked = true,
  93. };
  94. static const struct regmap_irq da9063l_irqs[] = {
  95. /* DA9063 event A register */
  96. REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
  97. DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
  98. REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
  99. DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
  100. REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
  101. DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
  102. /* DA9063 event B register */
  103. REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
  104. DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
  105. REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
  106. DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
  107. REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
  108. DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
  109. REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
  110. DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
  111. REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
  112. DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
  113. REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
  114. DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
  115. REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
  116. DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
  117. REGMAP_IRQ_REG(DA9063_IRQ_WARN,
  118. DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
  119. /* DA9063 event C register */
  120. REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
  121. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
  122. REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
  123. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
  124. REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
  125. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
  126. REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
  127. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
  128. REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
  129. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
  130. REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
  131. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
  132. REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
  133. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
  134. REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
  135. DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
  136. /* DA9063 event D register */
  137. REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
  138. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
  139. REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
  140. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
  141. REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
  142. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
  143. REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
  144. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
  145. REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
  146. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
  147. REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
  148. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
  149. REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
  150. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
  151. REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
  152. DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
  153. };
  154. static const struct regmap_irq_chip da9063l_irq_chip = {
  155. .name = "da9063l-irq",
  156. .irqs = da9063l_irqs,
  157. .num_irqs = ARRAY_SIZE(da9063l_irqs),
  158. .num_regs = 4,
  159. .status_base = DA9063_REG_EVENT_A,
  160. .mask_base = DA9063_REG_IRQ_MASK_A,
  161. .ack_base = DA9063_REG_EVENT_A,
  162. .init_ack_masked = true,
  163. };
  164. int da9063_irq_init(struct da9063 *da9063)
  165. {
  166. const struct regmap_irq_chip *irq_chip;
  167. int ret;
  168. if (!da9063->chip_irq) {
  169. dev_err(da9063->dev, "No IRQ configured\n");
  170. return -EINVAL;
  171. }
  172. if (da9063->type == PMIC_TYPE_DA9063)
  173. irq_chip = &da9063_irq_chip;
  174. else
  175. irq_chip = &da9063l_irq_chip;
  176. ret = devm_regmap_add_irq_chip(da9063->dev, da9063->regmap,
  177. da9063->chip_irq,
  178. IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
  179. da9063->irq_base, irq_chip, &da9063->regmap_irq);
  180. if (ret) {
  181. dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n",
  182. da9063->chip_irq, ret);
  183. return ret;
  184. }
  185. return 0;
  186. }