125ca4ae4SBaolin Wang /* 225ca4ae4SBaolin Wang * Copyright (C) 2017 Spreadtrum Communications Inc. 325ca4ae4SBaolin Wang * 425ca4ae4SBaolin Wang * This software is licensed under the terms of the GNU General Public 525ca4ae4SBaolin Wang * License version 2, as published by the Free Software Foundation, and 625ca4ae4SBaolin Wang * may be copied, distributed, and modified under those terms. 725ca4ae4SBaolin Wang * 825ca4ae4SBaolin Wang * This program is distributed in the hope that it will be useful, 925ca4ae4SBaolin Wang * but WITHOUT ANY WARRANTY; without even the implied warranty of 1025ca4ae4SBaolin Wang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1125ca4ae4SBaolin Wang * GNU General Public License for more details. 1225ca4ae4SBaolin Wang */ 1325ca4ae4SBaolin Wang 1425ca4ae4SBaolin Wang #include <linux/interrupt.h> 1525ca4ae4SBaolin Wang #include <linux/kernel.h> 1625ca4ae4SBaolin Wang #include <linux/module.h> 1725ca4ae4SBaolin Wang #include <linux/mfd/core.h> 1825ca4ae4SBaolin Wang #include <linux/of_device.h> 1925ca4ae4SBaolin Wang #include <linux/regmap.h> 2025ca4ae4SBaolin Wang #include <linux/spi/spi.h> 2125ca4ae4SBaolin Wang 2225ca4ae4SBaolin Wang #define SPRD_PMIC_INT_MASK_STATUS 0x0 2325ca4ae4SBaolin Wang #define SPRD_PMIC_INT_RAW_STATUS 0x4 2425ca4ae4SBaolin Wang #define SPRD_PMIC_INT_EN 0x8 2525ca4ae4SBaolin Wang 2625ca4ae4SBaolin Wang #define SPRD_SC2731_IRQ_BASE 0x140 2725ca4ae4SBaolin Wang #define SPRD_SC2731_IRQ_NUMS 16 2825ca4ae4SBaolin Wang 2925ca4ae4SBaolin Wang struct sprd_pmic { 3025ca4ae4SBaolin Wang struct regmap *regmap; 3125ca4ae4SBaolin Wang struct device *dev; 3225ca4ae4SBaolin Wang struct regmap_irq *irqs; 3325ca4ae4SBaolin Wang struct regmap_irq_chip irq_chip; 3425ca4ae4SBaolin Wang struct regmap_irq_chip_data *irq_data; 3525ca4ae4SBaolin Wang int irq; 3625ca4ae4SBaolin Wang }; 3725ca4ae4SBaolin Wang 3825ca4ae4SBaolin Wang struct sprd_pmic_data { 3925ca4ae4SBaolin Wang u32 irq_base; 4025ca4ae4SBaolin Wang u32 num_irqs; 4125ca4ae4SBaolin Wang }; 4225ca4ae4SBaolin Wang 4325ca4ae4SBaolin Wang /* 4425ca4ae4SBaolin Wang * Since different PMICs of SC27xx series can have different interrupt 4525ca4ae4SBaolin Wang * base address and irq number, we should save irq number and irq base 4625ca4ae4SBaolin Wang * in the device data structure. 4725ca4ae4SBaolin Wang */ 4825ca4ae4SBaolin Wang static const struct sprd_pmic_data sc2731_data = { 4925ca4ae4SBaolin Wang .irq_base = SPRD_SC2731_IRQ_BASE, 5025ca4ae4SBaolin Wang .num_irqs = SPRD_SC2731_IRQ_NUMS, 5125ca4ae4SBaolin Wang }; 5225ca4ae4SBaolin Wang 5325ca4ae4SBaolin Wang static const struct mfd_cell sprd_pmic_devs[] = { 5425ca4ae4SBaolin Wang { 5525ca4ae4SBaolin Wang .name = "sc27xx-wdt", 5625ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-wdt", 5725ca4ae4SBaolin Wang }, { 5825ca4ae4SBaolin Wang .name = "sc27xx-rtc", 5925ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-rtc", 6025ca4ae4SBaolin Wang }, { 6125ca4ae4SBaolin Wang .name = "sc27xx-charger", 6225ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-charger", 6325ca4ae4SBaolin Wang }, { 6425ca4ae4SBaolin Wang .name = "sc27xx-chg-timer", 6525ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-chg-timer", 6625ca4ae4SBaolin Wang }, { 6725ca4ae4SBaolin Wang .name = "sc27xx-fast-chg", 6825ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-fast-chg", 6925ca4ae4SBaolin Wang }, { 7025ca4ae4SBaolin Wang .name = "sc27xx-chg-wdt", 7125ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-chg-wdt", 7225ca4ae4SBaolin Wang }, { 7325ca4ae4SBaolin Wang .name = "sc27xx-typec", 7425ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-typec", 7525ca4ae4SBaolin Wang }, { 7625ca4ae4SBaolin Wang .name = "sc27xx-flash", 7725ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-flash", 7825ca4ae4SBaolin Wang }, { 7925ca4ae4SBaolin Wang .name = "sc27xx-eic", 8025ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-eic", 8125ca4ae4SBaolin Wang }, { 8225ca4ae4SBaolin Wang .name = "sc27xx-efuse", 8325ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-efuse", 8425ca4ae4SBaolin Wang }, { 8525ca4ae4SBaolin Wang .name = "sc27xx-thermal", 8625ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-thermal", 8725ca4ae4SBaolin Wang }, { 8825ca4ae4SBaolin Wang .name = "sc27xx-adc", 8925ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-adc", 9025ca4ae4SBaolin Wang }, { 9125ca4ae4SBaolin Wang .name = "sc27xx-audio-codec", 9225ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-audio-codec", 9325ca4ae4SBaolin Wang }, { 9425ca4ae4SBaolin Wang .name = "sc27xx-regulator", 9525ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-regulator", 9625ca4ae4SBaolin Wang }, { 9725ca4ae4SBaolin Wang .name = "sc27xx-vibrator", 9825ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-vibrator", 9925ca4ae4SBaolin Wang }, { 10025ca4ae4SBaolin Wang .name = "sc27xx-keypad-led", 10125ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-keypad-led", 10225ca4ae4SBaolin Wang }, { 10325ca4ae4SBaolin Wang .name = "sc27xx-bltc", 10425ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-bltc", 10525ca4ae4SBaolin Wang }, { 10625ca4ae4SBaolin Wang .name = "sc27xx-fgu", 10725ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-fgu", 10825ca4ae4SBaolin Wang }, { 10925ca4ae4SBaolin Wang .name = "sc27xx-7sreset", 11025ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-7sreset", 11125ca4ae4SBaolin Wang }, { 11225ca4ae4SBaolin Wang .name = "sc27xx-poweroff", 11325ca4ae4SBaolin Wang .of_compatible = "sprd,sc27xx-poweroff", 114e03273e4SBaolin Wang }, { 115e03273e4SBaolin Wang .name = "sc27xx-syscon", 116e03273e4SBaolin Wang .of_compatible = "sprd,sc27xx-syscon", 11725ca4ae4SBaolin Wang }, 11825ca4ae4SBaolin Wang }; 11925ca4ae4SBaolin Wang 12025ca4ae4SBaolin Wang static int sprd_pmic_spi_write(void *context, const void *data, size_t count) 12125ca4ae4SBaolin Wang { 12225ca4ae4SBaolin Wang struct device *dev = context; 12325ca4ae4SBaolin Wang struct spi_device *spi = to_spi_device(dev); 12425ca4ae4SBaolin Wang 12525ca4ae4SBaolin Wang return spi_write(spi, data, count); 12625ca4ae4SBaolin Wang } 12725ca4ae4SBaolin Wang 12825ca4ae4SBaolin Wang static int sprd_pmic_spi_read(void *context, 12925ca4ae4SBaolin Wang const void *reg, size_t reg_size, 13025ca4ae4SBaolin Wang void *val, size_t val_size) 13125ca4ae4SBaolin Wang { 13225ca4ae4SBaolin Wang struct device *dev = context; 13325ca4ae4SBaolin Wang struct spi_device *spi = to_spi_device(dev); 13425ca4ae4SBaolin Wang u32 rx_buf[2] = { 0 }; 13525ca4ae4SBaolin Wang int ret; 13625ca4ae4SBaolin Wang 13725ca4ae4SBaolin Wang /* Now we only support one PMIC register to read every time. */ 13825ca4ae4SBaolin Wang if (reg_size != sizeof(u32) || val_size != sizeof(u32)) 13925ca4ae4SBaolin Wang return -EINVAL; 14025ca4ae4SBaolin Wang 14125ca4ae4SBaolin Wang /* Copy address to read from into first element of SPI buffer. */ 14225ca4ae4SBaolin Wang memcpy(rx_buf, reg, sizeof(u32)); 14325ca4ae4SBaolin Wang ret = spi_read(spi, rx_buf, 1); 14425ca4ae4SBaolin Wang if (ret < 0) 14525ca4ae4SBaolin Wang return ret; 14625ca4ae4SBaolin Wang 14725ca4ae4SBaolin Wang memcpy(val, rx_buf, val_size); 14825ca4ae4SBaolin Wang return 0; 14925ca4ae4SBaolin Wang } 15025ca4ae4SBaolin Wang 15125ca4ae4SBaolin Wang static struct regmap_bus sprd_pmic_regmap = { 15225ca4ae4SBaolin Wang .write = sprd_pmic_spi_write, 15325ca4ae4SBaolin Wang .read = sprd_pmic_spi_read, 15425ca4ae4SBaolin Wang .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, 15525ca4ae4SBaolin Wang .val_format_endian_default = REGMAP_ENDIAN_NATIVE, 15625ca4ae4SBaolin Wang }; 15725ca4ae4SBaolin Wang 15825ca4ae4SBaolin Wang static const struct regmap_config sprd_pmic_config = { 15925ca4ae4SBaolin Wang .reg_bits = 32, 16025ca4ae4SBaolin Wang .val_bits = 32, 16125ca4ae4SBaolin Wang .reg_stride = 4, 16225ca4ae4SBaolin Wang .max_register = 0xffff, 16325ca4ae4SBaolin Wang }; 16425ca4ae4SBaolin Wang 16525ca4ae4SBaolin Wang static int sprd_pmic_probe(struct spi_device *spi) 16625ca4ae4SBaolin Wang { 16725ca4ae4SBaolin Wang struct sprd_pmic *ddata; 16825ca4ae4SBaolin Wang const struct sprd_pmic_data *pdata; 16925ca4ae4SBaolin Wang int ret, i; 17025ca4ae4SBaolin Wang 17125ca4ae4SBaolin Wang pdata = of_device_get_match_data(&spi->dev); 17225ca4ae4SBaolin Wang if (!pdata) { 17325ca4ae4SBaolin Wang dev_err(&spi->dev, "No matching driver data found\n"); 17425ca4ae4SBaolin Wang return -EINVAL; 17525ca4ae4SBaolin Wang } 17625ca4ae4SBaolin Wang 17725ca4ae4SBaolin Wang ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL); 17825ca4ae4SBaolin Wang if (!ddata) 17925ca4ae4SBaolin Wang return -ENOMEM; 18025ca4ae4SBaolin Wang 18125ca4ae4SBaolin Wang ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap, 18225ca4ae4SBaolin Wang &spi->dev, &sprd_pmic_config); 18325ca4ae4SBaolin Wang if (IS_ERR(ddata->regmap)) { 18425ca4ae4SBaolin Wang ret = PTR_ERR(ddata->regmap); 18525ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to allocate register map %d\n", ret); 18625ca4ae4SBaolin Wang return ret; 18725ca4ae4SBaolin Wang } 18825ca4ae4SBaolin Wang 18925ca4ae4SBaolin Wang spi_set_drvdata(spi, ddata); 19025ca4ae4SBaolin Wang ddata->dev = &spi->dev; 19125ca4ae4SBaolin Wang ddata->irq = spi->irq; 19225ca4ae4SBaolin Wang 19325ca4ae4SBaolin Wang ddata->irq_chip.name = dev_name(&spi->dev); 19425ca4ae4SBaolin Wang ddata->irq_chip.status_base = 19525ca4ae4SBaolin Wang pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS; 19625ca4ae4SBaolin Wang ddata->irq_chip.mask_base = pdata->irq_base + SPRD_PMIC_INT_EN; 19725ca4ae4SBaolin Wang ddata->irq_chip.ack_base = 0; 19825ca4ae4SBaolin Wang ddata->irq_chip.num_regs = 1; 19925ca4ae4SBaolin Wang ddata->irq_chip.num_irqs = pdata->num_irqs; 20025ca4ae4SBaolin Wang ddata->irq_chip.mask_invert = true; 20125ca4ae4SBaolin Wang 202*a86854d0SKees Cook ddata->irqs = devm_kcalloc(&spi->dev, 203*a86854d0SKees Cook pdata->num_irqs, sizeof(struct regmap_irq), 204*a86854d0SKees Cook GFP_KERNEL); 20525ca4ae4SBaolin Wang if (!ddata->irqs) 20625ca4ae4SBaolin Wang return -ENOMEM; 20725ca4ae4SBaolin Wang 20825ca4ae4SBaolin Wang ddata->irq_chip.irqs = ddata->irqs; 20925ca4ae4SBaolin Wang for (i = 0; i < pdata->num_irqs; i++) { 21025ca4ae4SBaolin Wang ddata->irqs[i].reg_offset = i / pdata->num_irqs; 21125ca4ae4SBaolin Wang ddata->irqs[i].mask = BIT(i % pdata->num_irqs); 21225ca4ae4SBaolin Wang } 21325ca4ae4SBaolin Wang 21425ca4ae4SBaolin Wang ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq, 21525ca4ae4SBaolin Wang IRQF_ONESHOT | IRQF_NO_SUSPEND, 0, 21625ca4ae4SBaolin Wang &ddata->irq_chip, &ddata->irq_data); 21725ca4ae4SBaolin Wang if (ret) { 21825ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret); 21925ca4ae4SBaolin Wang return ret; 22025ca4ae4SBaolin Wang } 22125ca4ae4SBaolin Wang 22225ca4ae4SBaolin Wang ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO, 22325ca4ae4SBaolin Wang sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs), 22425ca4ae4SBaolin Wang NULL, 0, 22525ca4ae4SBaolin Wang regmap_irq_get_domain(ddata->irq_data)); 22625ca4ae4SBaolin Wang if (ret) { 22725ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to register device %d\n", ret); 22825ca4ae4SBaolin Wang return ret; 22925ca4ae4SBaolin Wang } 23025ca4ae4SBaolin Wang 23125ca4ae4SBaolin Wang return 0; 23225ca4ae4SBaolin Wang } 23325ca4ae4SBaolin Wang 23425ca4ae4SBaolin Wang static const struct of_device_id sprd_pmic_match[] = { 23525ca4ae4SBaolin Wang { .compatible = "sprd,sc2731", .data = &sc2731_data }, 23625ca4ae4SBaolin Wang {}, 23725ca4ae4SBaolin Wang }; 23825ca4ae4SBaolin Wang MODULE_DEVICE_TABLE(of, sprd_pmic_match); 23925ca4ae4SBaolin Wang 24025ca4ae4SBaolin Wang static struct spi_driver sprd_pmic_driver = { 24125ca4ae4SBaolin Wang .driver = { 24225ca4ae4SBaolin Wang .name = "sc27xx-pmic", 24325ca4ae4SBaolin Wang .bus = &spi_bus_type, 24425ca4ae4SBaolin Wang .of_match_table = sprd_pmic_match, 24525ca4ae4SBaolin Wang }, 24625ca4ae4SBaolin Wang .probe = sprd_pmic_probe, 24725ca4ae4SBaolin Wang }; 24825ca4ae4SBaolin Wang 24925ca4ae4SBaolin Wang static int __init sprd_pmic_init(void) 25025ca4ae4SBaolin Wang { 25125ca4ae4SBaolin Wang return spi_register_driver(&sprd_pmic_driver); 25225ca4ae4SBaolin Wang } 25325ca4ae4SBaolin Wang subsys_initcall(sprd_pmic_init); 25425ca4ae4SBaolin Wang 25525ca4ae4SBaolin Wang static void __exit sprd_pmic_exit(void) 25625ca4ae4SBaolin Wang { 25725ca4ae4SBaolin Wang spi_unregister_driver(&sprd_pmic_driver); 25825ca4ae4SBaolin Wang } 25925ca4ae4SBaolin Wang module_exit(sprd_pmic_exit); 26025ca4ae4SBaolin Wang 26125ca4ae4SBaolin Wang MODULE_LICENSE("GPL v2"); 26225ca4ae4SBaolin Wang MODULE_DESCRIPTION("Spreadtrum SC27xx PMICs driver"); 26325ca4ae4SBaolin Wang MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>"); 264