Merge tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
[linux-2.6-microblaze.git] / drivers / power / supply / max8925_power.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Battery driver for Maxim MAX8925
4  *
5  * Copyright (c) 2009-2010 Marvell International Ltd.
6  *      Haojian Zhuang <haojian.zhuang@marvell.com>
7  */
8
9 #include <linux/module.h>
10 #include <linux/err.h>
11 #include <linux/slab.h>
12 #include <linux/of.h>
13 #include <linux/i2c.h>
14 #include <linux/interrupt.h>
15 #include <linux/platform_device.h>
16 #include <linux/power_supply.h>
17 #include <linux/mfd/max8925.h>
18
19 /* registers in GPM */
20 #define MAX8925_OUT5VEN                 0x54
21 #define MAX8925_OUT3VEN                 0x58
22 #define MAX8925_CHG_CNTL1               0x7c
23
24 /* bits definition */
25 #define MAX8925_CHG_STAT_VSYSLOW        (1 << 0)
26 #define MAX8925_CHG_STAT_MODE_MASK      (3 << 2)
27 #define MAX8925_CHG_STAT_EN_MASK        (1 << 4)
28 #define MAX8925_CHG_MBDET               (1 << 1)
29 #define MAX8925_CHG_AC_RANGE_MASK       (3 << 6)
30
31 /* registers in ADC */
32 #define MAX8925_ADC_RES_CNFG1           0x06
33 #define MAX8925_ADC_AVG_CNFG1           0x07
34 #define MAX8925_ADC_ACQ_CNFG1           0x08
35 #define MAX8925_ADC_ACQ_CNFG2           0x09
36 /* 2 bytes registers in below. MSB is 1st, LSB is 2nd. */
37 #define MAX8925_ADC_AUX2                0x62
38 #define MAX8925_ADC_VCHG                0x64
39 #define MAX8925_ADC_VBBATT              0x66
40 #define MAX8925_ADC_VMBATT              0x68
41 #define MAX8925_ADC_ISNS                0x6a
42 #define MAX8925_ADC_THM                 0x6c
43 #define MAX8925_ADC_TDIE                0x6e
44 #define MAX8925_CMD_AUX2                0xc8
45 #define MAX8925_CMD_VCHG                0xd0
46 #define MAX8925_CMD_VBBATT              0xd8
47 #define MAX8925_CMD_VMBATT              0xe0
48 #define MAX8925_CMD_ISNS                0xe8
49 #define MAX8925_CMD_THM                 0xf0
50 #define MAX8925_CMD_TDIE                0xf8
51
52 enum {
53         MEASURE_AUX2,
54         MEASURE_VCHG,
55         MEASURE_VBBATT,
56         MEASURE_VMBATT,
57         MEASURE_ISNS,
58         MEASURE_THM,
59         MEASURE_TDIE,
60         MEASURE_MAX,
61 };
62
63 struct max8925_power_info {
64         struct max8925_chip     *chip;
65         struct i2c_client       *gpm;
66         struct i2c_client       *adc;
67
68         struct power_supply     *ac;
69         struct power_supply     *usb;
70         struct power_supply     *battery;
71         int                     irq_base;
72         unsigned                ac_online:1;
73         unsigned                usb_online:1;
74         unsigned                bat_online:1;
75         unsigned                chg_mode:2;
76         unsigned                batt_detect:1;  /* detecing MB by ID pin */
77         unsigned                topoff_threshold:2;
78         unsigned                fast_charge:3;
79         unsigned                no_temp_support:1;
80         unsigned                no_insert_detect:1;
81
82         int (*set_charger) (int);
83 };
84
85 static int __set_charger(struct max8925_power_info *info, int enable)
86 {
87         struct max8925_chip *chip = info->chip;
88         if (enable) {
89                 /* enable charger in platform */
90                 if (info->set_charger)
91                         info->set_charger(1);
92                 /* enable charger */
93                 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 0);
94         } else {
95                 /* disable charge */
96                 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
97                 if (info->set_charger)
98                         info->set_charger(0);
99         }
100         dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger"
101                 : "Disable charger");
102         return 0;
103 }
104
105 static irqreturn_t max8925_charger_handler(int irq, void *data)
106 {
107         struct max8925_power_info *info = (struct max8925_power_info *)data;
108         struct max8925_chip *chip = info->chip;
109
110         switch (irq - chip->irq_base) {
111         case MAX8925_IRQ_VCHG_DC_R:
112                 info->ac_online = 1;
113                 __set_charger(info, 1);
114                 dev_dbg(chip->dev, "Adapter inserted\n");
115                 break;
116         case MAX8925_IRQ_VCHG_DC_F:
117                 info->ac_online = 0;
118                 __set_charger(info, 0);
119                 dev_dbg(chip->dev, "Adapter removed\n");
120                 break;
121         case MAX8925_IRQ_VCHG_THM_OK_F:
122                 /* Battery is not ready yet */
123                 dev_dbg(chip->dev, "Battery temperature is out of range\n");
124                 fallthrough;
125         case MAX8925_IRQ_VCHG_DC_OVP:
126                 dev_dbg(chip->dev, "Error detection\n");
127                 __set_charger(info, 0);
128                 break;
129         case MAX8925_IRQ_VCHG_THM_OK_R:
130                 /* Battery is ready now */
131                 dev_dbg(chip->dev, "Battery temperature is in range\n");
132                 break;
133         case MAX8925_IRQ_VCHG_SYSLOW_R:
134                 /* VSYS is low */
135                 dev_info(chip->dev, "Sys power is too low\n");
136                 break;
137         case MAX8925_IRQ_VCHG_SYSLOW_F:
138                 dev_dbg(chip->dev, "Sys power is above low threshold\n");
139                 break;
140         case MAX8925_IRQ_VCHG_DONE:
141                 __set_charger(info, 0);
142                 dev_dbg(chip->dev, "Charging is done\n");
143                 break;
144         case MAX8925_IRQ_VCHG_TOPOFF:
145                 dev_dbg(chip->dev, "Charging in top-off mode\n");
146                 break;
147         case MAX8925_IRQ_VCHG_TMR_FAULT:
148                 __set_charger(info, 0);
149                 dev_dbg(chip->dev, "Safe timer is expired\n");
150                 break;
151         case MAX8925_IRQ_VCHG_RST:
152                 __set_charger(info, 0);
153                 dev_dbg(chip->dev, "Charger is reset\n");
154                 break;
155         }
156         return IRQ_HANDLED;
157 }
158
159 static int start_measure(struct max8925_power_info *info, int type)
160 {
161         unsigned char buf[2] = {0, 0};
162         int meas_cmd;
163         int meas_reg = 0, ret;
164
165         switch (type) {
166         case MEASURE_VCHG:
167                 meas_cmd = MAX8925_CMD_VCHG;
168                 meas_reg = MAX8925_ADC_VCHG;
169                 break;
170         case MEASURE_VBBATT:
171                 meas_cmd = MAX8925_CMD_VBBATT;
172                 meas_reg = MAX8925_ADC_VBBATT;
173                 break;
174         case MEASURE_VMBATT:
175                 meas_cmd = MAX8925_CMD_VMBATT;
176                 meas_reg = MAX8925_ADC_VMBATT;
177                 break;
178         case MEASURE_ISNS:
179                 meas_cmd = MAX8925_CMD_ISNS;
180                 meas_reg = MAX8925_ADC_ISNS;
181                 break;
182         default:
183                 return -EINVAL;
184         }
185
186         max8925_reg_write(info->adc, meas_cmd, 0);
187         max8925_bulk_read(info->adc, meas_reg, 2, buf);
188         ret = ((buf[0]<<8) | buf[1]) >> 4;
189
190         return ret;
191 }
192
193 static int max8925_ac_get_prop(struct power_supply *psy,
194                                enum power_supply_property psp,
195                                union power_supply_propval *val)
196 {
197         struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent);
198         int ret = 0;
199
200         switch (psp) {
201         case POWER_SUPPLY_PROP_ONLINE:
202                 val->intval = info->ac_online;
203                 break;
204         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
205                 if (info->ac_online) {
206                         ret = start_measure(info, MEASURE_VCHG);
207                         if (ret >= 0) {
208                                 val->intval = ret * 2000;       /* unit is uV */
209                                 goto out;
210                         }
211                 }
212                 ret = -ENODATA;
213                 break;
214         default:
215                 ret = -ENODEV;
216                 break;
217         }
218 out:
219         return ret;
220 }
221
222 static enum power_supply_property max8925_ac_props[] = {
223         POWER_SUPPLY_PROP_ONLINE,
224         POWER_SUPPLY_PROP_VOLTAGE_NOW,
225 };
226
227 static int max8925_usb_get_prop(struct power_supply *psy,
228                                 enum power_supply_property psp,
229                                 union power_supply_propval *val)
230 {
231         struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent);
232         int ret = 0;
233
234         switch (psp) {
235         case POWER_SUPPLY_PROP_ONLINE:
236                 val->intval = info->usb_online;
237                 break;
238         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
239                 if (info->usb_online) {
240                         ret = start_measure(info, MEASURE_VCHG);
241                         if (ret >= 0) {
242                                 val->intval = ret * 2000;       /* unit is uV */
243                                 goto out;
244                         }
245                 }
246                 ret = -ENODATA;
247                 break;
248         default:
249                 ret = -ENODEV;
250                 break;
251         }
252 out:
253         return ret;
254 }
255
256 static enum power_supply_property max8925_usb_props[] = {
257         POWER_SUPPLY_PROP_ONLINE,
258         POWER_SUPPLY_PROP_VOLTAGE_NOW,
259 };
260
261 static int max8925_bat_get_prop(struct power_supply *psy,
262                                 enum power_supply_property psp,
263                                 union power_supply_propval *val)
264 {
265         struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent);
266         int ret = 0;
267
268         switch (psp) {
269         case POWER_SUPPLY_PROP_ONLINE:
270                 val->intval = info->bat_online;
271                 break;
272         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
273                 if (info->bat_online) {
274                         ret = start_measure(info, MEASURE_VMBATT);
275                         if (ret >= 0) {
276                                 val->intval = ret * 2000;       /* unit is uV */
277                                 ret = 0;
278                                 break;
279                         }
280                 }
281                 ret = -ENODATA;
282                 break;
283         case POWER_SUPPLY_PROP_CURRENT_NOW:
284                 if (info->bat_online) {
285                         ret = start_measure(info, MEASURE_ISNS);
286                         if (ret >= 0) {
287                                 /* assume r_sns is 0.02 */
288                                 ret = ((ret * 6250) - 3125) /* uA */;
289                                 val->intval = 0;
290                                 if (ret > 0)
291                                         val->intval = ret; /* unit is mA */
292                                 ret = 0;
293                                 break;
294                         }
295                 }
296                 ret = -ENODATA;
297                 break;
298         case POWER_SUPPLY_PROP_CHARGE_TYPE:
299                 if (!info->bat_online) {
300                         ret = -ENODATA;
301                         break;
302                 }
303                 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
304                 ret = (ret & MAX8925_CHG_STAT_MODE_MASK) >> 2;
305                 switch (ret) {
306                 case 1:
307                         val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
308                         break;
309                 case 0:
310                 case 2:
311                         val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
312                         break;
313                 case 3:
314                         val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
315                         break;
316                 }
317                 ret = 0;
318                 break;
319         case POWER_SUPPLY_PROP_STATUS:
320                 if (!info->bat_online) {
321                         ret = -ENODATA;
322                         break;
323                 }
324                 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
325                 if (info->usb_online || info->ac_online) {
326                         val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
327                         if (ret & MAX8925_CHG_STAT_EN_MASK)
328                                 val->intval = POWER_SUPPLY_STATUS_CHARGING;
329                 } else
330                         val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
331                 ret = 0;
332                 break;
333         default:
334                 ret = -ENODEV;
335                 break;
336         }
337         return ret;
338 }
339
340 static enum power_supply_property max8925_battery_props[] = {
341         POWER_SUPPLY_PROP_ONLINE,
342         POWER_SUPPLY_PROP_VOLTAGE_NOW,
343         POWER_SUPPLY_PROP_CURRENT_NOW,
344         POWER_SUPPLY_PROP_CHARGE_TYPE,
345         POWER_SUPPLY_PROP_STATUS,
346 };
347
348 static const struct power_supply_desc ac_desc = {
349         .name           = "max8925-ac",
350         .type           = POWER_SUPPLY_TYPE_MAINS,
351         .properties     = max8925_ac_props,
352         .num_properties = ARRAY_SIZE(max8925_ac_props),
353         .get_property   = max8925_ac_get_prop,
354 };
355
356 static const struct power_supply_desc usb_desc = {
357         .name           = "max8925-usb",
358         .type           = POWER_SUPPLY_TYPE_USB,
359         .properties     = max8925_usb_props,
360         .num_properties = ARRAY_SIZE(max8925_usb_props),
361         .get_property   = max8925_usb_get_prop,
362 };
363
364 static const struct power_supply_desc battery_desc = {
365         .name           = "max8925-battery",
366         .type           = POWER_SUPPLY_TYPE_BATTERY,
367         .properties     = max8925_battery_props,
368         .num_properties = ARRAY_SIZE(max8925_battery_props),
369         .get_property   = max8925_bat_get_prop,
370 };
371
372 #define REQUEST_IRQ(_irq, _name)                                        \
373 do {                                                                    \
374         ret = request_threaded_irq(chip->irq_base + _irq, NULL,         \
375                                     max8925_charger_handler,            \
376                                     IRQF_ONESHOT, _name, info);         \
377         if (ret)                                                        \
378                 dev_err(chip->dev, "Failed to request IRQ #%d: %d\n",   \
379                         _irq, ret);                                     \
380 } while (0)
381
382 static int max8925_init_charger(struct max8925_chip *chip,
383                                           struct max8925_power_info *info)
384 {
385         int ret;
386
387         REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp");
388         if (!info->no_insert_detect) {
389                 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
390                 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
391         }
392         if (!info->no_temp_support) {
393                 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
394                 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
395         }
396         REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high");
397         REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low");
398         REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset");
399         REQUEST_IRQ(MAX8925_IRQ_VCHG_DONE, "charger-done");
400         REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff");
401         REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire");
402
403         info->usb_online = 0;
404         info->bat_online = 0;
405
406         /* check for power - can miss interrupt at boot time */
407         if (start_measure(info, MEASURE_VCHG) * 2000 > 500000)
408                 info->ac_online = 1;
409         else
410                 info->ac_online = 0;
411
412         ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
413         if (ret >= 0) {
414                 /*
415                  * If battery detection is enabled, ID pin of battery is
416                  * connected to MBDET pin of MAX8925. It could be used to
417                  * detect battery presence.
418                  * Otherwise, we have to assume that battery is always on.
419                  */
420                 if (info->batt_detect)
421                         info->bat_online = (ret & MAX8925_CHG_MBDET) ? 0 : 1;
422                 else
423                         info->bat_online = 1;
424                 if (ret & MAX8925_CHG_AC_RANGE_MASK)
425                         info->ac_online = 1;
426                 else
427                         info->ac_online = 0;
428         }
429         /* disable charge */
430         max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
431         /* set charging current in charge topoff mode */
432         max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 3 << 5,
433                          info->topoff_threshold << 5);
434         /* set charing current in fast charge mode */
435         max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 7, info->fast_charge);
436
437         return 0;
438 }
439
440 static int max8925_deinit_charger(struct max8925_power_info *info)
441 {
442         struct max8925_chip *chip = info->chip;
443         int irq;
444
445         irq = chip->irq_base + MAX8925_IRQ_VCHG_DC_OVP;
446         for (; irq <= chip->irq_base + MAX8925_IRQ_VCHG_TMR_FAULT; irq++)
447                 free_irq(irq, info);
448
449         return 0;
450 }
451
452 #ifdef CONFIG_OF
453 static struct max8925_power_pdata *
454 max8925_power_dt_init(struct platform_device *pdev)
455 {
456         struct device_node *nproot = pdev->dev.parent->of_node;
457         struct device_node *np;
458         int batt_detect;
459         int topoff_threshold;
460         int fast_charge;
461         int no_temp_support;
462         int no_insert_detect;
463         struct max8925_power_pdata *pdata;
464
465         if (!nproot)
466                 return pdev->dev.platform_data;
467
468         np = of_get_child_by_name(nproot, "charger");
469         if (!np) {
470                 dev_err(&pdev->dev, "failed to find charger node\n");
471                 return NULL;
472         }
473
474         pdata = devm_kzalloc(&pdev->dev,
475                         sizeof(struct max8925_power_pdata),
476                         GFP_KERNEL);
477         if (!pdata)
478                 goto ret;
479
480         of_property_read_u32(np, "topoff-threshold", &topoff_threshold);
481         of_property_read_u32(np, "batt-detect", &batt_detect);
482         of_property_read_u32(np, "fast-charge", &fast_charge);
483         of_property_read_u32(np, "no-insert-detect", &no_insert_detect);
484         of_property_read_u32(np, "no-temp-support", &no_temp_support);
485
486         pdata->batt_detect = batt_detect;
487         pdata->fast_charge = fast_charge;
488         pdata->topoff_threshold = topoff_threshold;
489         pdata->no_insert_detect = no_insert_detect;
490         pdata->no_temp_support = no_temp_support;
491
492 ret:
493         of_node_put(np);
494         return pdata;
495 }
496 #else
497 static struct max8925_power_pdata *
498 max8925_power_dt_init(struct platform_device *pdev)
499 {
500         return pdev->dev.platform_data;
501 }
502 #endif
503
504 static int max8925_power_probe(struct platform_device *pdev)
505 {
506         struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
507         struct power_supply_config psy_cfg = {}; /* Only for ac and usb */
508         struct max8925_power_pdata *pdata = NULL;
509         struct max8925_power_info *info;
510
511         pdata = max8925_power_dt_init(pdev);
512         if (!pdata) {
513                 dev_err(&pdev->dev, "platform data isn't assigned to "
514                         "power supply\n");
515                 return -EINVAL;
516         }
517
518         info = devm_kzalloc(&pdev->dev, sizeof(struct max8925_power_info),
519                                 GFP_KERNEL);
520         if (!info)
521                 return -ENOMEM;
522         info->chip = chip;
523         info->gpm = chip->i2c;
524         info->adc = chip->adc;
525         platform_set_drvdata(pdev, info);
526
527         psy_cfg.supplied_to = pdata->supplied_to;
528         psy_cfg.num_supplicants = pdata->num_supplicants;
529
530         info->ac = devm_power_supply_register(&pdev->dev, &ac_desc, &psy_cfg);
531         if (IS_ERR(info->ac))
532                 return PTR_ERR(info->ac);
533         info->ac->dev.parent = &pdev->dev;
534
535         info->usb = devm_power_supply_register(&pdev->dev, &usb_desc, &psy_cfg);
536         if (IS_ERR(info->usb))
537                 return PTR_ERR(info->usb);
538         info->usb->dev.parent = &pdev->dev;
539
540         info->battery = devm_power_supply_register(&pdev->dev, &battery_desc, NULL);
541         if (IS_ERR(info->battery))
542                 return PTR_ERR(info->battery);
543         info->battery->dev.parent = &pdev->dev;
544
545         info->batt_detect = pdata->batt_detect;
546         info->topoff_threshold = pdata->topoff_threshold;
547         info->fast_charge = pdata->fast_charge;
548         info->set_charger = pdata->set_charger;
549         info->no_temp_support = pdata->no_temp_support;
550         info->no_insert_detect = pdata->no_insert_detect;
551
552         max8925_init_charger(chip, info);
553         return 0;
554 }
555
556 static void max8925_power_remove(struct platform_device *pdev)
557 {
558         struct max8925_power_info *info = platform_get_drvdata(pdev);
559
560         if (info)
561                 max8925_deinit_charger(info);
562 }
563
564 static struct platform_driver max8925_power_driver = {
565         .probe  = max8925_power_probe,
566         .remove_new = max8925_power_remove,
567         .driver = {
568                 .name   = "max8925-power",
569         },
570 };
571
572 module_platform_driver(max8925_power_driver);
573
574 MODULE_LICENSE("GPL");
575 MODULE_DESCRIPTION("Power supply driver for MAX8925");
576 MODULE_ALIAS("platform:max8925-power");