mt6397-core.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2014 MediaTek Inc.
  4. * Author: Flora Fu, MediaTek
  5. */
  6. #include <linux/interrupt.h>
  7. #include <linux/ioport.h>
  8. #include <linux/module.h>
  9. #include <linux/of_device.h>
  10. #include <linux/of_irq.h>
  11. #include <linux/regmap.h>
  12. #include <linux/mfd/core.h>
  13. #include <linux/mfd/mt6323/core.h>
  14. #include <linux/mfd/mt6331/core.h>
  15. #include <linux/mfd/mt6357/core.h>
  16. #include <linux/mfd/mt6358/core.h>
  17. #include <linux/mfd/mt6359/core.h>
  18. #include <linux/mfd/mt6397/core.h>
  19. #include <linux/mfd/mt6323/registers.h>
  20. #include <linux/mfd/mt6331/registers.h>
  21. #include <linux/mfd/mt6357/registers.h>
  22. #include <linux/mfd/mt6358/registers.h>
  23. #include <linux/mfd/mt6359/registers.h>
  24. #include <linux/mfd/mt6397/registers.h>
  25. #define MT6323_RTC_BASE 0x8000
  26. #define MT6323_RTC_SIZE 0x40
  27. #define MT6357_RTC_BASE 0x0588
  28. #define MT6357_RTC_SIZE 0x3c
  29. #define MT6331_RTC_BASE 0x4000
  30. #define MT6331_RTC_SIZE 0x40
  31. #define MT6358_RTC_BASE 0x0588
  32. #define MT6358_RTC_SIZE 0x3c
  33. #define MT6397_RTC_BASE 0xe000
  34. #define MT6397_RTC_SIZE 0x3e
  35. #define MT6323_PWRC_BASE 0x8000
  36. #define MT6323_PWRC_SIZE 0x40
  37. static const struct resource mt6323_rtc_resources[] = {
  38. DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE),
  39. DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC),
  40. };
  41. static const struct resource mt6357_rtc_resources[] = {
  42. DEFINE_RES_MEM(MT6357_RTC_BASE, MT6357_RTC_SIZE),
  43. DEFINE_RES_IRQ(MT6357_IRQ_RTC),
  44. };
  45. static const struct resource mt6331_rtc_resources[] = {
  46. DEFINE_RES_MEM(MT6331_RTC_BASE, MT6331_RTC_SIZE),
  47. DEFINE_RES_IRQ(MT6331_IRQ_STATUS_RTC),
  48. };
  49. static const struct resource mt6358_rtc_resources[] = {
  50. DEFINE_RES_MEM(MT6358_RTC_BASE, MT6358_RTC_SIZE),
  51. DEFINE_RES_IRQ(MT6358_IRQ_RTC),
  52. };
  53. static const struct resource mt6397_rtc_resources[] = {
  54. DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE),
  55. DEFINE_RES_IRQ(MT6397_IRQ_RTC),
  56. };
  57. static const struct resource mt6358_keys_resources[] = {
  58. DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY, "powerkey"),
  59. DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY, "homekey"),
  60. DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY_R, "powerkey_r"),
  61. DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY_R, "homekey_r"),
  62. };
  63. static const struct resource mt6359_keys_resources[] = {
  64. DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY, "powerkey"),
  65. DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY, "homekey"),
  66. DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY_R, "powerkey_r"),
  67. DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY_R, "homekey_r"),
  68. };
  69. static const struct resource mt6323_keys_resources[] = {
  70. DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"),
  71. DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"),
  72. };
  73. static const struct resource mt6357_keys_resources[] = {
  74. DEFINE_RES_IRQ_NAMED(MT6357_IRQ_PWRKEY, "powerkey"),
  75. DEFINE_RES_IRQ_NAMED(MT6357_IRQ_HOMEKEY, "homekey"),
  76. DEFINE_RES_IRQ_NAMED(MT6357_IRQ_PWRKEY_R, "powerkey_r"),
  77. DEFINE_RES_IRQ_NAMED(MT6357_IRQ_HOMEKEY_R, "homekey_r"),
  78. };
  79. static const struct resource mt6331_keys_resources[] = {
  80. DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_PWRKEY, "powerkey"),
  81. DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_HOMEKEY, "homekey"),
  82. };
  83. static const struct resource mt6397_keys_resources[] = {
  84. DEFINE_RES_IRQ_NAMED(MT6397_IRQ_PWRKEY, "powerkey"),
  85. DEFINE_RES_IRQ_NAMED(MT6397_IRQ_HOMEKEY, "homekey"),
  86. };
  87. static const struct resource mt6323_pwrc_resources[] = {
  88. DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE),
  89. };
  90. static const struct mfd_cell mt6323_devs[] = {
  91. {
  92. .name = "mt6323-rtc",
  93. .num_resources = ARRAY_SIZE(mt6323_rtc_resources),
  94. .resources = mt6323_rtc_resources,
  95. .of_compatible = "mediatek,mt6323-rtc",
  96. }, {
  97. .name = "mt6323-regulator",
  98. .of_compatible = "mediatek,mt6323-regulator"
  99. }, {
  100. .name = "mt6323-led",
  101. .of_compatible = "mediatek,mt6323-led"
  102. }, {
  103. .name = "mtk-pmic-keys",
  104. .num_resources = ARRAY_SIZE(mt6323_keys_resources),
  105. .resources = mt6323_keys_resources,
  106. .of_compatible = "mediatek,mt6323-keys"
  107. }, {
  108. .name = "mt6323-pwrc",
  109. .num_resources = ARRAY_SIZE(mt6323_pwrc_resources),
  110. .resources = mt6323_pwrc_resources,
  111. .of_compatible = "mediatek,mt6323-pwrc"
  112. },
  113. };
  114. static const struct mfd_cell mt6357_devs[] = {
  115. {
  116. .name = "mt6357-regulator",
  117. }, {
  118. .name = "mt6357-rtc",
  119. .num_resources = ARRAY_SIZE(mt6357_rtc_resources),
  120. .resources = mt6357_rtc_resources,
  121. .of_compatible = "mediatek,mt6357-rtc",
  122. }, {
  123. .name = "mtk-pmic-keys",
  124. .num_resources = ARRAY_SIZE(mt6357_keys_resources),
  125. .resources = mt6357_keys_resources,
  126. .of_compatible = "mediatek,mt6357-keys"
  127. },
  128. };
  129. /* MT6331 is always used in combination with MT6332 */
  130. static const struct mfd_cell mt6331_mt6332_devs[] = {
  131. {
  132. .name = "mt6331-rtc",
  133. .num_resources = ARRAY_SIZE(mt6331_rtc_resources),
  134. .resources = mt6331_rtc_resources,
  135. .of_compatible = "mediatek,mt6331-rtc",
  136. }, {
  137. .name = "mt6331-regulator",
  138. .of_compatible = "mediatek,mt6331-regulator"
  139. }, {
  140. .name = "mt6332-regulator",
  141. .of_compatible = "mediatek,mt6332-regulator"
  142. }, {
  143. .name = "mtk-pmic-keys",
  144. .num_resources = ARRAY_SIZE(mt6331_keys_resources),
  145. .resources = mt6331_keys_resources,
  146. .of_compatible = "mediatek,mt6331-keys"
  147. },
  148. };
  149. static const struct mfd_cell mt6358_devs[] = {
  150. {
  151. .name = "mt6358-regulator",
  152. .of_compatible = "mediatek,mt6358-regulator"
  153. }, {
  154. .name = "mt6358-rtc",
  155. .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
  156. .resources = mt6358_rtc_resources,
  157. .of_compatible = "mediatek,mt6358-rtc",
  158. }, {
  159. .name = "mt6358-sound",
  160. .of_compatible = "mediatek,mt6358-sound"
  161. }, {
  162. .name = "mt6358-keys",
  163. .num_resources = ARRAY_SIZE(mt6358_keys_resources),
  164. .resources = mt6358_keys_resources,
  165. .of_compatible = "mediatek,mt6358-keys"
  166. },
  167. };
  168. static const struct mfd_cell mt6359_devs[] = {
  169. { .name = "mt6359-regulator", },
  170. {
  171. .name = "mt6359-rtc",
  172. .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
  173. .resources = mt6358_rtc_resources,
  174. .of_compatible = "mediatek,mt6358-rtc",
  175. },
  176. { .name = "mt6359-sound", },
  177. {
  178. .name = "mtk-pmic-keys",
  179. .num_resources = ARRAY_SIZE(mt6359_keys_resources),
  180. .resources = mt6359_keys_resources,
  181. .of_compatible = "mediatek,mt6359-keys"
  182. },
  183. };
  184. static const struct mfd_cell mt6397_devs[] = {
  185. {
  186. .name = "mt6397-rtc",
  187. .num_resources = ARRAY_SIZE(mt6397_rtc_resources),
  188. .resources = mt6397_rtc_resources,
  189. .of_compatible = "mediatek,mt6397-rtc",
  190. }, {
  191. .name = "mt6397-regulator",
  192. .of_compatible = "mediatek,mt6397-regulator",
  193. }, {
  194. .name = "mt6397-codec",
  195. .of_compatible = "mediatek,mt6397-codec",
  196. }, {
  197. .name = "mt6397-clk",
  198. .of_compatible = "mediatek,mt6397-clk",
  199. }, {
  200. .name = "mt6397-pinctrl",
  201. .of_compatible = "mediatek,mt6397-pinctrl",
  202. }, {
  203. .name = "mtk-pmic-keys",
  204. .num_resources = ARRAY_SIZE(mt6397_keys_resources),
  205. .resources = mt6397_keys_resources,
  206. .of_compatible = "mediatek,mt6397-keys"
  207. }
  208. };
  209. struct chip_data {
  210. u32 cid_addr;
  211. u32 cid_shift;
  212. const struct mfd_cell *cells;
  213. int cell_size;
  214. int (*irq_init)(struct mt6397_chip *chip);
  215. };
  216. static const struct chip_data mt6323_core = {
  217. .cid_addr = MT6323_CID,
  218. .cid_shift = 0,
  219. .cells = mt6323_devs,
  220. .cell_size = ARRAY_SIZE(mt6323_devs),
  221. .irq_init = mt6397_irq_init,
  222. };
  223. static const struct chip_data mt6357_core = {
  224. .cid_addr = MT6357_SWCID,
  225. .cid_shift = 8,
  226. .cells = mt6357_devs,
  227. .cell_size = ARRAY_SIZE(mt6357_devs),
  228. .irq_init = mt6358_irq_init,
  229. };
  230. static const struct chip_data mt6331_mt6332_core = {
  231. .cid_addr = MT6331_HWCID,
  232. .cid_shift = 0,
  233. .cells = mt6331_mt6332_devs,
  234. .cell_size = ARRAY_SIZE(mt6331_mt6332_devs),
  235. .irq_init = mt6397_irq_init,
  236. };
  237. static const struct chip_data mt6358_core = {
  238. .cid_addr = MT6358_SWCID,
  239. .cid_shift = 8,
  240. .cells = mt6358_devs,
  241. .cell_size = ARRAY_SIZE(mt6358_devs),
  242. .irq_init = mt6358_irq_init,
  243. };
  244. static const struct chip_data mt6359_core = {
  245. .cid_addr = MT6359_SWCID,
  246. .cid_shift = 8,
  247. .cells = mt6359_devs,
  248. .cell_size = ARRAY_SIZE(mt6359_devs),
  249. .irq_init = mt6358_irq_init,
  250. };
  251. static const struct chip_data mt6397_core = {
  252. .cid_addr = MT6397_CID,
  253. .cid_shift = 0,
  254. .cells = mt6397_devs,
  255. .cell_size = ARRAY_SIZE(mt6397_devs),
  256. .irq_init = mt6397_irq_init,
  257. };
  258. static int mt6397_probe(struct platform_device *pdev)
  259. {
  260. int ret;
  261. unsigned int id = 0;
  262. struct mt6397_chip *pmic;
  263. const struct chip_data *pmic_core;
  264. pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
  265. if (!pmic)
  266. return -ENOMEM;
  267. pmic->dev = &pdev->dev;
  268. /*
  269. * mt6397 MFD is child device of soc pmic wrapper.
  270. * Regmap is set from its parent.
  271. */
  272. pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL);
  273. if (!pmic->regmap)
  274. return -ENODEV;
  275. pmic_core = of_device_get_match_data(&pdev->dev);
  276. if (!pmic_core)
  277. return -ENODEV;
  278. ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
  279. if (ret) {
  280. dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret);
  281. return ret;
  282. }
  283. pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff;
  284. platform_set_drvdata(pdev, pmic);
  285. pmic->irq = platform_get_irq(pdev, 0);
  286. if (pmic->irq <= 0)
  287. return pmic->irq;
  288. ret = pmic_core->irq_init(pmic);
  289. if (ret)
  290. return ret;
  291. ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
  292. pmic_core->cells, pmic_core->cell_size,
  293. NULL, 0, pmic->irq_domain);
  294. if (ret) {
  295. irq_domain_remove(pmic->irq_domain);
  296. dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
  297. }
  298. return ret;
  299. }
  300. static const struct of_device_id mt6397_of_match[] = {
  301. {
  302. .compatible = "mediatek,mt6323",
  303. .data = &mt6323_core,
  304. }, {
  305. .compatible = "mediatek,mt6331",
  306. .data = &mt6331_mt6332_core,
  307. }, {
  308. .compatible = "mediatek,mt6357",
  309. .data = &mt6357_core,
  310. }, {
  311. .compatible = "mediatek,mt6358",
  312. .data = &mt6358_core,
  313. }, {
  314. .compatible = "mediatek,mt6359",
  315. .data = &mt6359_core,
  316. }, {
  317. .compatible = "mediatek,mt6397",
  318. .data = &mt6397_core,
  319. }, {
  320. /* sentinel */
  321. }
  322. };
  323. MODULE_DEVICE_TABLE(of, mt6397_of_match);
  324. static const struct platform_device_id mt6397_id[] = {
  325. { "mt6397", 0 },
  326. { },
  327. };
  328. MODULE_DEVICE_TABLE(platform, mt6397_id);
  329. static struct platform_driver mt6397_driver = {
  330. .probe = mt6397_probe,
  331. .driver = {
  332. .name = "mt6397",
  333. .of_match_table = mt6397_of_match,
  334. },
  335. .id_table = mt6397_id,
  336. };
  337. module_platform_driver(mt6397_driver);
  338. MODULE_AUTHOR("Flora Fu, MediaTek");
  339. MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
  340. MODULE_LICENSE("GPL");