mt6397-core.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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/mt6397/registers.h>
  22. #define MT6397_RTC_BASE 0xe000
  23. #define MT6397_RTC_SIZE 0x3e
  24. static const struct resource mt6397_rtc_resources[] = {
  25. {
  26. .start = MT6397_RTC_BASE,
  27. .end = MT6397_RTC_BASE + MT6397_RTC_SIZE,
  28. .flags = IORESOURCE_MEM,
  29. },
  30. {
  31. .start = MT6397_IRQ_RTC,
  32. .end = MT6397_IRQ_RTC,
  33. .flags = IORESOURCE_IRQ,
  34. },
  35. };
  36. static const struct mfd_cell mt6397_devs[] = {
  37. {
  38. .name = "mt6397-rtc",
  39. .num_resources = ARRAY_SIZE(mt6397_rtc_resources),
  40. .resources = mt6397_rtc_resources,
  41. .of_compatible = "mediatek,mt6397-rtc",
  42. }, {
  43. .name = "mt6397-regulator",
  44. .of_compatible = "mediatek,mt6397-regulator",
  45. }, {
  46. .name = "mt6397-codec",
  47. .of_compatible = "mediatek,mt6397-codec",
  48. }, {
  49. .name = "mt6397-clk",
  50. .of_compatible = "mediatek,mt6397-clk",
  51. }, {
  52. .name = "mt6397-pinctrl",
  53. .of_compatible = "mediatek,mt6397-pinctrl",
  54. },
  55. };
  56. static void mt6397_irq_lock(struct irq_data *data)
  57. {
  58. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  59. mutex_lock(&mt6397->irqlock);
  60. }
  61. static void mt6397_irq_sync_unlock(struct irq_data *data)
  62. {
  63. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  64. regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
  65. regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
  66. mutex_unlock(&mt6397->irqlock);
  67. }
  68. static void mt6397_irq_disable(struct irq_data *data)
  69. {
  70. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  71. int shift = data->hwirq & 0xf;
  72. int reg = data->hwirq >> 4;
  73. mt6397->irq_masks_cur[reg] &= ~BIT(shift);
  74. }
  75. static void mt6397_irq_enable(struct irq_data *data)
  76. {
  77. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data);
  78. int shift = data->hwirq & 0xf;
  79. int reg = data->hwirq >> 4;
  80. mt6397->irq_masks_cur[reg] |= BIT(shift);
  81. }
  82. #ifdef CONFIG_PM_SLEEP
  83. static int mt6397_irq_set_wake(struct irq_data *irq_data, unsigned int on)
  84. {
  85. struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(irq_data);
  86. int shift = irq_data->hwirq & 0xf;
  87. int reg = irq_data->hwirq >> 4;
  88. if (on)
  89. mt6397->wake_mask[reg] |= BIT(shift);
  90. else
  91. mt6397->wake_mask[reg] &= ~BIT(shift);
  92. return 0;
  93. }
  94. #else
  95. #define mt6397_irq_set_wake NULL
  96. #endif
  97. static struct irq_chip mt6397_irq_chip = {
  98. .name = "mt6397-irq",
  99. .irq_bus_lock = mt6397_irq_lock,
  100. .irq_bus_sync_unlock = mt6397_irq_sync_unlock,
  101. .irq_enable = mt6397_irq_enable,
  102. .irq_disable = mt6397_irq_disable,
  103. .irq_set_wake = mt6397_irq_set_wake,
  104. };
  105. static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
  106. int irqbase)
  107. {
  108. unsigned int status;
  109. int i, irq, ret;
  110. ret = regmap_read(mt6397->regmap, reg, &status);
  111. if (ret) {
  112. dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
  113. return;
  114. }
  115. for (i = 0; i < 16; i++) {
  116. if (status & BIT(i)) {
  117. irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
  118. if (irq)
  119. handle_nested_irq(irq);
  120. }
  121. }
  122. regmap_write(mt6397->regmap, reg, status);
  123. }
  124. static irqreturn_t mt6397_irq_thread(int irq, void *data)
  125. {
  126. struct mt6397_chip *mt6397 = data;
  127. mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS0, 0);
  128. mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS1, 16);
  129. return IRQ_HANDLED;
  130. }
  131. static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
  132. irq_hw_number_t hw)
  133. {
  134. struct mt6397_chip *mt6397 = d->host_data;
  135. irq_set_chip_data(irq, mt6397);
  136. irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
  137. irq_set_nested_thread(irq, 1);
  138. irq_set_noprobe(irq);
  139. return 0;
  140. }
  141. static const struct irq_domain_ops mt6397_irq_domain_ops = {
  142. .map = mt6397_irq_domain_map,
  143. };
  144. static int mt6397_irq_init(struct mt6397_chip *mt6397)
  145. {
  146. int ret;
  147. mutex_init(&mt6397->irqlock);
  148. /* Mask all interrupt sources */
  149. regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
  150. regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
  151. mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
  152. MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
  153. if (!mt6397->irq_domain) {
  154. dev_err(mt6397->dev, "could not create irq domain\n");
  155. return -ENOMEM;
  156. }
  157. ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
  158. mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
  159. if (ret) {
  160. dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
  161. mt6397->irq, ret);
  162. return ret;
  163. }
  164. return 0;
  165. }
  166. #ifdef CONFIG_PM_SLEEP
  167. static int mt6397_irq_suspend(struct device *dev)
  168. {
  169. struct mt6397_chip *chip = dev_get_drvdata(dev);
  170. regmap_write(chip->regmap, MT6397_INT_CON0, chip->wake_mask[0]);
  171. regmap_write(chip->regmap, MT6397_INT_CON1, chip->wake_mask[1]);
  172. enable_irq_wake(chip->irq);
  173. return 0;
  174. }
  175. static int mt6397_irq_resume(struct device *dev)
  176. {
  177. struct mt6397_chip *chip = dev_get_drvdata(dev);
  178. regmap_write(chip->regmap, MT6397_INT_CON0, chip->irq_masks_cur[0]);
  179. regmap_write(chip->regmap, MT6397_INT_CON1, chip->irq_masks_cur[1]);
  180. disable_irq_wake(chip->irq);
  181. return 0;
  182. }
  183. #endif
  184. static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_irq_suspend,
  185. mt6397_irq_resume);
  186. static int mt6397_probe(struct platform_device *pdev)
  187. {
  188. int ret;
  189. struct mt6397_chip *mt6397;
  190. mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
  191. if (!mt6397)
  192. return -ENOMEM;
  193. mt6397->dev = &pdev->dev;
  194. /*
  195. * mt6397 MFD is child device of soc pmic wrapper.
  196. * Regmap is set from its parent.
  197. */
  198. mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
  199. if (!mt6397->regmap)
  200. return -ENODEV;
  201. platform_set_drvdata(pdev, mt6397);
  202. mt6397->irq = platform_get_irq(pdev, 0);
  203. if (mt6397->irq > 0) {
  204. ret = mt6397_irq_init(mt6397);
  205. if (ret)
  206. return ret;
  207. }
  208. ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
  209. ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
  210. if (ret)
  211. dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
  212. return ret;
  213. }
  214. static int mt6397_remove(struct platform_device *pdev)
  215. {
  216. mfd_remove_devices(&pdev->dev);
  217. return 0;
  218. }
  219. static const struct of_device_id mt6397_of_match[] = {
  220. { .compatible = "mediatek,mt6397" },
  221. { }
  222. };
  223. MODULE_DEVICE_TABLE(of, mt6397_of_match);
  224. static struct platform_driver mt6397_driver = {
  225. .probe = mt6397_probe,
  226. .remove = mt6397_remove,
  227. .driver = {
  228. .name = "mt6397",
  229. .of_match_table = of_match_ptr(mt6397_of_match),
  230. .pm = &mt6397_pm_ops,
  231. },
  232. };
  233. module_platform_driver(mt6397_driver);
  234. MODULE_AUTHOR("Flora Fu, MediaTek");
  235. MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
  236. MODULE_LICENSE("GPL");
  237. MODULE_ALIAS("platform:mt6397");