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> 103d4a8757SLee Jones #include <linux/mfd/sc27xx-pmic.h> 1125ca4ae4SBaolin Wang #include <linux/of_device.h> 12c61e1658SChunyan Zhang #include <linux/of_platform.h> 1325ca4ae4SBaolin Wang #include <linux/regmap.h> 1425ca4ae4SBaolin Wang #include <linux/spi/spi.h> 152a7e7274SBaolin Wang #include <uapi/linux/usb/charger.h> 1625ca4ae4SBaolin Wang 1725ca4ae4SBaolin Wang #define SPRD_PMIC_INT_MASK_STATUS 0x0 1825ca4ae4SBaolin Wang #define SPRD_PMIC_INT_RAW_STATUS 0x4 1925ca4ae4SBaolin Wang #define SPRD_PMIC_INT_EN 0x8 2025ca4ae4SBaolin Wang 2125ca4ae4SBaolin Wang #define SPRD_SC2731_IRQ_BASE 0x140 2225ca4ae4SBaolin Wang #define SPRD_SC2731_IRQ_NUMS 16 232a7e7274SBaolin Wang #define SPRD_SC2731_CHG_DET 0xedc 242a7e7274SBaolin Wang 252a7e7274SBaolin Wang /* PMIC charger detection definition */ 262a7e7274SBaolin Wang #define SPRD_PMIC_CHG_DET_DELAY_US 200000 272a7e7274SBaolin Wang #define SPRD_PMIC_CHG_DET_TIMEOUT 2000000 282a7e7274SBaolin Wang #define SPRD_PMIC_CHG_DET_DONE BIT(11) 292a7e7274SBaolin Wang #define SPRD_PMIC_SDP_TYPE BIT(7) 302a7e7274SBaolin Wang #define SPRD_PMIC_DCP_TYPE BIT(6) 312a7e7274SBaolin Wang #define SPRD_PMIC_CDP_TYPE BIT(5) 322a7e7274SBaolin Wang #define SPRD_PMIC_CHG_TYPE_MASK GENMASK(7, 5) 3325ca4ae4SBaolin Wang 3425ca4ae4SBaolin Wang struct sprd_pmic { 3525ca4ae4SBaolin Wang struct regmap *regmap; 3625ca4ae4SBaolin Wang struct device *dev; 3725ca4ae4SBaolin Wang struct regmap_irq *irqs; 3825ca4ae4SBaolin Wang struct regmap_irq_chip irq_chip; 3925ca4ae4SBaolin Wang struct regmap_irq_chip_data *irq_data; 402a7e7274SBaolin Wang const struct sprd_pmic_data *pdata; 4125ca4ae4SBaolin Wang int irq; 4225ca4ae4SBaolin Wang }; 4325ca4ae4SBaolin Wang 4425ca4ae4SBaolin Wang struct sprd_pmic_data { 4525ca4ae4SBaolin Wang u32 irq_base; 4625ca4ae4SBaolin Wang u32 num_irqs; 472a7e7274SBaolin Wang u32 charger_det; 4825ca4ae4SBaolin Wang }; 4925ca4ae4SBaolin Wang 5025ca4ae4SBaolin Wang /* 5125ca4ae4SBaolin Wang * Since different PMICs of SC27xx series can have different interrupt 5225ca4ae4SBaolin Wang * base address and irq number, we should save irq number and irq base 5325ca4ae4SBaolin Wang * in the device data structure. 5425ca4ae4SBaolin Wang */ 5525ca4ae4SBaolin Wang static const struct sprd_pmic_data sc2731_data = { 5625ca4ae4SBaolin Wang .irq_base = SPRD_SC2731_IRQ_BASE, 5725ca4ae4SBaolin Wang .num_irqs = SPRD_SC2731_IRQ_NUMS, 582a7e7274SBaolin Wang .charger_det = SPRD_SC2731_CHG_DET, 5925ca4ae4SBaolin Wang }; 6025ca4ae4SBaolin Wang 612a7e7274SBaolin Wang enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev) 622a7e7274SBaolin Wang { 632a7e7274SBaolin Wang struct spi_device *spi = to_spi_device(dev); 642a7e7274SBaolin Wang struct sprd_pmic *ddata = spi_get_drvdata(spi); 652a7e7274SBaolin Wang const struct sprd_pmic_data *pdata = ddata->pdata; 662a7e7274SBaolin Wang enum usb_charger_type type; 672a7e7274SBaolin Wang u32 val; 682a7e7274SBaolin Wang int ret; 692a7e7274SBaolin Wang 702a7e7274SBaolin Wang ret = regmap_read_poll_timeout(ddata->regmap, pdata->charger_det, val, 712a7e7274SBaolin Wang (val & SPRD_PMIC_CHG_DET_DONE), 722a7e7274SBaolin Wang SPRD_PMIC_CHG_DET_DELAY_US, 732a7e7274SBaolin Wang SPRD_PMIC_CHG_DET_TIMEOUT); 742a7e7274SBaolin Wang if (ret) { 752a7e7274SBaolin Wang dev_err(&spi->dev, "failed to detect charger type\n"); 762a7e7274SBaolin Wang return UNKNOWN_TYPE; 772a7e7274SBaolin Wang } 782a7e7274SBaolin Wang 792a7e7274SBaolin Wang switch (val & SPRD_PMIC_CHG_TYPE_MASK) { 802a7e7274SBaolin Wang case SPRD_PMIC_CDP_TYPE: 812a7e7274SBaolin Wang type = CDP_TYPE; 822a7e7274SBaolin Wang break; 832a7e7274SBaolin Wang case SPRD_PMIC_DCP_TYPE: 842a7e7274SBaolin Wang type = DCP_TYPE; 852a7e7274SBaolin Wang break; 862a7e7274SBaolin Wang case SPRD_PMIC_SDP_TYPE: 872a7e7274SBaolin Wang type = SDP_TYPE; 882a7e7274SBaolin Wang break; 892a7e7274SBaolin Wang default: 902a7e7274SBaolin Wang type = UNKNOWN_TYPE; 912a7e7274SBaolin Wang break; 922a7e7274SBaolin Wang } 932a7e7274SBaolin Wang 942a7e7274SBaolin Wang return type; 952a7e7274SBaolin Wang } 962a7e7274SBaolin Wang EXPORT_SYMBOL_GPL(sprd_pmic_detect_charger_type); 972a7e7274SBaolin Wang 9825ca4ae4SBaolin Wang static int sprd_pmic_spi_write(void *context, const void *data, size_t count) 9925ca4ae4SBaolin Wang { 10025ca4ae4SBaolin Wang struct device *dev = context; 10125ca4ae4SBaolin Wang struct spi_device *spi = to_spi_device(dev); 10225ca4ae4SBaolin Wang 10325ca4ae4SBaolin Wang return spi_write(spi, data, count); 10425ca4ae4SBaolin Wang } 10525ca4ae4SBaolin Wang 10625ca4ae4SBaolin Wang static int sprd_pmic_spi_read(void *context, 10725ca4ae4SBaolin Wang const void *reg, size_t reg_size, 10825ca4ae4SBaolin Wang void *val, size_t val_size) 10925ca4ae4SBaolin Wang { 11025ca4ae4SBaolin Wang struct device *dev = context; 11125ca4ae4SBaolin Wang struct spi_device *spi = to_spi_device(dev); 11225ca4ae4SBaolin Wang u32 rx_buf[2] = { 0 }; 11325ca4ae4SBaolin Wang int ret; 11425ca4ae4SBaolin Wang 11525ca4ae4SBaolin Wang /* Now we only support one PMIC register to read every time. */ 11625ca4ae4SBaolin Wang if (reg_size != sizeof(u32) || val_size != sizeof(u32)) 11725ca4ae4SBaolin Wang return -EINVAL; 11825ca4ae4SBaolin Wang 11925ca4ae4SBaolin Wang /* Copy address to read from into first element of SPI buffer. */ 12025ca4ae4SBaolin Wang memcpy(rx_buf, reg, sizeof(u32)); 12125ca4ae4SBaolin Wang ret = spi_read(spi, rx_buf, 1); 12225ca4ae4SBaolin Wang if (ret < 0) 12325ca4ae4SBaolin Wang return ret; 12425ca4ae4SBaolin Wang 12525ca4ae4SBaolin Wang memcpy(val, rx_buf, val_size); 12625ca4ae4SBaolin Wang return 0; 12725ca4ae4SBaolin Wang } 12825ca4ae4SBaolin Wang 12925ca4ae4SBaolin Wang static struct regmap_bus sprd_pmic_regmap = { 13025ca4ae4SBaolin Wang .write = sprd_pmic_spi_write, 13125ca4ae4SBaolin Wang .read = sprd_pmic_spi_read, 13225ca4ae4SBaolin Wang .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, 13325ca4ae4SBaolin Wang .val_format_endian_default = REGMAP_ENDIAN_NATIVE, 13425ca4ae4SBaolin Wang }; 13525ca4ae4SBaolin Wang 13625ca4ae4SBaolin Wang static const struct regmap_config sprd_pmic_config = { 13725ca4ae4SBaolin Wang .reg_bits = 32, 13825ca4ae4SBaolin Wang .val_bits = 32, 13925ca4ae4SBaolin Wang .reg_stride = 4, 14025ca4ae4SBaolin Wang .max_register = 0xffff, 14125ca4ae4SBaolin Wang }; 14225ca4ae4SBaolin Wang 14325ca4ae4SBaolin Wang static int sprd_pmic_probe(struct spi_device *spi) 14425ca4ae4SBaolin Wang { 14525ca4ae4SBaolin Wang struct sprd_pmic *ddata; 14625ca4ae4SBaolin Wang const struct sprd_pmic_data *pdata; 14725ca4ae4SBaolin Wang int ret, i; 14825ca4ae4SBaolin Wang 14925ca4ae4SBaolin Wang pdata = of_device_get_match_data(&spi->dev); 15025ca4ae4SBaolin Wang if (!pdata) { 15125ca4ae4SBaolin Wang dev_err(&spi->dev, "No matching driver data found\n"); 15225ca4ae4SBaolin Wang return -EINVAL; 15325ca4ae4SBaolin Wang } 15425ca4ae4SBaolin Wang 15525ca4ae4SBaolin Wang ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL); 15625ca4ae4SBaolin Wang if (!ddata) 15725ca4ae4SBaolin Wang return -ENOMEM; 15825ca4ae4SBaolin Wang 15925ca4ae4SBaolin Wang ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap, 16025ca4ae4SBaolin Wang &spi->dev, &sprd_pmic_config); 16125ca4ae4SBaolin Wang if (IS_ERR(ddata->regmap)) { 16225ca4ae4SBaolin Wang ret = PTR_ERR(ddata->regmap); 16325ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to allocate register map %d\n", ret); 16425ca4ae4SBaolin Wang return ret; 16525ca4ae4SBaolin Wang } 16625ca4ae4SBaolin Wang 16725ca4ae4SBaolin Wang spi_set_drvdata(spi, ddata); 16825ca4ae4SBaolin Wang ddata->dev = &spi->dev; 16925ca4ae4SBaolin Wang ddata->irq = spi->irq; 1702a7e7274SBaolin Wang ddata->pdata = pdata; 17125ca4ae4SBaolin Wang 17225ca4ae4SBaolin Wang ddata->irq_chip.name = dev_name(&spi->dev); 17325ca4ae4SBaolin Wang ddata->irq_chip.status_base = 17425ca4ae4SBaolin Wang pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS; 17525ca4ae4SBaolin Wang ddata->irq_chip.mask_base = pdata->irq_base + SPRD_PMIC_INT_EN; 17625ca4ae4SBaolin Wang ddata->irq_chip.ack_base = 0; 17725ca4ae4SBaolin Wang ddata->irq_chip.num_regs = 1; 17825ca4ae4SBaolin Wang ddata->irq_chip.num_irqs = pdata->num_irqs; 17925ca4ae4SBaolin Wang ddata->irq_chip.mask_invert = true; 18025ca4ae4SBaolin Wang 181a86854d0SKees Cook ddata->irqs = devm_kcalloc(&spi->dev, 182a86854d0SKees Cook pdata->num_irqs, sizeof(struct regmap_irq), 183a86854d0SKees Cook GFP_KERNEL); 18425ca4ae4SBaolin Wang if (!ddata->irqs) 18525ca4ae4SBaolin Wang return -ENOMEM; 18625ca4ae4SBaolin Wang 18725ca4ae4SBaolin Wang ddata->irq_chip.irqs = ddata->irqs; 188ec46855dSLee Jones for (i = 0; i < pdata->num_irqs; i++) 189ec46855dSLee Jones ddata->irqs[i].mask = BIT(i); 19025ca4ae4SBaolin Wang 19125ca4ae4SBaolin Wang ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq, 192*a75bfc82SBaolin Wang IRQF_ONESHOT, 0, 19325ca4ae4SBaolin Wang &ddata->irq_chip, &ddata->irq_data); 19425ca4ae4SBaolin Wang if (ret) { 19525ca4ae4SBaolin Wang dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret); 19625ca4ae4SBaolin Wang return ret; 19725ca4ae4SBaolin Wang } 19825ca4ae4SBaolin Wang 199c61e1658SChunyan Zhang ret = devm_of_platform_populate(&spi->dev); 20025ca4ae4SBaolin Wang if (ret) { 201c61e1658SChunyan Zhang dev_err(&spi->dev, "Failed to populate sub-devices %d\n", ret); 20225ca4ae4SBaolin Wang return ret; 20325ca4ae4SBaolin Wang } 20425ca4ae4SBaolin Wang 205*a75bfc82SBaolin Wang device_init_wakeup(&spi->dev, true); 20625ca4ae4SBaolin Wang return 0; 20725ca4ae4SBaolin Wang } 20825ca4ae4SBaolin Wang 209*a75bfc82SBaolin Wang #ifdef CONFIG_PM_SLEEP 210*a75bfc82SBaolin Wang static int sprd_pmic_suspend(struct device *dev) 211*a75bfc82SBaolin Wang { 212*a75bfc82SBaolin Wang struct sprd_pmic *ddata = dev_get_drvdata(dev); 213*a75bfc82SBaolin Wang 214*a75bfc82SBaolin Wang if (device_may_wakeup(dev)) 215*a75bfc82SBaolin Wang enable_irq_wake(ddata->irq); 216*a75bfc82SBaolin Wang 217*a75bfc82SBaolin Wang return 0; 218*a75bfc82SBaolin Wang } 219*a75bfc82SBaolin Wang 220*a75bfc82SBaolin Wang static int sprd_pmic_resume(struct device *dev) 221*a75bfc82SBaolin Wang { 222*a75bfc82SBaolin Wang struct sprd_pmic *ddata = dev_get_drvdata(dev); 223*a75bfc82SBaolin Wang 224*a75bfc82SBaolin Wang if (device_may_wakeup(dev)) 225*a75bfc82SBaolin Wang disable_irq_wake(ddata->irq); 226*a75bfc82SBaolin Wang 227*a75bfc82SBaolin Wang return 0; 228*a75bfc82SBaolin Wang } 229*a75bfc82SBaolin Wang #endif 230*a75bfc82SBaolin Wang 231*a75bfc82SBaolin Wang static SIMPLE_DEV_PM_OPS(sprd_pmic_pm_ops, sprd_pmic_suspend, sprd_pmic_resume); 232*a75bfc82SBaolin Wang 23325ca4ae4SBaolin Wang static const struct of_device_id sprd_pmic_match[] = { 23425ca4ae4SBaolin Wang { .compatible = "sprd,sc2731", .data = &sc2731_data }, 23525ca4ae4SBaolin Wang {}, 23625ca4ae4SBaolin Wang }; 23725ca4ae4SBaolin Wang MODULE_DEVICE_TABLE(of, sprd_pmic_match); 23825ca4ae4SBaolin Wang 23925ca4ae4SBaolin Wang static struct spi_driver sprd_pmic_driver = { 24025ca4ae4SBaolin Wang .driver = { 24125ca4ae4SBaolin Wang .name = "sc27xx-pmic", 24225ca4ae4SBaolin Wang .of_match_table = sprd_pmic_match, 243*a75bfc82SBaolin Wang .pm = &sprd_pmic_pm_ops, 24425ca4ae4SBaolin Wang }, 24525ca4ae4SBaolin Wang .probe = sprd_pmic_probe, 24625ca4ae4SBaolin Wang }; 24725ca4ae4SBaolin Wang 24825ca4ae4SBaolin Wang static int __init sprd_pmic_init(void) 24925ca4ae4SBaolin Wang { 25025ca4ae4SBaolin Wang return spi_register_driver(&sprd_pmic_driver); 25125ca4ae4SBaolin Wang } 25225ca4ae4SBaolin Wang subsys_initcall(sprd_pmic_init); 25325ca4ae4SBaolin Wang 25425ca4ae4SBaolin Wang static void __exit sprd_pmic_exit(void) 25525ca4ae4SBaolin Wang { 25625ca4ae4SBaolin Wang spi_unregister_driver(&sprd_pmic_driver); 25725ca4ae4SBaolin Wang } 25825ca4ae4SBaolin Wang module_exit(sprd_pmic_exit); 25925ca4ae4SBaolin Wang 26025ca4ae4SBaolin Wang MODULE_LICENSE("GPL v2"); 26125ca4ae4SBaolin Wang MODULE_DESCRIPTION("Spreadtrum SC27xx PMICs driver"); 26225ca4ae4SBaolin Wang MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>"); 263