wm831x-irq.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. /*
  2. * wm831x-irq.c -- Interrupt controller support for Wolfson WM831x PMICs
  3. *
  4. * Copyright 2009 Wolfson Microelectronics PLC.
  5. *
  6. * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  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/i2c.h>
  17. #include <linux/irq.h>
  18. #include <linux/mfd/core.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/mfd/wm831x/core.h>
  21. #include <linux/mfd/wm831x/pdata.h>
  22. #include <linux/mfd/wm831x/irq.h>
  23. #include <linux/delay.h>
  24. /*
  25. * Since generic IRQs don't currently support interrupt controllers on
  26. * interrupt driven buses we don't use genirq but instead provide an
  27. * interface that looks very much like the standard ones. This leads
  28. * to some bodges, including storing interrupt handler information in
  29. * the static irq_data table we use to look up the data for individual
  30. * interrupts, but hopefully won't last too long.
  31. */
  32. struct wm831x_irq_data {
  33. int primary;
  34. int reg;
  35. int mask;
  36. irq_handler_t handler;
  37. void *handler_data;
  38. };
  39. static struct wm831x_irq_data wm831x_irqs[] = {
  40. [WM831X_IRQ_TEMP_THW] = {
  41. .primary = WM831X_TEMP_INT,
  42. .reg = 1,
  43. .mask = WM831X_TEMP_THW_EINT,
  44. },
  45. [WM831X_IRQ_GPIO_1] = {
  46. .primary = WM831X_GP_INT,
  47. .reg = 5,
  48. .mask = WM831X_GP1_EINT,
  49. },
  50. [WM831X_IRQ_GPIO_2] = {
  51. .primary = WM831X_GP_INT,
  52. .reg = 5,
  53. .mask = WM831X_GP2_EINT,
  54. },
  55. [WM831X_IRQ_GPIO_3] = {
  56. .primary = WM831X_GP_INT,
  57. .reg = 5,
  58. .mask = WM831X_GP3_EINT,
  59. },
  60. [WM831X_IRQ_GPIO_4] = {
  61. .primary = WM831X_GP_INT,
  62. .reg = 5,
  63. .mask = WM831X_GP4_EINT,
  64. },
  65. [WM831X_IRQ_GPIO_5] = {
  66. .primary = WM831X_GP_INT,
  67. .reg = 5,
  68. .mask = WM831X_GP5_EINT,
  69. },
  70. [WM831X_IRQ_GPIO_6] = {
  71. .primary = WM831X_GP_INT,
  72. .reg = 5,
  73. .mask = WM831X_GP6_EINT,
  74. },
  75. [WM831X_IRQ_GPIO_7] = {
  76. .primary = WM831X_GP_INT,
  77. .reg = 5,
  78. .mask = WM831X_GP7_EINT,
  79. },
  80. [WM831X_IRQ_GPIO_8] = {
  81. .primary = WM831X_GP_INT,
  82. .reg = 5,
  83. .mask = WM831X_GP8_EINT,
  84. },
  85. [WM831X_IRQ_GPIO_9] = {
  86. .primary = WM831X_GP_INT,
  87. .reg = 5,
  88. .mask = WM831X_GP9_EINT,
  89. },
  90. [WM831X_IRQ_GPIO_10] = {
  91. .primary = WM831X_GP_INT,
  92. .reg = 5,
  93. .mask = WM831X_GP10_EINT,
  94. },
  95. [WM831X_IRQ_GPIO_11] = {
  96. .primary = WM831X_GP_INT,
  97. .reg = 5,
  98. .mask = WM831X_GP11_EINT,
  99. },
  100. [WM831X_IRQ_GPIO_12] = {
  101. .primary = WM831X_GP_INT,
  102. .reg = 5,
  103. .mask = WM831X_GP12_EINT,
  104. },
  105. [WM831X_IRQ_GPIO_13] = {
  106. .primary = WM831X_GP_INT,
  107. .reg = 5,
  108. .mask = WM831X_GP13_EINT,
  109. },
  110. [WM831X_IRQ_GPIO_14] = {
  111. .primary = WM831X_GP_INT,
  112. .reg = 5,
  113. .mask = WM831X_GP14_EINT,
  114. },
  115. [WM831X_IRQ_GPIO_15] = {
  116. .primary = WM831X_GP_INT,
  117. .reg = 5,
  118. .mask = WM831X_GP15_EINT,
  119. },
  120. [WM831X_IRQ_GPIO_16] = {
  121. .primary = WM831X_GP_INT,
  122. .reg = 5,
  123. .mask = WM831X_GP16_EINT,
  124. },
  125. [WM831X_IRQ_ON] = {
  126. .primary = WM831X_ON_PIN_INT,
  127. .reg = 1,
  128. .mask = WM831X_ON_PIN_EINT,
  129. },
  130. [WM831X_IRQ_PPM_SYSLO] = {
  131. .primary = WM831X_PPM_INT,
  132. .reg = 1,
  133. .mask = WM831X_PPM_SYSLO_EINT,
  134. },
  135. [WM831X_IRQ_PPM_PWR_SRC] = {
  136. .primary = WM831X_PPM_INT,
  137. .reg = 1,
  138. .mask = WM831X_PPM_PWR_SRC_EINT,
  139. },
  140. [WM831X_IRQ_PPM_USB_CURR] = {
  141. .primary = WM831X_PPM_INT,
  142. .reg = 1,
  143. .mask = WM831X_PPM_USB_CURR_EINT,
  144. },
  145. [WM831X_IRQ_WDOG_TO] = {
  146. .primary = WM831X_WDOG_INT,
  147. .reg = 1,
  148. .mask = WM831X_WDOG_TO_EINT,
  149. },
  150. [WM831X_IRQ_RTC_PER] = {
  151. .primary = WM831X_RTC_INT,
  152. .reg = 1,
  153. .mask = WM831X_RTC_PER_EINT,
  154. },
  155. [WM831X_IRQ_RTC_ALM] = {
  156. .primary = WM831X_RTC_INT,
  157. .reg = 1,
  158. .mask = WM831X_RTC_ALM_EINT,
  159. },
  160. [WM831X_IRQ_CHG_BATT_HOT] = {
  161. .primary = WM831X_CHG_INT,
  162. .reg = 2,
  163. .mask = WM831X_CHG_BATT_HOT_EINT,
  164. },
  165. [WM831X_IRQ_CHG_BATT_COLD] = {
  166. .primary = WM831X_CHG_INT,
  167. .reg = 2,
  168. .mask = WM831X_CHG_BATT_COLD_EINT,
  169. },
  170. [WM831X_IRQ_CHG_BATT_FAIL] = {
  171. .primary = WM831X_CHG_INT,
  172. .reg = 2,
  173. .mask = WM831X_CHG_BATT_FAIL_EINT,
  174. },
  175. [WM831X_IRQ_CHG_OV] = {
  176. .primary = WM831X_CHG_INT,
  177. .reg = 2,
  178. .mask = WM831X_CHG_OV_EINT,
  179. },
  180. [WM831X_IRQ_CHG_END] = {
  181. .primary = WM831X_CHG_INT,
  182. .reg = 2,
  183. .mask = WM831X_CHG_END_EINT,
  184. },
  185. [WM831X_IRQ_CHG_TO] = {
  186. .primary = WM831X_CHG_INT,
  187. .reg = 2,
  188. .mask = WM831X_CHG_TO_EINT,
  189. },
  190. [WM831X_IRQ_CHG_MODE] = {
  191. .primary = WM831X_CHG_INT,
  192. .reg = 2,
  193. .mask = WM831X_CHG_MODE_EINT,
  194. },
  195. [WM831X_IRQ_CHG_START] = {
  196. .primary = WM831X_CHG_INT,
  197. .reg = 2,
  198. .mask = WM831X_CHG_START_EINT,
  199. },
  200. [WM831X_IRQ_TCHDATA] = {
  201. .primary = WM831X_TCHDATA_INT,
  202. .reg = 1,
  203. .mask = WM831X_TCHDATA_EINT,
  204. },
  205. [WM831X_IRQ_TCHPD] = {
  206. .primary = WM831X_TCHPD_INT,
  207. .reg = 1,
  208. .mask = WM831X_TCHPD_EINT,
  209. },
  210. [WM831X_IRQ_AUXADC_DATA] = {
  211. .primary = WM831X_AUXADC_INT,
  212. .reg = 1,
  213. .mask = WM831X_AUXADC_DATA_EINT,
  214. },
  215. [WM831X_IRQ_AUXADC_DCOMP1] = {
  216. .primary = WM831X_AUXADC_INT,
  217. .reg = 1,
  218. .mask = WM831X_AUXADC_DCOMP1_EINT,
  219. },
  220. [WM831X_IRQ_AUXADC_DCOMP2] = {
  221. .primary = WM831X_AUXADC_INT,
  222. .reg = 1,
  223. .mask = WM831X_AUXADC_DCOMP2_EINT,
  224. },
  225. [WM831X_IRQ_AUXADC_DCOMP3] = {
  226. .primary = WM831X_AUXADC_INT,
  227. .reg = 1,
  228. .mask = WM831X_AUXADC_DCOMP3_EINT,
  229. },
  230. [WM831X_IRQ_AUXADC_DCOMP4] = {
  231. .primary = WM831X_AUXADC_INT,
  232. .reg = 1,
  233. .mask = WM831X_AUXADC_DCOMP4_EINT,
  234. },
  235. [WM831X_IRQ_CS1] = {
  236. .primary = WM831X_CS_INT,
  237. .reg = 2,
  238. .mask = WM831X_CS1_EINT,
  239. },
  240. [WM831X_IRQ_CS2] = {
  241. .primary = WM831X_CS_INT,
  242. .reg = 2,
  243. .mask = WM831X_CS2_EINT,
  244. },
  245. [WM831X_IRQ_HC_DC1] = {
  246. .primary = WM831X_HC_INT,
  247. .reg = 4,
  248. .mask = WM831X_HC_DC1_EINT,
  249. },
  250. [WM831X_IRQ_HC_DC2] = {
  251. .primary = WM831X_HC_INT,
  252. .reg = 4,
  253. .mask = WM831X_HC_DC2_EINT,
  254. },
  255. [WM831X_IRQ_UV_LDO1] = {
  256. .primary = WM831X_UV_INT,
  257. .reg = 3,
  258. .mask = WM831X_UV_LDO1_EINT,
  259. },
  260. [WM831X_IRQ_UV_LDO2] = {
  261. .primary = WM831X_UV_INT,
  262. .reg = 3,
  263. .mask = WM831X_UV_LDO2_EINT,
  264. },
  265. [WM831X_IRQ_UV_LDO3] = {
  266. .primary = WM831X_UV_INT,
  267. .reg = 3,
  268. .mask = WM831X_UV_LDO3_EINT,
  269. },
  270. [WM831X_IRQ_UV_LDO4] = {
  271. .primary = WM831X_UV_INT,
  272. .reg = 3,
  273. .mask = WM831X_UV_LDO4_EINT,
  274. },
  275. [WM831X_IRQ_UV_LDO5] = {
  276. .primary = WM831X_UV_INT,
  277. .reg = 3,
  278. .mask = WM831X_UV_LDO5_EINT,
  279. },
  280. [WM831X_IRQ_UV_LDO6] = {
  281. .primary = WM831X_UV_INT,
  282. .reg = 3,
  283. .mask = WM831X_UV_LDO6_EINT,
  284. },
  285. [WM831X_IRQ_UV_LDO7] = {
  286. .primary = WM831X_UV_INT,
  287. .reg = 3,
  288. .mask = WM831X_UV_LDO7_EINT,
  289. },
  290. [WM831X_IRQ_UV_LDO8] = {
  291. .primary = WM831X_UV_INT,
  292. .reg = 3,
  293. .mask = WM831X_UV_LDO8_EINT,
  294. },
  295. [WM831X_IRQ_UV_LDO9] = {
  296. .primary = WM831X_UV_INT,
  297. .reg = 3,
  298. .mask = WM831X_UV_LDO9_EINT,
  299. },
  300. [WM831X_IRQ_UV_LDO10] = {
  301. .primary = WM831X_UV_INT,
  302. .reg = 3,
  303. .mask = WM831X_UV_LDO10_EINT,
  304. },
  305. [WM831X_IRQ_UV_DC1] = {
  306. .primary = WM831X_UV_INT,
  307. .reg = 4,
  308. .mask = WM831X_UV_DC1_EINT,
  309. },
  310. [WM831X_IRQ_UV_DC2] = {
  311. .primary = WM831X_UV_INT,
  312. .reg = 4,
  313. .mask = WM831X_UV_DC2_EINT,
  314. },
  315. [WM831X_IRQ_UV_DC3] = {
  316. .primary = WM831X_UV_INT,
  317. .reg = 4,
  318. .mask = WM831X_UV_DC3_EINT,
  319. },
  320. [WM831X_IRQ_UV_DC4] = {
  321. .primary = WM831X_UV_INT,
  322. .reg = 4,
  323. .mask = WM831X_UV_DC4_EINT,
  324. },
  325. };
  326. static inline int irq_data_to_status_reg(struct wm831x_irq_data *irq_data)
  327. {
  328. return WM831X_INTERRUPT_STATUS_1 - 1 + irq_data->reg;
  329. }
  330. static inline int irq_data_to_mask_reg(struct wm831x_irq_data *irq_data)
  331. {
  332. return WM831X_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg;
  333. }
  334. static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x,
  335. int irq)
  336. {
  337. return &wm831x_irqs[irq - wm831x->irq_base];
  338. }
  339. static void wm831x_irq_lock(unsigned int irq)
  340. {
  341. struct wm831x *wm831x = get_irq_chip_data(irq);
  342. mutex_lock(&wm831x->irq_lock);
  343. }
  344. static void wm831x_irq_sync_unlock(unsigned int irq)
  345. {
  346. struct wm831x *wm831x = get_irq_chip_data(irq);
  347. int i;
  348. for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
  349. /* If there's been a change in the mask write it back
  350. * to the hardware. */
  351. if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) {
  352. wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i];
  353. wm831x_reg_write(wm831x,
  354. WM831X_INTERRUPT_STATUS_1_MASK + i,
  355. wm831x->irq_masks_cur[i]);
  356. }
  357. }
  358. mutex_unlock(&wm831x->irq_lock);
  359. }
  360. static void wm831x_irq_unmask(unsigned int irq)
  361. {
  362. struct wm831x *wm831x = get_irq_chip_data(irq);
  363. struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq);
  364. wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
  365. }
  366. static void wm831x_irq_mask(unsigned int irq)
  367. {
  368. struct wm831x *wm831x = get_irq_chip_data(irq);
  369. struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq);
  370. wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
  371. }
  372. static struct irq_chip wm831x_irq_chip = {
  373. .name = "wm831x",
  374. .bus_lock = wm831x_irq_lock,
  375. .bus_sync_unlock = wm831x_irq_sync_unlock,
  376. .mask = wm831x_irq_mask,
  377. .unmask = wm831x_irq_unmask,
  378. };
  379. /* The processing of the primary interrupt occurs in a thread so that
  380. * we can interact with the device over I2C or SPI. */
  381. static irqreturn_t wm831x_irq_thread(int irq, void *data)
  382. {
  383. struct wm831x *wm831x = data;
  384. unsigned int i;
  385. int primary;
  386. int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
  387. int read[WM831X_NUM_IRQ_REGS] = { 0 };
  388. int *status;
  389. primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS);
  390. if (primary < 0) {
  391. dev_err(wm831x->dev, "Failed to read system interrupt: %d\n",
  392. primary);
  393. goto out;
  394. }
  395. for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) {
  396. int offset = wm831x_irqs[i].reg - 1;
  397. if (!(primary & wm831x_irqs[i].primary))
  398. continue;
  399. status = &status_regs[offset];
  400. /* Hopefully there should only be one register to read
  401. * each time otherwise we ought to do a block read. */
  402. if (!read[offset]) {
  403. *status = wm831x_reg_read(wm831x,
  404. irq_data_to_status_reg(&wm831x_irqs[i]));
  405. if (*status < 0) {
  406. dev_err(wm831x->dev,
  407. "Failed to read IRQ status: %d\n",
  408. *status);
  409. goto out;
  410. }
  411. read[offset] = 1;
  412. }
  413. /* Report it if it isn't masked, or forget the status. */
  414. if ((*status & ~wm831x->irq_masks_cur[offset])
  415. & wm831x_irqs[i].mask)
  416. handle_nested_irq(wm831x->irq_base + i);
  417. else
  418. *status &= ~wm831x_irqs[i].mask;
  419. }
  420. out:
  421. for (i = 0; i < ARRAY_SIZE(status_regs); i++) {
  422. if (status_regs[i])
  423. wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
  424. status_regs[i]);
  425. }
  426. return IRQ_HANDLED;
  427. }
  428. int wm831x_irq_init(struct wm831x *wm831x, int irq)
  429. {
  430. struct wm831x_pdata *pdata = wm831x->dev->platform_data;
  431. int i, cur_irq, ret;
  432. mutex_init(&wm831x->irq_lock);
  433. if (!irq) {
  434. dev_warn(wm831x->dev,
  435. "No interrupt specified - functionality limited\n");
  436. return 0;
  437. }
  438. if (!pdata || !pdata->irq_base) {
  439. dev_err(wm831x->dev,
  440. "No interrupt base specified, no interrupts\n");
  441. return 0;
  442. }
  443. wm831x->irq = irq;
  444. wm831x->irq_base = pdata->irq_base;
  445. /* Mask the individual interrupt sources */
  446. for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
  447. wm831x->irq_masks_cur[i] = 0xffff;
  448. wm831x->irq_masks_cache[i] = 0xffff;
  449. wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i,
  450. 0xffff);
  451. }
  452. /* Register them with genirq */
  453. for (cur_irq = wm831x->irq_base;
  454. cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base;
  455. cur_irq++) {
  456. set_irq_chip_data(cur_irq, wm831x);
  457. set_irq_chip_and_handler(cur_irq, &wm831x_irq_chip,
  458. handle_edge_irq);
  459. set_irq_nested_thread(cur_irq, 1);
  460. /* ARM needs us to explicitly flag the IRQ as valid
  461. * and will set them noprobe when we do so. */
  462. #ifdef CONFIG_ARM
  463. set_irq_flags(cur_irq, IRQF_VALID);
  464. #else
  465. set_irq_noprobe(cur_irq);
  466. #endif
  467. }
  468. ret = request_threaded_irq(irq, NULL, wm831x_irq_thread,
  469. IRQF_TRIGGER_LOW | IRQF_ONESHOT,
  470. "wm831x", wm831x);
  471. if (ret != 0) {
  472. dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n",
  473. irq, ret);
  474. return ret;
  475. }
  476. /* Enable top level interrupts, we mask at secondary level */
  477. wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0);
  478. return 0;
  479. }
  480. void wm831x_irq_exit(struct wm831x *wm831x)
  481. {
  482. if (wm831x->irq)
  483. free_irq(wm831x->irq, wm831x);
  484. }