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