16df8dd5cSFlora Fu /* 26df8dd5cSFlora Fu * Copyright (c) 2014 MediaTek Inc. 36df8dd5cSFlora Fu * Author: Flora Fu, MediaTek 46df8dd5cSFlora Fu * 56df8dd5cSFlora Fu * This program is free software; you can redistribute it and/or modify 66df8dd5cSFlora Fu * it under the terms of the GNU General Public License version 2 as 76df8dd5cSFlora Fu * published by the Free Software Foundation. 86df8dd5cSFlora Fu * 96df8dd5cSFlora Fu * This program is distributed in the hope that it will be useful, 106df8dd5cSFlora Fu * but WITHOUT ANY WARRANTY; without even the implied warranty of 116df8dd5cSFlora Fu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 126df8dd5cSFlora Fu * GNU General Public License for more details. 136df8dd5cSFlora Fu */ 146df8dd5cSFlora Fu 156df8dd5cSFlora Fu #include <linux/interrupt.h> 166df8dd5cSFlora Fu #include <linux/module.h> 176df8dd5cSFlora Fu #include <linux/of_device.h> 186df8dd5cSFlora Fu #include <linux/of_irq.h> 196df8dd5cSFlora Fu #include <linux/regmap.h> 206df8dd5cSFlora Fu #include <linux/mfd/core.h> 216df8dd5cSFlora Fu #include <linux/mfd/mt6397/core.h> 2244760cf3SJohn Crispin #include <linux/mfd/mt6323/core.h> 236df8dd5cSFlora Fu #include <linux/mfd/mt6397/registers.h> 2444760cf3SJohn Crispin #include <linux/mfd/mt6323/registers.h> 256df8dd5cSFlora Fu 26a5d7ea09SEddie Huang #define MT6397_RTC_BASE 0xe000 27a5d7ea09SEddie Huang #define MT6397_RTC_SIZE 0x3e 28a5d7ea09SEddie Huang 2944760cf3SJohn Crispin #define MT6323_CID_CODE 0x23 301d2c25edSJohn Crispin #define MT6391_CID_CODE 0x91 311d2c25edSJohn Crispin #define MT6397_CID_CODE 0x97 321d2c25edSJohn Crispin 33a5d7ea09SEddie Huang static const struct resource mt6397_rtc_resources[] = { 34a5d7ea09SEddie Huang { 35a5d7ea09SEddie Huang .start = MT6397_RTC_BASE, 36a5d7ea09SEddie Huang .end = MT6397_RTC_BASE + MT6397_RTC_SIZE, 37a5d7ea09SEddie Huang .flags = IORESOURCE_MEM, 38a5d7ea09SEddie Huang }, 39a5d7ea09SEddie Huang { 40a5d7ea09SEddie Huang .start = MT6397_IRQ_RTC, 41a5d7ea09SEddie Huang .end = MT6397_IRQ_RTC, 42a5d7ea09SEddie Huang .flags = IORESOURCE_IRQ, 43a5d7ea09SEddie Huang }, 44a5d7ea09SEddie Huang }; 45a5d7ea09SEddie Huang 4655d1d154SChen Zhong static const struct resource mt6323_keys_resources[] = { 4755d1d154SChen Zhong DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY), 4855d1d154SChen Zhong DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY), 4955d1d154SChen Zhong }; 5055d1d154SChen Zhong 5155d1d154SChen Zhong static const struct resource mt6397_keys_resources[] = { 5255d1d154SChen Zhong DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY), 5355d1d154SChen Zhong DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY), 5455d1d154SChen Zhong }; 5555d1d154SChen Zhong 5644760cf3SJohn Crispin static const struct mfd_cell mt6323_devs[] = { 5744760cf3SJohn Crispin { 5844760cf3SJohn Crispin .name = "mt6323-regulator", 5944760cf3SJohn Crispin .of_compatible = "mediatek,mt6323-regulator" 60040fc9b1SSean Wang }, { 611cb8af8dSSean Wang .name = "mt6323-led", 621cb8af8dSSean Wang .of_compatible = "mediatek,mt6323-led" 6355d1d154SChen Zhong }, { 6455d1d154SChen Zhong .name = "mtk-pmic-keys", 6555d1d154SChen Zhong .num_resources = ARRAY_SIZE(mt6323_keys_resources), 6655d1d154SChen Zhong .resources = mt6323_keys_resources, 6755d1d154SChen Zhong .of_compatible = "mediatek,mt6323-keys" 681cb8af8dSSean Wang }, 6944760cf3SJohn Crispin }; 7044760cf3SJohn Crispin 716df8dd5cSFlora Fu static const struct mfd_cell mt6397_devs[] = { 726df8dd5cSFlora Fu { 736df8dd5cSFlora Fu .name = "mt6397-rtc", 74a5d7ea09SEddie Huang .num_resources = ARRAY_SIZE(mt6397_rtc_resources), 75a5d7ea09SEddie Huang .resources = mt6397_rtc_resources, 766df8dd5cSFlora Fu .of_compatible = "mediatek,mt6397-rtc", 776df8dd5cSFlora Fu }, { 786df8dd5cSFlora Fu .name = "mt6397-regulator", 796df8dd5cSFlora Fu .of_compatible = "mediatek,mt6397-regulator", 806df8dd5cSFlora Fu }, { 816df8dd5cSFlora Fu .name = "mt6397-codec", 826df8dd5cSFlora Fu .of_compatible = "mediatek,mt6397-codec", 836df8dd5cSFlora Fu }, { 846df8dd5cSFlora Fu .name = "mt6397-clk", 856df8dd5cSFlora Fu .of_compatible = "mediatek,mt6397-clk", 86cf55078bSHongzhou Yang }, { 87cf55078bSHongzhou Yang .name = "mt6397-pinctrl", 88cf55078bSHongzhou Yang .of_compatible = "mediatek,mt6397-pinctrl", 8955d1d154SChen Zhong }, { 9055d1d154SChen Zhong .name = "mtk-pmic-keys", 9155d1d154SChen Zhong .num_resources = ARRAY_SIZE(mt6397_keys_resources), 9255d1d154SChen Zhong .resources = mt6397_keys_resources, 9355d1d154SChen Zhong .of_compatible = "mediatek,mt6397-keys" 9455d1d154SChen Zhong } 956df8dd5cSFlora Fu }; 966df8dd5cSFlora Fu 976df8dd5cSFlora Fu static void mt6397_irq_lock(struct irq_data *data) 986df8dd5cSFlora Fu { 991e84aa44SJiang Liu struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data); 1006df8dd5cSFlora Fu 1016df8dd5cSFlora Fu mutex_lock(&mt6397->irqlock); 1026df8dd5cSFlora Fu } 1036df8dd5cSFlora Fu 1046df8dd5cSFlora Fu static void mt6397_irq_sync_unlock(struct irq_data *data) 1056df8dd5cSFlora Fu { 1061e84aa44SJiang Liu struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data); 1076df8dd5cSFlora Fu 108feec4799SJohn Crispin regmap_write(mt6397->regmap, mt6397->int_con[0], 109feec4799SJohn Crispin mt6397->irq_masks_cur[0]); 110feec4799SJohn Crispin regmap_write(mt6397->regmap, mt6397->int_con[1], 111feec4799SJohn Crispin mt6397->irq_masks_cur[1]); 1126df8dd5cSFlora Fu 1136df8dd5cSFlora Fu mutex_unlock(&mt6397->irqlock); 1146df8dd5cSFlora Fu } 1156df8dd5cSFlora Fu 1166df8dd5cSFlora Fu static void mt6397_irq_disable(struct irq_data *data) 1176df8dd5cSFlora Fu { 1181e84aa44SJiang Liu struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data); 1196df8dd5cSFlora Fu int shift = data->hwirq & 0xf; 1206df8dd5cSFlora Fu int reg = data->hwirq >> 4; 1216df8dd5cSFlora Fu 1226df8dd5cSFlora Fu mt6397->irq_masks_cur[reg] &= ~BIT(shift); 1236df8dd5cSFlora Fu } 1246df8dd5cSFlora Fu 1256df8dd5cSFlora Fu static void mt6397_irq_enable(struct irq_data *data) 1266df8dd5cSFlora Fu { 1271e84aa44SJiang Liu struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data); 1286df8dd5cSFlora Fu int shift = data->hwirq & 0xf; 1296df8dd5cSFlora Fu int reg = data->hwirq >> 4; 1306df8dd5cSFlora Fu 1316df8dd5cSFlora Fu mt6397->irq_masks_cur[reg] |= BIT(shift); 1326df8dd5cSFlora Fu } 1336df8dd5cSFlora Fu 134f3151ab4SHenry Chen #ifdef CONFIG_PM_SLEEP 135f3151ab4SHenry Chen static int mt6397_irq_set_wake(struct irq_data *irq_data, unsigned int on) 136f3151ab4SHenry Chen { 137f3151ab4SHenry Chen struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(irq_data); 138f3151ab4SHenry Chen int shift = irq_data->hwirq & 0xf; 139f3151ab4SHenry Chen int reg = irq_data->hwirq >> 4; 140f3151ab4SHenry Chen 141f3151ab4SHenry Chen if (on) 142f3151ab4SHenry Chen mt6397->wake_mask[reg] |= BIT(shift); 143f3151ab4SHenry Chen else 144f3151ab4SHenry Chen mt6397->wake_mask[reg] &= ~BIT(shift); 145f3151ab4SHenry Chen 146f3151ab4SHenry Chen return 0; 147f3151ab4SHenry Chen } 148f3151ab4SHenry Chen #else 149f3151ab4SHenry Chen #define mt6397_irq_set_wake NULL 150f3151ab4SHenry Chen #endif 151f3151ab4SHenry Chen 1526df8dd5cSFlora Fu static struct irq_chip mt6397_irq_chip = { 1536df8dd5cSFlora Fu .name = "mt6397-irq", 1546df8dd5cSFlora Fu .irq_bus_lock = mt6397_irq_lock, 1556df8dd5cSFlora Fu .irq_bus_sync_unlock = mt6397_irq_sync_unlock, 1566df8dd5cSFlora Fu .irq_enable = mt6397_irq_enable, 1576df8dd5cSFlora Fu .irq_disable = mt6397_irq_disable, 158f3151ab4SHenry Chen .irq_set_wake = mt6397_irq_set_wake, 1596df8dd5cSFlora Fu }; 1606df8dd5cSFlora Fu 1616df8dd5cSFlora Fu static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg, 1626df8dd5cSFlora Fu int irqbase) 1636df8dd5cSFlora Fu { 1646df8dd5cSFlora Fu unsigned int status; 1656df8dd5cSFlora Fu int i, irq, ret; 1666df8dd5cSFlora Fu 1676df8dd5cSFlora Fu ret = regmap_read(mt6397->regmap, reg, &status); 1686df8dd5cSFlora Fu if (ret) { 1696df8dd5cSFlora Fu dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret); 1706df8dd5cSFlora Fu return; 1716df8dd5cSFlora Fu } 1726df8dd5cSFlora Fu 1736df8dd5cSFlora Fu for (i = 0; i < 16; i++) { 1746df8dd5cSFlora Fu if (status & BIT(i)) { 1756df8dd5cSFlora Fu irq = irq_find_mapping(mt6397->irq_domain, irqbase + i); 1766df8dd5cSFlora Fu if (irq) 1776df8dd5cSFlora Fu handle_nested_irq(irq); 1786df8dd5cSFlora Fu } 1796df8dd5cSFlora Fu } 1806df8dd5cSFlora Fu 1816df8dd5cSFlora Fu regmap_write(mt6397->regmap, reg, status); 1826df8dd5cSFlora Fu } 1836df8dd5cSFlora Fu 1846df8dd5cSFlora Fu static irqreturn_t mt6397_irq_thread(int irq, void *data) 1856df8dd5cSFlora Fu { 1866df8dd5cSFlora Fu struct mt6397_chip *mt6397 = data; 1876df8dd5cSFlora Fu 188feec4799SJohn Crispin mt6397_irq_handle_reg(mt6397, mt6397->int_status[0], 0); 189feec4799SJohn Crispin mt6397_irq_handle_reg(mt6397, mt6397->int_status[1], 16); 1906df8dd5cSFlora Fu 1916df8dd5cSFlora Fu return IRQ_HANDLED; 1926df8dd5cSFlora Fu } 1936df8dd5cSFlora Fu 1946df8dd5cSFlora Fu static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq, 1956df8dd5cSFlora Fu irq_hw_number_t hw) 1966df8dd5cSFlora Fu { 1976df8dd5cSFlora Fu struct mt6397_chip *mt6397 = d->host_data; 1986df8dd5cSFlora Fu 1996df8dd5cSFlora Fu irq_set_chip_data(irq, mt6397); 2006df8dd5cSFlora Fu irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq); 2016df8dd5cSFlora Fu irq_set_nested_thread(irq, 1); 2026df8dd5cSFlora Fu irq_set_noprobe(irq); 2036df8dd5cSFlora Fu 2046df8dd5cSFlora Fu return 0; 2056df8dd5cSFlora Fu } 2066df8dd5cSFlora Fu 2077ce7b26fSKrzysztof Kozlowski static const struct irq_domain_ops mt6397_irq_domain_ops = { 2086df8dd5cSFlora Fu .map = mt6397_irq_domain_map, 2096df8dd5cSFlora Fu }; 2106df8dd5cSFlora Fu 2116df8dd5cSFlora Fu static int mt6397_irq_init(struct mt6397_chip *mt6397) 2126df8dd5cSFlora Fu { 2136df8dd5cSFlora Fu int ret; 2146df8dd5cSFlora Fu 2156df8dd5cSFlora Fu mutex_init(&mt6397->irqlock); 2166df8dd5cSFlora Fu 2176df8dd5cSFlora Fu /* Mask all interrupt sources */ 218feec4799SJohn Crispin regmap_write(mt6397->regmap, mt6397->int_con[0], 0x0); 219feec4799SJohn Crispin regmap_write(mt6397->regmap, mt6397->int_con[1], 0x0); 2206df8dd5cSFlora Fu 2216df8dd5cSFlora Fu mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node, 2226df8dd5cSFlora Fu MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397); 2236df8dd5cSFlora Fu if (!mt6397->irq_domain) { 2246df8dd5cSFlora Fu dev_err(mt6397->dev, "could not create irq domain\n"); 2256df8dd5cSFlora Fu return -ENOMEM; 2266df8dd5cSFlora Fu } 2276df8dd5cSFlora Fu 2286df8dd5cSFlora Fu ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL, 2296df8dd5cSFlora Fu mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397); 2306df8dd5cSFlora Fu if (ret) { 2316df8dd5cSFlora Fu dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n", 2326df8dd5cSFlora Fu mt6397->irq, ret); 2336df8dd5cSFlora Fu return ret; 2346df8dd5cSFlora Fu } 2356df8dd5cSFlora Fu 2366df8dd5cSFlora Fu return 0; 2376df8dd5cSFlora Fu } 2386df8dd5cSFlora Fu 239f3151ab4SHenry Chen #ifdef CONFIG_PM_SLEEP 240f3151ab4SHenry Chen static int mt6397_irq_suspend(struct device *dev) 241f3151ab4SHenry Chen { 242f3151ab4SHenry Chen struct mt6397_chip *chip = dev_get_drvdata(dev); 243f3151ab4SHenry Chen 244feec4799SJohn Crispin regmap_write(chip->regmap, chip->int_con[0], chip->wake_mask[0]); 245feec4799SJohn Crispin regmap_write(chip->regmap, chip->int_con[1], chip->wake_mask[1]); 246f3151ab4SHenry Chen 247f3151ab4SHenry Chen enable_irq_wake(chip->irq); 248f3151ab4SHenry Chen 249f3151ab4SHenry Chen return 0; 250f3151ab4SHenry Chen } 251f3151ab4SHenry Chen 252f3151ab4SHenry Chen static int mt6397_irq_resume(struct device *dev) 253f3151ab4SHenry Chen { 254f3151ab4SHenry Chen struct mt6397_chip *chip = dev_get_drvdata(dev); 255f3151ab4SHenry Chen 256feec4799SJohn Crispin regmap_write(chip->regmap, chip->int_con[0], chip->irq_masks_cur[0]); 257feec4799SJohn Crispin regmap_write(chip->regmap, chip->int_con[1], chip->irq_masks_cur[1]); 258f3151ab4SHenry Chen 259f3151ab4SHenry Chen disable_irq_wake(chip->irq); 260f3151ab4SHenry Chen 261f3151ab4SHenry Chen return 0; 262f3151ab4SHenry Chen } 263f3151ab4SHenry Chen #endif 264f3151ab4SHenry Chen 265f3151ab4SHenry Chen static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_irq_suspend, 266f3151ab4SHenry Chen mt6397_irq_resume); 267f3151ab4SHenry Chen 2686df8dd5cSFlora Fu static int mt6397_probe(struct platform_device *pdev) 2696df8dd5cSFlora Fu { 2706df8dd5cSFlora Fu int ret; 2711d2c25edSJohn Crispin unsigned int id; 2721d2c25edSJohn Crispin struct mt6397_chip *pmic; 2736df8dd5cSFlora Fu 2741d2c25edSJohn Crispin pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 2751d2c25edSJohn Crispin if (!pmic) 2766df8dd5cSFlora Fu return -ENOMEM; 2776df8dd5cSFlora Fu 2781d2c25edSJohn Crispin pmic->dev = &pdev->dev; 279feec4799SJohn Crispin 2806df8dd5cSFlora Fu /* 2816df8dd5cSFlora Fu * mt6397 MFD is child device of soc pmic wrapper. 2826df8dd5cSFlora Fu * Regmap is set from its parent. 2836df8dd5cSFlora Fu */ 2841d2c25edSJohn Crispin pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL); 2851d2c25edSJohn Crispin if (!pmic->regmap) 2866df8dd5cSFlora Fu return -ENODEV; 2876df8dd5cSFlora Fu 2881d2c25edSJohn Crispin platform_set_drvdata(pdev, pmic); 2896df8dd5cSFlora Fu 2901d2c25edSJohn Crispin ret = regmap_read(pmic->regmap, MT6397_CID, &id); 2911d2c25edSJohn Crispin if (ret) { 2921d2c25edSJohn Crispin dev_err(pmic->dev, "Failed to read chip id: %d\n", ret); 2931387ff53SHenry Chen return ret; 2941d2c25edSJohn Crispin } 2951d2c25edSJohn Crispin 2961387ff53SHenry Chen pmic->irq = platform_get_irq(pdev, 0); 2971387ff53SHenry Chen if (pmic->irq <= 0) 2981387ff53SHenry Chen return pmic->irq; 2991387ff53SHenry Chen 3001d2c25edSJohn Crispin switch (id & 0xff) { 30144760cf3SJohn Crispin case MT6323_CID_CODE: 30244760cf3SJohn Crispin pmic->int_con[0] = MT6323_INT_CON0; 30344760cf3SJohn Crispin pmic->int_con[1] = MT6323_INT_CON1; 30444760cf3SJohn Crispin pmic->int_status[0] = MT6323_INT_STATUS0; 30544760cf3SJohn Crispin pmic->int_status[1] = MT6323_INT_STATUS1; 3061387ff53SHenry Chen ret = mt6397_irq_init(pmic); 3071387ff53SHenry Chen if (ret) 3081387ff53SHenry Chen return ret; 3091387ff53SHenry Chen 31008e380a5SLaxman Dewangan ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs, 31108e380a5SLaxman Dewangan ARRAY_SIZE(mt6323_devs), NULL, 312e695d3a0SChen Zhong 0, pmic->irq_domain); 31344760cf3SJohn Crispin break; 31444760cf3SJohn Crispin 3151d2c25edSJohn Crispin case MT6397_CID_CODE: 3161d2c25edSJohn Crispin case MT6391_CID_CODE: 3171d2c25edSJohn Crispin pmic->int_con[0] = MT6397_INT_CON0; 3181d2c25edSJohn Crispin pmic->int_con[1] = MT6397_INT_CON1; 3191d2c25edSJohn Crispin pmic->int_status[0] = MT6397_INT_STATUS0; 3201d2c25edSJohn Crispin pmic->int_status[1] = MT6397_INT_STATUS1; 3211387ff53SHenry Chen ret = mt6397_irq_init(pmic); 3221387ff53SHenry Chen if (ret) 3231387ff53SHenry Chen return ret; 3241387ff53SHenry Chen 32508e380a5SLaxman Dewangan ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs, 32608e380a5SLaxman Dewangan ARRAY_SIZE(mt6397_devs), NULL, 327e695d3a0SChen Zhong 0, pmic->irq_domain); 3281d2c25edSJohn Crispin break; 3291d2c25edSJohn Crispin 3301d2c25edSJohn Crispin default: 3311d2c25edSJohn Crispin dev_err(&pdev->dev, "unsupported chip: %d\n", id); 3321d2c25edSJohn Crispin ret = -ENODEV; 3331d2c25edSJohn Crispin break; 3341d2c25edSJohn Crispin } 3351d2c25edSJohn Crispin 3361d2c25edSJohn Crispin if (ret) { 3371d2c25edSJohn Crispin irq_domain_remove(pmic->irq_domain); 3386df8dd5cSFlora Fu dev_err(&pdev->dev, "failed to add child devices: %d\n", ret); 3391d2c25edSJohn Crispin } 3406df8dd5cSFlora Fu 3416df8dd5cSFlora Fu return ret; 3426df8dd5cSFlora Fu } 3436df8dd5cSFlora Fu 3446df8dd5cSFlora Fu static const struct of_device_id mt6397_of_match[] = { 3456df8dd5cSFlora Fu { .compatible = "mediatek,mt6397" }, 34644760cf3SJohn Crispin { .compatible = "mediatek,mt6323" }, 3476df8dd5cSFlora Fu { } 3486df8dd5cSFlora Fu }; 3496df8dd5cSFlora Fu MODULE_DEVICE_TABLE(of, mt6397_of_match); 3506df8dd5cSFlora Fu 351e1d9a109SJavier Martinez Canillas static const struct platform_device_id mt6397_id[] = { 352e1d9a109SJavier Martinez Canillas { "mt6397", 0 }, 353e1d9a109SJavier Martinez Canillas { }, 354e1d9a109SJavier Martinez Canillas }; 355e1d9a109SJavier Martinez Canillas MODULE_DEVICE_TABLE(platform, mt6397_id); 356e1d9a109SJavier Martinez Canillas 3576df8dd5cSFlora Fu static struct platform_driver mt6397_driver = { 3586df8dd5cSFlora Fu .probe = mt6397_probe, 3596df8dd5cSFlora Fu .driver = { 3606df8dd5cSFlora Fu .name = "mt6397", 3616df8dd5cSFlora Fu .of_match_table = of_match_ptr(mt6397_of_match), 362f3151ab4SHenry Chen .pm = &mt6397_pm_ops, 3636df8dd5cSFlora Fu }, 364e1d9a109SJavier Martinez Canillas .id_table = mt6397_id, 3656df8dd5cSFlora Fu }; 3666df8dd5cSFlora Fu 3676df8dd5cSFlora Fu module_platform_driver(mt6397_driver); 3686df8dd5cSFlora Fu 3696df8dd5cSFlora Fu MODULE_AUTHOR("Flora Fu, MediaTek"); 3706df8dd5cSFlora Fu MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC"); 3716df8dd5cSFlora Fu MODULE_LICENSE("GPL"); 372