da9063-irq.c 7.1 KB

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