11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 26df8dd5cSFlora Fu /* 36df8dd5cSFlora Fu * Copyright (c) 2014 MediaTek Inc. 46df8dd5cSFlora Fu * Author: Flora Fu, MediaTek 56df8dd5cSFlora Fu */ 66df8dd5cSFlora Fu 76df8dd5cSFlora Fu #include <linux/interrupt.h> 87c3f7cd5SJosef Friedl #include <linux/ioport.h> 96df8dd5cSFlora Fu #include <linux/module.h> 106df8dd5cSFlora Fu #include <linux/of_device.h> 116df8dd5cSFlora Fu #include <linux/of_irq.h> 126df8dd5cSFlora Fu #include <linux/regmap.h> 136df8dd5cSFlora Fu #include <linux/mfd/core.h> 1444760cf3SJohn Crispin #include <linux/mfd/mt6323/core.h> 152b91c28fSHsin-Hsiung Wang #include <linux/mfd/mt6358/core.h> 16708cb5ccSHsin-Hsiung Wang #include <linux/mfd/mt6397/core.h> 1744760cf3SJohn Crispin #include <linux/mfd/mt6323/registers.h> 182b91c28fSHsin-Hsiung Wang #include <linux/mfd/mt6358/registers.h> 19708cb5ccSHsin-Hsiung Wang #include <linux/mfd/mt6397/registers.h> 206df8dd5cSFlora Fu 218391c6cbSJosef Friedl #define MT6323_RTC_BASE 0x8000 228391c6cbSJosef Friedl #define MT6323_RTC_SIZE 0x40 238391c6cbSJosef Friedl 242b91c28fSHsin-Hsiung Wang #define MT6358_RTC_BASE 0x0588 252b91c28fSHsin-Hsiung Wang #define MT6358_RTC_SIZE 0x3c 262b91c28fSHsin-Hsiung Wang 27a5d7ea09SEddie Huang #define MT6397_RTC_BASE 0xe000 28a5d7ea09SEddie Huang #define MT6397_RTC_SIZE 0x3e 29a5d7ea09SEddie Huang 308391c6cbSJosef Friedl #define MT6323_PWRC_BASE 0x8000 318391c6cbSJosef Friedl #define MT6323_PWRC_SIZE 0x40 328391c6cbSJosef Friedl 338391c6cbSJosef Friedl static const struct resource mt6323_rtc_resources[] = { 348391c6cbSJosef Friedl DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE), 358391c6cbSJosef Friedl DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC), 368391c6cbSJosef Friedl }; 378391c6cbSJosef Friedl 382b91c28fSHsin-Hsiung Wang static const struct resource mt6358_rtc_resources[] = { 392b91c28fSHsin-Hsiung Wang DEFINE_RES_MEM(MT6358_RTC_BASE, MT6358_RTC_SIZE), 402b91c28fSHsin-Hsiung Wang DEFINE_RES_IRQ(MT6358_IRQ_RTC), 412b91c28fSHsin-Hsiung Wang }; 422b91c28fSHsin-Hsiung Wang 43a5d7ea09SEddie Huang static const struct resource mt6397_rtc_resources[] = { 447c3f7cd5SJosef Friedl DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE), 457c3f7cd5SJosef Friedl DEFINE_RES_IRQ(MT6397_IRQ_RTC), 46a5d7ea09SEddie Huang }; 47a5d7ea09SEddie Huang 4855d1d154SChen Zhong static const struct resource mt6323_keys_resources[] = { 4955d1d154SChen Zhong DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY), 5055d1d154SChen Zhong DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY), 5155d1d154SChen Zhong }; 5255d1d154SChen Zhong 5355d1d154SChen Zhong static const struct resource mt6397_keys_resources[] = { 5455d1d154SChen Zhong DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY), 5555d1d154SChen Zhong DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY), 5655d1d154SChen Zhong }; 5755d1d154SChen Zhong 588391c6cbSJosef Friedl static const struct resource mt6323_pwrc_resources[] = { 598391c6cbSJosef Friedl DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE), 608391c6cbSJosef Friedl }; 618391c6cbSJosef Friedl 6244760cf3SJohn Crispin static const struct mfd_cell mt6323_devs[] = { 6344760cf3SJohn Crispin { 648391c6cbSJosef Friedl .name = "mt6323-rtc", 658391c6cbSJosef Friedl .num_resources = ARRAY_SIZE(mt6323_rtc_resources), 668391c6cbSJosef Friedl .resources = mt6323_rtc_resources, 678391c6cbSJosef Friedl .of_compatible = "mediatek,mt6323-rtc", 688391c6cbSJosef Friedl }, { 6944760cf3SJohn Crispin .name = "mt6323-regulator", 7044760cf3SJohn Crispin .of_compatible = "mediatek,mt6323-regulator" 71040fc9b1SSean Wang }, { 721cb8af8dSSean Wang .name = "mt6323-led", 731cb8af8dSSean Wang .of_compatible = "mediatek,mt6323-led" 7455d1d154SChen Zhong }, { 7555d1d154SChen Zhong .name = "mtk-pmic-keys", 7655d1d154SChen Zhong .num_resources = ARRAY_SIZE(mt6323_keys_resources), 7755d1d154SChen Zhong .resources = mt6323_keys_resources, 7855d1d154SChen Zhong .of_compatible = "mediatek,mt6323-keys" 798391c6cbSJosef Friedl }, { 808391c6cbSJosef Friedl .name = "mt6323-pwrc", 818391c6cbSJosef Friedl .num_resources = ARRAY_SIZE(mt6323_pwrc_resources), 828391c6cbSJosef Friedl .resources = mt6323_pwrc_resources, 838391c6cbSJosef Friedl .of_compatible = "mediatek,mt6323-pwrc" 841cb8af8dSSean Wang }, 8544760cf3SJohn Crispin }; 8644760cf3SJohn Crispin 872b91c28fSHsin-Hsiung Wang static const struct mfd_cell mt6358_devs[] = { 882b91c28fSHsin-Hsiung Wang { 892b91c28fSHsin-Hsiung Wang .name = "mt6358-regulator", 902b91c28fSHsin-Hsiung Wang .of_compatible = "mediatek,mt6358-regulator" 912b91c28fSHsin-Hsiung Wang }, { 922b91c28fSHsin-Hsiung Wang .name = "mt6358-rtc", 932b91c28fSHsin-Hsiung Wang .num_resources = ARRAY_SIZE(mt6358_rtc_resources), 942b91c28fSHsin-Hsiung Wang .resources = mt6358_rtc_resources, 952b91c28fSHsin-Hsiung Wang .of_compatible = "mediatek,mt6358-rtc", 962b91c28fSHsin-Hsiung Wang }, { 972b91c28fSHsin-Hsiung Wang .name = "mt6358-sound", 982b91c28fSHsin-Hsiung Wang .of_compatible = "mediatek,mt6358-sound" 992b91c28fSHsin-Hsiung Wang }, 1002b91c28fSHsin-Hsiung Wang }; 1012b91c28fSHsin-Hsiung Wang 1026df8dd5cSFlora Fu static const struct mfd_cell mt6397_devs[] = { 1036df8dd5cSFlora Fu { 1046df8dd5cSFlora Fu .name = "mt6397-rtc", 105a5d7ea09SEddie Huang .num_resources = ARRAY_SIZE(mt6397_rtc_resources), 106a5d7ea09SEddie Huang .resources = mt6397_rtc_resources, 1076df8dd5cSFlora Fu .of_compatible = "mediatek,mt6397-rtc", 1086df8dd5cSFlora Fu }, { 1096df8dd5cSFlora Fu .name = "mt6397-regulator", 1106df8dd5cSFlora Fu .of_compatible = "mediatek,mt6397-regulator", 1116df8dd5cSFlora Fu }, { 1126df8dd5cSFlora Fu .name = "mt6397-codec", 1136df8dd5cSFlora Fu .of_compatible = "mediatek,mt6397-codec", 1146df8dd5cSFlora Fu }, { 1156df8dd5cSFlora Fu .name = "mt6397-clk", 1166df8dd5cSFlora Fu .of_compatible = "mediatek,mt6397-clk", 117cf55078bSHongzhou Yang }, { 118cf55078bSHongzhou Yang .name = "mt6397-pinctrl", 119cf55078bSHongzhou Yang .of_compatible = "mediatek,mt6397-pinctrl", 12055d1d154SChen Zhong }, { 12155d1d154SChen Zhong .name = "mtk-pmic-keys", 12255d1d154SChen Zhong .num_resources = ARRAY_SIZE(mt6397_keys_resources), 12355d1d154SChen Zhong .resources = mt6397_keys_resources, 12455d1d154SChen Zhong .of_compatible = "mediatek,mt6397-keys" 12555d1d154SChen Zhong } 1266df8dd5cSFlora Fu }; 1276df8dd5cSFlora Fu 12811c4f2beSFrank Wunderlich struct chip_data { 12911c4f2beSFrank Wunderlich u32 cid_addr; 13011c4f2beSFrank Wunderlich u32 cid_shift; 131d0c7347dSHsin-Hsiung Wang const struct mfd_cell *cells; 132d0c7347dSHsin-Hsiung Wang int cell_size; 133d0c7347dSHsin-Hsiung Wang int (*irq_init)(struct mt6397_chip *chip); 13411c4f2beSFrank Wunderlich }; 13511c4f2beSFrank Wunderlich 13611c4f2beSFrank Wunderlich static const struct chip_data mt6323_core = { 13711c4f2beSFrank Wunderlich .cid_addr = MT6323_CID, 13811c4f2beSFrank Wunderlich .cid_shift = 0, 139d0c7347dSHsin-Hsiung Wang .cells = mt6323_devs, 140d0c7347dSHsin-Hsiung Wang .cell_size = ARRAY_SIZE(mt6323_devs), 141d0c7347dSHsin-Hsiung Wang .irq_init = mt6397_irq_init, 14211c4f2beSFrank Wunderlich }; 14311c4f2beSFrank Wunderlich 1442b91c28fSHsin-Hsiung Wang static const struct chip_data mt6358_core = { 1452b91c28fSHsin-Hsiung Wang .cid_addr = MT6358_SWCID, 1462b91c28fSHsin-Hsiung Wang .cid_shift = 8, 1472b91c28fSHsin-Hsiung Wang .cells = mt6358_devs, 1482b91c28fSHsin-Hsiung Wang .cell_size = ARRAY_SIZE(mt6358_devs), 1492b91c28fSHsin-Hsiung Wang .irq_init = mt6358_irq_init, 1502b91c28fSHsin-Hsiung Wang }; 1512b91c28fSHsin-Hsiung Wang 15211c4f2beSFrank Wunderlich static const struct chip_data mt6397_core = { 15311c4f2beSFrank Wunderlich .cid_addr = MT6397_CID, 15411c4f2beSFrank Wunderlich .cid_shift = 0, 155d0c7347dSHsin-Hsiung Wang .cells = mt6397_devs, 156d0c7347dSHsin-Hsiung Wang .cell_size = ARRAY_SIZE(mt6397_devs), 157d0c7347dSHsin-Hsiung Wang .irq_init = mt6397_irq_init, 15811c4f2beSFrank Wunderlich }; 15911c4f2beSFrank Wunderlich 1606df8dd5cSFlora Fu static int mt6397_probe(struct platform_device *pdev) 1616df8dd5cSFlora Fu { 1626df8dd5cSFlora Fu int ret; 163d0c7347dSHsin-Hsiung Wang unsigned int id = 0; 1641d2c25edSJohn Crispin struct mt6397_chip *pmic; 16511c4f2beSFrank Wunderlich const struct chip_data *pmic_core; 1666df8dd5cSFlora Fu 1671d2c25edSJohn Crispin pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 1681d2c25edSJohn Crispin if (!pmic) 1696df8dd5cSFlora Fu return -ENOMEM; 1706df8dd5cSFlora Fu 1711d2c25edSJohn Crispin pmic->dev = &pdev->dev; 172feec4799SJohn Crispin 1736df8dd5cSFlora Fu /* 1746df8dd5cSFlora Fu * mt6397 MFD is child device of soc pmic wrapper. 1756df8dd5cSFlora Fu * Regmap is set from its parent. 1766df8dd5cSFlora Fu */ 1771d2c25edSJohn Crispin pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL); 1781d2c25edSJohn Crispin if (!pmic->regmap) 1796df8dd5cSFlora Fu return -ENODEV; 1806df8dd5cSFlora Fu 18111c4f2beSFrank Wunderlich pmic_core = of_device_get_match_data(&pdev->dev); 18211c4f2beSFrank Wunderlich if (!pmic_core) 18311c4f2beSFrank Wunderlich return -ENODEV; 1846df8dd5cSFlora Fu 18511c4f2beSFrank Wunderlich ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id); 1861d2c25edSJohn Crispin if (ret) { 18711c4f2beSFrank Wunderlich dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret); 1881387ff53SHenry Chen return ret; 1891d2c25edSJohn Crispin } 1901d2c25edSJohn Crispin 19111c4f2beSFrank Wunderlich pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff; 19211c4f2beSFrank Wunderlich 19311c4f2beSFrank Wunderlich platform_set_drvdata(pdev, pmic); 19411c4f2beSFrank Wunderlich 1951387ff53SHenry Chen pmic->irq = platform_get_irq(pdev, 0); 1961387ff53SHenry Chen if (pmic->irq <= 0) 1971387ff53SHenry Chen return pmic->irq; 1981387ff53SHenry Chen 199d0c7347dSHsin-Hsiung Wang ret = pmic_core->irq_init(pmic); 2001387ff53SHenry Chen if (ret) 2011387ff53SHenry Chen return ret; 2021387ff53SHenry Chen 203eb00f70dSFabien Parent ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, 204d0c7347dSHsin-Hsiung Wang pmic_core->cells, pmic_core->cell_size, 205eb00f70dSFabien Parent NULL, 0, pmic->irq_domain); 2061d2c25edSJohn Crispin if (ret) { 2071d2c25edSJohn Crispin irq_domain_remove(pmic->irq_domain); 2086df8dd5cSFlora Fu dev_err(&pdev->dev, "failed to add child devices: %d\n", ret); 2091d2c25edSJohn Crispin } 2106df8dd5cSFlora Fu 2116df8dd5cSFlora Fu return ret; 2126df8dd5cSFlora Fu } 2136df8dd5cSFlora Fu 2146df8dd5cSFlora Fu static const struct of_device_id mt6397_of_match[] = { 21511c4f2beSFrank Wunderlich { 21611c4f2beSFrank Wunderlich .compatible = "mediatek,mt6323", 21711c4f2beSFrank Wunderlich .data = &mt6323_core, 21811c4f2beSFrank Wunderlich }, { 2192b91c28fSHsin-Hsiung Wang .compatible = "mediatek,mt6358", 2202b91c28fSHsin-Hsiung Wang .data = &mt6358_core, 2212b91c28fSHsin-Hsiung Wang }, { 22211c4f2beSFrank Wunderlich .compatible = "mediatek,mt6397", 22311c4f2beSFrank Wunderlich .data = &mt6397_core, 22411c4f2beSFrank Wunderlich }, { 22511c4f2beSFrank Wunderlich /* sentinel */ 22611c4f2beSFrank Wunderlich } 2276df8dd5cSFlora Fu }; 2286df8dd5cSFlora Fu MODULE_DEVICE_TABLE(of, mt6397_of_match); 2296df8dd5cSFlora Fu 230e1d9a109SJavier Martinez Canillas static const struct platform_device_id mt6397_id[] = { 231e1d9a109SJavier Martinez Canillas { "mt6397", 0 }, 232e1d9a109SJavier Martinez Canillas { }, 233e1d9a109SJavier Martinez Canillas }; 234e1d9a109SJavier Martinez Canillas MODULE_DEVICE_TABLE(platform, mt6397_id); 235e1d9a109SJavier Martinez Canillas 2366df8dd5cSFlora Fu static struct platform_driver mt6397_driver = { 2376df8dd5cSFlora Fu .probe = mt6397_probe, 2386df8dd5cSFlora Fu .driver = { 2396df8dd5cSFlora Fu .name = "mt6397", 240*4fae3010SKrzysztof Kozlowski .of_match_table = mt6397_of_match, 2416df8dd5cSFlora Fu }, 242e1d9a109SJavier Martinez Canillas .id_table = mt6397_id, 2436df8dd5cSFlora Fu }; 2446df8dd5cSFlora Fu 2456df8dd5cSFlora Fu module_platform_driver(mt6397_driver); 2466df8dd5cSFlora Fu 2476df8dd5cSFlora Fu MODULE_AUTHOR("Flora Fu, MediaTek"); 2486df8dd5cSFlora Fu MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC"); 2496df8dd5cSFlora Fu MODULE_LICENSE("GPL"); 250