1*9c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 225ca4ae4SBaolin Wang /* 325ca4ae4SBaolin Wang * Copyright (C) 2017 Spreadtrum Communications Inc. 425ca4ae4SBaolin Wang */ 525ca4ae4SBaolin Wang 625ca4ae4SBaolin Wang #include <linux/interrupt.h> 725ca4ae4SBaolin Wang #include <linux/kernel.h> 825ca4ae4SBaolin Wang #include <linux/module.h> 925ca4ae4SBaolin Wang #include <linux/mfd/core.h> 1025ca4ae4SBaolin Wang #include <linux/of_device.h> 1125ca4ae4SBaolin Wang #include <linux/regmap.h> 1225ca4ae4SBaolin Wang #include <linux/spi/spi.h> 1325ca4ae4SBaolin Wang 1425ca4ae4SBaolin Wang #define SPRD_PMIC_INT_MASK_STATUS 0x0 1525ca4ae4SBaolin Wang #define SPRD_PMIC_INT_RAW_STATUS 0x4 1625ca4ae4SBaolin Wang #define SPRD_PMIC_INT_EN 0x8 1725ca4ae4SBaolin Wang 1825ca4ae4SBaolin Wang #define SPRD_SC2731_IRQ_BASE 0x140 1925ca4ae4SBaolin Wang #define SPRD_SC2731_IRQ_NUMS 16 2025ca4ae4SBaolin Wang 2125ca4ae4SBaolin Wang struct sprd_pmic { 2225ca4ae4SBaolin Wang struct regmap *regmap; 2325ca4ae4SBaolin Wang struct device *dev; 2425ca4ae4SBaolin Wang struct regmap_irq *irqs; 2525ca4ae4SBaolin Wang struct regmap_irq_chip irq_chip; 2625ca4ae4SBaolin Wang struct regmap_irq_chip_data *irq_data; 2725ca4ae4SBaolin Wang int irq; 2825ca4ae4SBaolin Wang }; 2925ca4ae4SBaolin Wang 3025ca4ae4SBaolin Wang struct sprd_pmic_data { 3125ca4ae4SBaolin Wang u32 irq_base; 3225ca4ae4SBaolin Wang u32 num_irqs; 3325ca4ae4SBaolin Wang }; 3425ca4ae4SBaolin Wang 3525ca4ae4SBaolin Wang /* 3625ca4ae4SBaolin Wang * Since different PMICs of SC27xx series can have different interrupt 3725ca4ae4SBaolin Wang * base address and irq number, we should save irq number and irq base 3825ca4ae4SBaolin Wang * in the device data structure. 3925ca4ae4SBaolin Wang */ 4025ca4ae4SBaolin Wang static const struct sprd_pmic_data sc2731_data = { 4125ca4ae4SBaolin Wang .irq_base = SPRD_SC2731_IRQ_BASE, 4225ca4ae4SBaolin Wang .num_irqs = SPRD_SC2731_IRQ_NUMS, 4325ca4ae4SBaolin Wang }; 4425ca4ae4SBaolin Wang 4525ca4ae4SBaolin Wang static const struct mfd_cell sprd_pmic_devs[] = { 4625ca4ae4SBaolin Wang { 4725ca4ae4SBaolin Wang .name = "sc27xx-wdt", 481d71670eSBaolin Wang .of_compatible = "sprd,sc2731-wdt", 4925ca4ae4SBaolin Wang }, { 5025ca4ae4SBaolin Wang .name = "sc27xx-rtc", 511d71670eSBaolin Wang .of_compatible = "sprd,sc2731-rtc", 5225ca4ae4SBaolin Wang }, { 5325ca4ae4SBaolin Wang .name = "sc27xx-charger", 541d71670eSBaolin Wang .of_compatible = "sprd,sc2731-charger", 5525ca4ae4SBaolin Wang }, { 5625ca4ae4SBaolin Wang .name = "sc27xx-chg-timer", 571d71670eSBaolin Wang .of_compatible = "sprd,sc2731-chg-timer", 5825ca4ae4SBaolin Wang }, { 5925ca4ae4SBaolin Wang .name = "sc27xx-fast-chg", 601d71670eSBaolin Wang .of_compatible = "sprd,sc2731-fast-chg", 6125ca4ae4SBaolin Wang }, { 6225ca4ae4SBaolin Wang .name = "sc27xx-chg-wdt", 631d71670eSBaolin Wang .of_compatible = "sprd,sc2731-chg-wdt", 6425ca4ae4SBaolin Wang }, { 6525ca4ae4SBaolin Wang .name = "sc27xx-typec", 661d71670eSBaolin Wang .of_compatible = "sprd,sc2731-typec", 6725ca4ae4SBaolin Wang }, { 6825ca4ae4SBaolin Wang .name = "sc27xx-flash", 691d71670eSBaolin Wang .of_compatible = "sprd,sc2731-flash", 7025ca4ae4SBaolin Wang }, { 7125ca4ae4SBaolin Wang .name = "sc27xx-eic", 721d71670eSBaolin Wang .of_compatible = "sprd,sc2731-eic", 7325ca4ae4SBaolin Wang }, { 7425ca4ae4SBaolin Wang .name = "sc27xx-efuse", 751d71670eSBaolin Wang .of_compatible = "sprd,sc2731-efuse", 7625ca4ae4SBaolin Wang }, { 7725ca4ae4SBaolin Wang .name = "sc27xx-thermal", 781d71670eSBaolin Wang .of_compatible = "sprd,sc2731-thermal", 7925ca4ae4SBaolin Wang }, { 8025ca4ae4SBaolin Wang .name = "sc27xx-adc", 811d71670eSBaolin Wang .of_compatible = "sprd,sc2731-adc", 8225ca4ae4SBaolin Wang }, { 8325ca4ae4SBaolin Wang .name = "sc27xx-audio-codec", 841d71670eSBaolin Wang .of_compatible = "sprd,sc2731-audio-codec", 8525ca4ae4SBaolin Wang }, { 8625ca4ae4SBaolin Wang .name = "sc27xx-regulator", 871d71670eSBaolin Wang .of_compatible = "sprd,sc2731-regulator", 8825ca4ae4SBaolin Wang }, { 8925ca4ae4SBaolin Wang .name = "sc27xx-vibrator", 901d71670eSBaolin Wang .of_compatible = "sprd,sc2731-vibrator", 9125ca4ae4SBaolin Wang }, { 9225ca4ae4SBaolin Wang .name = "sc27xx-keypad-led", 931d71670eSBaolin Wang .of_compatible = "sprd,sc2731-keypad-led", 9425ca4ae4SBaolin Wang }, { 9525ca4ae4SBaolin Wang .name = "sc27xx-bltc", 961d71670eSBaolin Wang .of_compatible = "sprd,sc2731-bltc", 9725ca4ae4SBaolin Wang }, { 9825ca4ae4SBaolin Wang .name = "sc27xx-fgu", 991d71670eSBaolin Wang .of_compatible = "sprd,sc2731-fgu", 10025ca4ae4SBaolin Wang }, { 10125ca4ae4SBaolin Wang .name = "sc27xx-7sreset", 1021d71670eSBaolin Wang .of_compatible = "sprd,sc2731-7sreset", 10325ca4ae4SBaolin Wang }, { 10425ca4ae4SBaolin Wang .name = "sc27xx-poweroff", 1051d71670eSBaolin Wang .of_compatible = "sprd,sc2731-poweroff", 106e03273e4SBaolin Wang }, { 107e03273e4SBaolin Wang .name = "sc27xx-syscon", 1081d71670eSBaolin Wang .of_compatible = "sprd,sc2731-syscon", 10925ca4ae4SBaolin Wang }, 11025ca4ae4SBaolin Wang }; 11125ca4ae4SBaolin Wang 11225ca4ae4SBaolin Wang static int sprd_pmic_spi_write(void *context, const void *data, size_t count) 11325ca4ae4SBaolin Wang { 11425ca4ae4SBaolin Wang struct device *dev = context; 11525ca4ae4SBaolin Wang struct spi_device *spi = to_spi_device(dev); 11625ca4ae4SBaolin Wang 11725ca4ae4SBaolin Wang return spi_write(spi, data, count); 11825ca4ae4SBaolin Wang } 11925ca4ae4SBaolin Wang 12025ca4ae4SBaolin Wang static int sprd_pmic_spi_read(void *context, 12125ca4ae4SBaolin Wang const void *reg, size_t reg_size, 12225ca4ae4SBaolin Wang void *val, size_t val_size) 12325ca4ae4SBaolin Wang { 12425ca4ae4SBaolin Wang struct device *dev = context; 12525ca4ae4SBaolin Wang struct spi_device *spi = to_spi_device(dev); 12625ca4ae4SBaolin Wang u32 rx_buf[2] = { 0 }; 12725ca4ae4SBaolin Wang int ret; 12825ca4ae4SBaolin Wang 12925ca4ae4SBaolin Wang /* Now we only support one PMIC register to read every time. */ 13025ca4ae4SBaolin Wang if (reg_size != sizeof(u32) || val_size != sizeof(u32)) 13125ca4ae4SBaolin Wang return -EINVAL; 13225ca4ae4SBaolin Wang 13325ca4ae4SBaolin Wang /* Copy address to read from into first element of SPI buffer. */ 13425ca4ae4SBaolin Wang memcpy(rx_buf, reg, sizeof(u32)); 13525ca4ae4SBaolin Wang ret = spi_read(spi, rx_buf, 1); 13625ca4ae4SBaolin Wang if (ret < 0) 13725ca4ae4SBaolin Wang return ret; 13825ca4ae4SBaolin Wang 13925ca4ae4SBaolin Wang memcpy(val, rx_buf, val_size); 14025ca4ae4SBaolin Wang return 0; 14125ca4ae4SBaolin Wang } 14225ca4ae4SBaolin Wang 14325ca4ae4SBaolin Wang static struct regmap_bus sprd_pmic_regmap = { 14425ca4ae4SBaolin Wang .write = sprd_pmic_spi_write, 14525ca4ae4SBaolin Wang .read = sprd_pmic_spi_read, 14625ca4ae4SBaolin Wang .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, 14725ca4ae4SBaolin Wang .val_format_endian_default = REGMAP_ENDIAN_NATIVE, 14825ca4ae4SBaolin Wang }; 14925ca4ae4SBaolin Wang 15025ca4ae4SBaolin Wang static const struct regmap_config sprd_pmic_config = { 15125ca4ae4SBaolin Wang .reg_bits = 32, 15225ca4ae4SBaolin Wang .val_bits = 32, 15325ca4ae4SBaolin Wang .reg_stride = 4, 15425ca4ae4SBaolin Wang .max_register = 0xffff, 15525ca4ae4SBaolin Wang }; 15625ca4ae4SBaolin Wang 15725ca4ae4SBaolin Wang static int sprd_pmic_probe(struct spi_device *spi) 15825ca4ae4SBaolin Wang { 15925ca4ae4SBaolin Wang struct sprd_pmic *ddata; 16025ca4ae4SBaolin Wang const struct sprd_pmic_data *pdata; 16125ca4ae4SBaolin Wang int ret, i; 16225ca4ae4SBaolin Wang 16325ca4ae4SBaolin Wang pdata = of_device_get_match_data(&spi->dev); 16425ca4ae4SBaolin Wang if (!pdata) { 16525ca4ae4SBaolin Wang dev_err(&spi->dev, "No matching driver data found\n"); 16625ca4ae4SBaolin Wang return -EINVAL; 16725ca4ae4SBaolin Wang } 16825ca4ae4SBaolin Wang 16925ca4ae4SBaolin Wang ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL); 17025ca4ae4SBaolin Wang if (!ddata) 17125ca4ae4SBaolin Wang return -ENOMEM; 17225ca4ae4SBaolin Wang 17325ca4ae4SBaolin Wang ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap, 17425ca4ae4SBaolin Wang &spi->dev, &sprd_pmic_config); 17525ca4ae4SBaolin Wang if (IS_ERR(ddata->regmap)) { 17625ca4ae4SBaolin Wang ret = PTR_ERR(ddata->regmap); 17725ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to allocate register map %d\n", ret); 17825ca4ae4SBaolin Wang return ret; 17925ca4ae4SBaolin Wang } 18025ca4ae4SBaolin Wang 18125ca4ae4SBaolin Wang spi_set_drvdata(spi, ddata); 18225ca4ae4SBaolin Wang ddata->dev = &spi->dev; 18325ca4ae4SBaolin Wang ddata->irq = spi->irq; 18425ca4ae4SBaolin Wang 18525ca4ae4SBaolin Wang ddata->irq_chip.name = dev_name(&spi->dev); 18625ca4ae4SBaolin Wang ddata->irq_chip.status_base = 18725ca4ae4SBaolin Wang pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS; 18825ca4ae4SBaolin Wang ddata->irq_chip.mask_base = pdata->irq_base + SPRD_PMIC_INT_EN; 18925ca4ae4SBaolin Wang ddata->irq_chip.ack_base = 0; 19025ca4ae4SBaolin Wang ddata->irq_chip.num_regs = 1; 19125ca4ae4SBaolin Wang ddata->irq_chip.num_irqs = pdata->num_irqs; 19225ca4ae4SBaolin Wang ddata->irq_chip.mask_invert = true; 19325ca4ae4SBaolin Wang 194a86854d0SKees Cook ddata->irqs = devm_kcalloc(&spi->dev, 195a86854d0SKees Cook pdata->num_irqs, sizeof(struct regmap_irq), 196a86854d0SKees Cook GFP_KERNEL); 19725ca4ae4SBaolin Wang if (!ddata->irqs) 19825ca4ae4SBaolin Wang return -ENOMEM; 19925ca4ae4SBaolin Wang 20025ca4ae4SBaolin Wang ddata->irq_chip.irqs = ddata->irqs; 20125ca4ae4SBaolin Wang for (i = 0; i < pdata->num_irqs; i++) { 20225ca4ae4SBaolin Wang ddata->irqs[i].reg_offset = i / pdata->num_irqs; 20325ca4ae4SBaolin Wang ddata->irqs[i].mask = BIT(i % pdata->num_irqs); 20425ca4ae4SBaolin Wang } 20525ca4ae4SBaolin Wang 20625ca4ae4SBaolin Wang ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq, 20725ca4ae4SBaolin Wang IRQF_ONESHOT | IRQF_NO_SUSPEND, 0, 20825ca4ae4SBaolin Wang &ddata->irq_chip, &ddata->irq_data); 20925ca4ae4SBaolin Wang if (ret) { 21025ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret); 21125ca4ae4SBaolin Wang return ret; 21225ca4ae4SBaolin Wang } 21325ca4ae4SBaolin Wang 21425ca4ae4SBaolin Wang ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO, 21525ca4ae4SBaolin Wang sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs), 21625ca4ae4SBaolin Wang NULL, 0, 21725ca4ae4SBaolin Wang regmap_irq_get_domain(ddata->irq_data)); 21825ca4ae4SBaolin Wang if (ret) { 21925ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to register device %d\n", ret); 22025ca4ae4SBaolin Wang return ret; 22125ca4ae4SBaolin Wang } 22225ca4ae4SBaolin Wang 22325ca4ae4SBaolin Wang return 0; 22425ca4ae4SBaolin Wang } 22525ca4ae4SBaolin Wang 22625ca4ae4SBaolin Wang static const struct of_device_id sprd_pmic_match[] = { 22725ca4ae4SBaolin Wang { .compatible = "sprd,sc2731", .data = &sc2731_data }, 22825ca4ae4SBaolin Wang {}, 22925ca4ae4SBaolin Wang }; 23025ca4ae4SBaolin Wang MODULE_DEVICE_TABLE(of, sprd_pmic_match); 23125ca4ae4SBaolin Wang 23225ca4ae4SBaolin Wang static struct spi_driver sprd_pmic_driver = { 23325ca4ae4SBaolin Wang .driver = { 23425ca4ae4SBaolin Wang .name = "sc27xx-pmic", 23525ca4ae4SBaolin Wang .bus = &spi_bus_type, 23625ca4ae4SBaolin Wang .of_match_table = sprd_pmic_match, 23725ca4ae4SBaolin Wang }, 23825ca4ae4SBaolin Wang .probe = sprd_pmic_probe, 23925ca4ae4SBaolin Wang }; 24025ca4ae4SBaolin Wang 24125ca4ae4SBaolin Wang static int __init sprd_pmic_init(void) 24225ca4ae4SBaolin Wang { 24325ca4ae4SBaolin Wang return spi_register_driver(&sprd_pmic_driver); 24425ca4ae4SBaolin Wang } 24525ca4ae4SBaolin Wang subsys_initcall(sprd_pmic_init); 24625ca4ae4SBaolin Wang 24725ca4ae4SBaolin Wang static void __exit sprd_pmic_exit(void) 24825ca4ae4SBaolin Wang { 24925ca4ae4SBaolin Wang spi_unregister_driver(&sprd_pmic_driver); 25025ca4ae4SBaolin Wang } 25125ca4ae4SBaolin Wang module_exit(sprd_pmic_exit); 25225ca4ae4SBaolin Wang 25325ca4ae4SBaolin Wang MODULE_LICENSE("GPL v2"); 25425ca4ae4SBaolin Wang MODULE_DESCRIPTION("Spreadtrum SC27xx PMICs driver"); 25525ca4ae4SBaolin Wang MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>"); 256