18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014 MediaTek Inc. 48c2ecf20Sopenharmony_ci * Author: Flora Fu, MediaTek 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 88c2ecf20Sopenharmony_ci#include <linux/ioport.h> 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/of_device.h> 118c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 128c2ecf20Sopenharmony_ci#include <linux/regmap.h> 138c2ecf20Sopenharmony_ci#include <linux/mfd/core.h> 148c2ecf20Sopenharmony_ci#include <linux/mfd/mt6323/core.h> 158c2ecf20Sopenharmony_ci#include <linux/mfd/mt6358/core.h> 168c2ecf20Sopenharmony_ci#include <linux/mfd/mt6397/core.h> 178c2ecf20Sopenharmony_ci#include <linux/mfd/mt6323/registers.h> 188c2ecf20Sopenharmony_ci#include <linux/mfd/mt6358/registers.h> 198c2ecf20Sopenharmony_ci#include <linux/mfd/mt6397/registers.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define MT6323_RTC_BASE 0x8000 228c2ecf20Sopenharmony_ci#define MT6323_RTC_SIZE 0x40 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define MT6358_RTC_BASE 0x0588 258c2ecf20Sopenharmony_ci#define MT6358_RTC_SIZE 0x3c 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define MT6397_RTC_BASE 0xe000 288c2ecf20Sopenharmony_ci#define MT6397_RTC_SIZE 0x3e 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define MT6323_PWRC_BASE 0x8000 318c2ecf20Sopenharmony_ci#define MT6323_PWRC_SIZE 0x40 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic const struct resource mt6323_rtc_resources[] = { 348c2ecf20Sopenharmony_ci DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE), 358c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC), 368c2ecf20Sopenharmony_ci}; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic const struct resource mt6358_rtc_resources[] = { 398c2ecf20Sopenharmony_ci DEFINE_RES_MEM(MT6358_RTC_BASE, MT6358_RTC_SIZE), 408c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(MT6358_IRQ_RTC), 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic const struct resource mt6397_rtc_resources[] = { 448c2ecf20Sopenharmony_ci DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE), 458c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(MT6397_IRQ_RTC), 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic const struct resource mt6323_keys_resources[] = { 498c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY), 508c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY), 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic const struct resource mt6397_keys_resources[] = { 548c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY), 558c2ecf20Sopenharmony_ci DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY), 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic const struct resource mt6323_pwrc_resources[] = { 598c2ecf20Sopenharmony_ci DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE), 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic const struct mfd_cell mt6323_devs[] = { 638c2ecf20Sopenharmony_ci { 648c2ecf20Sopenharmony_ci .name = "mt6323-rtc", 658c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(mt6323_rtc_resources), 668c2ecf20Sopenharmony_ci .resources = mt6323_rtc_resources, 678c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6323-rtc", 688c2ecf20Sopenharmony_ci }, { 698c2ecf20Sopenharmony_ci .name = "mt6323-regulator", 708c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6323-regulator" 718c2ecf20Sopenharmony_ci }, { 728c2ecf20Sopenharmony_ci .name = "mt6323-led", 738c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6323-led" 748c2ecf20Sopenharmony_ci }, { 758c2ecf20Sopenharmony_ci .name = "mtk-pmic-keys", 768c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(mt6323_keys_resources), 778c2ecf20Sopenharmony_ci .resources = mt6323_keys_resources, 788c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6323-keys" 798c2ecf20Sopenharmony_ci }, { 808c2ecf20Sopenharmony_ci .name = "mt6323-pwrc", 818c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(mt6323_pwrc_resources), 828c2ecf20Sopenharmony_ci .resources = mt6323_pwrc_resources, 838c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6323-pwrc" 848c2ecf20Sopenharmony_ci }, 858c2ecf20Sopenharmony_ci}; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic const struct mfd_cell mt6358_devs[] = { 888c2ecf20Sopenharmony_ci { 898c2ecf20Sopenharmony_ci .name = "mt6358-regulator", 908c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6358-regulator" 918c2ecf20Sopenharmony_ci }, { 928c2ecf20Sopenharmony_ci .name = "mt6358-rtc", 938c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(mt6358_rtc_resources), 948c2ecf20Sopenharmony_ci .resources = mt6358_rtc_resources, 958c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6358-rtc", 968c2ecf20Sopenharmony_ci }, { 978c2ecf20Sopenharmony_ci .name = "mt6358-sound", 988c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6358-sound" 998c2ecf20Sopenharmony_ci }, 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic const struct mfd_cell mt6397_devs[] = { 1038c2ecf20Sopenharmony_ci { 1048c2ecf20Sopenharmony_ci .name = "mt6397-rtc", 1058c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(mt6397_rtc_resources), 1068c2ecf20Sopenharmony_ci .resources = mt6397_rtc_resources, 1078c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6397-rtc", 1088c2ecf20Sopenharmony_ci }, { 1098c2ecf20Sopenharmony_ci .name = "mt6397-regulator", 1108c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6397-regulator", 1118c2ecf20Sopenharmony_ci }, { 1128c2ecf20Sopenharmony_ci .name = "mt6397-codec", 1138c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6397-codec", 1148c2ecf20Sopenharmony_ci }, { 1158c2ecf20Sopenharmony_ci .name = "mt6397-clk", 1168c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6397-clk", 1178c2ecf20Sopenharmony_ci }, { 1188c2ecf20Sopenharmony_ci .name = "mt6397-pinctrl", 1198c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6397-pinctrl", 1208c2ecf20Sopenharmony_ci }, { 1218c2ecf20Sopenharmony_ci .name = "mtk-pmic-keys", 1228c2ecf20Sopenharmony_ci .num_resources = ARRAY_SIZE(mt6397_keys_resources), 1238c2ecf20Sopenharmony_ci .resources = mt6397_keys_resources, 1248c2ecf20Sopenharmony_ci .of_compatible = "mediatek,mt6397-keys" 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci}; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistruct chip_data { 1298c2ecf20Sopenharmony_ci u32 cid_addr; 1308c2ecf20Sopenharmony_ci u32 cid_shift; 1318c2ecf20Sopenharmony_ci const struct mfd_cell *cells; 1328c2ecf20Sopenharmony_ci int cell_size; 1338c2ecf20Sopenharmony_ci int (*irq_init)(struct mt6397_chip *chip); 1348c2ecf20Sopenharmony_ci}; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic const struct chip_data mt6323_core = { 1378c2ecf20Sopenharmony_ci .cid_addr = MT6323_CID, 1388c2ecf20Sopenharmony_ci .cid_shift = 0, 1398c2ecf20Sopenharmony_ci .cells = mt6323_devs, 1408c2ecf20Sopenharmony_ci .cell_size = ARRAY_SIZE(mt6323_devs), 1418c2ecf20Sopenharmony_ci .irq_init = mt6397_irq_init, 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic const struct chip_data mt6358_core = { 1458c2ecf20Sopenharmony_ci .cid_addr = MT6358_SWCID, 1468c2ecf20Sopenharmony_ci .cid_shift = 8, 1478c2ecf20Sopenharmony_ci .cells = mt6358_devs, 1488c2ecf20Sopenharmony_ci .cell_size = ARRAY_SIZE(mt6358_devs), 1498c2ecf20Sopenharmony_ci .irq_init = mt6358_irq_init, 1508c2ecf20Sopenharmony_ci}; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic const struct chip_data mt6397_core = { 1538c2ecf20Sopenharmony_ci .cid_addr = MT6397_CID, 1548c2ecf20Sopenharmony_ci .cid_shift = 0, 1558c2ecf20Sopenharmony_ci .cells = mt6397_devs, 1568c2ecf20Sopenharmony_ci .cell_size = ARRAY_SIZE(mt6397_devs), 1578c2ecf20Sopenharmony_ci .irq_init = mt6397_irq_init, 1588c2ecf20Sopenharmony_ci}; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic int mt6397_probe(struct platform_device *pdev) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci int ret; 1638c2ecf20Sopenharmony_ci unsigned int id = 0; 1648c2ecf20Sopenharmony_ci struct mt6397_chip *pmic; 1658c2ecf20Sopenharmony_ci const struct chip_data *pmic_core; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 1688c2ecf20Sopenharmony_ci if (!pmic) 1698c2ecf20Sopenharmony_ci return -ENOMEM; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci pmic->dev = &pdev->dev; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* 1748c2ecf20Sopenharmony_ci * mt6397 MFD is child device of soc pmic wrapper. 1758c2ecf20Sopenharmony_ci * Regmap is set from its parent. 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_ci pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL); 1788c2ecf20Sopenharmony_ci if (!pmic->regmap) 1798c2ecf20Sopenharmony_ci return -ENODEV; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci pmic_core = of_device_get_match_data(&pdev->dev); 1828c2ecf20Sopenharmony_ci if (!pmic_core) 1838c2ecf20Sopenharmony_ci return -ENODEV; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id); 1868c2ecf20Sopenharmony_ci if (ret) { 1878c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret); 1888c2ecf20Sopenharmony_ci return ret; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, pmic); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci pmic->irq = platform_get_irq(pdev, 0); 1968c2ecf20Sopenharmony_ci if (pmic->irq <= 0) 1978c2ecf20Sopenharmony_ci return pmic->irq; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci ret = pmic_core->irq_init(pmic); 2008c2ecf20Sopenharmony_ci if (ret) 2018c2ecf20Sopenharmony_ci return ret; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, 2048c2ecf20Sopenharmony_ci pmic_core->cells, pmic_core->cell_size, 2058c2ecf20Sopenharmony_ci NULL, 0, pmic->irq_domain); 2068c2ecf20Sopenharmony_ci if (ret) { 2078c2ecf20Sopenharmony_ci irq_domain_remove(pmic->irq_domain); 2088c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to add child devices: %d\n", ret); 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci return ret; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic const struct of_device_id mt6397_of_match[] = { 2158c2ecf20Sopenharmony_ci { 2168c2ecf20Sopenharmony_ci .compatible = "mediatek,mt6323", 2178c2ecf20Sopenharmony_ci .data = &mt6323_core, 2188c2ecf20Sopenharmony_ci }, { 2198c2ecf20Sopenharmony_ci .compatible = "mediatek,mt6358", 2208c2ecf20Sopenharmony_ci .data = &mt6358_core, 2218c2ecf20Sopenharmony_ci }, { 2228c2ecf20Sopenharmony_ci .compatible = "mediatek,mt6397", 2238c2ecf20Sopenharmony_ci .data = &mt6397_core, 2248c2ecf20Sopenharmony_ci }, { 2258c2ecf20Sopenharmony_ci /* sentinel */ 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci}; 2288c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, mt6397_of_match); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic const struct platform_device_id mt6397_id[] = { 2318c2ecf20Sopenharmony_ci { "mt6397", 0 }, 2328c2ecf20Sopenharmony_ci { }, 2338c2ecf20Sopenharmony_ci}; 2348c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(platform, mt6397_id); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic struct platform_driver mt6397_driver = { 2378c2ecf20Sopenharmony_ci .probe = mt6397_probe, 2388c2ecf20Sopenharmony_ci .driver = { 2398c2ecf20Sopenharmony_ci .name = "mt6397", 2408c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(mt6397_of_match), 2418c2ecf20Sopenharmony_ci }, 2428c2ecf20Sopenharmony_ci .id_table = mt6397_id, 2438c2ecf20Sopenharmony_ci}; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cimodule_platform_driver(mt6397_driver); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ciMODULE_AUTHOR("Flora Fu, MediaTek"); 2488c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC"); 2498c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 250