Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2014 MediaTek Inc.
0004  * Author: Flora Fu, MediaTek
0005  */
0006 
0007 #include <linux/interrupt.h>
0008 #include <linux/ioport.h>
0009 #include <linux/module.h>
0010 #include <linux/of_device.h>
0011 #include <linux/of_irq.h>
0012 #include <linux/regmap.h>
0013 #include <linux/mfd/core.h>
0014 #include <linux/mfd/mt6323/core.h>
0015 #include <linux/mfd/mt6331/core.h>
0016 #include <linux/mfd/mt6357/core.h>
0017 #include <linux/mfd/mt6358/core.h>
0018 #include <linux/mfd/mt6359/core.h>
0019 #include <linux/mfd/mt6397/core.h>
0020 #include <linux/mfd/mt6323/registers.h>
0021 #include <linux/mfd/mt6331/registers.h>
0022 #include <linux/mfd/mt6357/registers.h>
0023 #include <linux/mfd/mt6358/registers.h>
0024 #include <linux/mfd/mt6359/registers.h>
0025 #include <linux/mfd/mt6397/registers.h>
0026 
0027 #define MT6323_RTC_BASE     0x8000
0028 #define MT6323_RTC_SIZE     0x40
0029 
0030 #define MT6357_RTC_BASE     0x0588
0031 #define MT6357_RTC_SIZE     0x3c
0032 
0033 #define MT6331_RTC_BASE     0x4000
0034 #define MT6331_RTC_SIZE     0x40
0035 
0036 #define MT6358_RTC_BASE     0x0588
0037 #define MT6358_RTC_SIZE     0x3c
0038 
0039 #define MT6397_RTC_BASE     0xe000
0040 #define MT6397_RTC_SIZE     0x3e
0041 
0042 #define MT6323_PWRC_BASE    0x8000
0043 #define MT6323_PWRC_SIZE    0x40
0044 
0045 static const struct resource mt6323_rtc_resources[] = {
0046     DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE),
0047     DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC),
0048 };
0049 
0050 static const struct resource mt6357_rtc_resources[] = {
0051     DEFINE_RES_MEM(MT6357_RTC_BASE, MT6357_RTC_SIZE),
0052     DEFINE_RES_IRQ(MT6357_IRQ_RTC),
0053 };
0054 
0055 static const struct resource mt6331_rtc_resources[] = {
0056     DEFINE_RES_MEM(MT6331_RTC_BASE, MT6331_RTC_SIZE),
0057     DEFINE_RES_IRQ(MT6331_IRQ_STATUS_RTC),
0058 };
0059 
0060 static const struct resource mt6358_rtc_resources[] = {
0061     DEFINE_RES_MEM(MT6358_RTC_BASE, MT6358_RTC_SIZE),
0062     DEFINE_RES_IRQ(MT6358_IRQ_RTC),
0063 };
0064 
0065 static const struct resource mt6397_rtc_resources[] = {
0066     DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE),
0067     DEFINE_RES_IRQ(MT6397_IRQ_RTC),
0068 };
0069 
0070 static const struct resource mt6358_keys_resources[] = {
0071     DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY, "powerkey"),
0072     DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY, "homekey"),
0073     DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY_R, "powerkey_r"),
0074     DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY_R, "homekey_r"),
0075 };
0076 
0077 static const struct resource mt6359_keys_resources[] = {
0078     DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY, "powerkey"),
0079     DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY, "homekey"),
0080     DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY_R, "powerkey_r"),
0081     DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY_R, "homekey_r"),
0082 };
0083 
0084 static const struct resource mt6323_keys_resources[] = {
0085     DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"),
0086     DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"),
0087 };
0088 
0089 static const struct resource mt6357_keys_resources[] = {
0090     DEFINE_RES_IRQ_NAMED(MT6357_IRQ_PWRKEY, "powerkey"),
0091     DEFINE_RES_IRQ_NAMED(MT6357_IRQ_HOMEKEY, "homekey"),
0092     DEFINE_RES_IRQ_NAMED(MT6357_IRQ_PWRKEY_R, "powerkey_r"),
0093     DEFINE_RES_IRQ_NAMED(MT6357_IRQ_HOMEKEY_R, "homekey_r"),
0094 };
0095 
0096 static const struct resource mt6331_keys_resources[] = {
0097     DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_PWRKEY, "powerkey"),
0098     DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_HOMEKEY, "homekey"),
0099 };
0100 
0101 static const struct resource mt6397_keys_resources[] = {
0102     DEFINE_RES_IRQ_NAMED(MT6397_IRQ_PWRKEY, "powerkey"),
0103     DEFINE_RES_IRQ_NAMED(MT6397_IRQ_HOMEKEY, "homekey"),
0104 };
0105 
0106 static const struct resource mt6323_pwrc_resources[] = {
0107     DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE),
0108 };
0109 
0110 static const struct mfd_cell mt6323_devs[] = {
0111     {
0112         .name = "mt6323-rtc",
0113         .num_resources = ARRAY_SIZE(mt6323_rtc_resources),
0114         .resources = mt6323_rtc_resources,
0115         .of_compatible = "mediatek,mt6323-rtc",
0116     }, {
0117         .name = "mt6323-regulator",
0118         .of_compatible = "mediatek,mt6323-regulator"
0119     }, {
0120         .name = "mt6323-led",
0121         .of_compatible = "mediatek,mt6323-led"
0122     }, {
0123         .name = "mtk-pmic-keys",
0124         .num_resources = ARRAY_SIZE(mt6323_keys_resources),
0125         .resources = mt6323_keys_resources,
0126         .of_compatible = "mediatek,mt6323-keys"
0127     }, {
0128         .name = "mt6323-pwrc",
0129         .num_resources = ARRAY_SIZE(mt6323_pwrc_resources),
0130         .resources = mt6323_pwrc_resources,
0131         .of_compatible = "mediatek,mt6323-pwrc"
0132     },
0133 };
0134 
0135 static const struct mfd_cell mt6357_devs[] = {
0136     {
0137         .name = "mt6357-regulator",
0138     }, {
0139         .name = "mt6357-rtc",
0140         .num_resources = ARRAY_SIZE(mt6357_rtc_resources),
0141         .resources = mt6357_rtc_resources,
0142         .of_compatible = "mediatek,mt6357-rtc",
0143     }, {
0144         .name = "mtk-pmic-keys",
0145         .num_resources = ARRAY_SIZE(mt6357_keys_resources),
0146         .resources = mt6357_keys_resources,
0147         .of_compatible = "mediatek,mt6357-keys"
0148     },
0149 };
0150 
0151 /* MT6331 is always used in combination with MT6332 */
0152 static const struct mfd_cell mt6331_mt6332_devs[] = {
0153     {
0154         .name = "mt6331-rtc",
0155         .num_resources = ARRAY_SIZE(mt6331_rtc_resources),
0156         .resources = mt6331_rtc_resources,
0157         .of_compatible = "mediatek,mt6331-rtc",
0158     }, {
0159         .name = "mt6331-regulator",
0160         .of_compatible = "mediatek,mt6331-regulator"
0161     }, {
0162         .name = "mt6332-regulator",
0163         .of_compatible = "mediatek,mt6332-regulator"
0164     }, {
0165         .name = "mtk-pmic-keys",
0166         .num_resources = ARRAY_SIZE(mt6331_keys_resources),
0167         .resources = mt6331_keys_resources,
0168         .of_compatible = "mediatek,mt6331-keys"
0169     },
0170 };
0171 
0172 static const struct mfd_cell mt6358_devs[] = {
0173     {
0174         .name = "mt6358-regulator",
0175         .of_compatible = "mediatek,mt6358-regulator"
0176     }, {
0177         .name = "mt6358-rtc",
0178         .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
0179         .resources = mt6358_rtc_resources,
0180         .of_compatible = "mediatek,mt6358-rtc",
0181     }, {
0182         .name = "mt6358-sound",
0183         .of_compatible = "mediatek,mt6358-sound"
0184     }, {
0185         .name = "mt6358-keys",
0186         .num_resources = ARRAY_SIZE(mt6358_keys_resources),
0187         .resources = mt6358_keys_resources,
0188         .of_compatible = "mediatek,mt6358-keys"
0189     },
0190 };
0191 
0192 static const struct mfd_cell mt6359_devs[] = {
0193     { .name = "mt6359-regulator", },
0194     {
0195         .name = "mt6359-rtc",
0196         .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
0197         .resources = mt6358_rtc_resources,
0198         .of_compatible = "mediatek,mt6358-rtc",
0199     },
0200     { .name = "mt6359-sound", },
0201     {
0202         .name = "mtk-pmic-keys",
0203         .num_resources = ARRAY_SIZE(mt6359_keys_resources),
0204         .resources = mt6359_keys_resources,
0205         .of_compatible = "mediatek,mt6359-keys"
0206     },
0207 };
0208 
0209 static const struct mfd_cell mt6397_devs[] = {
0210     {
0211         .name = "mt6397-rtc",
0212         .num_resources = ARRAY_SIZE(mt6397_rtc_resources),
0213         .resources = mt6397_rtc_resources,
0214         .of_compatible = "mediatek,mt6397-rtc",
0215     }, {
0216         .name = "mt6397-regulator",
0217         .of_compatible = "mediatek,mt6397-regulator",
0218     }, {
0219         .name = "mt6397-codec",
0220         .of_compatible = "mediatek,mt6397-codec",
0221     }, {
0222         .name = "mt6397-clk",
0223         .of_compatible = "mediatek,mt6397-clk",
0224     }, {
0225         .name = "mt6397-pinctrl",
0226         .of_compatible = "mediatek,mt6397-pinctrl",
0227     }, {
0228         .name = "mtk-pmic-keys",
0229         .num_resources = ARRAY_SIZE(mt6397_keys_resources),
0230         .resources = mt6397_keys_resources,
0231         .of_compatible = "mediatek,mt6397-keys"
0232     }
0233 };
0234 
0235 struct chip_data {
0236     u32 cid_addr;
0237     u32 cid_shift;
0238     const struct mfd_cell *cells;
0239     int cell_size;
0240     int (*irq_init)(struct mt6397_chip *chip);
0241 };
0242 
0243 static const struct chip_data mt6323_core = {
0244     .cid_addr = MT6323_CID,
0245     .cid_shift = 0,
0246     .cells = mt6323_devs,
0247     .cell_size = ARRAY_SIZE(mt6323_devs),
0248     .irq_init = mt6397_irq_init,
0249 };
0250 
0251 static const struct chip_data mt6357_core = {
0252     .cid_addr = MT6357_SWCID,
0253     .cid_shift = 8,
0254     .cells = mt6357_devs,
0255     .cell_size = ARRAY_SIZE(mt6357_devs),
0256     .irq_init = mt6358_irq_init,
0257 };
0258 
0259 static const struct chip_data mt6331_mt6332_core = {
0260     .cid_addr = MT6331_HWCID,
0261     .cid_shift = 0,
0262     .cells = mt6331_mt6332_devs,
0263     .cell_size = ARRAY_SIZE(mt6331_mt6332_devs),
0264     .irq_init = mt6397_irq_init,
0265 };
0266 
0267 static const struct chip_data mt6358_core = {
0268     .cid_addr = MT6358_SWCID,
0269     .cid_shift = 8,
0270     .cells = mt6358_devs,
0271     .cell_size = ARRAY_SIZE(mt6358_devs),
0272     .irq_init = mt6358_irq_init,
0273 };
0274 
0275 static const struct chip_data mt6359_core = {
0276     .cid_addr = MT6359_SWCID,
0277     .cid_shift = 8,
0278     .cells = mt6359_devs,
0279     .cell_size = ARRAY_SIZE(mt6359_devs),
0280     .irq_init = mt6358_irq_init,
0281 };
0282 
0283 static const struct chip_data mt6397_core = {
0284     .cid_addr = MT6397_CID,
0285     .cid_shift = 0,
0286     .cells = mt6397_devs,
0287     .cell_size = ARRAY_SIZE(mt6397_devs),
0288     .irq_init = mt6397_irq_init,
0289 };
0290 
0291 static int mt6397_probe(struct platform_device *pdev)
0292 {
0293     int ret;
0294     unsigned int id = 0;
0295     struct mt6397_chip *pmic;
0296     const struct chip_data *pmic_core;
0297 
0298     pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
0299     if (!pmic)
0300         return -ENOMEM;
0301 
0302     pmic->dev = &pdev->dev;
0303 
0304     /*
0305      * mt6397 MFD is child device of soc pmic wrapper.
0306      * Regmap is set from its parent.
0307      */
0308     pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL);
0309     if (!pmic->regmap)
0310         return -ENODEV;
0311 
0312     pmic_core = of_device_get_match_data(&pdev->dev);
0313     if (!pmic_core)
0314         return -ENODEV;
0315 
0316     ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
0317     if (ret) {
0318         dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret);
0319         return ret;
0320     }
0321 
0322     pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff;
0323 
0324     platform_set_drvdata(pdev, pmic);
0325 
0326     pmic->irq = platform_get_irq(pdev, 0);
0327     if (pmic->irq <= 0)
0328         return pmic->irq;
0329 
0330     ret = pmic_core->irq_init(pmic);
0331     if (ret)
0332         return ret;
0333 
0334     ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
0335                    pmic_core->cells, pmic_core->cell_size,
0336                    NULL, 0, pmic->irq_domain);
0337     if (ret) {
0338         irq_domain_remove(pmic->irq_domain);
0339         dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
0340     }
0341 
0342     return ret;
0343 }
0344 
0345 static const struct of_device_id mt6397_of_match[] = {
0346     {
0347         .compatible = "mediatek,mt6323",
0348         .data = &mt6323_core,
0349     }, {
0350         .compatible = "mediatek,mt6331",
0351         .data = &mt6331_mt6332_core,
0352     }, {
0353         .compatible = "mediatek,mt6357",
0354         .data = &mt6357_core,
0355     }, {
0356         .compatible = "mediatek,mt6358",
0357         .data = &mt6358_core,
0358     }, {
0359         .compatible = "mediatek,mt6359",
0360         .data = &mt6359_core,
0361     }, {
0362         .compatible = "mediatek,mt6397",
0363         .data = &mt6397_core,
0364     }, {
0365         /* sentinel */
0366     }
0367 };
0368 MODULE_DEVICE_TABLE(of, mt6397_of_match);
0369 
0370 static const struct platform_device_id mt6397_id[] = {
0371     { "mt6397", 0 },
0372     { },
0373 };
0374 MODULE_DEVICE_TABLE(platform, mt6397_id);
0375 
0376 static struct platform_driver mt6397_driver = {
0377     .probe = mt6397_probe,
0378     .driver = {
0379         .name = "mt6397",
0380         .of_match_table = mt6397_of_match,
0381     },
0382     .id_table = mt6397_id,
0383 };
0384 
0385 module_platform_driver(mt6397_driver);
0386 
0387 MODULE_AUTHOR("Flora Fu, MediaTek");
0388 MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
0389 MODULE_LICENSE("GPL");