linux/drivers/mfd/mt6397-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2014 MediaTek Inc.
   4 * Author: Flora Fu, MediaTek
   5 */
   6
   7#include <linux/interrupt.h>
   8#include <linux/ioport.h>
   9#include <linux/module.h>
  10#include <linux/of_device.h>
  11#include <linux/of_irq.h>
  12#include <linux/regmap.h>
  13#include <linux/mfd/core.h>
  14#include <linux/mfd/mt6323/core.h>
  15#include <linux/mfd/mt6358/core.h>
  16#include <linux/mfd/mt6397/core.h>
  17#include <linux/mfd/mt6323/registers.h>
  18#include <linux/mfd/mt6358/registers.h>
  19#include <linux/mfd/mt6397/registers.h>
  20
  21#define MT6323_RTC_BASE         0x8000
  22#define MT6323_RTC_SIZE         0x40
  23
  24#define MT6358_RTC_BASE         0x0588
  25#define MT6358_RTC_SIZE         0x3c
  26
  27#define MT6397_RTC_BASE         0xe000
  28#define MT6397_RTC_SIZE         0x3e
  29
  30#define MT6323_PWRC_BASE        0x8000
  31#define MT6323_PWRC_SIZE        0x40
  32
  33static const struct resource mt6323_rtc_resources[] = {
  34        DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE),
  35        DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC),
  36};
  37
  38static const struct resource mt6358_rtc_resources[] = {
  39        DEFINE_RES_MEM(MT6358_RTC_BASE, MT6358_RTC_SIZE),
  40        DEFINE_RES_IRQ(MT6358_IRQ_RTC),
  41};
  42
  43static const struct resource mt6397_rtc_resources[] = {
  44        DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE),
  45        DEFINE_RES_IRQ(MT6397_IRQ_RTC),
  46};
  47
  48static const struct resource mt6323_keys_resources[] = {
  49        DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY),
  50        DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY),
  51};
  52
  53static const struct resource mt6397_keys_resources[] = {
  54        DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY),
  55        DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY),
  56};
  57
  58static const struct resource mt6323_pwrc_resources[] = {
  59        DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE),
  60};
  61
  62static const struct mfd_cell mt6323_devs[] = {
  63        {
  64                .name = "mt6323-rtc",
  65                .num_resources = ARRAY_SIZE(mt6323_rtc_resources),
  66                .resources = mt6323_rtc_resources,
  67                .of_compatible = "mediatek,mt6323-rtc",
  68        }, {
  69                .name = "mt6323-regulator",
  70                .of_compatible = "mediatek,mt6323-regulator"
  71        }, {
  72                .name = "mt6323-led",
  73                .of_compatible = "mediatek,mt6323-led"
  74        }, {
  75                .name = "mtk-pmic-keys",
  76                .num_resources = ARRAY_SIZE(mt6323_keys_resources),
  77                .resources = mt6323_keys_resources,
  78                .of_compatible = "mediatek,mt6323-keys"
  79        }, {
  80                .name = "mt6323-pwrc",
  81                .num_resources = ARRAY_SIZE(mt6323_pwrc_resources),
  82                .resources = mt6323_pwrc_resources,
  83                .of_compatible = "mediatek,mt6323-pwrc"
  84        },
  85};
  86
  87static const struct mfd_cell mt6358_devs[] = {
  88        {
  89                .name = "mt6358-regulator",
  90                .of_compatible = "mediatek,mt6358-regulator"
  91        }, {
  92                .name = "mt6358-rtc",
  93                .num_resources = ARRAY_SIZE(mt6358_rtc_resources),
  94                .resources = mt6358_rtc_resources,
  95                .of_compatible = "mediatek,mt6358-rtc",
  96        }, {
  97                .name = "mt6358-sound",
  98                .of_compatible = "mediatek,mt6358-sound"
  99        },
 100};
 101
 102static const struct mfd_cell mt6397_devs[] = {
 103        {
 104                .name = "mt6397-rtc",
 105                .num_resources = ARRAY_SIZE(mt6397_rtc_resources),
 106                .resources = mt6397_rtc_resources,
 107                .of_compatible = "mediatek,mt6397-rtc",
 108        }, {
 109                .name = "mt6397-regulator",
 110                .of_compatible = "mediatek,mt6397-regulator",
 111        }, {
 112                .name = "mt6397-codec",
 113                .of_compatible = "mediatek,mt6397-codec",
 114        }, {
 115                .name = "mt6397-clk",
 116                .of_compatible = "mediatek,mt6397-clk",
 117        }, {
 118                .name = "mt6397-pinctrl",
 119                .of_compatible = "mediatek,mt6397-pinctrl",
 120        }, {
 121                .name = "mtk-pmic-keys",
 122                .num_resources = ARRAY_SIZE(mt6397_keys_resources),
 123                .resources = mt6397_keys_resources,
 124                .of_compatible = "mediatek,mt6397-keys"
 125        }
 126};
 127
 128struct chip_data {
 129        u32 cid_addr;
 130        u32 cid_shift;
 131        const struct mfd_cell *cells;
 132        int cell_size;
 133        int (*irq_init)(struct mt6397_chip *chip);
 134};
 135
 136static const struct chip_data mt6323_core = {
 137        .cid_addr = MT6323_CID,
 138        .cid_shift = 0,
 139        .cells = mt6323_devs,
 140        .cell_size = ARRAY_SIZE(mt6323_devs),
 141        .irq_init = mt6397_irq_init,
 142};
 143
 144static const struct chip_data mt6358_core = {
 145        .cid_addr = MT6358_SWCID,
 146        .cid_shift = 8,
 147        .cells = mt6358_devs,
 148        .cell_size = ARRAY_SIZE(mt6358_devs),
 149        .irq_init = mt6358_irq_init,
 150};
 151
 152static const struct chip_data mt6397_core = {
 153        .cid_addr = MT6397_CID,
 154        .cid_shift = 0,
 155        .cells = mt6397_devs,
 156        .cell_size = ARRAY_SIZE(mt6397_devs),
 157        .irq_init = mt6397_irq_init,
 158};
 159
 160static int mt6397_probe(struct platform_device *pdev)
 161{
 162        int ret;
 163        unsigned int id = 0;
 164        struct mt6397_chip *pmic;
 165        const struct chip_data *pmic_core;
 166
 167        pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
 168        if (!pmic)
 169                return -ENOMEM;
 170
 171        pmic->dev = &pdev->dev;
 172
 173        /*
 174         * mt6397 MFD is child device of soc pmic wrapper.
 175         * Regmap is set from its parent.
 176         */
 177        pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL);
 178        if (!pmic->regmap)
 179                return -ENODEV;
 180
 181        pmic_core = of_device_get_match_data(&pdev->dev);
 182        if (!pmic_core)
 183                return -ENODEV;
 184
 185        ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
 186        if (ret) {
 187                dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret);
 188                return ret;
 189        }
 190
 191        pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff;
 192
 193        platform_set_drvdata(pdev, pmic);
 194
 195        pmic->irq = platform_get_irq(pdev, 0);
 196        if (pmic->irq <= 0)
 197                return pmic->irq;
 198
 199        ret = pmic_core->irq_init(pmic);
 200        if (ret)
 201                return ret;
 202
 203        ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
 204                                   pmic_core->cells, pmic_core->cell_size,
 205                                   NULL, 0, pmic->irq_domain);
 206        if (ret) {
 207                irq_domain_remove(pmic->irq_domain);
 208                dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
 209        }
 210
 211        return ret;
 212}
 213
 214static const struct of_device_id mt6397_of_match[] = {
 215        {
 216                .compatible = "mediatek,mt6323",
 217                .data = &mt6323_core,
 218        }, {
 219                .compatible = "mediatek,mt6358",
 220                .data = &mt6358_core,
 221        }, {
 222                .compatible = "mediatek,mt6397",
 223                .data = &mt6397_core,
 224        }, {
 225                /* sentinel */
 226        }
 227};
 228MODULE_DEVICE_TABLE(of, mt6397_of_match);
 229
 230static const struct platform_device_id mt6397_id[] = {
 231        { "mt6397", 0 },
 232        { },
 233};
 234MODULE_DEVICE_TABLE(platform, mt6397_id);
 235
 236static struct platform_driver mt6397_driver = {
 237        .probe = mt6397_probe,
 238        .driver = {
 239                .name = "mt6397",
 240                .of_match_table = of_match_ptr(mt6397_of_match),
 241        },
 242        .id_table = mt6397_id,
 243};
 244
 245module_platform_driver(mt6397_driver);
 246
 247MODULE_AUTHOR("Flora Fu, MediaTek");
 248MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
 249MODULE_LICENSE("GPL");
 250