GNU Linux-libre 4.14.324-gnu1
[releases.git] / drivers / power / supply / act8945a_charger.c
1 /*
2  * Power supply driver for the Active-semi ACT8945A PMIC
3  *
4  * Copyright (C) 2015 Atmel Corporation
5  *
6  * Author: Wenyou Yang <wenyou.yang@atmel.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  */
13 #include <linux/interrupt.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/of_irq.h>
17 #include <linux/platform_device.h>
18 #include <linux/power_supply.h>
19 #include <linux/regmap.h>
20 #include <linux/gpio/consumer.h>
21
22 static const char *act8945a_charger_model = "ACT8945A";
23 static const char *act8945a_charger_manufacturer = "Active-semi";
24
25 /**
26  * ACT8945A Charger Register Map
27  */
28
29 /* 0x70: Reserved */
30 #define ACT8945A_APCH_CFG               0x71
31 #define ACT8945A_APCH_STATUS            0x78
32 #define ACT8945A_APCH_CTRL              0x79
33 #define ACT8945A_APCH_STATE             0x7A
34
35 /* ACT8945A_APCH_CFG */
36 #define APCH_CFG_OVPSET                 (0x3 << 0)
37 #define APCH_CFG_OVPSET_6V6             (0x0 << 0)
38 #define APCH_CFG_OVPSET_7V              (0x1 << 0)
39 #define APCH_CFG_OVPSET_7V5             (0x2 << 0)
40 #define APCH_CFG_OVPSET_8V              (0x3 << 0)
41 #define APCH_CFG_PRETIMO                (0x3 << 2)
42 #define APCH_CFG_PRETIMO_40_MIN         (0x0 << 2)
43 #define APCH_CFG_PRETIMO_60_MIN         (0x1 << 2)
44 #define APCH_CFG_PRETIMO_80_MIN         (0x2 << 2)
45 #define APCH_CFG_PRETIMO_DISABLED       (0x3 << 2)
46 #define APCH_CFG_TOTTIMO                (0x3 << 4)
47 #define APCH_CFG_TOTTIMO_3_HOUR         (0x0 << 4)
48 #define APCH_CFG_TOTTIMO_4_HOUR         (0x1 << 4)
49 #define APCH_CFG_TOTTIMO_5_HOUR         (0x2 << 4)
50 #define APCH_CFG_TOTTIMO_DISABLED       (0x3 << 4)
51 #define APCH_CFG_SUSCHG                 (0x1 << 7)
52
53 #define APCH_STATUS_CHGDAT              BIT(0)
54 #define APCH_STATUS_INDAT               BIT(1)
55 #define APCH_STATUS_TEMPDAT             BIT(2)
56 #define APCH_STATUS_TIMRDAT             BIT(3)
57 #define APCH_STATUS_CHGSTAT             BIT(4)
58 #define APCH_STATUS_INSTAT              BIT(5)
59 #define APCH_STATUS_TEMPSTAT            BIT(6)
60 #define APCH_STATUS_TIMRSTAT            BIT(7)
61
62 #define APCH_CTRL_CHGEOCOUT             BIT(0)
63 #define APCH_CTRL_INDIS                 BIT(1)
64 #define APCH_CTRL_TEMPOUT               BIT(2)
65 #define APCH_CTRL_TIMRPRE               BIT(3)
66 #define APCH_CTRL_CHGEOCIN              BIT(4)
67 #define APCH_CTRL_INCON                 BIT(5)
68 #define APCH_CTRL_TEMPIN                BIT(6)
69 #define APCH_CTRL_TIMRTOT               BIT(7)
70
71 #define APCH_STATE_ACINSTAT             (0x1 << 1)
72 #define APCH_STATE_CSTATE               (0x3 << 4)
73 #define APCH_STATE_CSTATE_SHIFT         4
74 #define APCH_STATE_CSTATE_DISABLED      0x00
75 #define APCH_STATE_CSTATE_EOC           0x01
76 #define APCH_STATE_CSTATE_FAST          0x02
77 #define APCH_STATE_CSTATE_PRE           0x03
78
79 struct act8945a_charger {
80         struct power_supply *psy;
81         struct power_supply_desc desc;
82         struct regmap *regmap;
83         struct work_struct work;
84
85         bool init_done;
86         struct gpio_desc *lbo_gpio;
87         struct gpio_desc *chglev_gpio;
88 };
89
90 static int act8945a_get_charger_state(struct regmap *regmap, int *val)
91 {
92         int ret;
93         unsigned int status, state;
94
95         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
96         if (ret < 0)
97                 return ret;
98
99         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
100         if (ret < 0)
101                 return ret;
102
103         state &= APCH_STATE_CSTATE;
104         state >>= APCH_STATE_CSTATE_SHIFT;
105
106         switch (state) {
107         case APCH_STATE_CSTATE_PRE:
108         case APCH_STATE_CSTATE_FAST:
109                 *val = POWER_SUPPLY_STATUS_CHARGING;
110                 break;
111         case APCH_STATE_CSTATE_EOC:
112                 if (status & APCH_STATUS_CHGDAT)
113                         *val = POWER_SUPPLY_STATUS_FULL;
114                 else
115                         *val = POWER_SUPPLY_STATUS_CHARGING;
116                 break;
117         case APCH_STATE_CSTATE_DISABLED:
118         default:
119                 if (!(status & APCH_STATUS_INDAT))
120                         *val = POWER_SUPPLY_STATUS_DISCHARGING;
121                 else
122                         *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
123                 break;
124         }
125
126         return 0;
127 }
128
129 static int act8945a_get_charge_type(struct regmap *regmap, int *val)
130 {
131         int ret;
132         unsigned int status, state;
133
134         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
135         if (ret < 0)
136                 return ret;
137
138         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
139         if (ret < 0)
140                 return ret;
141
142         state &= APCH_STATE_CSTATE;
143         state >>= APCH_STATE_CSTATE_SHIFT;
144
145         switch (state) {
146         case APCH_STATE_CSTATE_PRE:
147                 *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
148                 break;
149         case APCH_STATE_CSTATE_FAST:
150                 *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
151                 break;
152         case APCH_STATE_CSTATE_EOC:
153                 *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
154                 break;
155         case APCH_STATE_CSTATE_DISABLED:
156         default:
157                 if (!(status & APCH_STATUS_INDAT))
158                         *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
159                 else
160                         *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
161                 break;
162         }
163
164         return 0;
165 }
166
167 static int act8945a_get_battery_health(struct regmap *regmap, int *val)
168 {
169         int ret;
170         unsigned int status, state, config;
171
172         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
173         if (ret < 0)
174                 return ret;
175
176         ret = regmap_read(regmap, ACT8945A_APCH_CFG, &config);
177         if (ret < 0)
178                 return ret;
179
180         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
181         if (ret < 0)
182                 return ret;
183
184         state &= APCH_STATE_CSTATE;
185         state >>= APCH_STATE_CSTATE_SHIFT;
186
187         switch (state) {
188         case APCH_STATE_CSTATE_DISABLED:
189                 if (config & APCH_CFG_SUSCHG) {
190                         *val = POWER_SUPPLY_HEALTH_UNKNOWN;
191                 } else if (status & APCH_STATUS_INDAT) {
192                         if (!(status & APCH_STATUS_TEMPDAT))
193                                 *val = POWER_SUPPLY_HEALTH_OVERHEAT;
194                         else if (status & APCH_STATUS_TIMRDAT)
195                                 *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
196                         else
197                                 *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
198                 } else {
199                         *val = POWER_SUPPLY_HEALTH_GOOD;
200                 }
201                 break;
202         case APCH_STATE_CSTATE_PRE:
203         case APCH_STATE_CSTATE_FAST:
204         case APCH_STATE_CSTATE_EOC:
205         default:
206                 *val = POWER_SUPPLY_HEALTH_GOOD;
207                 break;
208         }
209
210         return 0;
211 }
212
213 static int act8945a_get_capacity_level(struct act8945a_charger *charger,
214                                        struct regmap *regmap, int *val)
215 {
216         int ret;
217         unsigned int status, state, config;
218         int lbo_level = gpiod_get_value(charger->lbo_gpio);
219
220         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
221         if (ret < 0)
222                 return ret;
223
224         ret = regmap_read(regmap, ACT8945A_APCH_CFG, &config);
225         if (ret < 0)
226                 return ret;
227
228         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
229         if (ret < 0)
230                 return ret;
231
232         state &= APCH_STATE_CSTATE;
233         state >>= APCH_STATE_CSTATE_SHIFT;
234
235         switch (state) {
236         case APCH_STATE_CSTATE_PRE:
237                 *val = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
238                 break;
239         case APCH_STATE_CSTATE_FAST:
240                 if (lbo_level)
241                         *val = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
242                 else
243                         *val = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
244                 break;
245         case APCH_STATE_CSTATE_EOC:
246                 if (status & APCH_STATUS_CHGDAT)
247                         *val = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
248                 else
249                         *val = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
250                 break;
251         case APCH_STATE_CSTATE_DISABLED:
252         default:
253                 if (config & APCH_CFG_SUSCHG) {
254                         *val = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
255                 } else {
256                         *val = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
257                         if (!(status & APCH_STATUS_INDAT)) {
258                                 if (!lbo_level)
259                                         *val = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
260                         }
261                 }
262                 break;
263         }
264
265         return 0;
266 }
267
268 #define MAX_CURRENT_USB_HIGH    450000
269 #define MAX_CURRENT_USB_LOW     90000
270 #define MAX_CURRENT_USB_PRE     45000
271 /*
272  * Riset(K) = 2336 * (1V/Ichg(mA)) - 0.205
273  * Riset = 2.43K
274  */
275 #define MAX_CURRENT_AC_HIGH             886527
276 #define MAX_CURRENT_AC_LOW              117305
277 #define MAX_CURRENT_AC_HIGH_PRE         88653
278 #define MAX_CURRENT_AC_LOW_PRE          11731
279
280 static int act8945a_get_current_max(struct act8945a_charger *charger,
281                                     struct regmap *regmap, int *val)
282 {
283         int ret;
284         unsigned int status, state;
285         unsigned int acin_state;
286         int chgin_level = gpiod_get_value(charger->chglev_gpio);
287
288         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
289         if (ret < 0)
290                 return ret;
291
292         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
293         if (ret < 0)
294                 return ret;
295
296         acin_state = (state & APCH_STATE_ACINSTAT) >> 1;
297
298         state &= APCH_STATE_CSTATE;
299         state >>= APCH_STATE_CSTATE_SHIFT;
300
301         switch (state) {
302         case APCH_STATE_CSTATE_PRE:
303                 if (acin_state) {
304                         if (chgin_level)
305                                 *val = MAX_CURRENT_AC_HIGH_PRE;
306                         else
307                                 *val = MAX_CURRENT_AC_LOW_PRE;
308                 } else {
309                         *val = MAX_CURRENT_USB_PRE;
310                 }
311                 break;
312         case APCH_STATE_CSTATE_FAST:
313                 if (acin_state) {
314                         if (chgin_level)
315                                 *val = MAX_CURRENT_AC_HIGH;
316                         else
317                                 *val = MAX_CURRENT_AC_LOW;
318                 } else {
319                         if (chgin_level)
320                                 *val = MAX_CURRENT_USB_HIGH;
321                         else
322                                 *val = MAX_CURRENT_USB_LOW;
323                 }
324                 break;
325         case APCH_STATE_CSTATE_EOC:
326         case APCH_STATE_CSTATE_DISABLED:
327         default:
328                 *val = 0;
329                 break;
330         }
331
332         return 0;
333 }
334
335 static enum power_supply_property act8945a_charger_props[] = {
336         POWER_SUPPLY_PROP_STATUS,
337         POWER_SUPPLY_PROP_CHARGE_TYPE,
338         POWER_SUPPLY_PROP_TECHNOLOGY,
339         POWER_SUPPLY_PROP_HEALTH,
340         POWER_SUPPLY_PROP_CAPACITY_LEVEL,
341         POWER_SUPPLY_PROP_CURRENT_MAX,
342         POWER_SUPPLY_PROP_MODEL_NAME,
343         POWER_SUPPLY_PROP_MANUFACTURER
344 };
345
346 static int act8945a_charger_get_property(struct power_supply *psy,
347                                          enum power_supply_property prop,
348                                          union power_supply_propval *val)
349 {
350         struct act8945a_charger *charger = power_supply_get_drvdata(psy);
351         struct regmap *regmap = charger->regmap;
352         int ret = 0;
353
354         switch (prop) {
355         case POWER_SUPPLY_PROP_STATUS:
356                 ret = act8945a_get_charger_state(regmap, &val->intval);
357                 break;
358         case POWER_SUPPLY_PROP_CHARGE_TYPE:
359                 ret = act8945a_get_charge_type(regmap, &val->intval);
360                 break;
361         case POWER_SUPPLY_PROP_TECHNOLOGY:
362                 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
363                 break;
364         case POWER_SUPPLY_PROP_HEALTH:
365                 ret = act8945a_get_battery_health(regmap, &val->intval);
366                 break;
367         case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
368                 ret = act8945a_get_capacity_level(charger,
369                                                   regmap, &val->intval);
370                 break;
371         case POWER_SUPPLY_PROP_CURRENT_MAX:
372                 ret = act8945a_get_current_max(charger,
373                                                regmap, &val->intval);
374                 break;
375         case POWER_SUPPLY_PROP_MODEL_NAME:
376                 val->strval = act8945a_charger_model;
377                 break;
378         case POWER_SUPPLY_PROP_MANUFACTURER:
379                 val->strval = act8945a_charger_manufacturer;
380                 break;
381         default:
382                 return -EINVAL;
383         }
384
385         return ret;
386 }
387
388 static int act8945a_enable_interrupt(struct act8945a_charger *charger)
389 {
390         struct regmap *regmap = charger->regmap;
391         unsigned char ctrl;
392         int ret;
393
394         ctrl = APCH_CTRL_CHGEOCOUT | APCH_CTRL_CHGEOCIN |
395                APCH_CTRL_INDIS | APCH_CTRL_INCON |
396                APCH_CTRL_TEMPOUT | APCH_CTRL_TEMPIN |
397                APCH_CTRL_TIMRPRE | APCH_CTRL_TIMRTOT;
398         ret = regmap_write(regmap, ACT8945A_APCH_CTRL, ctrl);
399         if (ret)
400                 return ret;
401
402         ctrl = APCH_STATUS_CHGSTAT | APCH_STATUS_INSTAT |
403                APCH_STATUS_TEMPSTAT | APCH_STATUS_TIMRSTAT;
404         ret = regmap_write(regmap, ACT8945A_APCH_STATUS, ctrl);
405         if (ret)
406                 return ret;
407
408         return 0;
409 }
410
411 static unsigned int act8945a_set_supply_type(struct act8945a_charger *charger,
412                                              unsigned int *type)
413 {
414         unsigned int status, state;
415         int ret;
416
417         ret = regmap_read(charger->regmap, ACT8945A_APCH_STATUS, &status);
418         if (ret < 0)
419                 return ret;
420
421         ret = regmap_read(charger->regmap, ACT8945A_APCH_STATE, &state);
422         if (ret < 0)
423                 return ret;
424
425         if (status & APCH_STATUS_INDAT) {
426                 if (state & APCH_STATE_ACINSTAT)
427                         *type = POWER_SUPPLY_TYPE_MAINS;
428                 else
429                         *type = POWER_SUPPLY_TYPE_USB;
430         } else {
431                 *type = POWER_SUPPLY_TYPE_BATTERY;
432         }
433
434         return 0;
435 }
436
437 static void act8945a_work(struct work_struct *work)
438 {
439         struct act8945a_charger *charger =
440                         container_of(work, struct act8945a_charger, work);
441
442         act8945a_set_supply_type(charger, &charger->desc.type);
443
444         power_supply_changed(charger->psy);
445 }
446
447 static irqreturn_t act8945a_status_changed(int irq, void *dev_id)
448 {
449         struct act8945a_charger *charger = dev_id;
450
451         if (charger->init_done)
452                 schedule_work(&charger->work);
453
454         return IRQ_HANDLED;
455 }
456
457 #define DEFAULT_TOTAL_TIME_OUT          3
458 #define DEFAULT_PRE_TIME_OUT            40
459 #define DEFAULT_INPUT_OVP_THRESHOLD     6600
460
461 static int act8945a_charger_config(struct device *dev,
462                                    struct act8945a_charger *charger)
463 {
464         struct device_node *np = dev->of_node;
465         struct regmap *regmap = charger->regmap;
466
467         u32 total_time_out;
468         u32 pre_time_out;
469         u32 input_voltage_threshold;
470         int err, ret;
471
472         unsigned int tmp;
473         unsigned int value = 0;
474
475         if (!np) {
476                 dev_err(dev, "no charger of node\n");
477                 return -EINVAL;
478         }
479
480         ret = regmap_read(regmap, ACT8945A_APCH_CFG, &tmp);
481         if (ret)
482                 return ret;
483
484         if (tmp & APCH_CFG_SUSCHG) {
485                 value |= APCH_CFG_SUSCHG;
486                 dev_info(dev, "have been suspended\n");
487         }
488
489         charger->lbo_gpio = devm_gpiod_get_optional(dev, "active-semi,lbo",
490                                                     GPIOD_IN);
491         if (IS_ERR(charger->lbo_gpio)) {
492                 err = PTR_ERR(charger->lbo_gpio);
493                 dev_err(dev, "unable to claim gpio \"lbo\": %d\n", err);
494                 return err;
495         }
496
497         ret = devm_request_irq(dev, gpiod_to_irq(charger->lbo_gpio),
498                                act8945a_status_changed,
499                                (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING),
500                                "act8945a_lbo_detect", charger);
501         if (ret)
502                 dev_info(dev, "failed to request gpio \"lbo\" IRQ\n");
503
504         charger->chglev_gpio = devm_gpiod_get_optional(dev,
505                                                        "active-semi,chglev",
506                                                        GPIOD_IN);
507         if (IS_ERR(charger->chglev_gpio)) {
508                 err = PTR_ERR(charger->chglev_gpio);
509                 dev_err(dev, "unable to claim gpio \"chglev\": %d\n", err);
510                 return err;
511         }
512
513         if (of_property_read_u32(np,
514                                  "active-semi,input-voltage-threshold-microvolt",
515                                  &input_voltage_threshold))
516                 input_voltage_threshold = DEFAULT_INPUT_OVP_THRESHOLD;
517
518         if (of_property_read_u32(np,
519                                  "active-semi,precondition-timeout",
520                                  &pre_time_out))
521                 pre_time_out = DEFAULT_PRE_TIME_OUT;
522
523         if (of_property_read_u32(np, "active-semi,total-timeout",
524                                  &total_time_out))
525                 total_time_out = DEFAULT_TOTAL_TIME_OUT;
526
527         switch (input_voltage_threshold) {
528         case 8000:
529                 value |= APCH_CFG_OVPSET_8V;
530                 break;
531         case 7500:
532                 value |= APCH_CFG_OVPSET_7V5;
533                 break;
534         case 7000:
535                 value |= APCH_CFG_OVPSET_7V;
536                 break;
537         case 6600:
538         default:
539                 value |= APCH_CFG_OVPSET_6V6;
540                 break;
541         }
542
543         switch (pre_time_out) {
544         case 60:
545                 value |= APCH_CFG_PRETIMO_60_MIN;
546                 break;
547         case 80:
548                 value |= APCH_CFG_PRETIMO_80_MIN;
549                 break;
550         case 0:
551                 value |= APCH_CFG_PRETIMO_DISABLED;
552                 break;
553         case 40:
554         default:
555                 value |= APCH_CFG_PRETIMO_40_MIN;
556                 break;
557         }
558
559         switch (total_time_out) {
560         case 4:
561                 value |= APCH_CFG_TOTTIMO_4_HOUR;
562                 break;
563         case 5:
564                 value |= APCH_CFG_TOTTIMO_5_HOUR;
565                 break;
566         case 0:
567                 value |= APCH_CFG_TOTTIMO_DISABLED;
568                 break;
569         case 3:
570         default:
571                 value |= APCH_CFG_TOTTIMO_3_HOUR;
572                 break;
573         }
574
575         return regmap_write(regmap, ACT8945A_APCH_CFG, value);
576 }
577
578 static int act8945a_charger_probe(struct platform_device *pdev)
579 {
580         struct act8945a_charger *charger;
581         struct power_supply_config psy_cfg = {};
582         int irq, ret;
583
584         charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
585         if (!charger)
586                 return -ENOMEM;
587
588         charger->regmap = dev_get_regmap(pdev->dev.parent, NULL);
589         if (!charger->regmap) {
590                 dev_err(&pdev->dev, "Parent did not provide regmap\n");
591                 return -EINVAL;
592         }
593
594         ret = act8945a_charger_config(&pdev->dev, charger);
595         if (ret)
596                 return ret;
597
598         irq = of_irq_get(pdev->dev.of_node, 0);
599         if (irq <= 0) {
600                 dev_err(&pdev->dev, "failed to find IRQ number\n");
601                 return irq ?: -ENXIO;
602         }
603
604         ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed,
605                                IRQF_TRIGGER_FALLING, "act8945a_interrupt",
606                                charger);
607         if (ret) {
608                 dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n");
609                 return ret;
610         }
611
612         charger->desc.name = "act8945a-charger";
613         charger->desc.get_property = act8945a_charger_get_property;
614         charger->desc.properties = act8945a_charger_props;
615         charger->desc.num_properties = ARRAY_SIZE(act8945a_charger_props);
616
617         ret = act8945a_set_supply_type(charger, &charger->desc.type);
618         if (ret)
619                 return -EINVAL;
620
621         psy_cfg.of_node = pdev->dev.of_node;
622         psy_cfg.drv_data = charger;
623
624         charger->psy = devm_power_supply_register(&pdev->dev,
625                                                   &charger->desc,
626                                                   &psy_cfg);
627         if (IS_ERR(charger->psy)) {
628                 dev_err(&pdev->dev, "failed to register power supply\n");
629                 return PTR_ERR(charger->psy);
630         }
631
632         platform_set_drvdata(pdev, charger);
633
634         INIT_WORK(&charger->work, act8945a_work);
635
636         ret = act8945a_enable_interrupt(charger);
637         if (ret)
638                 return -EIO;
639
640         charger->init_done = true;
641
642         return 0;
643 }
644
645 static int act8945a_charger_remove(struct platform_device *pdev)
646 {
647         struct act8945a_charger *charger = platform_get_drvdata(pdev);
648
649         charger->init_done = false;
650         cancel_work_sync(&charger->work);
651
652         return 0;
653 }
654
655 static struct platform_driver act8945a_charger_driver = {
656         .driver = {
657                 .name = "act8945a-charger",
658         },
659         .probe  = act8945a_charger_probe,
660         .remove = act8945a_charger_remove,
661 };
662 module_platform_driver(act8945a_charger_driver);
663
664 MODULE_DESCRIPTION("Active-semi ACT8945A ActivePath charger driver");
665 MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
666 MODULE_LICENSE("GPL");