1 #define pr_fmt(x) KBUILD_MODNAME ": " x "\n"
2
3 #include <linux/kernel.h>
4 #include <linux/module.h>
5 #include <linux/init.h>
6 #include "linux/irq.h"
7 #include <linux/slab.h>
8 #include <linux/interrupt.h>
9 #include <linux/device.h>
10 #include <linux/mutex.h>
11 #include <linux/param.h>
12 #include <linux/jiffies.h>
13 #include <linux/platform_device.h>
14 #include <linux/power_supply.h>
15 #include <linux/fs.h>
16 #include <linux/kernel.h>
17 #include <linux/ktime.h>
18 #include <linux/of.h>
19 #include <linux/timekeeping.h>
20 #include <linux/types.h>
21 #include <linux/string.h>
22 #include <asm/irq.h>
23 #include <linux/cdev.h>
24 #include <linux/delay.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/kthread.h>
27 #include <linux/freezer.h>
28 #include <linux/err.h>
29 #include "power/axp2101.h"
30
31 #include <linux/err.h>
32 //#include "../drivers/gpio/gpiolib.h"
33 #include "axp2202_charger.h"
34
35 struct axp2202_usb_power {
36 char *name;
37 struct device *dev;
38 struct regmap *regmap;
39 struct power_supply *usb_supply;
40 struct axp_config_info dts_info;
41 struct delayed_work usb_supply_mon;
42 struct delayed_work usb_chg_state;
43
44 atomic_t set_current_limit;
45 };
46
47 static enum power_supply_property axp2202_usb_props[] = {
48 POWER_SUPPLY_PROP_PRESENT,
49 POWER_SUPPLY_PROP_VOLTAGE_NOW,
50 POWER_SUPPLY_PROP_MANUFACTURER,
51 POWER_SUPPLY_PROP_ONLINE,
52 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
53 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
54
55 };
56
57
58
axp2202_get_vbus_vol(struct power_supply * ps,union power_supply_propval * val)59 static int axp2202_get_vbus_vol(struct power_supply *ps,
60 union power_supply_propval *val)
61 {
62 struct axp2202_usb_power *usb_power = power_supply_get_drvdata(ps);
63 struct regmap *regmap = usb_power->regmap;
64
65 uint8_t data[2];
66 uint16_t vol;
67 int ret = 0;
68
69 ret = regmap_bulk_read(regmap, AXP2202_VBUS_H, data, 2);
70 if (ret < 0)
71 return ret;
72 vol = (((data[0] & GENMASK(5, 0)) << 8) | (data[1])); /* mA */
73 val->intval = vol;
74
75 return 0;
76 }
77
axp2202_get_vbus_online(struct power_supply * ps,union power_supply_propval * val)78 static int axp2202_get_vbus_online(struct power_supply *ps,
79 union power_supply_propval *val)
80 {
81 struct axp2202_usb_power *usb_power = power_supply_get_drvdata(ps);
82 struct regmap *regmap = usb_power->regmap;
83
84 unsigned int data;
85 int ret = 0;
86
87 ret = regmap_read(regmap, AXP2202_COMM_STAT0, &data);
88 if (ret < 0)
89 return ret;
90
91 if (data & AXP2202_MASK_VBUS_STAT)
92 val->intval = 1;
93 else
94 val->intval = 0;
95
96 return ret;
97 }
98
axp2202_get_vbus_state(struct power_supply * ps,union power_supply_propval * val)99 static int axp2202_get_vbus_state(struct power_supply *ps,
100 union power_supply_propval *val)
101 {
102 struct axp2202_usb_power *usb_power = power_supply_get_drvdata(ps);
103 struct regmap *regmap = usb_power->regmap;
104 unsigned int data;
105 int ret = 0;
106
107 ret = regmap_read(regmap, AXP2202_COMM_STAT0, &data);
108 if (ret < 0)
109 return ret;
110
111 /* vbus is good when vbus state set */
112 val->intval = !!(data & AXP2202_MASK_VBUS_STAT);
113
114 return ret;
115 }
116
axp2202_get_iin_limit(struct power_supply * ps,union power_supply_propval * val)117 static int axp2202_get_iin_limit(struct power_supply *ps,
118 union power_supply_propval *val)
119 {
120 struct axp2202_usb_power *usb_power = power_supply_get_drvdata(ps);
121 struct regmap *regmap = usb_power->regmap;
122 unsigned int data;
123 int ret = 0;
124
125 ret = regmap_read(regmap, AXP2202_IIN_LIM, &data);
126 if (ret < 0)
127 return ret;
128
129 data = (data * 50) + 100;
130 val->intval = data;
131
132 return ret;
133 }
134
135
axp2202_get_vindpm(struct power_supply * ps,union power_supply_propval * val)136 static int axp2202_get_vindpm(struct power_supply *ps,
137 union power_supply_propval *val)
138 {
139 struct axp2202_usb_power *usb_power = power_supply_get_drvdata(ps);
140 struct regmap *regmap = usb_power->regmap;
141 unsigned int data;
142 int ret = 0;
143
144 ret = regmap_read(regmap, AXP2202_VINDPM_CFG, &data);
145 if (ret < 0)
146 return ret;
147
148 data = (data * 80) + 3880;
149 val->intval = data;
150
151 return ret;
152 }
153
axp2202_get_usb_type(struct power_supply * ps,union power_supply_propval * val)154 static int axp2202_get_usb_type(struct power_supply *ps,
155 union power_supply_propval *val)
156 {
157 struct axp2202_usb_power *usb_power = power_supply_get_drvdata(ps);
158 struct axp_config_info *dinfo = &usb_power->dts_info;
159 int ret = 0;
160
161 if (dinfo->pmu_usb_typec_used)
162 val->intval = POWER_SUPPLY_TYPE_USB_TYPE_C;
163 else
164 val->intval = POWER_SUPPLY_TYPE_USB;
165
166 return ret;
167 }
168
axp2202_get_cc_status(struct power_supply * ps,union power_supply_propval * val)169 static int axp2202_get_cc_status(struct power_supply *ps,
170 union power_supply_propval *val)
171 {
172 struct axp2202_usb_power *usb_power = power_supply_get_drvdata(ps);
173 struct axp_config_info *dinfo = &usb_power->dts_info;
174 struct regmap *regmap = usb_power->regmap;
175 unsigned int data;
176 int ret = 0;
177
178 if (!dinfo->pmu_usb_typec_used) {
179 val->intval = POWER_SUPPLY_SCOPE_UNKNOWN;
180 return ret;
181 }
182
183 ret = regmap_read(regmap, AXP2202_CC_STAT0, &data);
184 if (ret < 0)
185 return ret;
186
187 data &= 0x0f;
188
189 if (data == 5 || data == 6 || data == 9 || data == 12) {
190 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;//source/host
191 } else if (data == 2 || data == 3 || data == 10 || data == 11) {
192 val->intval = POWER_SUPPLY_SCOPE_DEVICE;//sink/
193 } else {
194 val->intval = POWER_SUPPLY_SCOPE_UNKNOWN;//disable
195 }
196
197 return ret;
198 }
199
axp2202_set_iin_limit(struct regmap * regmap,int mA)200 static int axp2202_set_iin_limit(struct regmap *regmap, int mA)
201 {
202 unsigned int data;
203 int ret = 0;
204
205 data = mA;
206
207 if (data > 3250)
208 data = 3250;
209 if (data < 100)
210 data = 100;
211 data = ((data - 100) / 50);
212 ret = regmap_update_bits(regmap, AXP2202_IIN_LIM, GENMASK(5, 0),
213 data);
214 if (ret < 0)
215 return ret;
216
217 return 0;
218 }
219
220
axp2202_set_vindpm(struct regmap * regmap,int mV)221 static int axp2202_set_vindpm(struct regmap *regmap, int mV)
222 {
223 unsigned int data;
224 int ret = 0;
225
226 data = mV;
227
228 if (data > 5080)
229 data = 5080;
230 if (data < 3880)
231 data = 3880;
232 data = ((data - 3880) / 80);
233 ret = regmap_update_bits(regmap, AXP2202_VINDPM_CFG, GENMASK(3, 0),
234 data);
235 if (ret < 0)
236 return ret;
237
238 return 0;
239 }
240
axp2202_usb_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)241 static int axp2202_usb_get_property(struct power_supply *psy,
242 enum power_supply_property psp,
243 union power_supply_propval *val)
244 {
245 int ret = 0;
246
247 switch (psp) {
248 case POWER_SUPPLY_PROP_ONLINE:
249 ret = axp2202_get_vbus_online(psy, val);
250 break;
251 case POWER_SUPPLY_PROP_PRESENT:
252 ret = axp2202_get_vbus_state(psy, val);
253 break;
254 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
255 ret = axp2202_get_vbus_vol(psy, val);
256 break;
257 case POWER_SUPPLY_PROP_MANUFACTURER:
258 val->strval = AXP2202_MANUFACTURER;
259 break;
260 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
261 ret = axp2202_get_iin_limit(psy, val);
262 break;
263 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
264 ret = axp2202_get_vindpm(psy, val);
265 break;
266 case POWER_SUPPLY_PROP_USB_TYPE:
267 ret = axp2202_get_usb_type(psy, val);
268 break;
269 case POWER_SUPPLY_PROP_SCOPE:
270 ret = axp2202_get_cc_status(psy, val);
271 break;
272 default:
273 break;
274 }
275
276 return ret;
277 }
278
axp2202_usb_set_property(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)279 static int axp2202_usb_set_property(struct power_supply *psy,
280 enum power_supply_property psp,
281 const union power_supply_propval *val)
282 {
283 struct axp2202_usb_power *usb_power = power_supply_get_drvdata(psy);
284 struct regmap *regmap = usb_power->regmap;
285 int ret = 0;
286
287 switch (psp) {
288 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
289 ret = axp2202_set_iin_limit(regmap, val->intval);
290 atomic_set(&usb_power->set_current_limit, 1);
291 break;
292 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
293 ret = axp2202_set_vindpm(regmap, val->intval);
294 break;
295 default:
296 ret = -EINVAL;
297 }
298 return ret;
299 }
300
axp2202_usb_power_property_is_writeable(struct power_supply * psy,enum power_supply_property psp)301 static int axp2202_usb_power_property_is_writeable(struct power_supply *psy,
302 enum power_supply_property psp)
303 {
304 int ret = 0;
305 switch (psp) {
306 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
307 ret = 0;
308 break;
309 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
310 ret = 0;
311 break;
312 default:
313 ret = -EINVAL;
314 }
315 return ret;
316
317 }
318
319 static const struct power_supply_desc axp2202_usb_desc = {
320 .name = "axp2202-usb",
321 .type = POWER_SUPPLY_TYPE_USB,
322 .get_property = axp2202_usb_get_property,
323 .properties = axp2202_usb_props,
324 .set_property = axp2202_usb_set_property,
325 .num_properties = ARRAY_SIZE(axp2202_usb_props),
326 .property_is_writeable = axp2202_usb_power_property_is_writeable,
327 };
328
329
axp2202_irq_handler_usb_in(int irq,void * data)330 static irqreturn_t axp2202_irq_handler_usb_in(int irq, void *data)
331 {
332 struct axp2202_usb_power *usb_power = data;
333 struct axp_config_info *axp_config = &usb_power->dts_info;
334
335 power_supply_changed(usb_power->usb_supply);
336
337 if (!axp_config->pmu_bc12_en) {
338 axp2202_set_iin_limit(usb_power->regmap, axp_config->pmu_usbpc_cur);
339 atomic_set(&usb_power->set_current_limit, 0);
340 cancel_delayed_work_sync(&usb_power->usb_chg_state);
341 schedule_delayed_work(&usb_power->usb_chg_state, msecs_to_jiffies(5 * 1000));
342 }
343
344 return IRQ_HANDLED;
345 }
346
axp2202_irq_handler_usb_out(int irq,void * data)347 static irqreturn_t axp2202_irq_handler_usb_out(int irq, void *data)
348 {
349 struct axp2202_usb_power *usb_power = data;
350
351 power_supply_changed(usb_power->usb_supply);
352
353 return IRQ_HANDLED;
354 }
355
356 enum axp2202_usb_virq_index {
357 AXP2202_VIRQ_USB_IN,
358 AXP2202_VIRQ_USB_OUT,
359
360 AXP2202_USB_VIRQ_MAX_VIRQ,
361 };
362
363 static struct axp_interrupts axp_usb_irq[] = {
364 [AXP2202_VIRQ_USB_IN] = { "vbus_insert", axp2202_irq_handler_usb_in },
365 [AXP2202_VIRQ_USB_OUT] = { "vbus_remove", axp2202_irq_handler_usb_out },
366 };
367
368
369
axp2202_usb_power_monitor(struct work_struct * work)370 static void axp2202_usb_power_monitor(struct work_struct *work)
371 {
372 struct axp2202_usb_power *usb_power =
373 container_of(work, typeof(*usb_power), usb_supply_mon.work);
374
375 schedule_delayed_work(&usb_power->usb_supply_mon, msecs_to_jiffies(500));
376 }
377
378
379
axp2202_usb_set_current_fsm(struct work_struct * work)380 static void axp2202_usb_set_current_fsm(struct work_struct *work)
381 {
382 struct axp2202_usb_power *usb_power =
383 container_of(work, typeof(*usb_power), usb_chg_state.work);
384 struct axp_config_info *axp_config = &usb_power->dts_info;
385
386 if (atomic_read(&usb_power->set_current_limit)) {
387 pr_info("current limit setted: usb pc type\n");
388 } else {
389 axp2202_set_iin_limit(usb_power->regmap, axp_config->pmu_usbad_cur);
390 pr_info("current limit not set: usb adapter type\n");
391 }
392 }
393
394
395
axp2202_usb_power_init(struct axp2202_usb_power * usb_power)396 static void axp2202_usb_power_init(struct axp2202_usb_power *usb_power)
397 {
398 struct regmap *regmap = usb_power->regmap;
399 struct axp_config_info *dinfo = &usb_power->dts_info;
400
401 unsigned int data = 0;
402
403 /* set vindpm value */
404 axp2202_set_vindpm(regmap, dinfo->pmu_usbad_vol);
405
406 /* set bc12 en/disable */
407 if (dinfo->pmu_bc12_en) {
408 regmap_update_bits(regmap, AXP2202_CLK_EN, BIT(4), BIT(4));
409 regmap_update_bits(regmap, AXP2202_IIN_LIM, BIT(7), 0);
410 } else {
411 regmap_update_bits(regmap, AXP2202_CLK_EN, BIT(4), 0);
412 regmap_update_bits(regmap, AXP2202_IIN_LIM, BIT(7), BIT(7));
413 }
414
415 /* set cc logic en/disable */
416 if (dinfo->pmu_cc_logic_en)
417 regmap_update_bits(regmap, AXP2202_CLK_EN, BIT(3), BIT(3));
418 else
419 regmap_update_bits(regmap, AXP2202_CLK_EN, BIT(3), 0);
420
421 /* set boost vol */
422 data = (dinfo->pmu_boost_vol - 4550) / 64;
423 regmap_update_bits(regmap, AXP2202_BST_CFG0, GENMASK(7, 4), data << 4);
424 regmap_write(regmap, AXP2202_BST_CFG1, 0x03);
425
426 /* set type-c en/disable & mode */
427 if (dinfo->pmu_usb_typec_used) {
428 regmap_update_bits(regmap, AXP2202_CC_GLB_CTRL, BIT(2), 0);
429 regmap_update_bits(regmap, AXP2202_CC_MODE_CTRL, BIT(1), BIT(1));
430 regmap_update_bits(regmap, AXP2202_CC_MODE_CTRL, BIT(0), BIT(0));
431 } else {
432 regmap_update_bits(regmap, AXP2202_CC_MODE_CTRL, BIT(1), 0);
433 regmap_update_bits(regmap, AXP2202_CC_MODE_CTRL, BIT(0), 0);
434 }
435 }
436
437
axp2202_usb_dt_parse(struct device_node * node,struct axp_config_info * axp_config)438 int axp2202_usb_dt_parse(struct device_node *node,
439 struct axp_config_info *axp_config)
440 {
441 if (!of_device_is_available(node)) {
442 pr_err("%s: failed\n", __func__);
443 return -1;
444 }
445
446
447 AXP_OF_PROP_READ(pmu_usbpc_vol, 4600);
448 AXP_OF_PROP_READ(pmu_usbpc_cur, 500);
449 AXP_OF_PROP_READ(pmu_usbad_vol, 4600);
450 AXP_OF_PROP_READ(pmu_usbad_cur, 1500);
451 AXP_OF_PROP_READ(pmu_bc12_en, 0);
452 AXP_OF_PROP_READ(pmu_cc_logic_en, 1);
453 AXP_OF_PROP_READ(pmu_boost_en, 0);
454 AXP_OF_PROP_READ(pmu_boost_vol, 5126);
455 AXP_OF_PROP_READ(pmu_usb_typec_used, 0);
456
457 axp_config->wakeup_usb_in =
458 of_property_read_bool(node, "wakeup_usb_in");
459 axp_config->wakeup_usb_out =
460 of_property_read_bool(node, "wakeup_usb_out");
461
462 return 0;
463 }
464
axp2202_usb_parse_device_tree(struct axp2202_usb_power * usb_power)465 static void axp2202_usb_parse_device_tree(struct axp2202_usb_power *usb_power)
466 {
467 int ret;
468 struct axp_config_info *cfg;
469
470 /* set input current limit */
471 if (!usb_power->dev->of_node) {
472 pr_info("can not find device tree\n");
473 return;
474 }
475
476 cfg = &usb_power->dts_info;
477 ret = axp2202_usb_dt_parse(usb_power->dev->of_node, cfg);
478 if (ret) {
479 pr_info("can not parse device tree err\n");
480 return;
481 }
482
483 /*init axp2202 usb by device tree*/
484 axp2202_usb_power_init(usb_power);
485 }
486
487
axp2202_usb_probe(struct platform_device * pdev)488 static int axp2202_usb_probe(struct platform_device *pdev)
489 {
490 int ret = 0;
491 int i = 0, irq;
492
493 struct axp2202_usb_power *usb_power;
494
495 struct axp20x_dev *axp_dev = dev_get_drvdata(pdev->dev.parent);
496 struct power_supply_config psy_cfg = {};
497
498 if (!axp_dev->irq) {
499 pr_err("can not register axp2202-usb without irq\n");
500 return -EINVAL;
501 }
502
503 usb_power = devm_kzalloc(&pdev->dev, sizeof(*usb_power), GFP_KERNEL);
504 if (usb_power == NULL) {
505 pr_err("axp2202_usb_power alloc failed\n");
506 ret = -ENOMEM;
507 goto err;
508 }
509
510 usb_power->name = "axp2202_usb";
511 usb_power->dev = &pdev->dev;
512 usb_power->regmap = axp_dev->regmap;
513
514 /* parse device tree and set register */
515 axp2202_usb_parse_device_tree(usb_power);
516
517 psy_cfg.of_node = pdev->dev.of_node;
518 psy_cfg.drv_data = usb_power;
519
520 usb_power->usb_supply = devm_power_supply_register(usb_power->dev,
521 &axp2202_usb_desc, &psy_cfg);
522
523 if (IS_ERR(usb_power->usb_supply)) {
524 pr_err("axp2202 failed to register usb power\n");
525 ret = PTR_ERR(usb_power->usb_supply);
526 return ret;
527 }
528
529 for (i = 0; i < ARRAY_SIZE(axp_usb_irq); i++) {
530 irq = platform_get_irq_byname(pdev, axp_usb_irq[i].name);
531 if (irq < 0)
532 continue;
533
534 irq = regmap_irq_get_virq(axp_dev->regmap_irqc, irq);
535 if (irq < 0) {
536 dev_err(&pdev->dev, "can not get irq\n");
537 return irq;
538 }
539 /* we use this variable to suspend irq */
540 axp_usb_irq[i].irq = irq;
541 ret = devm_request_any_context_irq(&pdev->dev, irq,
542 axp_usb_irq[i].isr, 0,
543 axp_usb_irq[i].name, usb_power);
544 if (ret < 0) {
545 dev_err(&pdev->dev, "failed to request %s IRQ %d: %d\n",
546 axp_usb_irq[i].name, irq, ret);
547 return ret;
548 } else {
549 ret = 0;
550 }
551
552 dev_dbg(&pdev->dev, "Requested %s IRQ %d: %d\n",
553 axp_usb_irq[i].name, irq, ret);
554 }
555 platform_set_drvdata(pdev, usb_power);
556
557 if (!usb_power->dts_info.pmu_bc12_en) {
558 INIT_DELAYED_WORK(&usb_power->usb_supply_mon, axp2202_usb_power_monitor);
559 schedule_delayed_work(&usb_power->usb_supply_mon, msecs_to_jiffies(500));
560
561 INIT_DELAYED_WORK(&usb_power->usb_chg_state, axp2202_usb_set_current_fsm);
562 schedule_delayed_work(&usb_power->usb_chg_state, msecs_to_jiffies(20 * 1000));
563 }
564
565 return ret;
566
567
568 err:
569 pr_err("%s,probe fail, ret = %d\n", __func__, ret);
570
571 return ret;
572 }
573
axp2202_usb_remove(struct platform_device * pdev)574 static int axp2202_usb_remove(struct platform_device *pdev)
575 {
576 struct axp2202_usb_power *usb_power = platform_get_drvdata(pdev);
577
578 cancel_delayed_work_sync(&usb_power->usb_supply_mon);
579 cancel_delayed_work_sync(&usb_power->usb_chg_state);
580
581 dev_dbg(&pdev->dev, "==============AXP2202 usb unegister==============\n");
582 if (usb_power->usb_supply)
583 power_supply_unregister(usb_power->usb_supply);
584 dev_dbg(&pdev->dev, "axp2202 teardown usb dev\n");
585
586 return 0;
587 }
588
589
590
axp2202_usb_irq_set(unsigned int irq,bool enable)591 static inline void axp2202_usb_irq_set(unsigned int irq, bool enable)
592 {
593 if (enable)
594 enable_irq(irq);
595 else
596 disable_irq(irq);
597 }
598
axp2202_usb_virq_dts_set(struct axp2202_usb_power * usb_power,bool enable)599 static void axp2202_usb_virq_dts_set(struct axp2202_usb_power *usb_power, bool enable)
600 {
601 struct axp_config_info *dts_info = &usb_power->dts_info;
602
603 if (!dts_info->wakeup_usb_in)
604 axp2202_usb_irq_set(axp_usb_irq[AXP2202_VIRQ_USB_IN].irq,
605 enable);
606 if (!dts_info->wakeup_usb_out)
607 axp2202_usb_irq_set(axp_usb_irq[AXP2202_VIRQ_USB_OUT].irq,
608 enable);
609
610 }
611
612
613
axp2202_usb_suspend(struct platform_device * p,pm_message_t state)614 static int axp2202_usb_suspend(struct platform_device *p, pm_message_t state)
615 {
616 struct axp2202_usb_power *usb_power = platform_get_drvdata(p);
617
618
619 axp2202_usb_virq_dts_set(usb_power, false);
620 return 0;
621 }
622
axp2202_usb_resume(struct platform_device * p)623 static int axp2202_usb_resume(struct platform_device *p)
624 {
625 struct axp2202_usb_power *usb_power = platform_get_drvdata(p);
626
627
628 axp2202_usb_virq_dts_set(usb_power, true);
629
630 return 0;
631 }
632
633 static const struct of_device_id axp2202_usb_power_match[] = {
634 {
635 .compatible = "x-powers,axp2202-usb-power-supply",
636 .data = (void *)AXP2202_ID,
637 }, {/* sentinel */}
638 };
639 MODULE_DEVICE_TABLE(of, axp2202_usb_power_match);
640
641 static struct platform_driver axp2202_usb_power_driver = {
642 .driver = {
643 .name = "axp2202-usb-power-supply",
644 .of_match_table = axp2202_usb_power_match,
645 },
646 .probe = axp2202_usb_probe,
647 .remove = axp2202_usb_remove,
648 .suspend = axp2202_usb_suspend,
649 .resume = axp2202_usb_resume,
650 };
651
652 module_platform_driver(axp2202_usb_power_driver);
653
654 MODULE_AUTHOR("wangxiaoliang <wangxiaoliang@x-powers.com>");
655 MODULE_DESCRIPTION("axp2202 usb driver");
656 MODULE_LICENSE("GPL");
657
658