linux/drivers/mfd/sprd-sc27xx-spi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2017 Spreadtrum Communications Inc.
   4 */
   5
   6#include <linux/interrupt.h>
   7#include <linux/kernel.h>
   8#include <linux/module.h>
   9#include <linux/mfd/core.h>
  10#include <linux/of_device.h>
  11#include <linux/regmap.h>
  12#include <linux/spi/spi.h>
  13
  14#define SPRD_PMIC_INT_MASK_STATUS       0x0
  15#define SPRD_PMIC_INT_RAW_STATUS        0x4
  16#define SPRD_PMIC_INT_EN                0x8
  17
  18#define SPRD_SC2731_IRQ_BASE            0x140
  19#define SPRD_SC2731_IRQ_NUMS            16
  20
  21struct sprd_pmic {
  22        struct regmap *regmap;
  23        struct device *dev;
  24        struct regmap_irq *irqs;
  25        struct regmap_irq_chip irq_chip;
  26        struct regmap_irq_chip_data *irq_data;
  27        int irq;
  28};
  29
  30struct sprd_pmic_data {
  31        u32 irq_base;
  32        u32 num_irqs;
  33};
  34
  35/*
  36 * Since different PMICs of SC27xx series can have different interrupt
  37 * base address and irq number, we should save irq number and irq base
  38 * in the device data structure.
  39 */
  40static const struct sprd_pmic_data sc2731_data = {
  41        .irq_base = SPRD_SC2731_IRQ_BASE,
  42        .num_irqs = SPRD_SC2731_IRQ_NUMS,
  43};
  44
  45static const struct mfd_cell sprd_pmic_devs[] = {
  46        {
  47                .name = "sc27xx-wdt",
  48                .of_compatible = "sprd,sc2731-wdt",
  49        }, {
  50                .name = "sc27xx-rtc",
  51                .of_compatible = "sprd,sc2731-rtc",
  52        }, {
  53                .name = "sc27xx-charger",
  54                .of_compatible = "sprd,sc2731-charger",
  55        }, {
  56                .name = "sc27xx-chg-timer",
  57                .of_compatible = "sprd,sc2731-chg-timer",
  58        }, {
  59                .name = "sc27xx-fast-chg",
  60                .of_compatible = "sprd,sc2731-fast-chg",
  61        }, {
  62                .name = "sc27xx-chg-wdt",
  63                .of_compatible = "sprd,sc2731-chg-wdt",
  64        }, {
  65                .name = "sc27xx-typec",
  66                .of_compatible = "sprd,sc2731-typec",
  67        }, {
  68                .name = "sc27xx-flash",
  69                .of_compatible = "sprd,sc2731-flash",
  70        }, {
  71                .name = "sc27xx-eic",
  72                .of_compatible = "sprd,sc2731-eic",
  73        }, {
  74                .name = "sc27xx-efuse",
  75                .of_compatible = "sprd,sc2731-efuse",
  76        }, {
  77                .name = "sc27xx-thermal",
  78                .of_compatible = "sprd,sc2731-thermal",
  79        }, {
  80                .name = "sc27xx-adc",
  81                .of_compatible = "sprd,sc2731-adc",
  82        }, {
  83                .name = "sc27xx-audio-codec",
  84                .of_compatible = "sprd,sc2731-audio-codec",
  85        }, {
  86                .name = "sc27xx-regulator",
  87                .of_compatible = "sprd,sc2731-regulator",
  88        }, {
  89                .name = "sc27xx-vibrator",
  90                .of_compatible = "sprd,sc2731-vibrator",
  91        }, {
  92                .name = "sc27xx-keypad-led",
  93                .of_compatible = "sprd,sc2731-keypad-led",
  94        }, {
  95                .name = "sc27xx-bltc",
  96                .of_compatible = "sprd,sc2731-bltc",
  97        }, {
  98                .name = "sc27xx-fgu",
  99                .of_compatible = "sprd,sc2731-fgu",
 100        }, {
 101                .name = "sc27xx-7sreset",
 102                .of_compatible = "sprd,sc2731-7sreset",
 103        }, {
 104                .name = "sc27xx-poweroff",
 105                .of_compatible = "sprd,sc2731-poweroff",
 106        }, {
 107                .name = "sc27xx-syscon",
 108                .of_compatible = "sprd,sc2731-syscon",
 109        },
 110};
 111
 112static int sprd_pmic_spi_write(void *context, const void *data, size_t count)
 113{
 114        struct device *dev = context;
 115        struct spi_device *spi = to_spi_device(dev);
 116
 117        return spi_write(spi, data, count);
 118}
 119
 120static int sprd_pmic_spi_read(void *context,
 121                              const void *reg, size_t reg_size,
 122                              void *val, size_t val_size)
 123{
 124        struct device *dev = context;
 125        struct spi_device *spi = to_spi_device(dev);
 126        u32 rx_buf[2] = { 0 };
 127        int ret;
 128
 129        /* Now we only support one PMIC register to read every time. */
 130        if (reg_size != sizeof(u32) || val_size != sizeof(u32))
 131                return -EINVAL;
 132
 133        /* Copy address to read from into first element of SPI buffer. */
 134        memcpy(rx_buf, reg, sizeof(u32));
 135        ret = spi_read(spi, rx_buf, 1);
 136        if (ret < 0)
 137                return ret;
 138
 139        memcpy(val, rx_buf, val_size);
 140        return 0;
 141}
 142
 143static struct regmap_bus sprd_pmic_regmap = {
 144        .write = sprd_pmic_spi_write,
 145        .read = sprd_pmic_spi_read,
 146        .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
 147        .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
 148};
 149
 150static const struct regmap_config sprd_pmic_config = {
 151        .reg_bits = 32,
 152        .val_bits = 32,
 153        .reg_stride = 4,
 154        .max_register = 0xffff,
 155};
 156
 157static int sprd_pmic_probe(struct spi_device *spi)
 158{
 159        struct sprd_pmic *ddata;
 160        const struct sprd_pmic_data *pdata;
 161        int ret, i;
 162
 163        pdata = of_device_get_match_data(&spi->dev);
 164        if (!pdata) {
 165                dev_err(&spi->dev, "No matching driver data found\n");
 166                return -EINVAL;
 167        }
 168
 169        ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
 170        if (!ddata)
 171                return -ENOMEM;
 172
 173        ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap,
 174                                         &spi->dev, &sprd_pmic_config);
 175        if (IS_ERR(ddata->regmap)) {
 176                ret = PTR_ERR(ddata->regmap);
 177                dev_err(&spi->dev, "Failed to allocate register map %d\n", ret);
 178                return ret;
 179        }
 180
 181        spi_set_drvdata(spi, ddata);
 182        ddata->dev = &spi->dev;
 183        ddata->irq = spi->irq;
 184
 185        ddata->irq_chip.name = dev_name(&spi->dev);
 186        ddata->irq_chip.status_base =
 187                pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS;
 188        ddata->irq_chip.mask_base = pdata->irq_base + SPRD_PMIC_INT_EN;
 189        ddata->irq_chip.ack_base = 0;
 190        ddata->irq_chip.num_regs = 1;
 191        ddata->irq_chip.num_irqs = pdata->num_irqs;
 192        ddata->irq_chip.mask_invert = true;
 193
 194        ddata->irqs = devm_kcalloc(&spi->dev,
 195                                   pdata->num_irqs, sizeof(struct regmap_irq),
 196                                   GFP_KERNEL);
 197        if (!ddata->irqs)
 198                return -ENOMEM;
 199
 200        ddata->irq_chip.irqs = ddata->irqs;
 201        for (i = 0; i < pdata->num_irqs; i++) {
 202                ddata->irqs[i].reg_offset = i / pdata->num_irqs;
 203                ddata->irqs[i].mask = BIT(i % pdata->num_irqs);
 204        }
 205
 206        ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq,
 207                                       IRQF_ONESHOT | IRQF_NO_SUSPEND, 0,
 208                                       &ddata->irq_chip, &ddata->irq_data);
 209        if (ret) {
 210                dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret);
 211                return ret;
 212        }
 213
 214        ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO,
 215                                   sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs),
 216                                   NULL, 0,
 217                                   regmap_irq_get_domain(ddata->irq_data));
 218        if (ret) {
 219                dev_err(&spi->dev, "Failed to register device %d\n", ret);
 220                return ret;
 221        }
 222
 223        return 0;
 224}
 225
 226static const struct of_device_id sprd_pmic_match[] = {
 227        { .compatible = "sprd,sc2731", .data = &sc2731_data },
 228        {},
 229};
 230MODULE_DEVICE_TABLE(of, sprd_pmic_match);
 231
 232static struct spi_driver sprd_pmic_driver = {
 233        .driver = {
 234                .name = "sc27xx-pmic",
 235                .bus = &spi_bus_type,
 236                .of_match_table = sprd_pmic_match,
 237        },
 238        .probe = sprd_pmic_probe,
 239};
 240
 241static int __init sprd_pmic_init(void)
 242{
 243        return spi_register_driver(&sprd_pmic_driver);
 244}
 245subsys_initcall(sprd_pmic_init);
 246
 247static void __exit sprd_pmic_exit(void)
 248{
 249        spi_unregister_driver(&sprd_pmic_driver);
 250}
 251module_exit(sprd_pmic_exit);
 252
 253MODULE_LICENSE("GPL v2");
 254MODULE_DESCRIPTION("Spreadtrum SC27xx PMICs driver");
 255MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>");
 256