rc5t583-irq.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Interrupt driver for RICOH583 power management chip.
  4. *
  5. * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
  6. * Author: Laxman dewangan <[email protected]>
  7. *
  8. * based on code
  9. * Copyright (C) 2011 RICOH COMPANY,LTD
  10. */
  11. #include <linux/interrupt.h>
  12. #include <linux/irq.h>
  13. #include <linux/i2c.h>
  14. #include <linux/mfd/rc5t583.h>
  15. enum int_type {
  16. SYS_INT = 0x1,
  17. DCDC_INT = 0x2,
  18. RTC_INT = 0x4,
  19. ADC_INT = 0x8,
  20. GPIO_INT = 0x10,
  21. };
  22. static int gpedge_add[] = {
  23. RC5T583_GPIO_GPEDGE2,
  24. RC5T583_GPIO_GPEDGE2
  25. };
  26. static int irq_en_add[] = {
  27. RC5T583_INT_EN_SYS1,
  28. RC5T583_INT_EN_SYS2,
  29. RC5T583_INT_EN_DCDC,
  30. RC5T583_INT_EN_RTC,
  31. RC5T583_INT_EN_ADC1,
  32. RC5T583_INT_EN_ADC2,
  33. RC5T583_INT_EN_ADC3,
  34. RC5T583_GPIO_EN_INT
  35. };
  36. static int irq_mon_add[] = {
  37. RC5T583_INT_MON_SYS1,
  38. RC5T583_INT_MON_SYS2,
  39. RC5T583_INT_MON_DCDC,
  40. RC5T583_INT_MON_RTC,
  41. RC5T583_INT_IR_ADCL,
  42. RC5T583_INT_IR_ADCH,
  43. RC5T583_INT_IR_ADCEND,
  44. RC5T583_INT_IR_GPIOF,
  45. RC5T583_INT_IR_GPIOR
  46. };
  47. static int irq_clr_add[] = {
  48. RC5T583_INT_IR_SYS1,
  49. RC5T583_INT_IR_SYS2,
  50. RC5T583_INT_IR_DCDC,
  51. RC5T583_INT_IR_RTC,
  52. RC5T583_INT_IR_ADCL,
  53. RC5T583_INT_IR_ADCH,
  54. RC5T583_INT_IR_ADCEND,
  55. RC5T583_INT_IR_GPIOF,
  56. RC5T583_INT_IR_GPIOR
  57. };
  58. static int main_int_type[] = {
  59. SYS_INT,
  60. SYS_INT,
  61. DCDC_INT,
  62. RTC_INT,
  63. ADC_INT,
  64. ADC_INT,
  65. ADC_INT,
  66. GPIO_INT,
  67. GPIO_INT,
  68. };
  69. struct rc5t583_irq_data {
  70. u8 int_type;
  71. u8 master_bit;
  72. u8 int_en_bit;
  73. u8 mask_reg_index;
  74. int grp_index;
  75. };
  76. #define RC5T583_IRQ(_int_type, _master_bit, _grp_index, \
  77. _int_bit, _mask_ind) \
  78. { \
  79. .int_type = _int_type, \
  80. .master_bit = _master_bit, \
  81. .grp_index = _grp_index, \
  82. .int_en_bit = _int_bit, \
  83. .mask_reg_index = _mask_ind, \
  84. }
  85. static const struct rc5t583_irq_data rc5t583_irqs[RC5T583_MAX_IRQS] = {
  86. [RC5T583_IRQ_ONKEY] = RC5T583_IRQ(SYS_INT, 0, 0, 0, 0),
  87. [RC5T583_IRQ_ACOK] = RC5T583_IRQ(SYS_INT, 0, 1, 1, 0),
  88. [RC5T583_IRQ_LIDOPEN] = RC5T583_IRQ(SYS_INT, 0, 2, 2, 0),
  89. [RC5T583_IRQ_PREOT] = RC5T583_IRQ(SYS_INT, 0, 3, 3, 0),
  90. [RC5T583_IRQ_CLKSTP] = RC5T583_IRQ(SYS_INT, 0, 4, 4, 0),
  91. [RC5T583_IRQ_ONKEY_OFF] = RC5T583_IRQ(SYS_INT, 0, 5, 5, 0),
  92. [RC5T583_IRQ_WD] = RC5T583_IRQ(SYS_INT, 0, 7, 7, 0),
  93. [RC5T583_IRQ_EN_PWRREQ1] = RC5T583_IRQ(SYS_INT, 0, 8, 0, 1),
  94. [RC5T583_IRQ_EN_PWRREQ2] = RC5T583_IRQ(SYS_INT, 0, 9, 1, 1),
  95. [RC5T583_IRQ_PRE_VINDET] = RC5T583_IRQ(SYS_INT, 0, 10, 2, 1),
  96. [RC5T583_IRQ_DC0LIM] = RC5T583_IRQ(DCDC_INT, 1, 0, 0, 2),
  97. [RC5T583_IRQ_DC1LIM] = RC5T583_IRQ(DCDC_INT, 1, 1, 1, 2),
  98. [RC5T583_IRQ_DC2LIM] = RC5T583_IRQ(DCDC_INT, 1, 2, 2, 2),
  99. [RC5T583_IRQ_DC3LIM] = RC5T583_IRQ(DCDC_INT, 1, 3, 3, 2),
  100. [RC5T583_IRQ_CTC] = RC5T583_IRQ(RTC_INT, 2, 0, 0, 3),
  101. [RC5T583_IRQ_YALE] = RC5T583_IRQ(RTC_INT, 2, 5, 5, 3),
  102. [RC5T583_IRQ_DALE] = RC5T583_IRQ(RTC_INT, 2, 6, 6, 3),
  103. [RC5T583_IRQ_WALE] = RC5T583_IRQ(RTC_INT, 2, 7, 7, 3),
  104. [RC5T583_IRQ_AIN1L] = RC5T583_IRQ(ADC_INT, 3, 0, 0, 4),
  105. [RC5T583_IRQ_AIN2L] = RC5T583_IRQ(ADC_INT, 3, 1, 1, 4),
  106. [RC5T583_IRQ_AIN3L] = RC5T583_IRQ(ADC_INT, 3, 2, 2, 4),
  107. [RC5T583_IRQ_VBATL] = RC5T583_IRQ(ADC_INT, 3, 3, 3, 4),
  108. [RC5T583_IRQ_VIN3L] = RC5T583_IRQ(ADC_INT, 3, 4, 4, 4),
  109. [RC5T583_IRQ_VIN8L] = RC5T583_IRQ(ADC_INT, 3, 5, 5, 4),
  110. [RC5T583_IRQ_AIN1H] = RC5T583_IRQ(ADC_INT, 3, 6, 0, 5),
  111. [RC5T583_IRQ_AIN2H] = RC5T583_IRQ(ADC_INT, 3, 7, 1, 5),
  112. [RC5T583_IRQ_AIN3H] = RC5T583_IRQ(ADC_INT, 3, 8, 2, 5),
  113. [RC5T583_IRQ_VBATH] = RC5T583_IRQ(ADC_INT, 3, 9, 3, 5),
  114. [RC5T583_IRQ_VIN3H] = RC5T583_IRQ(ADC_INT, 3, 10, 4, 5),
  115. [RC5T583_IRQ_VIN8H] = RC5T583_IRQ(ADC_INT, 3, 11, 5, 5),
  116. [RC5T583_IRQ_ADCEND] = RC5T583_IRQ(ADC_INT, 3, 12, 0, 6),
  117. [RC5T583_IRQ_GPIO0] = RC5T583_IRQ(GPIO_INT, 4, 0, 0, 7),
  118. [RC5T583_IRQ_GPIO1] = RC5T583_IRQ(GPIO_INT, 4, 1, 1, 7),
  119. [RC5T583_IRQ_GPIO2] = RC5T583_IRQ(GPIO_INT, 4, 2, 2, 7),
  120. [RC5T583_IRQ_GPIO3] = RC5T583_IRQ(GPIO_INT, 4, 3, 3, 7),
  121. [RC5T583_IRQ_GPIO4] = RC5T583_IRQ(GPIO_INT, 4, 4, 4, 7),
  122. [RC5T583_IRQ_GPIO5] = RC5T583_IRQ(GPIO_INT, 4, 5, 5, 7),
  123. [RC5T583_IRQ_GPIO6] = RC5T583_IRQ(GPIO_INT, 4, 6, 6, 7),
  124. [RC5T583_IRQ_GPIO7] = RC5T583_IRQ(GPIO_INT, 4, 7, 7, 7),
  125. };
  126. static void rc5t583_irq_lock(struct irq_data *irq_data)
  127. {
  128. struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
  129. mutex_lock(&rc5t583->irq_lock);
  130. }
  131. static void rc5t583_irq_unmask(struct irq_data *irq_data)
  132. {
  133. struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
  134. unsigned int __irq = irq_data->irq - rc5t583->irq_base;
  135. const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
  136. rc5t583->group_irq_en[data->grp_index] |= 1 << data->grp_index;
  137. rc5t583->intc_inten_reg |= 1 << data->master_bit;
  138. rc5t583->irq_en_reg[data->mask_reg_index] |= 1 << data->int_en_bit;
  139. }
  140. static void rc5t583_irq_mask(struct irq_data *irq_data)
  141. {
  142. struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
  143. unsigned int __irq = irq_data->irq - rc5t583->irq_base;
  144. const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
  145. rc5t583->group_irq_en[data->grp_index] &= ~(1 << data->grp_index);
  146. if (!rc5t583->group_irq_en[data->grp_index])
  147. rc5t583->intc_inten_reg &= ~(1 << data->master_bit);
  148. rc5t583->irq_en_reg[data->mask_reg_index] &= ~(1 << data->int_en_bit);
  149. }
  150. static int rc5t583_irq_set_type(struct irq_data *irq_data, unsigned int type)
  151. {
  152. struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
  153. unsigned int __irq = irq_data->irq - rc5t583->irq_base;
  154. const struct rc5t583_irq_data *data = &rc5t583_irqs[__irq];
  155. int val = 0;
  156. int gpedge_index;
  157. int gpedge_bit_pos;
  158. /* Supporting only trigger level inetrrupt */
  159. if ((data->int_type & GPIO_INT) && (type & IRQ_TYPE_EDGE_BOTH)) {
  160. gpedge_index = data->int_en_bit / 4;
  161. gpedge_bit_pos = data->int_en_bit % 4;
  162. if (type & IRQ_TYPE_EDGE_FALLING)
  163. val |= 0x2;
  164. if (type & IRQ_TYPE_EDGE_RISING)
  165. val |= 0x1;
  166. rc5t583->gpedge_reg[gpedge_index] &= ~(3 << gpedge_bit_pos);
  167. rc5t583->gpedge_reg[gpedge_index] |= (val << gpedge_bit_pos);
  168. rc5t583_irq_unmask(irq_data);
  169. return 0;
  170. }
  171. return -EINVAL;
  172. }
  173. static void rc5t583_irq_sync_unlock(struct irq_data *irq_data)
  174. {
  175. struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
  176. int i;
  177. int ret;
  178. for (i = 0; i < ARRAY_SIZE(rc5t583->gpedge_reg); i++) {
  179. ret = rc5t583_write(rc5t583->dev, gpedge_add[i],
  180. rc5t583->gpedge_reg[i]);
  181. if (ret < 0)
  182. dev_warn(rc5t583->dev,
  183. "Error in writing reg 0x%02x error: %d\n",
  184. gpedge_add[i], ret);
  185. }
  186. for (i = 0; i < ARRAY_SIZE(rc5t583->irq_en_reg); i++) {
  187. ret = rc5t583_write(rc5t583->dev, irq_en_add[i],
  188. rc5t583->irq_en_reg[i]);
  189. if (ret < 0)
  190. dev_warn(rc5t583->dev,
  191. "Error in writing reg 0x%02x error: %d\n",
  192. irq_en_add[i], ret);
  193. }
  194. ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN,
  195. rc5t583->intc_inten_reg);
  196. if (ret < 0)
  197. dev_warn(rc5t583->dev,
  198. "Error in writing reg 0x%02x error: %d\n",
  199. RC5T583_INTC_INTEN, ret);
  200. mutex_unlock(&rc5t583->irq_lock);
  201. }
  202. #ifdef CONFIG_PM_SLEEP
  203. static int rc5t583_irq_set_wake(struct irq_data *irq_data, unsigned int on)
  204. {
  205. struct rc5t583 *rc5t583 = irq_data_get_irq_chip_data(irq_data);
  206. return irq_set_irq_wake(rc5t583->chip_irq, on);
  207. }
  208. #else
  209. #define rc5t583_irq_set_wake NULL
  210. #endif
  211. static irqreturn_t rc5t583_irq(int irq, void *data)
  212. {
  213. struct rc5t583 *rc5t583 = data;
  214. uint8_t int_sts[RC5T583_MAX_INTERRUPT_MASK_REGS];
  215. uint8_t master_int = 0;
  216. int i;
  217. int ret;
  218. unsigned int rtc_int_sts = 0;
  219. /* Clear the status */
  220. for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++)
  221. int_sts[i] = 0;
  222. ret = rc5t583_read(rc5t583->dev, RC5T583_INTC_INTMON, &master_int);
  223. if (ret < 0) {
  224. dev_err(rc5t583->dev,
  225. "Error in reading reg 0x%02x error: %d\n",
  226. RC5T583_INTC_INTMON, ret);
  227. return IRQ_HANDLED;
  228. }
  229. for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; ++i) {
  230. if (!(master_int & main_int_type[i]))
  231. continue;
  232. ret = rc5t583_read(rc5t583->dev, irq_mon_add[i], &int_sts[i]);
  233. if (ret < 0) {
  234. dev_warn(rc5t583->dev,
  235. "Error in reading reg 0x%02x error: %d\n",
  236. irq_mon_add[i], ret);
  237. int_sts[i] = 0;
  238. continue;
  239. }
  240. if (main_int_type[i] & RTC_INT) {
  241. rtc_int_sts = 0;
  242. if (int_sts[i] & 0x1)
  243. rtc_int_sts |= BIT(6);
  244. if (int_sts[i] & 0x2)
  245. rtc_int_sts |= BIT(7);
  246. if (int_sts[i] & 0x4)
  247. rtc_int_sts |= BIT(0);
  248. if (int_sts[i] & 0x8)
  249. rtc_int_sts |= BIT(5);
  250. }
  251. ret = rc5t583_write(rc5t583->dev, irq_clr_add[i],
  252. ~int_sts[i]);
  253. if (ret < 0)
  254. dev_warn(rc5t583->dev,
  255. "Error in reading reg 0x%02x error: %d\n",
  256. irq_clr_add[i], ret);
  257. if (main_int_type[i] & RTC_INT)
  258. int_sts[i] = rtc_int_sts;
  259. }
  260. /* Merge gpio interrupts for rising and falling case*/
  261. int_sts[7] |= int_sts[8];
  262. /* Call interrupt handler if enabled */
  263. for (i = 0; i < RC5T583_MAX_IRQS; ++i) {
  264. const struct rc5t583_irq_data *data = &rc5t583_irqs[i];
  265. if ((int_sts[data->mask_reg_index] & (1 << data->int_en_bit)) &&
  266. (rc5t583->group_irq_en[data->master_bit] &
  267. (1 << data->grp_index)))
  268. handle_nested_irq(rc5t583->irq_base + i);
  269. }
  270. return IRQ_HANDLED;
  271. }
  272. static struct irq_chip rc5t583_irq_chip = {
  273. .name = "rc5t583-irq",
  274. .irq_mask = rc5t583_irq_mask,
  275. .irq_unmask = rc5t583_irq_unmask,
  276. .irq_bus_lock = rc5t583_irq_lock,
  277. .irq_bus_sync_unlock = rc5t583_irq_sync_unlock,
  278. .irq_set_type = rc5t583_irq_set_type,
  279. .irq_set_wake = rc5t583_irq_set_wake,
  280. };
  281. int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base)
  282. {
  283. int i, ret;
  284. if (!irq_base) {
  285. dev_warn(rc5t583->dev, "No interrupt support on IRQ base\n");
  286. return -EINVAL;
  287. }
  288. mutex_init(&rc5t583->irq_lock);
  289. /* Initailize all int register to 0 */
  290. for (i = 0; i < RC5T583_MAX_INTERRUPT_EN_REGS; i++) {
  291. ret = rc5t583_write(rc5t583->dev, irq_en_add[i],
  292. rc5t583->irq_en_reg[i]);
  293. if (ret < 0)
  294. dev_warn(rc5t583->dev,
  295. "Error in writing reg 0x%02x error: %d\n",
  296. irq_en_add[i], ret);
  297. }
  298. for (i = 0; i < RC5T583_MAX_GPEDGE_REG; i++) {
  299. ret = rc5t583_write(rc5t583->dev, gpedge_add[i],
  300. rc5t583->gpedge_reg[i]);
  301. if (ret < 0)
  302. dev_warn(rc5t583->dev,
  303. "Error in writing reg 0x%02x error: %d\n",
  304. gpedge_add[i], ret);
  305. }
  306. ret = rc5t583_write(rc5t583->dev, RC5T583_INTC_INTEN, 0x0);
  307. if (ret < 0)
  308. dev_warn(rc5t583->dev,
  309. "Error in writing reg 0x%02x error: %d\n",
  310. RC5T583_INTC_INTEN, ret);
  311. /* Clear all interrupts in case they woke up active. */
  312. for (i = 0; i < RC5T583_MAX_INTERRUPT_MASK_REGS; i++) {
  313. ret = rc5t583_write(rc5t583->dev, irq_clr_add[i], 0);
  314. if (ret < 0)
  315. dev_warn(rc5t583->dev,
  316. "Error in writing reg 0x%02x error: %d\n",
  317. irq_clr_add[i], ret);
  318. }
  319. rc5t583->irq_base = irq_base;
  320. rc5t583->chip_irq = irq;
  321. for (i = 0; i < RC5T583_MAX_IRQS; i++) {
  322. int __irq = i + rc5t583->irq_base;
  323. irq_set_chip_data(__irq, rc5t583);
  324. irq_set_chip_and_handler(__irq, &rc5t583_irq_chip,
  325. handle_simple_irq);
  326. irq_set_nested_thread(__irq, 1);
  327. irq_clear_status_flags(__irq, IRQ_NOREQUEST);
  328. }
  329. ret = devm_request_threaded_irq(rc5t583->dev, irq, NULL, rc5t583_irq,
  330. IRQF_ONESHOT, "rc5t583", rc5t583);
  331. if (ret < 0)
  332. dev_err(rc5t583->dev,
  333. "Error in registering interrupt error: %d\n", ret);
  334. return ret;
  335. }