Merge tag 'rtc-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
[linux-2.6-microblaze.git] / drivers / power / supply / bd70528-charger.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 //
3 // Copyright (C) 2018 ROHM Semiconductors
4 //
5 // power-supply driver for ROHM BD70528 PMIC
6
7 /*
8  * BD70528 charger HW state machine.
9  *
10  * The thermal shutdown state is not drawn. From any other state but
11  * battery error and suspend it is possible to go to TSD/TMP states
12  * if temperature is out of bounds.
13  *
14  *  CHG_RST = H
15  *  or CHG_EN=L
16  *  or (DCIN2_UVLO=L && DCIN1_UVLO=L)
17  *  or (DCIN2_OVLO=H & DCIN1_UVKLO=L)
18  *
19  *  +--------------+         +--------------+
20  *  |              |         |              |
21  *  |  Any state   +-------> |    Suspend   |
22  *  |              |         |              |
23  *  +--------------+         +------+-------+
24  *                                  |
25  *  CHG_EN = H && BAT_DET = H &&    |
26  *  No errors (temp, bat_ov, UVLO,  |
27  *  OVLO...)                        |
28  *                                  |
29  *  BAT_OV or             +---------v----------+
30  *  (DBAT && TTRI)        |                    |
31  *      +-----------------+   Trickle Charge   | <---------------+
32  *      |                 |                    |                 |
33  *      |                 +-------+------------+                 |
34  *      |                         |                              |
35  *      |                         |     ^                        |
36  *      |        V_BAT > VTRI_TH  |     |  VBAT < VTRI_TH - 50mV |
37  *      |                         |     |                        |
38  *      |                         v     |                        |
39  *      |                               |                        |
40  *      |     BAT_OV or      +----------+----+                   |
41  *      |     (DBAT && TFST) |               |                   |
42  *      |   +----------------+  Fast Charge  |                   |
43  *      |   |                |               |                   |
44  *      v   v                +----+----------+                   |
45  *                                |                              |
46  *+----------------+   ILIM_DET=L |    ^ ILIM_DET                |
47  *|                |   & CV_DET=H |    | or CV_DET=L             |
48  *|  Battery Error |   & VBAT >   |    | or VBAT < VRECHG_TH     |
49  *|                |   VRECHG_TH  |    | or IBAT  > IFST/x       |
50  *+----------------+   & IBAT <   |    |                         |
51  *                     IFST/x     v    |                         |
52  *       ^                             |                         |
53  *       |                   +---------+-+                       |
54  *       |                   |           |                       |
55  *       +-------------------+  Top OFF  |                       |
56  *  BAT_OV = H or            |           |                       |
57  *  (DBAT && TFST)           +-----+-----+                       |
58  *                                 |                             |
59  *           Stay top-off for 15s  |                             |
60  *                                 v                             |
61  *                                                               |
62  *                            +--------+                         |
63  *                            |        |                         |
64  *                            |  Done  +-------------------------+
65  *                            |        |
66  *                            +--------+   VBAT < VRECHG_TH
67  */
68
69 #include <linux/kernel.h>
70 #include <linux/interrupt.h>
71 #include <linux/mfd/rohm-bd70528.h>
72 #include <linux/module.h>
73 #include <linux/platform_device.h>
74 #include <linux/power_supply.h>
75 #include <linux/linear_range.h>
76
77 #define CHG_STAT_SUSPEND        0x0
78 #define CHG_STAT_TRICKLE        0x1
79 #define CHG_STAT_FAST           0x3
80 #define CHG_STAT_TOPOFF         0xe
81 #define CHG_STAT_DONE           0xf
82 #define CHG_STAT_OTP_TRICKLE    0x10
83 #define CHG_STAT_OTP_FAST       0x11
84 #define CHG_STAT_OTP_DONE       0x12
85 #define CHG_STAT_TSD_TRICKLE    0x20
86 #define CHG_STAT_TSD_FAST       0x21
87 #define CHG_STAT_TSD_TOPOFF     0x22
88 #define CHG_STAT_BAT_ERR        0x7f
89
90 static const char *bd70528_charger_model = "BD70528";
91 static const char *bd70528_charger_manufacturer = "ROHM Semiconductors";
92
93 #define BD_ERR_IRQ_HND(_name_, _wrn_)                                   \
94 static irqreturn_t bd0528_##_name_##_interrupt(int irq, void *arg)      \
95 {                                                                       \
96         struct power_supply *psy = (struct power_supply *)arg;          \
97                                                                         \
98         power_supply_changed(psy);                                      \
99         dev_err(&psy->dev, (_wrn_));                                    \
100                                                                         \
101         return IRQ_HANDLED;                                             \
102 }
103
104 #define BD_INFO_IRQ_HND(_name_, _wrn_)                                  \
105 static irqreturn_t bd0528_##_name_##_interrupt(int irq, void *arg)      \
106 {                                                                       \
107         struct power_supply *psy = (struct power_supply *)arg;          \
108                                                                         \
109         power_supply_changed(psy);                                      \
110         dev_dbg(&psy->dev, (_wrn_));                                    \
111                                                                         \
112         return IRQ_HANDLED;                                             \
113 }
114
115 #define BD_IRQ_HND(_name_) bd0528_##_name_##_interrupt
116
117 struct bd70528_psy {
118         struct regmap *regmap;
119         struct device *dev;
120         struct power_supply *psy;
121 };
122
123 BD_ERR_IRQ_HND(BAT_OV_DET, "Battery overvoltage detected\n");
124 BD_ERR_IRQ_HND(DBAT_DET, "Dead battery detected\n");
125 BD_ERR_IRQ_HND(COLD_DET, "Battery cold\n");
126 BD_ERR_IRQ_HND(HOT_DET, "Battery hot\n");
127 BD_ERR_IRQ_HND(CHG_TSD, "Charger thermal shutdown\n");
128 BD_ERR_IRQ_HND(DCIN2_OV_DET, "DCIN2 overvoltage detected\n");
129
130 BD_INFO_IRQ_HND(BAT_OV_RES, "Battery voltage back to normal\n");
131 BD_INFO_IRQ_HND(COLD_RES, "Battery temperature back to normal\n");
132 BD_INFO_IRQ_HND(HOT_RES, "Battery temperature back to normal\n");
133 BD_INFO_IRQ_HND(BAT_RMV, "Battery removed\n");
134 BD_INFO_IRQ_HND(BAT_DET, "Battery detected\n");
135 BD_INFO_IRQ_HND(DCIN2_OV_RES, "DCIN2 voltage back to normal\n");
136 BD_INFO_IRQ_HND(DCIN2_RMV, "DCIN2 removed\n");
137 BD_INFO_IRQ_HND(DCIN2_DET, "DCIN2 detected\n");
138 BD_INFO_IRQ_HND(DCIN1_RMV, "DCIN1 removed\n");
139 BD_INFO_IRQ_HND(DCIN1_DET, "DCIN1 detected\n");
140
141 struct irq_name_pair {
142         const char *n;
143         irqreturn_t (*h)(int irq, void *arg);
144 };
145
146 static int bd70528_get_irqs(struct platform_device *pdev,
147                             struct bd70528_psy *bdpsy)
148 {
149         int irq, i, ret;
150         unsigned int mask;
151         static const struct irq_name_pair bd70528_chg_irqs[] = {
152                 { .n = "bd70528-bat-ov-res", .h = BD_IRQ_HND(BAT_OV_RES) },
153                 { .n = "bd70528-bat-ov-det", .h = BD_IRQ_HND(BAT_OV_DET) },
154                 { .n = "bd70528-bat-dead", .h = BD_IRQ_HND(DBAT_DET) },
155                 { .n = "bd70528-bat-warmed", .h = BD_IRQ_HND(COLD_RES) },
156                 { .n = "bd70528-bat-cold", .h = BD_IRQ_HND(COLD_DET) },
157                 { .n = "bd70528-bat-cooled", .h = BD_IRQ_HND(HOT_RES) },
158                 { .n = "bd70528-bat-hot", .h = BD_IRQ_HND(HOT_DET) },
159                 { .n = "bd70528-chg-tshd", .h = BD_IRQ_HND(CHG_TSD) },
160                 { .n = "bd70528-bat-removed", .h = BD_IRQ_HND(BAT_RMV) },
161                 { .n = "bd70528-bat-detected", .h = BD_IRQ_HND(BAT_DET) },
162                 { .n = "bd70528-dcin2-ov-res", .h = BD_IRQ_HND(DCIN2_OV_RES) },
163                 { .n = "bd70528-dcin2-ov-det", .h = BD_IRQ_HND(DCIN2_OV_DET) },
164                 { .n = "bd70528-dcin2-removed", .h = BD_IRQ_HND(DCIN2_RMV) },
165                 { .n = "bd70528-dcin2-detected", .h = BD_IRQ_HND(DCIN2_DET) },
166                 { .n = "bd70528-dcin1-removed", .h = BD_IRQ_HND(DCIN1_RMV) },
167                 { .n = "bd70528-dcin1-detected", .h = BD_IRQ_HND(DCIN1_DET) },
168         };
169
170         for (i = 0; i < ARRAY_SIZE(bd70528_chg_irqs); i++) {
171                 irq = platform_get_irq_byname(pdev, bd70528_chg_irqs[i].n);
172                 if (irq < 0) {
173                         dev_err(&pdev->dev, "Bad IRQ information for %s (%d)\n",
174                                 bd70528_chg_irqs[i].n, irq);
175                         return irq;
176                 }
177                 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
178                                                 bd70528_chg_irqs[i].h,
179                                                 IRQF_ONESHOT,
180                                                 bd70528_chg_irqs[i].n,
181                                                 bdpsy->psy);
182
183                 if (ret)
184                         return ret;
185         }
186         /*
187          * BD70528 irq controller is not touching the main mask register.
188          * So enable the charger block interrupts at main level. We can just
189          * leave them enabled as irq-controller should disable irqs
190          * from sub-registers when IRQ is disabled or freed.
191          */
192         mask = BD70528_REG_INT_BAT1_MASK | BD70528_REG_INT_BAT2_MASK;
193         ret = regmap_update_bits(bdpsy->regmap,
194                                  BD70528_REG_INT_MAIN_MASK, mask, 0);
195         if (ret)
196                 dev_err(&pdev->dev, "Failed to enable charger IRQs\n");
197
198         return ret;
199 }
200
201 static int bd70528_get_charger_status(struct bd70528_psy *bdpsy, int *val)
202 {
203         int ret;
204         unsigned int v;
205
206         ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CURR_STAT, &v);
207         if (ret) {
208                 dev_err(bdpsy->dev, "Charger state read failure %d\n",
209                         ret);
210                 return ret;
211         }
212
213         switch (v & BD70528_MASK_CHG_STAT) {
214         case CHG_STAT_SUSPEND:
215         /* Maybe we should check the CHG_TTRI_EN? */
216         case CHG_STAT_OTP_TRICKLE:
217         case CHG_STAT_OTP_FAST:
218         case CHG_STAT_OTP_DONE:
219         case CHG_STAT_TSD_TRICKLE:
220         case CHG_STAT_TSD_FAST:
221         case CHG_STAT_TSD_TOPOFF:
222         case CHG_STAT_BAT_ERR:
223                 *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
224                 break;
225         case CHG_STAT_DONE:
226                 *val = POWER_SUPPLY_STATUS_FULL;
227                 break;
228         case CHG_STAT_TRICKLE:
229         case CHG_STAT_FAST:
230         case CHG_STAT_TOPOFF:
231                 *val = POWER_SUPPLY_STATUS_CHARGING;
232                 break;
233         default:
234                 *val = POWER_SUPPLY_STATUS_UNKNOWN;
235                 break;
236         }
237
238         return 0;
239 }
240
241 static int bd70528_get_charge_type(struct bd70528_psy *bdpsy, int *val)
242 {
243         int ret;
244         unsigned int v;
245
246         ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CURR_STAT, &v);
247         if (ret) {
248                 dev_err(bdpsy->dev, "Charger state read failure %d\n",
249                         ret);
250                 return ret;
251         }
252
253         switch (v & BD70528_MASK_CHG_STAT) {
254         case CHG_STAT_TRICKLE:
255                 *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
256                 break;
257         case CHG_STAT_FAST:
258         case CHG_STAT_TOPOFF:
259                 *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
260                 break;
261         case CHG_STAT_DONE:
262         case CHG_STAT_SUSPEND:
263         /* Maybe we should check the CHG_TTRI_EN? */
264         case CHG_STAT_OTP_TRICKLE:
265         case CHG_STAT_OTP_FAST:
266         case CHG_STAT_OTP_DONE:
267         case CHG_STAT_TSD_TRICKLE:
268         case CHG_STAT_TSD_FAST:
269         case CHG_STAT_TSD_TOPOFF:
270         case CHG_STAT_BAT_ERR:
271                 *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
272                 break;
273         default:
274                 *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
275                 break;
276         }
277
278         return 0;
279 }
280
281 static int bd70528_get_battery_health(struct bd70528_psy *bdpsy, int *val)
282 {
283         int ret;
284         unsigned int v;
285
286         ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_BAT_STAT, &v);
287         if (ret) {
288                 dev_err(bdpsy->dev, "Battery state read failure %d\n",
289                         ret);
290                 return ret;
291         }
292         /* No battery? */
293         if (!(v & BD70528_MASK_CHG_BAT_DETECT))
294                 *val = POWER_SUPPLY_HEALTH_DEAD;
295         else if (v & BD70528_MASK_CHG_BAT_OVERVOLT)
296                 *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
297         else if (v & BD70528_MASK_CHG_BAT_TIMER)
298                 *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
299         else
300                 *val = POWER_SUPPLY_HEALTH_GOOD;
301
302         return 0;
303 }
304
305 static int bd70528_get_online(struct bd70528_psy *bdpsy, int *val)
306 {
307         int ret;
308         unsigned int v;
309
310         ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_IN_STAT, &v);
311         if (ret) {
312                 dev_err(bdpsy->dev, "DC1 IN state read failure %d\n",
313                         ret);
314                 return ret;
315         }
316
317         *val = (v & BD70528_MASK_CHG_DCIN1_UVLO) ? 1 : 0;
318
319         return 0;
320 }
321
322 static int bd70528_get_present(struct bd70528_psy *bdpsy, int *val)
323 {
324         int ret;
325         unsigned int v;
326
327         ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_BAT_STAT, &v);
328         if (ret) {
329                 dev_err(bdpsy->dev, "Battery state read failure %d\n",
330                         ret);
331                 return ret;
332         }
333
334         *val = (v & BD70528_MASK_CHG_BAT_DETECT) ? 1 : 0;
335
336         return 0;
337 }
338
339 static const struct linear_range current_limit_ranges[] = {
340         {
341                 .min = 5,
342                 .step = 1,
343                 .min_sel = 0,
344                 .max_sel = 0x22,
345         },
346         {
347                 .min = 40,
348                 .step = 5,
349                 .min_sel = 0x23,
350                 .max_sel = 0x26,
351         },
352         {
353                 .min = 60,
354                 .step = 20,
355                 .min_sel = 0x27,
356                 .max_sel = 0x2d,
357         },
358         {
359                 .min = 200,
360                 .step = 50,
361                 .min_sel = 0x2e,
362                 .max_sel = 0x34,
363         },
364         {
365                 .min = 500,
366                 .step = 0,
367                 .min_sel = 0x35,
368                 .max_sel = 0x3f,
369         },
370 };
371
372 /*
373  * BD70528 would support setting and getting own charge current/
374  * voltage for low temperatures. The driver currently only reads
375  * the charge current at room temperature. We do set both though.
376  */
377 static const struct linear_range warm_charge_curr[] = {
378         {
379                 .min = 10,
380                 .step = 10,
381                 .min_sel = 0,
382                 .max_sel = 0x12,
383         },
384         {
385                 .min = 200,
386                 .step = 25,
387                 .min_sel = 0x13,
388                 .max_sel = 0x1f,
389         },
390 };
391
392 /*
393  * Cold charge current selectors are identical to warm charge current
394  * selectors. The difference is that only smaller currents are available
395  * at cold charge range.
396  */
397 #define MAX_COLD_CHG_CURR_SEL 0x15
398 #define MAX_WARM_CHG_CURR_SEL 0x1f
399 #define MIN_CHG_CURR_SEL 0x0
400
401 static int get_charge_current(struct bd70528_psy *bdpsy, int *ma)
402 {
403         unsigned int sel;
404         int ret;
405
406         ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_CHG_CURR_WARM,
407                           &sel);
408         if (ret) {
409                 dev_err(bdpsy->dev,
410                         "Charge current reading failed (%d)\n", ret);
411                 return ret;
412         }
413
414         sel &= BD70528_MASK_CHG_CHG_CURR;
415
416         ret = linear_range_get_value_array(&warm_charge_curr[0],
417                                            ARRAY_SIZE(warm_charge_curr),
418                                            sel, ma);
419         if (ret) {
420                 dev_err(bdpsy->dev,
421                         "Unknown charge current value 0x%x\n",
422                         sel);
423         }
424
425         return ret;
426 }
427
428 static int get_current_limit(struct bd70528_psy *bdpsy, int *ma)
429 {
430         unsigned int sel;
431         int ret;
432
433         ret = regmap_read(bdpsy->regmap, BD70528_REG_CHG_DCIN_ILIM,
434                           &sel);
435
436         if (ret) {
437                 dev_err(bdpsy->dev,
438                         "Input current limit reading failed (%d)\n", ret);
439                 return ret;
440         }
441
442         sel &= BD70528_MASK_CHG_DCIN_ILIM;
443
444         ret = linear_range_get_value_array(&current_limit_ranges[0],
445                                            ARRAY_SIZE(current_limit_ranges),
446                                            sel, ma);
447         if (ret) {
448                 /* Unspecified values mean 500 mA */
449                 *ma = 500;
450         }
451         return 0;
452 }
453
454 static enum power_supply_property bd70528_charger_props[] = {
455         POWER_SUPPLY_PROP_STATUS,
456         POWER_SUPPLY_PROP_CHARGE_TYPE,
457         POWER_SUPPLY_PROP_HEALTH,
458         POWER_SUPPLY_PROP_PRESENT,
459         POWER_SUPPLY_PROP_ONLINE,
460         POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
461         POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
462         POWER_SUPPLY_PROP_MODEL_NAME,
463         POWER_SUPPLY_PROP_MANUFACTURER,
464 };
465
466 static int bd70528_charger_get_property(struct power_supply *psy,
467                                         enum power_supply_property psp,
468                                         union power_supply_propval *val)
469 {
470         struct bd70528_psy *bdpsy = power_supply_get_drvdata(psy);
471         int ret = 0;
472
473         switch (psp) {
474         case POWER_SUPPLY_PROP_STATUS:
475                 return bd70528_get_charger_status(bdpsy, &val->intval);
476         case POWER_SUPPLY_PROP_CHARGE_TYPE:
477                 return bd70528_get_charge_type(bdpsy, &val->intval);
478         case POWER_SUPPLY_PROP_HEALTH:
479                 return bd70528_get_battery_health(bdpsy, &val->intval);
480         case POWER_SUPPLY_PROP_PRESENT:
481                 return bd70528_get_present(bdpsy, &val->intval);
482         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
483                 ret = get_current_limit(bdpsy, &val->intval);
484                 val->intval *= 1000;
485                 return ret;
486         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
487                 ret = get_charge_current(bdpsy, &val->intval);
488                 val->intval *= 1000;
489                 return ret;
490         case POWER_SUPPLY_PROP_ONLINE:
491                 return bd70528_get_online(bdpsy, &val->intval);
492         case POWER_SUPPLY_PROP_MODEL_NAME:
493                 val->strval = bd70528_charger_model;
494                 return 0;
495         case POWER_SUPPLY_PROP_MANUFACTURER:
496                 val->strval = bd70528_charger_manufacturer;
497                 return 0;
498         default:
499                 break;
500         }
501
502         return -EINVAL;
503 }
504
505 static int bd70528_prop_is_writable(struct power_supply *psy,
506                                     enum power_supply_property psp)
507 {
508         switch (psp) {
509         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
510         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
511                 return 1;
512         default:
513                 break;
514         }
515         return 0;
516 }
517
518 static int set_charge_current(struct bd70528_psy *bdpsy, int ma)
519 {
520         unsigned int reg;
521         int ret = 0, tmpret;
522         bool found;
523
524         if (ma > 500) {
525                 dev_warn(bdpsy->dev,
526                          "Requested charge current %u exceed maximum (500mA)\n",
527                          ma);
528                 reg = MAX_WARM_CHG_CURR_SEL;
529                 goto set;
530         }
531         if (ma < 10) {
532                 dev_err(bdpsy->dev,
533                         "Requested charge current %u smaller than min (10mA)\n",
534                          ma);
535                 reg = MIN_CHG_CURR_SEL;
536                 ret = -EINVAL;
537                 goto set;
538         }
539
540 /*
541  * For BD70528 voltage/current limits we happily accept any value which
542  * belongs the range. We could check if value matching the selector is
543  * desired by computing the range min + (sel - sel_low) * range step - but
544  * I guess it is enough if we use voltage/current which is closest (below)
545  * the requested?
546  */
547
548         ret = linear_range_get_selector_low_array(warm_charge_curr,
549                                                   ARRAY_SIZE(warm_charge_curr),
550                                                   ma, &reg, &found);
551         if (ret) {
552                 dev_err(bdpsy->dev,
553                          "Unsupported charge current %u mA\n", ma);
554                 reg = MIN_CHG_CURR_SEL;
555                 goto set;
556         }
557         if (!found) {
558                 /*
559                  * There was a gap in supported values and we hit it.
560                  * Yet a smaller value was found so we use it.
561                  */
562                 dev_warn(bdpsy->dev,
563                          "Unsupported charge current %u mA\n", ma);
564         }
565 set:
566
567         tmpret = regmap_update_bits(bdpsy->regmap,
568                                     BD70528_REG_CHG_CHG_CURR_WARM,
569                                     BD70528_MASK_CHG_CHG_CURR, reg);
570         if (tmpret)
571                 dev_err(bdpsy->dev,
572                         "Charge current write failure (%d)\n", tmpret);
573
574         if (reg > MAX_COLD_CHG_CURR_SEL)
575                 reg = MAX_COLD_CHG_CURR_SEL;
576
577         if (!tmpret)
578                 tmpret = regmap_update_bits(bdpsy->regmap,
579                                             BD70528_REG_CHG_CHG_CURR_COLD,
580                                             BD70528_MASK_CHG_CHG_CURR, reg);
581
582         if (!ret)
583                 ret = tmpret;
584
585         return ret;
586 }
587
588 #define MAX_CURR_LIMIT_SEL 0x34
589 #define MIN_CURR_LIMIT_SEL 0x0
590
591 static int set_current_limit(struct bd70528_psy *bdpsy, int ma)
592 {
593         unsigned int reg;
594         int ret = 0, tmpret;
595         bool found;
596
597         if (ma > 500) {
598                 dev_warn(bdpsy->dev,
599                          "Requested current limit %u exceed maximum (500mA)\n",
600                          ma);
601                 reg = MAX_CURR_LIMIT_SEL;
602                 goto set;
603         }
604         if (ma < 5) {
605                 dev_err(bdpsy->dev,
606                         "Requested current limit %u smaller than min (5mA)\n",
607                         ma);
608                 reg = MIN_CURR_LIMIT_SEL;
609                 ret = -EINVAL;
610                 goto set;
611         }
612
613         ret = linear_range_get_selector_low_array(current_limit_ranges,
614                                         ARRAY_SIZE(current_limit_ranges),
615                                         ma, &reg, &found);
616         if (ret) {
617                 dev_err(bdpsy->dev, "Unsupported current limit %umA\n", ma);
618                 reg = MIN_CURR_LIMIT_SEL;
619                 goto set;
620         }
621         if (!found) {
622                 /*
623                  * There was a gap in supported values and we hit it.
624                  * We found a smaller value from ranges and use it.
625                  * Warn user though.
626                  */
627                 dev_warn(bdpsy->dev, "Unsupported current limit %umA\n", ma);
628         }
629
630 set:
631         tmpret = regmap_update_bits(bdpsy->regmap,
632                                     BD70528_REG_CHG_DCIN_ILIM,
633                                     BD70528_MASK_CHG_DCIN_ILIM, reg);
634
635         if (!ret)
636                 ret = tmpret;
637
638         return ret;
639 }
640
641 static int bd70528_charger_set_property(struct power_supply *psy,
642                                         enum power_supply_property psp,
643                                         const union power_supply_propval *val)
644 {
645         struct bd70528_psy *bdpsy = power_supply_get_drvdata(psy);
646
647         switch (psp) {
648         case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
649                 return set_current_limit(bdpsy, val->intval / 1000);
650         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
651                 return set_charge_current(bdpsy, val->intval / 1000);
652         default:
653                 break;
654         }
655         return -EINVAL;
656 }
657
658 static const struct power_supply_desc bd70528_charger_desc = {
659         .name           = "bd70528-charger",
660         .type           = POWER_SUPPLY_TYPE_MAINS,
661         .properties     = bd70528_charger_props,
662         .num_properties = ARRAY_SIZE(bd70528_charger_props),
663         .get_property   = bd70528_charger_get_property,
664         .set_property   = bd70528_charger_set_property,
665         .property_is_writeable  = bd70528_prop_is_writable,
666 };
667
668 static int bd70528_power_probe(struct platform_device *pdev)
669 {
670         struct bd70528_psy *bdpsy;
671         struct power_supply_config cfg = {};
672
673         bdpsy = devm_kzalloc(&pdev->dev, sizeof(*bdpsy), GFP_KERNEL);
674         if (!bdpsy)
675                 return -ENOMEM;
676
677         bdpsy->regmap = dev_get_regmap(pdev->dev.parent, NULL);
678         if (!bdpsy->regmap) {
679                 dev_err(&pdev->dev, "No regmap found for chip\n");
680                 return -EINVAL;
681         }
682         bdpsy->dev = &pdev->dev;
683
684         platform_set_drvdata(pdev, bdpsy);
685         cfg.drv_data = bdpsy;
686         cfg.of_node = pdev->dev.parent->of_node;
687
688         bdpsy->psy = devm_power_supply_register(&pdev->dev,
689                                                 &bd70528_charger_desc, &cfg);
690         if (IS_ERR(bdpsy->psy)) {
691                 dev_err(&pdev->dev, "failed: power supply register\n");
692                 return PTR_ERR(bdpsy->psy);
693         }
694
695         return bd70528_get_irqs(pdev, bdpsy);
696 }
697
698 static struct platform_driver bd70528_power = {
699         .driver = {
700                 .name = "bd70528-power"
701         },
702         .probe = bd70528_power_probe,
703 };
704
705 module_platform_driver(bd70528_power);
706
707 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
708 MODULE_DESCRIPTION("BD70528 power-supply driver");
709 MODULE_LICENSE("GPL");
710 MODULE_ALIAS("platform:bd70528-power");