sec-irq.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * sec-irq.c
  3. *
  4. * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd
  5. * http://www.samsung.com
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation; either version 2 of the License, or (at your
  10. * option) any later version.
  11. *
  12. */
  13. #include <linux/device.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/irq.h>
  16. #include <linux/regmap.h>
  17. #include <linux/mfd/samsung/core.h>
  18. #include <linux/mfd/samsung/irq.h>
  19. #include <linux/mfd/samsung/s2mps11.h>
  20. #include <linux/mfd/samsung/s2mps14.h>
  21. #include <linux/mfd/samsung/s2mpu02.h>
  22. #include <linux/mfd/samsung/s5m8763.h>
  23. #include <linux/mfd/samsung/s5m8767.h>
  24. static const struct regmap_irq s2mps11_irqs[] = {
  25. [S2MPS11_IRQ_PWRONF] = {
  26. .reg_offset = 0,
  27. .mask = S2MPS11_IRQ_PWRONF_MASK,
  28. },
  29. [S2MPS11_IRQ_PWRONR] = {
  30. .reg_offset = 0,
  31. .mask = S2MPS11_IRQ_PWRONR_MASK,
  32. },
  33. [S2MPS11_IRQ_JIGONBF] = {
  34. .reg_offset = 0,
  35. .mask = S2MPS11_IRQ_JIGONBF_MASK,
  36. },
  37. [S2MPS11_IRQ_JIGONBR] = {
  38. .reg_offset = 0,
  39. .mask = S2MPS11_IRQ_JIGONBR_MASK,
  40. },
  41. [S2MPS11_IRQ_ACOKBF] = {
  42. .reg_offset = 0,
  43. .mask = S2MPS11_IRQ_ACOKBF_MASK,
  44. },
  45. [S2MPS11_IRQ_ACOKBR] = {
  46. .reg_offset = 0,
  47. .mask = S2MPS11_IRQ_ACOKBR_MASK,
  48. },
  49. [S2MPS11_IRQ_PWRON1S] = {
  50. .reg_offset = 0,
  51. .mask = S2MPS11_IRQ_PWRON1S_MASK,
  52. },
  53. [S2MPS11_IRQ_MRB] = {
  54. .reg_offset = 0,
  55. .mask = S2MPS11_IRQ_MRB_MASK,
  56. },
  57. [S2MPS11_IRQ_RTC60S] = {
  58. .reg_offset = 1,
  59. .mask = S2MPS11_IRQ_RTC60S_MASK,
  60. },
  61. [S2MPS11_IRQ_RTCA1] = {
  62. .reg_offset = 1,
  63. .mask = S2MPS11_IRQ_RTCA1_MASK,
  64. },
  65. [S2MPS11_IRQ_RTCA0] = {
  66. .reg_offset = 1,
  67. .mask = S2MPS11_IRQ_RTCA0_MASK,
  68. },
  69. [S2MPS11_IRQ_SMPL] = {
  70. .reg_offset = 1,
  71. .mask = S2MPS11_IRQ_SMPL_MASK,
  72. },
  73. [S2MPS11_IRQ_RTC1S] = {
  74. .reg_offset = 1,
  75. .mask = S2MPS11_IRQ_RTC1S_MASK,
  76. },
  77. [S2MPS11_IRQ_WTSR] = {
  78. .reg_offset = 1,
  79. .mask = S2MPS11_IRQ_WTSR_MASK,
  80. },
  81. [S2MPS11_IRQ_INT120C] = {
  82. .reg_offset = 2,
  83. .mask = S2MPS11_IRQ_INT120C_MASK,
  84. },
  85. [S2MPS11_IRQ_INT140C] = {
  86. .reg_offset = 2,
  87. .mask = S2MPS11_IRQ_INT140C_MASK,
  88. },
  89. };
  90. static const struct regmap_irq s2mps14_irqs[] = {
  91. [S2MPS14_IRQ_PWRONF] = {
  92. .reg_offset = 0,
  93. .mask = S2MPS11_IRQ_PWRONF_MASK,
  94. },
  95. [S2MPS14_IRQ_PWRONR] = {
  96. .reg_offset = 0,
  97. .mask = S2MPS11_IRQ_PWRONR_MASK,
  98. },
  99. [S2MPS14_IRQ_JIGONBF] = {
  100. .reg_offset = 0,
  101. .mask = S2MPS11_IRQ_JIGONBF_MASK,
  102. },
  103. [S2MPS14_IRQ_JIGONBR] = {
  104. .reg_offset = 0,
  105. .mask = S2MPS11_IRQ_JIGONBR_MASK,
  106. },
  107. [S2MPS14_IRQ_ACOKBF] = {
  108. .reg_offset = 0,
  109. .mask = S2MPS11_IRQ_ACOKBF_MASK,
  110. },
  111. [S2MPS14_IRQ_ACOKBR] = {
  112. .reg_offset = 0,
  113. .mask = S2MPS11_IRQ_ACOKBR_MASK,
  114. },
  115. [S2MPS14_IRQ_PWRON1S] = {
  116. .reg_offset = 0,
  117. .mask = S2MPS11_IRQ_PWRON1S_MASK,
  118. },
  119. [S2MPS14_IRQ_MRB] = {
  120. .reg_offset = 0,
  121. .mask = S2MPS11_IRQ_MRB_MASK,
  122. },
  123. [S2MPS14_IRQ_RTC60S] = {
  124. .reg_offset = 1,
  125. .mask = S2MPS11_IRQ_RTC60S_MASK,
  126. },
  127. [S2MPS14_IRQ_RTCA1] = {
  128. .reg_offset = 1,
  129. .mask = S2MPS11_IRQ_RTCA1_MASK,
  130. },
  131. [S2MPS14_IRQ_RTCA0] = {
  132. .reg_offset = 1,
  133. .mask = S2MPS11_IRQ_RTCA0_MASK,
  134. },
  135. [S2MPS14_IRQ_SMPL] = {
  136. .reg_offset = 1,
  137. .mask = S2MPS11_IRQ_SMPL_MASK,
  138. },
  139. [S2MPS14_IRQ_RTC1S] = {
  140. .reg_offset = 1,
  141. .mask = S2MPS11_IRQ_RTC1S_MASK,
  142. },
  143. [S2MPS14_IRQ_WTSR] = {
  144. .reg_offset = 1,
  145. .mask = S2MPS11_IRQ_WTSR_MASK,
  146. },
  147. [S2MPS14_IRQ_INT120C] = {
  148. .reg_offset = 2,
  149. .mask = S2MPS11_IRQ_INT120C_MASK,
  150. },
  151. [S2MPS14_IRQ_INT140C] = {
  152. .reg_offset = 2,
  153. .mask = S2MPS11_IRQ_INT140C_MASK,
  154. },
  155. [S2MPS14_IRQ_TSD] = {
  156. .reg_offset = 2,
  157. .mask = S2MPS14_IRQ_TSD_MASK,
  158. },
  159. };
  160. static const struct regmap_irq s2mpu02_irqs[] = {
  161. [S2MPU02_IRQ_PWRONF] = {
  162. .reg_offset = 0,
  163. .mask = S2MPS11_IRQ_PWRONF_MASK,
  164. },
  165. [S2MPU02_IRQ_PWRONR] = {
  166. .reg_offset = 0,
  167. .mask = S2MPS11_IRQ_PWRONR_MASK,
  168. },
  169. [S2MPU02_IRQ_JIGONBF] = {
  170. .reg_offset = 0,
  171. .mask = S2MPS11_IRQ_JIGONBF_MASK,
  172. },
  173. [S2MPU02_IRQ_JIGONBR] = {
  174. .reg_offset = 0,
  175. .mask = S2MPS11_IRQ_JIGONBR_MASK,
  176. },
  177. [S2MPU02_IRQ_ACOKBF] = {
  178. .reg_offset = 0,
  179. .mask = S2MPS11_IRQ_ACOKBF_MASK,
  180. },
  181. [S2MPU02_IRQ_ACOKBR] = {
  182. .reg_offset = 0,
  183. .mask = S2MPS11_IRQ_ACOKBR_MASK,
  184. },
  185. [S2MPU02_IRQ_PWRON1S] = {
  186. .reg_offset = 0,
  187. .mask = S2MPS11_IRQ_PWRON1S_MASK,
  188. },
  189. [S2MPU02_IRQ_MRB] = {
  190. .reg_offset = 0,
  191. .mask = S2MPS11_IRQ_MRB_MASK,
  192. },
  193. [S2MPU02_IRQ_RTC60S] = {
  194. .reg_offset = 1,
  195. .mask = S2MPS11_IRQ_RTC60S_MASK,
  196. },
  197. [S2MPU02_IRQ_RTCA1] = {
  198. .reg_offset = 1,
  199. .mask = S2MPS11_IRQ_RTCA1_MASK,
  200. },
  201. [S2MPU02_IRQ_RTCA0] = {
  202. .reg_offset = 1,
  203. .mask = S2MPS11_IRQ_RTCA0_MASK,
  204. },
  205. [S2MPU02_IRQ_SMPL] = {
  206. .reg_offset = 1,
  207. .mask = S2MPS11_IRQ_SMPL_MASK,
  208. },
  209. [S2MPU02_IRQ_RTC1S] = {
  210. .reg_offset = 1,
  211. .mask = S2MPS11_IRQ_RTC1S_MASK,
  212. },
  213. [S2MPU02_IRQ_WTSR] = {
  214. .reg_offset = 1,
  215. .mask = S2MPS11_IRQ_WTSR_MASK,
  216. },
  217. [S2MPU02_IRQ_INT120C] = {
  218. .reg_offset = 2,
  219. .mask = S2MPS11_IRQ_INT120C_MASK,
  220. },
  221. [S2MPU02_IRQ_INT140C] = {
  222. .reg_offset = 2,
  223. .mask = S2MPS11_IRQ_INT140C_MASK,
  224. },
  225. [S2MPU02_IRQ_TSD] = {
  226. .reg_offset = 2,
  227. .mask = S2MPS14_IRQ_TSD_MASK,
  228. },
  229. };
  230. static const struct regmap_irq s5m8767_irqs[] = {
  231. [S5M8767_IRQ_PWRR] = {
  232. .reg_offset = 0,
  233. .mask = S5M8767_IRQ_PWRR_MASK,
  234. },
  235. [S5M8767_IRQ_PWRF] = {
  236. .reg_offset = 0,
  237. .mask = S5M8767_IRQ_PWRF_MASK,
  238. },
  239. [S5M8767_IRQ_PWR1S] = {
  240. .reg_offset = 0,
  241. .mask = S5M8767_IRQ_PWR1S_MASK,
  242. },
  243. [S5M8767_IRQ_JIGR] = {
  244. .reg_offset = 0,
  245. .mask = S5M8767_IRQ_JIGR_MASK,
  246. },
  247. [S5M8767_IRQ_JIGF] = {
  248. .reg_offset = 0,
  249. .mask = S5M8767_IRQ_JIGF_MASK,
  250. },
  251. [S5M8767_IRQ_LOWBAT2] = {
  252. .reg_offset = 0,
  253. .mask = S5M8767_IRQ_LOWBAT2_MASK,
  254. },
  255. [S5M8767_IRQ_LOWBAT1] = {
  256. .reg_offset = 0,
  257. .mask = S5M8767_IRQ_LOWBAT1_MASK,
  258. },
  259. [S5M8767_IRQ_MRB] = {
  260. .reg_offset = 1,
  261. .mask = S5M8767_IRQ_MRB_MASK,
  262. },
  263. [S5M8767_IRQ_DVSOK2] = {
  264. .reg_offset = 1,
  265. .mask = S5M8767_IRQ_DVSOK2_MASK,
  266. },
  267. [S5M8767_IRQ_DVSOK3] = {
  268. .reg_offset = 1,
  269. .mask = S5M8767_IRQ_DVSOK3_MASK,
  270. },
  271. [S5M8767_IRQ_DVSOK4] = {
  272. .reg_offset = 1,
  273. .mask = S5M8767_IRQ_DVSOK4_MASK,
  274. },
  275. [S5M8767_IRQ_RTC60S] = {
  276. .reg_offset = 2,
  277. .mask = S5M8767_IRQ_RTC60S_MASK,
  278. },
  279. [S5M8767_IRQ_RTCA1] = {
  280. .reg_offset = 2,
  281. .mask = S5M8767_IRQ_RTCA1_MASK,
  282. },
  283. [S5M8767_IRQ_RTCA2] = {
  284. .reg_offset = 2,
  285. .mask = S5M8767_IRQ_RTCA2_MASK,
  286. },
  287. [S5M8767_IRQ_SMPL] = {
  288. .reg_offset = 2,
  289. .mask = S5M8767_IRQ_SMPL_MASK,
  290. },
  291. [S5M8767_IRQ_RTC1S] = {
  292. .reg_offset = 2,
  293. .mask = S5M8767_IRQ_RTC1S_MASK,
  294. },
  295. [S5M8767_IRQ_WTSR] = {
  296. .reg_offset = 2,
  297. .mask = S5M8767_IRQ_WTSR_MASK,
  298. },
  299. };
  300. static const struct regmap_irq s5m8763_irqs[] = {
  301. [S5M8763_IRQ_DCINF] = {
  302. .reg_offset = 0,
  303. .mask = S5M8763_IRQ_DCINF_MASK,
  304. },
  305. [S5M8763_IRQ_DCINR] = {
  306. .reg_offset = 0,
  307. .mask = S5M8763_IRQ_DCINR_MASK,
  308. },
  309. [S5M8763_IRQ_JIGF] = {
  310. .reg_offset = 0,
  311. .mask = S5M8763_IRQ_JIGF_MASK,
  312. },
  313. [S5M8763_IRQ_JIGR] = {
  314. .reg_offset = 0,
  315. .mask = S5M8763_IRQ_JIGR_MASK,
  316. },
  317. [S5M8763_IRQ_PWRONF] = {
  318. .reg_offset = 0,
  319. .mask = S5M8763_IRQ_PWRONF_MASK,
  320. },
  321. [S5M8763_IRQ_PWRONR] = {
  322. .reg_offset = 0,
  323. .mask = S5M8763_IRQ_PWRONR_MASK,
  324. },
  325. [S5M8763_IRQ_WTSREVNT] = {
  326. .reg_offset = 1,
  327. .mask = S5M8763_IRQ_WTSREVNT_MASK,
  328. },
  329. [S5M8763_IRQ_SMPLEVNT] = {
  330. .reg_offset = 1,
  331. .mask = S5M8763_IRQ_SMPLEVNT_MASK,
  332. },
  333. [S5M8763_IRQ_ALARM1] = {
  334. .reg_offset = 1,
  335. .mask = S5M8763_IRQ_ALARM1_MASK,
  336. },
  337. [S5M8763_IRQ_ALARM0] = {
  338. .reg_offset = 1,
  339. .mask = S5M8763_IRQ_ALARM0_MASK,
  340. },
  341. [S5M8763_IRQ_ONKEY1S] = {
  342. .reg_offset = 2,
  343. .mask = S5M8763_IRQ_ONKEY1S_MASK,
  344. },
  345. [S5M8763_IRQ_TOPOFFR] = {
  346. .reg_offset = 2,
  347. .mask = S5M8763_IRQ_TOPOFFR_MASK,
  348. },
  349. [S5M8763_IRQ_DCINOVPR] = {
  350. .reg_offset = 2,
  351. .mask = S5M8763_IRQ_DCINOVPR_MASK,
  352. },
  353. [S5M8763_IRQ_CHGRSTF] = {
  354. .reg_offset = 2,
  355. .mask = S5M8763_IRQ_CHGRSTF_MASK,
  356. },
  357. [S5M8763_IRQ_DONER] = {
  358. .reg_offset = 2,
  359. .mask = S5M8763_IRQ_DONER_MASK,
  360. },
  361. [S5M8763_IRQ_CHGFAULT] = {
  362. .reg_offset = 2,
  363. .mask = S5M8763_IRQ_CHGFAULT_MASK,
  364. },
  365. [S5M8763_IRQ_LOBAT1] = {
  366. .reg_offset = 3,
  367. .mask = S5M8763_IRQ_LOBAT1_MASK,
  368. },
  369. [S5M8763_IRQ_LOBAT2] = {
  370. .reg_offset = 3,
  371. .mask = S5M8763_IRQ_LOBAT2_MASK,
  372. },
  373. };
  374. static const struct regmap_irq_chip s2mps11_irq_chip = {
  375. .name = "s2mps11",
  376. .irqs = s2mps11_irqs,
  377. .num_irqs = ARRAY_SIZE(s2mps11_irqs),
  378. .num_regs = 3,
  379. .status_base = S2MPS11_REG_INT1,
  380. .mask_base = S2MPS11_REG_INT1M,
  381. .ack_base = S2MPS11_REG_INT1,
  382. };
  383. #define S2MPS1X_IRQ_CHIP_COMMON_DATA \
  384. .irqs = s2mps14_irqs, \
  385. .num_irqs = ARRAY_SIZE(s2mps14_irqs), \
  386. .num_regs = 3, \
  387. .status_base = S2MPS14_REG_INT1, \
  388. .mask_base = S2MPS14_REG_INT1M, \
  389. .ack_base = S2MPS14_REG_INT1 \
  390. static const struct regmap_irq_chip s2mps13_irq_chip = {
  391. .name = "s2mps13",
  392. S2MPS1X_IRQ_CHIP_COMMON_DATA,
  393. };
  394. static const struct regmap_irq_chip s2mps14_irq_chip = {
  395. .name = "s2mps14",
  396. S2MPS1X_IRQ_CHIP_COMMON_DATA,
  397. };
  398. static const struct regmap_irq_chip s2mpu02_irq_chip = {
  399. .name = "s2mpu02",
  400. .irqs = s2mpu02_irqs,
  401. .num_irqs = ARRAY_SIZE(s2mpu02_irqs),
  402. .num_regs = 3,
  403. .status_base = S2MPU02_REG_INT1,
  404. .mask_base = S2MPU02_REG_INT1M,
  405. .ack_base = S2MPU02_REG_INT1,
  406. };
  407. static const struct regmap_irq_chip s5m8767_irq_chip = {
  408. .name = "s5m8767",
  409. .irqs = s5m8767_irqs,
  410. .num_irqs = ARRAY_SIZE(s5m8767_irqs),
  411. .num_regs = 3,
  412. .status_base = S5M8767_REG_INT1,
  413. .mask_base = S5M8767_REG_INT1M,
  414. .ack_base = S5M8767_REG_INT1,
  415. };
  416. static const struct regmap_irq_chip s5m8763_irq_chip = {
  417. .name = "s5m8763",
  418. .irqs = s5m8763_irqs,
  419. .num_irqs = ARRAY_SIZE(s5m8763_irqs),
  420. .num_regs = 4,
  421. .status_base = S5M8763_REG_IRQ1,
  422. .mask_base = S5M8763_REG_IRQM1,
  423. .ack_base = S5M8763_REG_IRQ1,
  424. };
  425. int sec_irq_init(struct sec_pmic_dev *sec_pmic)
  426. {
  427. int ret = 0;
  428. int type = sec_pmic->device_type;
  429. const struct regmap_irq_chip *sec_irq_chip;
  430. if (!sec_pmic->irq) {
  431. dev_warn(sec_pmic->dev,
  432. "No interrupt specified, no interrupts\n");
  433. sec_pmic->irq_base = 0;
  434. return 0;
  435. }
  436. switch (type) {
  437. case S5M8763X:
  438. sec_irq_chip = &s5m8763_irq_chip;
  439. break;
  440. case S5M8767X:
  441. sec_irq_chip = &s5m8767_irq_chip;
  442. break;
  443. case S2MPS11X:
  444. sec_irq_chip = &s2mps11_irq_chip;
  445. break;
  446. case S2MPS13X:
  447. sec_irq_chip = &s2mps13_irq_chip;
  448. break;
  449. case S2MPS14X:
  450. sec_irq_chip = &s2mps14_irq_chip;
  451. break;
  452. case S2MPU02:
  453. sec_irq_chip = &s2mpu02_irq_chip;
  454. break;
  455. default:
  456. dev_err(sec_pmic->dev, "Unknown device type %lu\n",
  457. sec_pmic->device_type);
  458. return -EINVAL;
  459. }
  460. ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
  461. IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
  462. sec_pmic->irq_base, sec_irq_chip,
  463. &sec_pmic->irq_data);
  464. if (ret != 0) {
  465. dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
  466. return ret;
  467. }
  468. /*
  469. * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11
  470. * so the interrupt number must be consistent.
  471. */
  472. BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0);
  473. return 0;
  474. }
  475. void sec_irq_exit(struct sec_pmic_dev *sec_pmic)
  476. {
  477. regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data);
  478. }