xref: /openbmc/linux/drivers/mfd/sprd-sc27xx-spi.c (revision 2a7e7274f3d43d2a072cab25c0035dc994903bb9)
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