mt6397-core.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*
  2. * Copyright (c) 2014 MediaTek Inc.
  3. * Author: Flora Fu, MediaTek
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/interrupt.h>
  15. #include <linux/module.h>
  16. #include <linux/of_device.h>
  17. #include <linux/of_irq.h>
  18. #include <linux/regmap.h>
  19. #include <linux/mfd/core.h>
  20. #include <linux/mfd/mt6397/core.h>
  21. #include <linux/mfd/mt6323/core.h>
  22. #include <linux/mfd/mt6397/registers.h>
  23. #include <linux/mfd/mt6323/registers.h>
  24. #define MT6397_RTC_BASE 0xe000
  25. #define MT6397_RTC_SIZE 0x3e
  26. #define MT6323_CID_CODE 0x23
  27. #define MT6391_CID_CODE 0x91
  28. #define MT6397_CID_CODE 0x97
  29. static const struct resource mt6397_rtc_resources[] = {
  30. {
  31. .start = MT6397_RTC_BASE,
  32. .end = MT6397_RTC_BASE + MT6397_RTC_SIZE,
  33. .flags = IORESOURCE_MEM,
  34. },
  35. {
  36. .start = MT6397_IRQ_RTC,
  37. .end = MT6397_IRQ_RTC,
  38. .flags = IORESOURCE_IRQ,
  39. },
  40. };
  41. static const struct resource mt6323_keys_resources[] = {
  42. DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY),
  43. DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY),
  44. };
  45. static const struct resource mt6397_keys_resources[] = {
  46. DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY),
  47. DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY),
  48. };
  49. static const struct mfd_cell mt6323_devs[] = {
  50. {
  51. .name = "mt6323-regulator",
  52. .of_compatible = "mediatek,mt6323-regulator"
  53. }, {
  54. .name = "mt6323-led",
  55. .of_compatible = "mediatek,mt6323-led"
  56. }, {
  57. .name = "mtk-pmic-keys",
  58. .num_resources = ARRAY_SIZE(mt6323_keys_resources),
  59. .resources = mt6323_keys_resources,
  60. .of_compatible = "mediatek,mt6323-keys"
  61. },
  62. };
  63. static const struct mfd_cell mt6397_devs[] = {
  64. {
  65. .name = "mt6397-rtc",
  66. .num_resources = ARRAY_SIZE(mt6397_rtc_resources),
  67. .resources = mt6397_rtc_resources,
  68. .of_compatible = "mediatek,mt6397-rtc",
  69. }, {
  70. .name = "mt6397-regulator",
  71. .of_compatible = "mediatek,mt6397-regulator",
  72. }, {
  73. .name = "mt6397-codec",
  74. .of_compatible = "mediatek,mt6397-codec",
  75. }, {
  76. .name = "mt6397-clk",
  77. .of_compatible = "mediatek,mt6397-clk",
  78. }, {
  79. .name = "mt6397-pinctrl",
  80. .of_compatible = "mediatek,mt6397-pinctrl",
  81. }, {
  82. .name = "mtk-pmic-keys",
  83. .num_resources = ARRAY_SIZE(mt6397_keys_resources),
  84. .resources = mt6397_keys_resources,
  85. .of_compatible = "mediatek,mt6397-keys"
  86. }
  87. };
  88. static void mt6397_irq_lock(struct irq_data *data)
  89. {
  90. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  91. mutex_lock(&mt6397->irqlock);
  92. }
  93. static void mt6397_irq_sync_unlock(struct irq_data *data)
  94. {
  95. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  96. regmap_write(mt6397->regmap, mt6397->int_con[0],
  97. mt6397->irq_masks_cur[0]);
  98. regmap_write(mt6397->regmap, mt6397->int_con[1],
  99. mt6397->irq_masks_cur[1]);
  100. mutex_unlock(&mt6397->irqlock);
  101. }
  102. static void mt6397_irq_disable(struct irq_data *data)
  103. {
  104. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  105. int shift = data->hwirq & 0xf;
  106. int reg = data->hwirq >> 4;
  107. mt6397->irq_masks_cur[reg] &= ~BIT(shift);
  108. }
  109. static void mt6397_irq_enable(struct irq_data *data)
  110. {
  111. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  112. int shift = data->hwirq & 0xf;
  113. int reg = data->hwirq >> 4;
  114. mt6397->irq_masks_cur[reg] |= BIT(shift);
  115. }
  116. #ifdef CONFIG_PM_SLEEP
  117. static int mt6397_irq_set_wake(struct irq_data *irq_data, unsigned int on)
  118. {
  119. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(irq_data);
  120. int shift = irq_data->hwirq & 0xf;
  121. int reg = irq_data->hwirq >> 4;
  122. if (on)
  123. mt6397->wake_mask[reg] |= BIT(shift);
  124. else
  125. mt6397->wake_mask[reg] &= ~BIT(shift);
  126. return 0;
  127. }
  128. #else
  129. #define mt6397_irq_set_wake NULL
  130. #endif
  131. static struct irq_chip mt6397_irq_chip = {
  132. .name = "mt6397-irq",
  133. .irq_bus_lock = mt6397_irq_lock,
  134. .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
  135. .irq_enable = mt6397_irq_enable,
  136. .irq_disable = mt6397_irq_disable,
  137. .irq_set_wake = mt6397_irq_set_wake,
  138. };
  139. static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
  140. int irqbase)
  141. {
  142. unsigned int status;
  143. int i, irq, ret;
  144. ret = regmap_read(mt6397->regmap, reg, &status);
  145. if (ret) {
  146. dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
  147. return;
  148. }
  149. for (i = 0; i < 16; i++) {
  150. if (status & BIT(i)) {
  151. irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
  152. if (irq)
  153. handle_nested_irq(irq);
  154. }
  155. }
  156. regmap_write(mt6397->regmap, reg, status);
  157. }
  158. static irqreturn_t mt6397_irq_thread(int irq, void *data)
  159. {
  160. struct mt6397_chip *mt6397 = data;
  161. mt6397_irq_handle_reg(mt6397, mt6397->int_status[0], 0);
  162. mt6397_irq_handle_reg(mt6397, mt6397->int_status[1], 16);
  163. return IRQ_HANDLED;
  164. }
  165. static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
  166. irq_hw_number_t hw)
  167. {
  168. struct mt6397_chip *mt6397 = d->host_data;
  169. irq_set_chip_data(irq, mt6397);
  170. irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
  171. irq_set_nested_thread(irq, 1);
  172. irq_set_noprobe(irq);
  173. return 0;
  174. }
  175. static const struct irq_domain_ops mt6397_irq_domain_ops = {
  176. .map = mt6397_irq_domain_map,
  177. };
  178. static int mt6397_irq_init(struct mt6397_chip *mt6397)
  179. {
  180. int ret;
  181. mutex_init(&mt6397->irqlock);
  182. /* Mask all interrupt sources */
  183. regmap_write(mt6397->regmap, mt6397->int_con[0], 0x0);
  184. regmap_write(mt6397->regmap, mt6397->int_con[1], 0x0);
  185. mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
  186. MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
  187. if (!mt6397->irq_domain) {
  188. dev_err(mt6397->dev, "could not create irq domain\n");
  189. return -ENOMEM;
  190. }
  191. ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
  192. mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
  193. if (ret) {
  194. dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
  195. mt6397->irq, ret);
  196. return ret;
  197. }
  198. return 0;
  199. }
  200. #ifdef CONFIG_PM_SLEEP
  201. static int mt6397_irq_suspend(struct device *dev)
  202. {
  203. struct mt6397_chip *chip = dev_get_drvdata(dev);
  204. regmap_write(chip->regmap, chip->int_con[0], chip->wake_mask[0]);
  205. regmap_write(chip->regmap, chip->int_con[1], chip->wake_mask[1]);
  206. enable_irq_wake(chip->irq);
  207. return 0;
  208. }
  209. static int mt6397_irq_resume(struct device *dev)
  210. {
  211. struct mt6397_chip *chip = dev_get_drvdata(dev);
  212. regmap_write(chip->regmap, chip->int_con[0], chip->irq_masks_cur[0]);
  213. regmap_write(chip->regmap, chip->int_con[1], chip->irq_masks_cur[1]);
  214. disable_irq_wake(chip->irq);
  215. return 0;
  216. }
  217. #endif
  218. static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_irq_suspend,
  219. mt6397_irq_resume);
  220. static int mt6397_probe(struct platform_device *pdev)
  221. {
  222. int ret;
  223. unsigned int id;
  224. struct mt6397_chip *pmic;
  225. pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
  226. if (!pmic)
  227. return -ENOMEM;
  228. pmic->dev = &pdev->dev;
  229. /*
  230. * mt6397 MFD is child device of soc pmic wrapper.
  231. * Regmap is set from its parent.
  232. */
  233. pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL);
  234. if (!pmic->regmap)
  235. return -ENODEV;
  236. platform_set_drvdata(pdev, pmic);
  237. ret = regmap_read(pmic->regmap, MT6397_CID, &id);
  238. if (ret) {
  239. dev_err(pmic->dev, "Failed to read chip id: %d\n", ret);
  240. return ret;
  241. }
  242. pmic->irq = platform_get_irq(pdev, 0);
  243. if (pmic->irq <= 0)
  244. return pmic->irq;
  245. switch (id & 0xff) {
  246. case MT6323_CID_CODE:
  247. pmic->int_con[0] = MT6323_INT_CON0;
  248. pmic->int_con[1] = MT6323_INT_CON1;
  249. pmic->int_status[0] = MT6323_INT_STATUS0;
  250. pmic->int_status[1] = MT6323_INT_STATUS1;
  251. ret = mt6397_irq_init(pmic);
  252. if (ret)
  253. return ret;
  254. ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs,
  255. ARRAY_SIZE(mt6323_devs), NULL,
  256. 0, pmic->irq_domain);
  257. break;
  258. case MT6397_CID_CODE:
  259. case MT6391_CID_CODE:
  260. pmic->int_con[0] = MT6397_INT_CON0;
  261. pmic->int_con[1] = MT6397_INT_CON1;
  262. pmic->int_status[0] = MT6397_INT_STATUS0;
  263. pmic->int_status[1] = MT6397_INT_STATUS1;
  264. ret = mt6397_irq_init(pmic);
  265. if (ret)
  266. return ret;
  267. ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs,
  268. ARRAY_SIZE(mt6397_devs), NULL,
  269. 0, pmic->irq_domain);
  270. break;
  271. default:
  272. dev_err(&pdev->dev, "unsupported chip: %d\n", id);
  273. return -ENODEV;
  274. }
  275. if (ret) {
  276. irq_domain_remove(pmic->irq_domain);
  277. dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
  278. }
  279. return ret;
  280. }
  281. static const struct of_device_id mt6397_of_match[] = {
  282. { .compatible = "mediatek,mt6397" },
  283. { .compatible = "mediatek,mt6323" },
  284. { }
  285. };
  286. MODULE_DEVICE_TABLE(of, mt6397_of_match);
  287. static const struct platform_device_id mt6397_id[] = {
  288. { "mt6397", 0 },
  289. { },
  290. };
  291. MODULE_DEVICE_TABLE(platform, mt6397_id);
  292. static struct platform_driver mt6397_driver = {
  293. .probe = mt6397_probe,
  294. .driver = {
  295. .name = "mt6397",
  296. .of_match_table = of_match_ptr(mt6397_of_match),
  297. .pm = &mt6397_pm_ops,
  298. },
  299. .id_table = mt6397_id,
  300. };
  301. module_platform_driver(mt6397_driver);
  302. MODULE_AUTHOR("Flora Fu, MediaTek");
  303. MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
  304. MODULE_LICENSE("GPL");