19c92ab61SThomas 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> 13*2a7e7274SBaolin Wang #include <uapi/linux/usb/charger.h> 1425ca4ae4SBaolin Wang 1525ca4ae4SBaolin Wang #define SPRD_PMIC_INT_MASK_STATUS 0x0 1625ca4ae4SBaolin Wang #define SPRD_PMIC_INT_RAW_STATUS 0x4 1725ca4ae4SBaolin Wang #define SPRD_PMIC_INT_EN 0x8 1825ca4ae4SBaolin Wang 1925ca4ae4SBaolin Wang #define SPRD_SC2731_IRQ_BASE 0x140 2025ca4ae4SBaolin Wang #define SPRD_SC2731_IRQ_NUMS 16 21*2a7e7274SBaolin Wang #define SPRD_SC2731_CHG_DET 0xedc 22*2a7e7274SBaolin Wang 23*2a7e7274SBaolin Wang /* PMIC charger detection definition */ 24*2a7e7274SBaolin Wang #define SPRD_PMIC_CHG_DET_DELAY_US 200000 25*2a7e7274SBaolin Wang #define SPRD_PMIC_CHG_DET_TIMEOUT 2000000 26*2a7e7274SBaolin Wang #define SPRD_PMIC_CHG_DET_DONE BIT(11) 27*2a7e7274SBaolin Wang #define SPRD_PMIC_SDP_TYPE BIT(7) 28*2a7e7274SBaolin Wang #define SPRD_PMIC_DCP_TYPE BIT(6) 29*2a7e7274SBaolin Wang #define SPRD_PMIC_CDP_TYPE BIT(5) 30*2a7e7274SBaolin Wang #define SPRD_PMIC_CHG_TYPE_MASK GENMASK(7, 5) 3125ca4ae4SBaolin Wang 3225ca4ae4SBaolin Wang struct sprd_pmic { 3325ca4ae4SBaolin Wang struct regmap *regmap; 3425ca4ae4SBaolin Wang struct device *dev; 3525ca4ae4SBaolin Wang struct regmap_irq *irqs; 3625ca4ae4SBaolin Wang struct regmap_irq_chip irq_chip; 3725ca4ae4SBaolin Wang struct regmap_irq_chip_data *irq_data; 38*2a7e7274SBaolin Wang const struct sprd_pmic_data *pdata; 3925ca4ae4SBaolin Wang int irq; 4025ca4ae4SBaolin Wang }; 4125ca4ae4SBaolin Wang 4225ca4ae4SBaolin Wang struct sprd_pmic_data { 4325ca4ae4SBaolin Wang u32 irq_base; 4425ca4ae4SBaolin Wang u32 num_irqs; 45*2a7e7274SBaolin Wang u32 charger_det; 4625ca4ae4SBaolin Wang }; 4725ca4ae4SBaolin Wang 4825ca4ae4SBaolin Wang /* 4925ca4ae4SBaolin Wang * Since different PMICs of SC27xx series can have different interrupt 5025ca4ae4SBaolin Wang * base address and irq number, we should save irq number and irq base 5125ca4ae4SBaolin Wang * in the device data structure. 5225ca4ae4SBaolin Wang */ 5325ca4ae4SBaolin Wang static const struct sprd_pmic_data sc2731_data = { 5425ca4ae4SBaolin Wang .irq_base = SPRD_SC2731_IRQ_BASE, 5525ca4ae4SBaolin Wang .num_irqs = SPRD_SC2731_IRQ_NUMS, 56*2a7e7274SBaolin Wang .charger_det = SPRD_SC2731_CHG_DET, 5725ca4ae4SBaolin Wang }; 5825ca4ae4SBaolin Wang 59*2a7e7274SBaolin Wang enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev) 60*2a7e7274SBaolin Wang { 61*2a7e7274SBaolin Wang struct spi_device *spi = to_spi_device(dev); 62*2a7e7274SBaolin Wang struct sprd_pmic *ddata = spi_get_drvdata(spi); 63*2a7e7274SBaolin Wang const struct sprd_pmic_data *pdata = ddata->pdata; 64*2a7e7274SBaolin Wang enum usb_charger_type type; 65*2a7e7274SBaolin Wang u32 val; 66*2a7e7274SBaolin Wang int ret; 67*2a7e7274SBaolin Wang 68*2a7e7274SBaolin Wang ret = regmap_read_poll_timeout(ddata->regmap, pdata->charger_det, val, 69*2a7e7274SBaolin Wang (val & SPRD_PMIC_CHG_DET_DONE), 70*2a7e7274SBaolin Wang SPRD_PMIC_CHG_DET_DELAY_US, 71*2a7e7274SBaolin Wang SPRD_PMIC_CHG_DET_TIMEOUT); 72*2a7e7274SBaolin Wang if (ret) { 73*2a7e7274SBaolin Wang dev_err(&spi->dev, "failed to detect charger type\n"); 74*2a7e7274SBaolin Wang return UNKNOWN_TYPE; 75*2a7e7274SBaolin Wang } 76*2a7e7274SBaolin Wang 77*2a7e7274SBaolin Wang switch (val & SPRD_PMIC_CHG_TYPE_MASK) { 78*2a7e7274SBaolin Wang case SPRD_PMIC_CDP_TYPE: 79*2a7e7274SBaolin Wang type = CDP_TYPE; 80*2a7e7274SBaolin Wang break; 81*2a7e7274SBaolin Wang case SPRD_PMIC_DCP_TYPE: 82*2a7e7274SBaolin Wang type = DCP_TYPE; 83*2a7e7274SBaolin Wang break; 84*2a7e7274SBaolin Wang case SPRD_PMIC_SDP_TYPE: 85*2a7e7274SBaolin Wang type = SDP_TYPE; 86*2a7e7274SBaolin Wang break; 87*2a7e7274SBaolin Wang default: 88*2a7e7274SBaolin Wang type = UNKNOWN_TYPE; 89*2a7e7274SBaolin Wang break; 90*2a7e7274SBaolin Wang } 91*2a7e7274SBaolin Wang 92*2a7e7274SBaolin Wang return type; 93*2a7e7274SBaolin Wang } 94*2a7e7274SBaolin Wang EXPORT_SYMBOL_GPL(sprd_pmic_detect_charger_type); 95*2a7e7274SBaolin Wang 9625ca4ae4SBaolin Wang static const struct mfd_cell sprd_pmic_devs[] = { 9725ca4ae4SBaolin Wang { 9825ca4ae4SBaolin Wang .name = "sc27xx-wdt", 991d71670eSBaolin Wang .of_compatible = "sprd,sc2731-wdt", 10025ca4ae4SBaolin Wang }, { 10125ca4ae4SBaolin Wang .name = "sc27xx-rtc", 1021d71670eSBaolin Wang .of_compatible = "sprd,sc2731-rtc", 10325ca4ae4SBaolin Wang }, { 10425ca4ae4SBaolin Wang .name = "sc27xx-charger", 1051d71670eSBaolin Wang .of_compatible = "sprd,sc2731-charger", 10625ca4ae4SBaolin Wang }, { 10725ca4ae4SBaolin Wang .name = "sc27xx-chg-timer", 1081d71670eSBaolin Wang .of_compatible = "sprd,sc2731-chg-timer", 10925ca4ae4SBaolin Wang }, { 11025ca4ae4SBaolin Wang .name = "sc27xx-fast-chg", 1111d71670eSBaolin Wang .of_compatible = "sprd,sc2731-fast-chg", 11225ca4ae4SBaolin Wang }, { 11325ca4ae4SBaolin Wang .name = "sc27xx-chg-wdt", 1141d71670eSBaolin Wang .of_compatible = "sprd,sc2731-chg-wdt", 11525ca4ae4SBaolin Wang }, { 11625ca4ae4SBaolin Wang .name = "sc27xx-typec", 1171d71670eSBaolin Wang .of_compatible = "sprd,sc2731-typec", 11825ca4ae4SBaolin Wang }, { 11925ca4ae4SBaolin Wang .name = "sc27xx-flash", 1201d71670eSBaolin Wang .of_compatible = "sprd,sc2731-flash", 12125ca4ae4SBaolin Wang }, { 12225ca4ae4SBaolin Wang .name = "sc27xx-eic", 1231d71670eSBaolin Wang .of_compatible = "sprd,sc2731-eic", 12425ca4ae4SBaolin Wang }, { 12525ca4ae4SBaolin Wang .name = "sc27xx-efuse", 1261d71670eSBaolin Wang .of_compatible = "sprd,sc2731-efuse", 12725ca4ae4SBaolin Wang }, { 12825ca4ae4SBaolin Wang .name = "sc27xx-thermal", 1291d71670eSBaolin Wang .of_compatible = "sprd,sc2731-thermal", 13025ca4ae4SBaolin Wang }, { 13125ca4ae4SBaolin Wang .name = "sc27xx-adc", 1321d71670eSBaolin Wang .of_compatible = "sprd,sc2731-adc", 13325ca4ae4SBaolin Wang }, { 13425ca4ae4SBaolin Wang .name = "sc27xx-audio-codec", 1351d71670eSBaolin Wang .of_compatible = "sprd,sc2731-audio-codec", 13625ca4ae4SBaolin Wang }, { 13725ca4ae4SBaolin Wang .name = "sc27xx-regulator", 1381d71670eSBaolin Wang .of_compatible = "sprd,sc2731-regulator", 13925ca4ae4SBaolin Wang }, { 14025ca4ae4SBaolin Wang .name = "sc27xx-vibrator", 1411d71670eSBaolin Wang .of_compatible = "sprd,sc2731-vibrator", 14225ca4ae4SBaolin Wang }, { 14325ca4ae4SBaolin Wang .name = "sc27xx-keypad-led", 1441d71670eSBaolin Wang .of_compatible = "sprd,sc2731-keypad-led", 14525ca4ae4SBaolin Wang }, { 14625ca4ae4SBaolin Wang .name = "sc27xx-bltc", 1471d71670eSBaolin Wang .of_compatible = "sprd,sc2731-bltc", 14825ca4ae4SBaolin Wang }, { 14925ca4ae4SBaolin Wang .name = "sc27xx-fgu", 1501d71670eSBaolin Wang .of_compatible = "sprd,sc2731-fgu", 15125ca4ae4SBaolin Wang }, { 15225ca4ae4SBaolin Wang .name = "sc27xx-7sreset", 1531d71670eSBaolin Wang .of_compatible = "sprd,sc2731-7sreset", 15425ca4ae4SBaolin Wang }, { 15525ca4ae4SBaolin Wang .name = "sc27xx-poweroff", 1561d71670eSBaolin Wang .of_compatible = "sprd,sc2731-poweroff", 157e03273e4SBaolin Wang }, { 158e03273e4SBaolin Wang .name = "sc27xx-syscon", 1591d71670eSBaolin Wang .of_compatible = "sprd,sc2731-syscon", 16025ca4ae4SBaolin Wang }, 16125ca4ae4SBaolin Wang }; 16225ca4ae4SBaolin Wang 16325ca4ae4SBaolin Wang static int sprd_pmic_spi_write(void *context, const void *data, size_t count) 16425ca4ae4SBaolin Wang { 16525ca4ae4SBaolin Wang struct device *dev = context; 16625ca4ae4SBaolin Wang struct spi_device *spi = to_spi_device(dev); 16725ca4ae4SBaolin Wang 16825ca4ae4SBaolin Wang return spi_write(spi, data, count); 16925ca4ae4SBaolin Wang } 17025ca4ae4SBaolin Wang 17125ca4ae4SBaolin Wang static int sprd_pmic_spi_read(void *context, 17225ca4ae4SBaolin Wang const void *reg, size_t reg_size, 17325ca4ae4SBaolin Wang void *val, size_t val_size) 17425ca4ae4SBaolin Wang { 17525ca4ae4SBaolin Wang struct device *dev = context; 17625ca4ae4SBaolin Wang struct spi_device *spi = to_spi_device(dev); 17725ca4ae4SBaolin Wang u32 rx_buf[2] = { 0 }; 17825ca4ae4SBaolin Wang int ret; 17925ca4ae4SBaolin Wang 18025ca4ae4SBaolin Wang /* Now we only support one PMIC register to read every time. */ 18125ca4ae4SBaolin Wang if (reg_size != sizeof(u32) || val_size != sizeof(u32)) 18225ca4ae4SBaolin Wang return -EINVAL; 18325ca4ae4SBaolin Wang 18425ca4ae4SBaolin Wang /* Copy address to read from into first element of SPI buffer. */ 18525ca4ae4SBaolin Wang memcpy(rx_buf, reg, sizeof(u32)); 18625ca4ae4SBaolin Wang ret = spi_read(spi, rx_buf, 1); 18725ca4ae4SBaolin Wang if (ret < 0) 18825ca4ae4SBaolin Wang return ret; 18925ca4ae4SBaolin Wang 19025ca4ae4SBaolin Wang memcpy(val, rx_buf, val_size); 19125ca4ae4SBaolin Wang return 0; 19225ca4ae4SBaolin Wang } 19325ca4ae4SBaolin Wang 19425ca4ae4SBaolin Wang static struct regmap_bus sprd_pmic_regmap = { 19525ca4ae4SBaolin Wang .write = sprd_pmic_spi_write, 19625ca4ae4SBaolin Wang .read = sprd_pmic_spi_read, 19725ca4ae4SBaolin Wang .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, 19825ca4ae4SBaolin Wang .val_format_endian_default = REGMAP_ENDIAN_NATIVE, 19925ca4ae4SBaolin Wang }; 20025ca4ae4SBaolin Wang 20125ca4ae4SBaolin Wang static const struct regmap_config sprd_pmic_config = { 20225ca4ae4SBaolin Wang .reg_bits = 32, 20325ca4ae4SBaolin Wang .val_bits = 32, 20425ca4ae4SBaolin Wang .reg_stride = 4, 20525ca4ae4SBaolin Wang .max_register = 0xffff, 20625ca4ae4SBaolin Wang }; 20725ca4ae4SBaolin Wang 20825ca4ae4SBaolin Wang static int sprd_pmic_probe(struct spi_device *spi) 20925ca4ae4SBaolin Wang { 21025ca4ae4SBaolin Wang struct sprd_pmic *ddata; 21125ca4ae4SBaolin Wang const struct sprd_pmic_data *pdata; 21225ca4ae4SBaolin Wang int ret, i; 21325ca4ae4SBaolin Wang 21425ca4ae4SBaolin Wang pdata = of_device_get_match_data(&spi->dev); 21525ca4ae4SBaolin Wang if (!pdata) { 21625ca4ae4SBaolin Wang dev_err(&spi->dev, "No matching driver data found\n"); 21725ca4ae4SBaolin Wang return -EINVAL; 21825ca4ae4SBaolin Wang } 21925ca4ae4SBaolin Wang 22025ca4ae4SBaolin Wang ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL); 22125ca4ae4SBaolin Wang if (!ddata) 22225ca4ae4SBaolin Wang return -ENOMEM; 22325ca4ae4SBaolin Wang 22425ca4ae4SBaolin Wang ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap, 22525ca4ae4SBaolin Wang &spi->dev, &sprd_pmic_config); 22625ca4ae4SBaolin Wang if (IS_ERR(ddata->regmap)) { 22725ca4ae4SBaolin Wang ret = PTR_ERR(ddata->regmap); 22825ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to allocate register map %d\n", ret); 22925ca4ae4SBaolin Wang return ret; 23025ca4ae4SBaolin Wang } 23125ca4ae4SBaolin Wang 23225ca4ae4SBaolin Wang spi_set_drvdata(spi, ddata); 23325ca4ae4SBaolin Wang ddata->dev = &spi->dev; 23425ca4ae4SBaolin Wang ddata->irq = spi->irq; 235*2a7e7274SBaolin Wang ddata->pdata = pdata; 23625ca4ae4SBaolin Wang 23725ca4ae4SBaolin Wang ddata->irq_chip.name = dev_name(&spi->dev); 23825ca4ae4SBaolin Wang ddata->irq_chip.status_base = 23925ca4ae4SBaolin Wang pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS; 24025ca4ae4SBaolin Wang ddata->irq_chip.mask_base = pdata->irq_base + SPRD_PMIC_INT_EN; 24125ca4ae4SBaolin Wang ddata->irq_chip.ack_base = 0; 24225ca4ae4SBaolin Wang ddata->irq_chip.num_regs = 1; 24325ca4ae4SBaolin Wang ddata->irq_chip.num_irqs = pdata->num_irqs; 24425ca4ae4SBaolin Wang ddata->irq_chip.mask_invert = true; 24525ca4ae4SBaolin Wang 246a86854d0SKees Cook ddata->irqs = devm_kcalloc(&spi->dev, 247a86854d0SKees Cook pdata->num_irqs, sizeof(struct regmap_irq), 248a86854d0SKees Cook GFP_KERNEL); 24925ca4ae4SBaolin Wang if (!ddata->irqs) 25025ca4ae4SBaolin Wang return -ENOMEM; 25125ca4ae4SBaolin Wang 25225ca4ae4SBaolin Wang ddata->irq_chip.irqs = ddata->irqs; 25325ca4ae4SBaolin Wang for (i = 0; i < pdata->num_irqs; i++) { 25425ca4ae4SBaolin Wang ddata->irqs[i].reg_offset = i / pdata->num_irqs; 25525ca4ae4SBaolin Wang ddata->irqs[i].mask = BIT(i % pdata->num_irqs); 25625ca4ae4SBaolin Wang } 25725ca4ae4SBaolin Wang 25825ca4ae4SBaolin Wang ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq, 25925ca4ae4SBaolin Wang IRQF_ONESHOT | IRQF_NO_SUSPEND, 0, 26025ca4ae4SBaolin Wang &ddata->irq_chip, &ddata->irq_data); 26125ca4ae4SBaolin Wang if (ret) { 26225ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret); 26325ca4ae4SBaolin Wang return ret; 26425ca4ae4SBaolin Wang } 26525ca4ae4SBaolin Wang 26625ca4ae4SBaolin Wang ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO, 26725ca4ae4SBaolin Wang sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs), 26825ca4ae4SBaolin Wang NULL, 0, 26925ca4ae4SBaolin Wang regmap_irq_get_domain(ddata->irq_data)); 27025ca4ae4SBaolin Wang if (ret) { 27125ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to register device %d\n", ret); 27225ca4ae4SBaolin Wang return ret; 27325ca4ae4SBaolin Wang } 27425ca4ae4SBaolin Wang 27525ca4ae4SBaolin Wang return 0; 27625ca4ae4SBaolin Wang } 27725ca4ae4SBaolin Wang 27825ca4ae4SBaolin Wang static const struct of_device_id sprd_pmic_match[] = { 27925ca4ae4SBaolin Wang { .compatible = "sprd,sc2731", .data = &sc2731_data }, 28025ca4ae4SBaolin Wang {}, 28125ca4ae4SBaolin Wang }; 28225ca4ae4SBaolin Wang MODULE_DEVICE_TABLE(of, sprd_pmic_match); 28325ca4ae4SBaolin Wang 28425ca4ae4SBaolin Wang static struct spi_driver sprd_pmic_driver = { 28525ca4ae4SBaolin Wang .driver = { 28625ca4ae4SBaolin Wang .name = "sc27xx-pmic", 28725ca4ae4SBaolin Wang .bus = &spi_bus_type, 28825ca4ae4SBaolin Wang .of_match_table = sprd_pmic_match, 28925ca4ae4SBaolin Wang }, 29025ca4ae4SBaolin Wang .probe = sprd_pmic_probe, 29125ca4ae4SBaolin Wang }; 29225ca4ae4SBaolin Wang 29325ca4ae4SBaolin Wang static int __init sprd_pmic_init(void) 29425ca4ae4SBaolin Wang { 29525ca4ae4SBaolin Wang return spi_register_driver(&sprd_pmic_driver); 29625ca4ae4SBaolin Wang } 29725ca4ae4SBaolin Wang subsys_initcall(sprd_pmic_init); 29825ca4ae4SBaolin Wang 29925ca4ae4SBaolin Wang static void __exit sprd_pmic_exit(void) 30025ca4ae4SBaolin Wang { 30125ca4ae4SBaolin Wang spi_unregister_driver(&sprd_pmic_driver); 30225ca4ae4SBaolin Wang } 30325ca4ae4SBaolin Wang module_exit(sprd_pmic_exit); 30425ca4ae4SBaolin Wang 30525ca4ae4SBaolin Wang MODULE_LICENSE("GPL v2"); 30625ca4ae4SBaolin Wang MODULE_DESCRIPTION("Spreadtrum SC27xx PMICs driver"); 30725ca4ae4SBaolin Wang MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>"); 308