cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sprd-sc27xx-spi.c (7101B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2017 Spreadtrum Communications Inc.
      4 */
      5
      6#include <linux/interrupt.h>
      7#include <linux/kernel.h>
      8#include <linux/module.h>
      9#include <linux/mfd/core.h>
     10#include <linux/mfd/sc27xx-pmic.h>
     11#include <linux/of_device.h>
     12#include <linux/of_platform.h>
     13#include <linux/regmap.h>
     14#include <linux/spi/spi.h>
     15#include <uapi/linux/usb/charger.h>
     16
     17#define SPRD_PMIC_INT_MASK_STATUS	0x0
     18#define SPRD_PMIC_INT_RAW_STATUS	0x4
     19#define SPRD_PMIC_INT_EN		0x8
     20
     21#define SPRD_SC2730_IRQ_BASE		0x80
     22#define SPRD_SC2730_IRQ_NUMS		10
     23#define SPRD_SC2730_CHG_DET		0x1b9c
     24#define SPRD_SC2731_IRQ_BASE		0x140
     25#define SPRD_SC2731_IRQ_NUMS		16
     26#define SPRD_SC2731_CHG_DET		0xedc
     27
     28/* PMIC charger detection definition */
     29#define SPRD_PMIC_CHG_DET_DELAY_US	200000
     30#define SPRD_PMIC_CHG_DET_TIMEOUT	2000000
     31#define SPRD_PMIC_CHG_DET_DONE		BIT(11)
     32#define SPRD_PMIC_SDP_TYPE		BIT(7)
     33#define SPRD_PMIC_DCP_TYPE		BIT(6)
     34#define SPRD_PMIC_CDP_TYPE		BIT(5)
     35#define SPRD_PMIC_CHG_TYPE_MASK		GENMASK(7, 5)
     36
     37struct sprd_pmic {
     38	struct regmap *regmap;
     39	struct device *dev;
     40	struct regmap_irq *irqs;
     41	struct regmap_irq_chip irq_chip;
     42	struct regmap_irq_chip_data *irq_data;
     43	const struct sprd_pmic_data *pdata;
     44	int irq;
     45};
     46
     47struct sprd_pmic_data {
     48	u32 irq_base;
     49	u32 num_irqs;
     50	u32 charger_det;
     51};
     52
     53/*
     54 * Since different PMICs of SC27xx series can have different interrupt
     55 * base address and irq number, we should save irq number and irq base
     56 * in the device data structure.
     57 */
     58static const struct sprd_pmic_data sc2730_data = {
     59	.irq_base = SPRD_SC2730_IRQ_BASE,
     60	.num_irqs = SPRD_SC2730_IRQ_NUMS,
     61	.charger_det = SPRD_SC2730_CHG_DET,
     62};
     63
     64static const struct sprd_pmic_data sc2731_data = {
     65	.irq_base = SPRD_SC2731_IRQ_BASE,
     66	.num_irqs = SPRD_SC2731_IRQ_NUMS,
     67	.charger_det = SPRD_SC2731_CHG_DET,
     68};
     69
     70enum usb_charger_type sprd_pmic_detect_charger_type(struct device *dev)
     71{
     72	struct spi_device *spi = to_spi_device(dev);
     73	struct sprd_pmic *ddata = spi_get_drvdata(spi);
     74	const struct sprd_pmic_data *pdata = ddata->pdata;
     75	enum usb_charger_type type;
     76	u32 val;
     77	int ret;
     78
     79	ret = regmap_read_poll_timeout(ddata->regmap, pdata->charger_det, val,
     80				       (val & SPRD_PMIC_CHG_DET_DONE),
     81				       SPRD_PMIC_CHG_DET_DELAY_US,
     82				       SPRD_PMIC_CHG_DET_TIMEOUT);
     83	if (ret) {
     84		dev_err(&spi->dev, "failed to detect charger type\n");
     85		return UNKNOWN_TYPE;
     86	}
     87
     88	switch (val & SPRD_PMIC_CHG_TYPE_MASK) {
     89	case SPRD_PMIC_CDP_TYPE:
     90		type = CDP_TYPE;
     91		break;
     92	case SPRD_PMIC_DCP_TYPE:
     93		type = DCP_TYPE;
     94		break;
     95	case SPRD_PMIC_SDP_TYPE:
     96		type = SDP_TYPE;
     97		break;
     98	default:
     99		type = UNKNOWN_TYPE;
    100		break;
    101	}
    102
    103	return type;
    104}
    105EXPORT_SYMBOL_GPL(sprd_pmic_detect_charger_type);
    106
    107static int sprd_pmic_spi_write(void *context, const void *data, size_t count)
    108{
    109	struct device *dev = context;
    110	struct spi_device *spi = to_spi_device(dev);
    111
    112	return spi_write(spi, data, count);
    113}
    114
    115static int sprd_pmic_spi_read(void *context,
    116			      const void *reg, size_t reg_size,
    117			      void *val, size_t val_size)
    118{
    119	struct device *dev = context;
    120	struct spi_device *spi = to_spi_device(dev);
    121	u32 rx_buf[2] = { 0 };
    122	int ret;
    123
    124	/* Now we only support one PMIC register to read every time. */
    125	if (reg_size != sizeof(u32) || val_size != sizeof(u32))
    126		return -EINVAL;
    127
    128	/* Copy address to read from into first element of SPI buffer. */
    129	memcpy(rx_buf, reg, sizeof(u32));
    130	ret = spi_read(spi, rx_buf, 1);
    131	if (ret < 0)
    132		return ret;
    133
    134	memcpy(val, rx_buf, val_size);
    135	return 0;
    136}
    137
    138static struct regmap_bus sprd_pmic_regmap = {
    139	.write = sprd_pmic_spi_write,
    140	.read = sprd_pmic_spi_read,
    141	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
    142	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
    143};
    144
    145static const struct regmap_config sprd_pmic_config = {
    146	.reg_bits = 32,
    147	.val_bits = 32,
    148	.reg_stride = 4,
    149	.max_register = 0xffff,
    150};
    151
    152static int sprd_pmic_probe(struct spi_device *spi)
    153{
    154	struct sprd_pmic *ddata;
    155	const struct sprd_pmic_data *pdata;
    156	int ret, i;
    157
    158	pdata = of_device_get_match_data(&spi->dev);
    159	if (!pdata) {
    160		dev_err(&spi->dev, "No matching driver data found\n");
    161		return -EINVAL;
    162	}
    163
    164	ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
    165	if (!ddata)
    166		return -ENOMEM;
    167
    168	ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap,
    169					 &spi->dev, &sprd_pmic_config);
    170	if (IS_ERR(ddata->regmap)) {
    171		ret = PTR_ERR(ddata->regmap);
    172		dev_err(&spi->dev, "Failed to allocate register map %d\n", ret);
    173		return ret;
    174	}
    175
    176	spi_set_drvdata(spi, ddata);
    177	ddata->dev = &spi->dev;
    178	ddata->irq = spi->irq;
    179	ddata->pdata = pdata;
    180
    181	ddata->irq_chip.name = dev_name(&spi->dev);
    182	ddata->irq_chip.status_base =
    183		pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS;
    184	ddata->irq_chip.mask_base = pdata->irq_base + SPRD_PMIC_INT_EN;
    185	ddata->irq_chip.ack_base = 0;
    186	ddata->irq_chip.num_regs = 1;
    187	ddata->irq_chip.num_irqs = pdata->num_irqs;
    188	ddata->irq_chip.mask_invert = true;
    189
    190	ddata->irqs = devm_kcalloc(&spi->dev,
    191				   pdata->num_irqs, sizeof(struct regmap_irq),
    192				   GFP_KERNEL);
    193	if (!ddata->irqs)
    194		return -ENOMEM;
    195
    196	ddata->irq_chip.irqs = ddata->irqs;
    197	for (i = 0; i < pdata->num_irqs; i++)
    198		ddata->irqs[i].mask = BIT(i);
    199
    200	ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq,
    201				       IRQF_ONESHOT, 0,
    202				       &ddata->irq_chip, &ddata->irq_data);
    203	if (ret) {
    204		dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret);
    205		return ret;
    206	}
    207
    208	ret = devm_of_platform_populate(&spi->dev);
    209	if (ret) {
    210		dev_err(&spi->dev, "Failed to populate sub-devices %d\n", ret);
    211		return ret;
    212	}
    213
    214	device_init_wakeup(&spi->dev, true);
    215	return 0;
    216}
    217
    218#ifdef CONFIG_PM_SLEEP
    219static int sprd_pmic_suspend(struct device *dev)
    220{
    221	struct sprd_pmic *ddata = dev_get_drvdata(dev);
    222
    223	if (device_may_wakeup(dev))
    224		enable_irq_wake(ddata->irq);
    225
    226	return 0;
    227}
    228
    229static int sprd_pmic_resume(struct device *dev)
    230{
    231	struct sprd_pmic *ddata = dev_get_drvdata(dev);
    232
    233	if (device_may_wakeup(dev))
    234		disable_irq_wake(ddata->irq);
    235
    236	return 0;
    237}
    238#endif
    239
    240static SIMPLE_DEV_PM_OPS(sprd_pmic_pm_ops, sprd_pmic_suspend, sprd_pmic_resume);
    241
    242static const struct of_device_id sprd_pmic_match[] = {
    243	{ .compatible = "sprd,sc2730", .data = &sc2730_data },
    244	{ .compatible = "sprd,sc2731", .data = &sc2731_data },
    245	{},
    246};
    247MODULE_DEVICE_TABLE(of, sprd_pmic_match);
    248
    249static const struct spi_device_id sprd_pmic_spi_ids[] = {
    250	{ .name = "sc2730", .driver_data = (unsigned long)&sc2730_data },
    251	{ .name = "sc2731", .driver_data = (unsigned long)&sc2731_data },
    252	{},
    253};
    254MODULE_DEVICE_TABLE(spi, sprd_pmic_spi_ids);
    255
    256static struct spi_driver sprd_pmic_driver = {
    257	.driver = {
    258		.name = "sc27xx-pmic",
    259		.of_match_table = sprd_pmic_match,
    260		.pm = &sprd_pmic_pm_ops,
    261	},
    262	.probe = sprd_pmic_probe,
    263	.id_table = sprd_pmic_spi_ids,
    264};
    265
    266static int __init sprd_pmic_init(void)
    267{
    268	return spi_register_driver(&sprd_pmic_driver);
    269}
    270subsys_initcall(sprd_pmic_init);
    271
    272static void __exit sprd_pmic_exit(void)
    273{
    274	spi_unregister_driver(&sprd_pmic_driver);
    275}
    276module_exit(sprd_pmic_exit);
    277
    278MODULE_LICENSE("GPL v2");
    279MODULE_DESCRIPTION("Spreadtrum SC27xx PMICs driver");
    280MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>");