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