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