Merge tag 'powerpc-4.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux-block.git] / drivers / mfd / sprd-sc27xx-spi.c
1 /*
2  * Copyright (C) 2017 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/interrupt.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/mfd/core.h>
18 #include <linux/of_device.h>
19 #include <linux/regmap.h>
20 #include <linux/spi/spi.h>
21
22 #define SPRD_PMIC_INT_MASK_STATUS       0x0
23 #define SPRD_PMIC_INT_RAW_STATUS        0x4
24 #define SPRD_PMIC_INT_EN                0x8
25
26 #define SPRD_SC2731_IRQ_BASE            0x140
27 #define SPRD_SC2731_IRQ_NUMS            16
28
29 struct sprd_pmic {
30         struct regmap *regmap;
31         struct device *dev;
32         struct regmap_irq *irqs;
33         struct regmap_irq_chip irq_chip;
34         struct regmap_irq_chip_data *irq_data;
35         int irq;
36 };
37
38 struct sprd_pmic_data {
39         u32 irq_base;
40         u32 num_irqs;
41 };
42
43 /*
44  * Since different PMICs of SC27xx series can have different interrupt
45  * base address and irq number, we should save irq number and irq base
46  * in the device data structure.
47  */
48 static const struct sprd_pmic_data sc2731_data = {
49         .irq_base = SPRD_SC2731_IRQ_BASE,
50         .num_irqs = SPRD_SC2731_IRQ_NUMS,
51 };
52
53 static const struct mfd_cell sprd_pmic_devs[] = {
54         {
55                 .name = "sc27xx-wdt",
56                 .of_compatible = "sprd,sc27xx-wdt",
57         }, {
58                 .name = "sc27xx-rtc",
59                 .of_compatible = "sprd,sc27xx-rtc",
60         }, {
61                 .name = "sc27xx-charger",
62                 .of_compatible = "sprd,sc27xx-charger",
63         }, {
64                 .name = "sc27xx-chg-timer",
65                 .of_compatible = "sprd,sc27xx-chg-timer",
66         }, {
67                 .name = "sc27xx-fast-chg",
68                 .of_compatible = "sprd,sc27xx-fast-chg",
69         }, {
70                 .name = "sc27xx-chg-wdt",
71                 .of_compatible = "sprd,sc27xx-chg-wdt",
72         }, {
73                 .name = "sc27xx-typec",
74                 .of_compatible = "sprd,sc27xx-typec",
75         }, {
76                 .name = "sc27xx-flash",
77                 .of_compatible = "sprd,sc27xx-flash",
78         }, {
79                 .name = "sc27xx-eic",
80                 .of_compatible = "sprd,sc27xx-eic",
81         }, {
82                 .name = "sc27xx-efuse",
83                 .of_compatible = "sprd,sc27xx-efuse",
84         }, {
85                 .name = "sc27xx-thermal",
86                 .of_compatible = "sprd,sc27xx-thermal",
87         }, {
88                 .name = "sc27xx-adc",
89                 .of_compatible = "sprd,sc27xx-adc",
90         }, {
91                 .name = "sc27xx-audio-codec",
92                 .of_compatible = "sprd,sc27xx-audio-codec",
93         }, {
94                 .name = "sc27xx-regulator",
95                 .of_compatible = "sprd,sc27xx-regulator",
96         }, {
97                 .name = "sc27xx-vibrator",
98                 .of_compatible = "sprd,sc27xx-vibrator",
99         }, {
100                 .name = "sc27xx-keypad-led",
101                 .of_compatible = "sprd,sc27xx-keypad-led",
102         }, {
103                 .name = "sc27xx-bltc",
104                 .of_compatible = "sprd,sc27xx-bltc",
105         }, {
106                 .name = "sc27xx-fgu",
107                 .of_compatible = "sprd,sc27xx-fgu",
108         }, {
109                 .name = "sc27xx-7sreset",
110                 .of_compatible = "sprd,sc27xx-7sreset",
111         }, {
112                 .name = "sc27xx-poweroff",
113                 .of_compatible = "sprd,sc27xx-poweroff",
114         },
115 };
116
117 static int sprd_pmic_spi_write(void *context, const void *data, size_t count)
118 {
119         struct device *dev = context;
120         struct spi_device *spi = to_spi_device(dev);
121
122         return spi_write(spi, data, count);
123 }
124
125 static int sprd_pmic_spi_read(void *context,
126                               const void *reg, size_t reg_size,
127                               void *val, size_t val_size)
128 {
129         struct device *dev = context;
130         struct spi_device *spi = to_spi_device(dev);
131         u32 rx_buf[2] = { 0 };
132         int ret;
133
134         /* Now we only support one PMIC register to read every time. */
135         if (reg_size != sizeof(u32) || val_size != sizeof(u32))
136                 return -EINVAL;
137
138         /* Copy address to read from into first element of SPI buffer. */
139         memcpy(rx_buf, reg, sizeof(u32));
140         ret = spi_read(spi, rx_buf, 1);
141         if (ret < 0)
142                 return ret;
143
144         memcpy(val, rx_buf, val_size);
145         return 0;
146 }
147
148 static struct regmap_bus sprd_pmic_regmap = {
149         .write = sprd_pmic_spi_write,
150         .read = sprd_pmic_spi_read,
151         .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
152         .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
153 };
154
155 static const struct regmap_config sprd_pmic_config = {
156         .reg_bits = 32,
157         .val_bits = 32,
158         .reg_stride = 4,
159         .max_register = 0xffff,
160 };
161
162 static int sprd_pmic_probe(struct spi_device *spi)
163 {
164         struct sprd_pmic *ddata;
165         const struct sprd_pmic_data *pdata;
166         int ret, i;
167
168         pdata = of_device_get_match_data(&spi->dev);
169         if (!pdata) {
170                 dev_err(&spi->dev, "No matching driver data found\n");
171                 return -EINVAL;
172         }
173
174         ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
175         if (!ddata)
176                 return -ENOMEM;
177
178         ddata->regmap = devm_regmap_init(&spi->dev, &sprd_pmic_regmap,
179                                          &spi->dev, &sprd_pmic_config);
180         if (IS_ERR(ddata->regmap)) {
181                 ret = PTR_ERR(ddata->regmap);
182                 dev_err(&spi->dev, "Failed to allocate register map %d\n", ret);
183                 return ret;
184         }
185
186         spi_set_drvdata(spi, ddata);
187         ddata->dev = &spi->dev;
188         ddata->irq = spi->irq;
189
190         ddata->irq_chip.name = dev_name(&spi->dev);
191         ddata->irq_chip.status_base =
192                 pdata->irq_base + SPRD_PMIC_INT_MASK_STATUS;
193         ddata->irq_chip.mask_base = pdata->irq_base + SPRD_PMIC_INT_EN;
194         ddata->irq_chip.ack_base = 0;
195         ddata->irq_chip.num_regs = 1;
196         ddata->irq_chip.num_irqs = pdata->num_irqs;
197         ddata->irq_chip.mask_invert = true;
198
199         ddata->irqs = devm_kzalloc(&spi->dev, sizeof(struct regmap_irq) *
200                                    pdata->num_irqs, GFP_KERNEL);
201         if (!ddata->irqs)
202                 return -ENOMEM;
203
204         ddata->irq_chip.irqs = ddata->irqs;
205         for (i = 0; i < pdata->num_irqs; i++) {
206                 ddata->irqs[i].reg_offset = i / pdata->num_irqs;
207                 ddata->irqs[i].mask = BIT(i % pdata->num_irqs);
208         }
209
210         ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq,
211                                        IRQF_ONESHOT | IRQF_NO_SUSPEND, 0,
212                                        &ddata->irq_chip, &ddata->irq_data);
213         if (ret) {
214                 dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret);
215                 return ret;
216         }
217
218         ret = devm_mfd_add_devices(&spi->dev, PLATFORM_DEVID_AUTO,
219                                    sprd_pmic_devs, ARRAY_SIZE(sprd_pmic_devs),
220                                    NULL, 0,
221                                    regmap_irq_get_domain(ddata->irq_data));
222         if (ret) {
223                 dev_err(&spi->dev, "Failed to register device %d\n", ret);
224                 return ret;
225         }
226
227         return 0;
228 }
229
230 static const struct of_device_id sprd_pmic_match[] = {
231         { .compatible = "sprd,sc2731", .data = &sc2731_data },
232         {},
233 };
234 MODULE_DEVICE_TABLE(of, sprd_pmic_match);
235
236 static struct spi_driver sprd_pmic_driver = {
237         .driver = {
238                 .name = "sc27xx-pmic",
239                 .bus = &spi_bus_type,
240                 .of_match_table = sprd_pmic_match,
241         },
242         .probe = sprd_pmic_probe,
243 };
244
245 static int __init sprd_pmic_init(void)
246 {
247         return spi_register_driver(&sprd_pmic_driver);
248 }
249 subsys_initcall(sprd_pmic_init);
250
251 static void __exit sprd_pmic_exit(void)
252 {
253         spi_unregister_driver(&sprd_pmic_driver);
254 }
255 module_exit(sprd_pmic_exit);
256
257 MODULE_LICENSE("GPL v2");
258 MODULE_DESCRIPTION("Spreadtrum SC27xx PMICs driver");
259 MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>");