Merge branch 'siginfo-si_trapno-for-v5.15' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / drivers / mfd / as3722.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Core driver for ams AS3722 PMICs
4  *
5  * Copyright (C) 2013 AMS AG
6  * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
7  *
8  * Author: Florian Lobmaier <florian.lobmaier@ams.com>
9  * Author: Laxman Dewangan <ldewangan@nvidia.com>
10  */
11
12 #include <linux/err.h>
13 #include <linux/i2c.h>
14 #include <linux/interrupt.h>
15 #include <linux/irq.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/mfd/core.h>
19 #include <linux/mfd/as3722.h>
20 #include <linux/of.h>
21 #include <linux/regmap.h>
22 #include <linux/slab.h>
23
24 #define AS3722_DEVICE_ID        0x0C
25
26 static const struct resource as3722_rtc_resource[] = {
27         DEFINE_RES_IRQ_NAMED(AS3722_IRQ_RTC_ALARM, "as3722-rtc-alarm"),
28 };
29
30 static const struct resource as3722_adc_resource[] = {
31         DEFINE_RES_IRQ_NAMED(AS3722_IRQ_ADC, "as3722-adc"),
32 };
33
34 static const struct mfd_cell as3722_devs[] = {
35         {
36                 .name = "as3722-pinctrl",
37         },
38         {
39                 .name = "as3722-regulator",
40         },
41         {
42                 .name = "as3722-rtc",
43                 .num_resources = ARRAY_SIZE(as3722_rtc_resource),
44                 .resources = as3722_rtc_resource,
45         },
46         {
47                 .name = "as3722-adc",
48                 .num_resources = ARRAY_SIZE(as3722_adc_resource),
49                 .resources = as3722_adc_resource,
50         },
51         {
52                 .name = "as3722-power-off",
53         },
54         {
55                 .name = "as3722-wdt",
56         },
57 };
58
59 static const struct regmap_irq as3722_irqs[] = {
60         /* INT1 IRQs */
61         [AS3722_IRQ_LID] = {
62                 .mask = AS3722_INTERRUPT_MASK1_LID,
63         },
64         [AS3722_IRQ_ACOK] = {
65                 .mask = AS3722_INTERRUPT_MASK1_ACOK,
66         },
67         [AS3722_IRQ_ENABLE1] = {
68                 .mask = AS3722_INTERRUPT_MASK1_ENABLE1,
69         },
70         [AS3722_IRQ_OCCUR_ALARM_SD0] = {
71                 .mask = AS3722_INTERRUPT_MASK1_OCURR_ALARM_SD0,
72         },
73         [AS3722_IRQ_ONKEY_LONG_PRESS] = {
74                 .mask = AS3722_INTERRUPT_MASK1_ONKEY_LONG,
75         },
76         [AS3722_IRQ_ONKEY] = {
77                 .mask = AS3722_INTERRUPT_MASK1_ONKEY,
78         },
79         [AS3722_IRQ_OVTMP] = {
80                 .mask = AS3722_INTERRUPT_MASK1_OVTMP,
81         },
82         [AS3722_IRQ_LOWBAT] = {
83                 .mask = AS3722_INTERRUPT_MASK1_LOWBAT,
84         },
85
86         /* INT2 IRQs */
87         [AS3722_IRQ_SD0_LV] = {
88                 .mask = AS3722_INTERRUPT_MASK2_SD0_LV,
89                 .reg_offset = 1,
90         },
91         [AS3722_IRQ_SD1_LV] = {
92                 .mask = AS3722_INTERRUPT_MASK2_SD1_LV,
93                 .reg_offset = 1,
94         },
95         [AS3722_IRQ_SD2_LV] = {
96                 .mask = AS3722_INTERRUPT_MASK2_SD2345_LV,
97                 .reg_offset = 1,
98         },
99         [AS3722_IRQ_PWM1_OV_PROT] = {
100                 .mask = AS3722_INTERRUPT_MASK2_PWM1_OV_PROT,
101                 .reg_offset = 1,
102         },
103         [AS3722_IRQ_PWM2_OV_PROT] = {
104                 .mask = AS3722_INTERRUPT_MASK2_PWM2_OV_PROT,
105                 .reg_offset = 1,
106         },
107         [AS3722_IRQ_ENABLE2] = {
108                 .mask = AS3722_INTERRUPT_MASK2_ENABLE2,
109                 .reg_offset = 1,
110         },
111         [AS3722_IRQ_SD6_LV] = {
112                 .mask = AS3722_INTERRUPT_MASK2_SD6_LV,
113                 .reg_offset = 1,
114         },
115         [AS3722_IRQ_RTC_REP] = {
116                 .mask = AS3722_INTERRUPT_MASK2_RTC_REP,
117                 .reg_offset = 1,
118         },
119
120         /* INT3 IRQs */
121         [AS3722_IRQ_RTC_ALARM] = {
122                 .mask = AS3722_INTERRUPT_MASK3_RTC_ALARM,
123                 .reg_offset = 2,
124         },
125         [AS3722_IRQ_GPIO1] = {
126                 .mask = AS3722_INTERRUPT_MASK3_GPIO1,
127                 .reg_offset = 2,
128         },
129         [AS3722_IRQ_GPIO2] = {
130                 .mask = AS3722_INTERRUPT_MASK3_GPIO2,
131                 .reg_offset = 2,
132         },
133         [AS3722_IRQ_GPIO3] = {
134                 .mask = AS3722_INTERRUPT_MASK3_GPIO3,
135                 .reg_offset = 2,
136         },
137         [AS3722_IRQ_GPIO4] = {
138                 .mask = AS3722_INTERRUPT_MASK3_GPIO4,
139                 .reg_offset = 2,
140         },
141         [AS3722_IRQ_GPIO5] = {
142                 .mask = AS3722_INTERRUPT_MASK3_GPIO5,
143                 .reg_offset = 2,
144         },
145         [AS3722_IRQ_WATCHDOG] = {
146                 .mask = AS3722_INTERRUPT_MASK3_WATCHDOG,
147                 .reg_offset = 2,
148         },
149         [AS3722_IRQ_ENABLE3] = {
150                 .mask = AS3722_INTERRUPT_MASK3_ENABLE3,
151                 .reg_offset = 2,
152         },
153
154         /* INT4 IRQs */
155         [AS3722_IRQ_TEMP_SD0_SHUTDOWN] = {
156                 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD0_SHUTDOWN,
157                 .reg_offset = 3,
158         },
159         [AS3722_IRQ_TEMP_SD1_SHUTDOWN] = {
160                 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD1_SHUTDOWN,
161                 .reg_offset = 3,
162         },
163         [AS3722_IRQ_TEMP_SD2_SHUTDOWN] = {
164                 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD6_SHUTDOWN,
165                 .reg_offset = 3,
166         },
167         [AS3722_IRQ_TEMP_SD0_ALARM] = {
168                 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD0_ALARM,
169                 .reg_offset = 3,
170         },
171         [AS3722_IRQ_TEMP_SD1_ALARM] = {
172                 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD1_ALARM,
173                 .reg_offset = 3,
174         },
175         [AS3722_IRQ_TEMP_SD6_ALARM] = {
176                 .mask = AS3722_INTERRUPT_MASK4_TEMP_SD6_ALARM,
177                 .reg_offset = 3,
178         },
179         [AS3722_IRQ_OCCUR_ALARM_SD6] = {
180                 .mask = AS3722_INTERRUPT_MASK4_OCCUR_ALARM_SD6,
181                 .reg_offset = 3,
182         },
183         [AS3722_IRQ_ADC] = {
184                 .mask = AS3722_INTERRUPT_MASK4_ADC,
185                 .reg_offset = 3,
186         },
187 };
188
189 static const struct regmap_irq_chip as3722_irq_chip = {
190         .name = "as3722",
191         .irqs = as3722_irqs,
192         .num_irqs = ARRAY_SIZE(as3722_irqs),
193         .num_regs = 4,
194         .status_base = AS3722_INTERRUPT_STATUS1_REG,
195         .mask_base = AS3722_INTERRUPT_MASK1_REG,
196 };
197
198 static int as3722_check_device_id(struct as3722 *as3722)
199 {
200         u32 val;
201         int ret;
202
203         /* Check that this is actually a AS3722 */
204         ret = as3722_read(as3722, AS3722_ASIC_ID1_REG, &val);
205         if (ret < 0) {
206                 dev_err(as3722->dev, "ASIC_ID1 read failed: %d\n", ret);
207                 return ret;
208         }
209
210         if (val != AS3722_DEVICE_ID) {
211                 dev_err(as3722->dev, "Device is not AS3722, ID is 0x%x\n", val);
212                 return -ENODEV;
213         }
214
215         ret = as3722_read(as3722, AS3722_ASIC_ID2_REG, &val);
216         if (ret < 0) {
217                 dev_err(as3722->dev, "ASIC_ID2 read failed: %d\n", ret);
218                 return ret;
219         }
220
221         dev_info(as3722->dev, "AS3722 with revision 0x%x found\n", val);
222         return 0;
223 }
224
225 static int as3722_configure_pullups(struct as3722 *as3722)
226 {
227         int ret;
228         u32 val = 0;
229
230         if (as3722->en_intern_int_pullup)
231                 val |= AS3722_INT_PULL_UP;
232         if (as3722->en_intern_i2c_pullup)
233                 val |= AS3722_I2C_PULL_UP;
234
235         ret = as3722_update_bits(as3722, AS3722_IOVOLTAGE_REG,
236                         AS3722_INT_PULL_UP | AS3722_I2C_PULL_UP, val);
237         if (ret < 0)
238                 dev_err(as3722->dev, "IOVOLTAGE_REG update failed: %d\n", ret);
239         return ret;
240 }
241
242 static const struct regmap_range as3722_readable_ranges[] = {
243         regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_SD6_VOLTAGE_REG),
244         regmap_reg_range(AS3722_GPIO0_CONTROL_REG, AS3722_LDO7_VOLTAGE_REG),
245         regmap_reg_range(AS3722_LDO9_VOLTAGE_REG, AS3722_REG_SEQU_MOD3_REG),
246         regmap_reg_range(AS3722_SD_PHSW_CTRL_REG, AS3722_PWM_CONTROL_H_REG),
247         regmap_reg_range(AS3722_WATCHDOG_TIMER_REG, AS3722_WATCHDOG_TIMER_REG),
248         regmap_reg_range(AS3722_WATCHDOG_SOFTWARE_SIGNAL_REG,
249                                         AS3722_BATTERY_VOLTAGE_MONITOR2_REG),
250         regmap_reg_range(AS3722_SD_CONTROL_REG, AS3722_PWM_VCONTROL4_REG),
251         regmap_reg_range(AS3722_BB_CHARGER_REG, AS3722_SRAM_REG),
252         regmap_reg_range(AS3722_RTC_ACCESS_REG, AS3722_RTC_ACCESS_REG),
253         regmap_reg_range(AS3722_RTC_STATUS_REG, AS3722_TEMP_STATUS_REG),
254         regmap_reg_range(AS3722_ADC0_CONTROL_REG, AS3722_ADC_CONFIGURATION_REG),
255         regmap_reg_range(AS3722_ASIC_ID1_REG, AS3722_ASIC_ID2_REG),
256         regmap_reg_range(AS3722_LOCK_REG, AS3722_LOCK_REG),
257         regmap_reg_range(AS3722_FUSE7_REG, AS3722_FUSE7_REG),
258 };
259
260 static const struct regmap_access_table as3722_readable_table = {
261         .yes_ranges = as3722_readable_ranges,
262         .n_yes_ranges = ARRAY_SIZE(as3722_readable_ranges),
263 };
264
265 static const struct regmap_range as3722_writable_ranges[] = {
266         regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_SD6_VOLTAGE_REG),
267         regmap_reg_range(AS3722_GPIO0_CONTROL_REG, AS3722_LDO7_VOLTAGE_REG),
268         regmap_reg_range(AS3722_LDO9_VOLTAGE_REG, AS3722_GPIO_SIGNAL_OUT_REG),
269         regmap_reg_range(AS3722_REG_SEQU_MOD1_REG, AS3722_REG_SEQU_MOD3_REG),
270         regmap_reg_range(AS3722_SD_PHSW_CTRL_REG, AS3722_PWM_CONTROL_H_REG),
271         regmap_reg_range(AS3722_WATCHDOG_TIMER_REG, AS3722_WATCHDOG_TIMER_REG),
272         regmap_reg_range(AS3722_WATCHDOG_SOFTWARE_SIGNAL_REG,
273                                         AS3722_BATTERY_VOLTAGE_MONITOR2_REG),
274         regmap_reg_range(AS3722_SD_CONTROL_REG, AS3722_PWM_VCONTROL4_REG),
275         regmap_reg_range(AS3722_BB_CHARGER_REG, AS3722_SRAM_REG),
276         regmap_reg_range(AS3722_INTERRUPT_MASK1_REG, AS3722_TEMP_STATUS_REG),
277         regmap_reg_range(AS3722_ADC0_CONTROL_REG, AS3722_ADC1_CONTROL_REG),
278         regmap_reg_range(AS3722_ADC1_THRESHOLD_HI_MSB_REG,
279                                         AS3722_ADC_CONFIGURATION_REG),
280         regmap_reg_range(AS3722_LOCK_REG, AS3722_LOCK_REG),
281 };
282
283 static const struct regmap_access_table as3722_writable_table = {
284         .yes_ranges = as3722_writable_ranges,
285         .n_yes_ranges = ARRAY_SIZE(as3722_writable_ranges),
286 };
287
288 static const struct regmap_range as3722_cacheable_ranges[] = {
289         regmap_reg_range(AS3722_SD0_VOLTAGE_REG, AS3722_LDO11_VOLTAGE_REG),
290         regmap_reg_range(AS3722_SD_CONTROL_REG, AS3722_LDOCONTROL1_REG),
291 };
292
293 static const struct regmap_access_table as3722_volatile_table = {
294         .no_ranges = as3722_cacheable_ranges,
295         .n_no_ranges = ARRAY_SIZE(as3722_cacheable_ranges),
296 };
297
298 static const struct regmap_config as3722_regmap_config = {
299         .reg_bits = 8,
300         .val_bits = 8,
301         .max_register = AS3722_MAX_REGISTER,
302         .cache_type = REGCACHE_RBTREE,
303         .rd_table = &as3722_readable_table,
304         .wr_table = &as3722_writable_table,
305         .volatile_table = &as3722_volatile_table,
306 };
307
308 static int as3722_i2c_of_probe(struct i2c_client *i2c,
309                         struct as3722 *as3722)
310 {
311         struct device_node *np = i2c->dev.of_node;
312         struct irq_data *irq_data;
313
314         if (!np) {
315                 dev_err(&i2c->dev, "Device Tree not found\n");
316                 return -EINVAL;
317         }
318
319         irq_data = irq_get_irq_data(i2c->irq);
320         if (!irq_data) {
321                 dev_err(&i2c->dev, "Invalid IRQ: %d\n", i2c->irq);
322                 return -EINVAL;
323         }
324
325         as3722->en_intern_int_pullup = of_property_read_bool(np,
326                                         "ams,enable-internal-int-pullup");
327         as3722->en_intern_i2c_pullup = of_property_read_bool(np,
328                                         "ams,enable-internal-i2c-pullup");
329         as3722->en_ac_ok_pwr_on = of_property_read_bool(np,
330                                         "ams,enable-ac-ok-power-on");
331         as3722->irq_flags = irqd_get_trigger_type(irq_data);
332         dev_dbg(&i2c->dev, "IRQ flags are 0x%08lx\n", as3722->irq_flags);
333         return 0;
334 }
335
336 static int as3722_i2c_probe(struct i2c_client *i2c,
337                         const struct i2c_device_id *id)
338 {
339         struct as3722 *as3722;
340         unsigned long irq_flags;
341         int ret;
342         u8 val = 0;
343
344         as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL);
345         if (!as3722)
346                 return -ENOMEM;
347
348         as3722->dev = &i2c->dev;
349         as3722->chip_irq = i2c->irq;
350         i2c_set_clientdata(i2c, as3722);
351
352         ret = as3722_i2c_of_probe(i2c, as3722);
353         if (ret < 0)
354                 return ret;
355
356         as3722->regmap = devm_regmap_init_i2c(i2c, &as3722_regmap_config);
357         if (IS_ERR(as3722->regmap)) {
358                 ret = PTR_ERR(as3722->regmap);
359                 dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
360                 return ret;
361         }
362
363         ret = as3722_check_device_id(as3722);
364         if (ret < 0)
365                 return ret;
366
367         irq_flags = as3722->irq_flags | IRQF_ONESHOT;
368         ret = devm_regmap_add_irq_chip(as3722->dev, as3722->regmap,
369                                        as3722->chip_irq,
370                                        irq_flags, -1, &as3722_irq_chip,
371                                        &as3722->irq_data);
372         if (ret < 0) {
373                 dev_err(as3722->dev, "Failed to add regmap irq: %d\n", ret);
374                 return ret;
375         }
376
377         ret = as3722_configure_pullups(as3722);
378         if (ret < 0)
379                 return ret;
380
381         if (as3722->en_ac_ok_pwr_on)
382                 val = AS3722_CTRL_SEQU1_AC_OK_PWR_ON;
383         ret = as3722_update_bits(as3722, AS3722_CTRL_SEQU1_REG,
384                         AS3722_CTRL_SEQU1_AC_OK_PWR_ON, val);
385         if (ret < 0) {
386                 dev_err(as3722->dev, "CTRLsequ1 update failed: %d\n", ret);
387                 return ret;
388         }
389
390         ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs,
391                                    ARRAY_SIZE(as3722_devs), NULL, 0,
392                                    regmap_irq_get_domain(as3722->irq_data));
393         if (ret) {
394                 dev_err(as3722->dev, "Failed to add MFD devices: %d\n", ret);
395                 return ret;
396         }
397
398         device_init_wakeup(as3722->dev, true);
399
400         dev_dbg(as3722->dev, "AS3722 core driver initialized successfully\n");
401         return 0;
402 }
403
404 static int __maybe_unused as3722_i2c_suspend(struct device *dev)
405 {
406         struct as3722 *as3722 = dev_get_drvdata(dev);
407
408         if (device_may_wakeup(dev))
409                 enable_irq_wake(as3722->chip_irq);
410         disable_irq(as3722->chip_irq);
411
412         return 0;
413 }
414
415 static int __maybe_unused as3722_i2c_resume(struct device *dev)
416 {
417         struct as3722 *as3722 = dev_get_drvdata(dev);
418
419         enable_irq(as3722->chip_irq);
420
421         if (device_may_wakeup(dev))
422                 disable_irq_wake(as3722->chip_irq);
423
424         return 0;
425 }
426
427 static const struct of_device_id as3722_of_match[] = {
428         { .compatible = "ams,as3722", },
429         {},
430 };
431 MODULE_DEVICE_TABLE(of, as3722_of_match);
432
433 static const struct i2c_device_id as3722_i2c_id[] = {
434         { "as3722", 0 },
435         {},
436 };
437 MODULE_DEVICE_TABLE(i2c, as3722_i2c_id);
438
439 static const struct dev_pm_ops as3722_pm_ops = {
440         SET_SYSTEM_SLEEP_PM_OPS(as3722_i2c_suspend, as3722_i2c_resume)
441 };
442
443 static struct i2c_driver as3722_i2c_driver = {
444         .driver = {
445                 .name = "as3722",
446                 .of_match_table = as3722_of_match,
447                 .pm = &as3722_pm_ops,
448         },
449         .probe = as3722_i2c_probe,
450         .id_table = as3722_i2c_id,
451 };
452
453 module_i2c_driver(as3722_i2c_driver);
454
455 MODULE_DESCRIPTION("I2C support for AS3722 PMICs");
456 MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
457 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
458 MODULE_LICENSE("GPL");