1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2021 MediaTek Inc.
6 #include <linux/devm-helpers.h>
7 #include <linux/init.h>
8 #include <linux/interrupt.h>
9 #include <linux/kernel.h>
10 #include <linux/linear_range.h>
11 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/power_supply.h>
15 #include <linux/property.h>
16 #include <linux/regmap.h>
17 #include <linux/regulator/driver.h>
19 #define MT6360_PMU_CHG_CTRL1 0x311
20 #define MT6360_PMU_CHG_CTRL2 0x312
21 #define MT6360_PMU_CHG_CTRL3 0x313
22 #define MT6360_PMU_CHG_CTRL4 0x314
23 #define MT6360_PMU_CHG_CTRL5 0x315
24 #define MT6360_PMU_CHG_CTRL6 0x316
25 #define MT6360_PMU_CHG_CTRL7 0x317
26 #define MT6360_PMU_CHG_CTRL8 0x318
27 #define MT6360_PMU_CHG_CTRL9 0x319
28 #define MT6360_PMU_CHG_CTRL10 0x31A
29 #define MT6360_PMU_DEVICE_TYPE 0x322
30 #define MT6360_PMU_USB_STATUS1 0x327
31 #define MT6360_PMU_CHG_STAT 0x34A
32 #define MT6360_PMU_CHG_CTRL19 0x361
33 #define MT6360_PMU_FOD_STAT 0x3E7
35 /* MT6360_PMU_CHG_CTRL1 */
36 #define MT6360_FSLP_SHFT (3)
37 #define MT6360_FSLP_MASK BIT(MT6360_FSLP_SHFT)
38 #define MT6360_OPA_MODE_SHFT (0)
39 #define MT6360_OPA_MODE_MASK BIT(MT6360_OPA_MODE_SHFT)
40 /* MT6360_PMU_CHG_CTRL2 */
41 #define MT6360_IINLMTSEL_SHFT (2)
42 #define MT6360_IINLMTSEL_MASK GENMASK(3, 2)
43 /* MT6360_PMU_CHG_CTRL3 */
44 #define MT6360_IAICR_SHFT (2)
45 #define MT6360_IAICR_MASK GENMASK(7, 2)
46 #define MT6360_ILIM_EN_MASK BIT(0)
47 /* MT6360_PMU_CHG_CTRL4 */
48 #define MT6360_VOREG_SHFT (1)
49 #define MT6360_VOREG_MASK GENMASK(7, 1)
50 /* MT6360_PMU_CHG_CTRL5 */
51 #define MT6360_VOBST_MASK GENMASK(7, 2)
52 /* MT6360_PMU_CHG_CTRL6 */
53 #define MT6360_VMIVR_SHFT (1)
54 #define MT6360_VMIVR_MASK GENMASK(7, 1)
55 /* MT6360_PMU_CHG_CTRL7 */
56 #define MT6360_ICHG_SHFT (2)
57 #define MT6360_ICHG_MASK GENMASK(7, 2)
58 /* MT6360_PMU_CHG_CTRL8 */
59 #define MT6360_IPREC_SHFT (0)
60 #define MT6360_IPREC_MASK GENMASK(3, 0)
61 /* MT6360_PMU_CHG_CTRL9 */
62 #define MT6360_IEOC_SHFT (4)
63 #define MT6360_IEOC_MASK GENMASK(7, 4)
64 /* MT6360_PMU_CHG_CTRL10 */
65 #define MT6360_OTG_OC_MASK GENMASK(3, 0)
66 /* MT6360_PMU_DEVICE_TYPE */
67 #define MT6360_USBCHGEN_MASK BIT(7)
68 /* MT6360_PMU_USB_STATUS1 */
69 #define MT6360_USB_STATUS_SHFT (4)
70 #define MT6360_USB_STATUS_MASK GENMASK(6, 4)
71 /* MT6360_PMU_CHG_STAT */
72 #define MT6360_CHG_STAT_SHFT (6)
73 #define MT6360_CHG_STAT_MASK GENMASK(7, 6)
74 #define MT6360_VBAT_LVL_MASK BIT(5)
75 /* MT6360_PMU_CHG_CTRL19 */
76 #define MT6360_VINOVP_SHFT (5)
77 #define MT6360_VINOVP_MASK GENMASK(6, 5)
78 /* MT6360_PMU_FOD_STAT */
79 #define MT6360_CHRDET_EXT_MASK BIT(4)
82 #define MT6360_VMIVR_MIN 3900000
83 #define MT6360_VMIVR_MAX 13400000
84 #define MT6360_VMIVR_STEP 100000
86 #define MT6360_ICHG_MIN 100000
87 #define MT6360_ICHG_MAX 5000000
88 #define MT6360_ICHG_STEP 100000
90 #define MT6360_VOREG_MIN 3900000
91 #define MT6360_VOREG_MAX 4710000
92 #define MT6360_VOREG_STEP 10000
94 #define MT6360_AICR_MIN 100000
95 #define MT6360_AICR_MAX 3250000
96 #define MT6360_AICR_STEP 50000
98 #define MT6360_IPREC_MIN 100000
99 #define MT6360_IPREC_MAX 850000
100 #define MT6360_IPREC_STEP 50000
102 #define MT6360_IEOC_MIN 100000
103 #define MT6360_IEOC_MAX 850000
104 #define MT6360_IEOC_STEP 50000
116 static const struct linear_range mt6360_chg_range
[MT6360_RANGE_MAX
] = {
117 LINEAR_RANGE_IDX(MT6360_RANGE_VMIVR
, 3900000, 0, 0x5F, 100000),
118 LINEAR_RANGE_IDX(MT6360_RANGE_ICHG
, 100000, 0, 0x31, 100000),
119 LINEAR_RANGE_IDX(MT6360_RANGE_VOREG
, 3900000, 0, 0x51, 10000),
120 LINEAR_RANGE_IDX(MT6360_RANGE_AICR
, 100000, 0, 0x3F, 50000),
121 LINEAR_RANGE_IDX(MT6360_RANGE_IPREC
, 100000, 0, 0x0F, 50000),
122 LINEAR_RANGE_IDX(MT6360_RANGE_IEOC
, 100000, 0, 0x0F, 50000),
125 struct mt6360_chg_info
{
127 struct regmap
*regmap
;
128 struct power_supply_desc psy_desc
;
129 struct power_supply
*psy
;
130 struct regulator_dev
*otg_rdev
;
131 struct mutex chgdet_lock
;
136 struct work_struct chrdet_work
;
139 enum mt6360_iinlmtsel
{
140 MT6360_IINLMTSEL_AICR_3250
= 0,
141 MT6360_IINLMTSEL_CHG_TYPE
,
142 MT6360_IINLMTSEL_AICR
,
143 MT6360_IINLMTSEL_LOWER_LEVEL
,
146 enum mt6360_pmu_chg_type
{
147 MT6360_CHG_TYPE_NOVBUS
= 0,
148 MT6360_CHG_TYPE_UNDER_GOING
,
150 MT6360_CHG_TYPE_SDPNSTD
,
153 MT6360_CHG_TYPE_DISABLE_BC12
,
157 static int mt6360_get_chrdet_ext_stat(struct mt6360_chg_info
*mci
,
163 ret
= regmap_read(mci
->regmap
, MT6360_PMU_FOD_STAT
, ®val
);
166 *pwr_rdy
= (regval
& MT6360_CHRDET_EXT_MASK
) ? true : false;
170 static int mt6360_charger_get_online(struct mt6360_chg_info
*mci
,
171 union power_supply_propval
*val
)
176 ret
= mt6360_get_chrdet_ext_stat(mci
, &pwr_rdy
);
179 val
->intval
= pwr_rdy
? true : false;
183 static int mt6360_charger_get_status(struct mt6360_chg_info
*mci
,
184 union power_supply_propval
*val
)
190 ret
= mt6360_get_chrdet_ext_stat(mci
, &pwr_rdy
);
194 status
= POWER_SUPPLY_STATUS_DISCHARGING
;
198 ret
= regmap_read(mci
->regmap
, MT6360_PMU_CHG_STAT
, ®val
);
201 regval
&= MT6360_CHG_STAT_MASK
;
202 regval
>>= MT6360_CHG_STAT_SHFT
;
205 status
= POWER_SUPPLY_STATUS_NOT_CHARGING
;
208 status
= POWER_SUPPLY_STATUS_CHARGING
;
211 status
= POWER_SUPPLY_STATUS_FULL
;
218 val
->intval
= status
;
222 static int mt6360_charger_get_charge_type(struct mt6360_chg_info
*mci
,
223 union power_supply_propval
*val
)
229 ret
= regmap_read(mci
->regmap
, MT6360_PMU_CHG_STAT
, ®val
);
233 chg_stat
= (regval
& MT6360_CHG_STAT_MASK
) >> MT6360_CHG_STAT_SHFT
;
235 case 0x01: /* Charge in Progress */
236 if (regval
& MT6360_VBAT_LVL_MASK
)
237 type
= POWER_SUPPLY_CHARGE_TYPE_FAST
;
239 type
= POWER_SUPPLY_CHARGE_TYPE_TRICKLE
;
241 case 0x00: /* Not Charging */
242 case 0x02: /* Charge Done */
243 case 0x03: /* Charge Fault */
245 type
= POWER_SUPPLY_CHARGE_TYPE_NONE
;
253 static int mt6360_charger_get_ichg(struct mt6360_chg_info
*mci
,
254 union power_supply_propval
*val
)
259 ret
= regmap_read(mci
->regmap
, MT6360_PMU_CHG_CTRL7
, &sel
);
262 sel
= (sel
& MT6360_ICHG_MASK
) >> MT6360_ICHG_SHFT
;
263 ret
= linear_range_get_value(&mt6360_chg_range
[MT6360_RANGE_ICHG
], sel
, &value
);
269 static int mt6360_charger_get_max_ichg(struct mt6360_chg_info
*mci
,
270 union power_supply_propval
*val
)
272 val
->intval
= MT6360_ICHG_MAX
;
276 static int mt6360_charger_get_cv(struct mt6360_chg_info
*mci
,
277 union power_supply_propval
*val
)
282 ret
= regmap_read(mci
->regmap
, MT6360_PMU_CHG_CTRL4
, &sel
);
285 sel
= (sel
& MT6360_VOREG_MASK
) >> MT6360_VOREG_SHFT
;
286 ret
= linear_range_get_value(&mt6360_chg_range
[MT6360_RANGE_VOREG
], sel
, &value
);
292 static int mt6360_charger_get_max_cv(struct mt6360_chg_info
*mci
,
293 union power_supply_propval
*val
)
295 val
->intval
= MT6360_VOREG_MAX
;
299 static int mt6360_charger_get_aicr(struct mt6360_chg_info
*mci
,
300 union power_supply_propval
*val
)
305 ret
= regmap_read(mci
->regmap
, MT6360_PMU_CHG_CTRL3
, &sel
);
308 sel
= (sel
& MT6360_IAICR_MASK
) >> MT6360_IAICR_SHFT
;
309 ret
= linear_range_get_value(&mt6360_chg_range
[MT6360_RANGE_AICR
], sel
, &value
);
315 static int mt6360_charger_get_mivr(struct mt6360_chg_info
*mci
,
316 union power_supply_propval
*val
)
321 ret
= regmap_read(mci
->regmap
, MT6360_PMU_CHG_CTRL6
, &sel
);
324 sel
= (sel
& MT6360_VMIVR_MASK
) >> MT6360_VMIVR_SHFT
;
325 ret
= linear_range_get_value(&mt6360_chg_range
[MT6360_RANGE_VMIVR
], sel
, &value
);
331 static int mt6360_charger_get_iprechg(struct mt6360_chg_info
*mci
,
332 union power_supply_propval
*val
)
337 ret
= regmap_read(mci
->regmap
, MT6360_PMU_CHG_CTRL8
, &sel
);
340 sel
= (sel
& MT6360_IPREC_MASK
) >> MT6360_IPREC_SHFT
;
341 ret
= linear_range_get_value(&mt6360_chg_range
[MT6360_RANGE_IPREC
], sel
, &value
);
347 static int mt6360_charger_get_ieoc(struct mt6360_chg_info
*mci
,
348 union power_supply_propval
*val
)
353 ret
= regmap_read(mci
->regmap
, MT6360_PMU_CHG_CTRL9
, &sel
);
356 sel
= (sel
& MT6360_IEOC_MASK
) >> MT6360_IEOC_SHFT
;
357 ret
= linear_range_get_value(&mt6360_chg_range
[MT6360_RANGE_IEOC
], sel
, &value
);
363 static int mt6360_charger_set_online(struct mt6360_chg_info
*mci
,
364 const union power_supply_propval
*val
)
366 u8 force_sleep
= val
->intval
? 0 : 1;
368 return regmap_update_bits(mci
->regmap
,
369 MT6360_PMU_CHG_CTRL1
,
371 force_sleep
<< MT6360_FSLP_SHFT
);
374 static int mt6360_charger_set_ichg(struct mt6360_chg_info
*mci
,
375 const union power_supply_propval
*val
)
379 linear_range_get_selector_within(&mt6360_chg_range
[MT6360_RANGE_ICHG
], val
->intval
, &sel
);
380 return regmap_update_bits(mci
->regmap
,
381 MT6360_PMU_CHG_CTRL7
,
383 sel
<< MT6360_ICHG_SHFT
);
386 static int mt6360_charger_set_cv(struct mt6360_chg_info
*mci
,
387 const union power_supply_propval
*val
)
391 linear_range_get_selector_within(&mt6360_chg_range
[MT6360_RANGE_VOREG
], val
->intval
, &sel
);
392 return regmap_update_bits(mci
->regmap
,
393 MT6360_PMU_CHG_CTRL4
,
395 sel
<< MT6360_VOREG_SHFT
);
398 static int mt6360_charger_set_aicr(struct mt6360_chg_info
*mci
,
399 const union power_supply_propval
*val
)
403 linear_range_get_selector_within(&mt6360_chg_range
[MT6360_RANGE_AICR
], val
->intval
, &sel
);
404 return regmap_update_bits(mci
->regmap
,
405 MT6360_PMU_CHG_CTRL3
,
407 sel
<< MT6360_IAICR_SHFT
);
410 static int mt6360_charger_set_mivr(struct mt6360_chg_info
*mci
,
411 const union power_supply_propval
*val
)
415 linear_range_get_selector_within(&mt6360_chg_range
[MT6360_RANGE_VMIVR
], val
->intval
, &sel
);
416 return regmap_update_bits(mci
->regmap
,
417 MT6360_PMU_CHG_CTRL3
,
419 sel
<< MT6360_VMIVR_SHFT
);
422 static int mt6360_charger_set_iprechg(struct mt6360_chg_info
*mci
,
423 const union power_supply_propval
*val
)
427 linear_range_get_selector_within(&mt6360_chg_range
[MT6360_RANGE_IPREC
], val
->intval
, &sel
);
428 return regmap_update_bits(mci
->regmap
,
429 MT6360_PMU_CHG_CTRL8
,
431 sel
<< MT6360_IPREC_SHFT
);
434 static int mt6360_charger_set_ieoc(struct mt6360_chg_info
*mci
,
435 const union power_supply_propval
*val
)
439 linear_range_get_selector_within(&mt6360_chg_range
[MT6360_RANGE_IEOC
], val
->intval
, &sel
);
440 return regmap_update_bits(mci
->regmap
,
441 MT6360_PMU_CHG_CTRL9
,
443 sel
<< MT6360_IEOC_SHFT
);
446 static int mt6360_charger_get_property(struct power_supply
*psy
,
447 enum power_supply_property psp
,
448 union power_supply_propval
*val
)
450 struct mt6360_chg_info
*mci
= power_supply_get_drvdata(psy
);
454 case POWER_SUPPLY_PROP_ONLINE
:
455 ret
= mt6360_charger_get_online(mci
, val
);
457 case POWER_SUPPLY_PROP_STATUS
:
458 ret
= mt6360_charger_get_status(mci
, val
);
460 case POWER_SUPPLY_PROP_CHARGE_TYPE
:
461 ret
= mt6360_charger_get_charge_type(mci
, val
);
463 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
:
464 ret
= mt6360_charger_get_ichg(mci
, val
);
466 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
:
467 ret
= mt6360_charger_get_max_ichg(mci
, val
);
469 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE
:
470 ret
= mt6360_charger_get_cv(mci
, val
);
472 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
:
473 ret
= mt6360_charger_get_max_cv(mci
, val
);
475 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT
:
476 ret
= mt6360_charger_get_aicr(mci
, val
);
478 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT
:
479 ret
= mt6360_charger_get_mivr(mci
, val
);
481 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT
:
482 ret
= mt6360_charger_get_iprechg(mci
, val
);
484 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT
:
485 ret
= mt6360_charger_get_ieoc(mci
, val
);
487 case POWER_SUPPLY_PROP_USB_TYPE
:
488 val
->intval
= mci
->psy_usb_type
;
496 static int mt6360_charger_set_property(struct power_supply
*psy
,
497 enum power_supply_property psp
,
498 const union power_supply_propval
*val
)
500 struct mt6360_chg_info
*mci
= power_supply_get_drvdata(psy
);
504 case POWER_SUPPLY_PROP_ONLINE
:
505 ret
= mt6360_charger_set_online(mci
, val
);
507 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
:
508 ret
= mt6360_charger_set_ichg(mci
, val
);
510 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE
:
511 ret
= mt6360_charger_set_cv(mci
, val
);
513 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT
:
514 ret
= mt6360_charger_set_aicr(mci
, val
);
516 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT
:
517 ret
= mt6360_charger_set_mivr(mci
, val
);
519 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT
:
520 ret
= mt6360_charger_set_iprechg(mci
, val
);
522 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT
:
523 ret
= mt6360_charger_set_ieoc(mci
, val
);
531 static int mt6360_charger_property_is_writeable(struct power_supply
*psy
,
532 enum power_supply_property psp
)
535 case POWER_SUPPLY_PROP_ONLINE
:
536 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
:
537 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE
:
538 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT
:
539 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT
:
540 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT
:
541 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT
:
548 static enum power_supply_property mt6360_charger_properties
[] = {
549 POWER_SUPPLY_PROP_ONLINE
,
550 POWER_SUPPLY_PROP_STATUS
,
551 POWER_SUPPLY_PROP_CHARGE_TYPE
,
552 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT
,
553 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX
,
554 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE
,
555 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX
,
556 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT
,
557 POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT
,
558 POWER_SUPPLY_PROP_PRECHARGE_CURRENT
,
559 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT
,
560 POWER_SUPPLY_PROP_USB_TYPE
,
563 static const struct power_supply_desc mt6360_charger_desc
= {
564 .type
= POWER_SUPPLY_TYPE_USB
,
565 .properties
= mt6360_charger_properties
,
566 .num_properties
= ARRAY_SIZE(mt6360_charger_properties
),
567 .get_property
= mt6360_charger_get_property
,
568 .set_property
= mt6360_charger_set_property
,
569 .property_is_writeable
= mt6360_charger_property_is_writeable
,
570 .usb_types
= BIT(POWER_SUPPLY_USB_TYPE_SDP
) |
571 BIT(POWER_SUPPLY_USB_TYPE_CDP
) |
572 BIT(POWER_SUPPLY_USB_TYPE_DCP
) |
573 BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN
),
576 static const struct regulator_ops mt6360_chg_otg_ops
= {
577 .list_voltage
= regulator_list_voltage_linear
,
578 .enable
= regulator_enable_regmap
,
579 .disable
= regulator_disable_regmap
,
580 .is_enabled
= regulator_is_enabled_regmap
,
581 .set_voltage_sel
= regulator_set_voltage_sel_regmap
,
582 .get_voltage_sel
= regulator_get_voltage_sel_regmap
,
585 static const struct regulator_desc mt6360_otg_rdesc
= {
586 .of_match
= "usb-otg-vbus-regulator",
587 .name
= "usb-otg-vbus",
588 .ops
= &mt6360_chg_otg_ops
,
589 .owner
= THIS_MODULE
,
590 .type
= REGULATOR_VOLTAGE
,
594 .vsel_reg
= MT6360_PMU_CHG_CTRL5
,
595 .vsel_mask
= MT6360_VOBST_MASK
,
596 .enable_reg
= MT6360_PMU_CHG_CTRL1
,
597 .enable_mask
= MT6360_OPA_MODE_MASK
,
600 static irqreturn_t
mt6360_pmu_attach_i_handler(int irq
, void *data
)
602 struct mt6360_chg_info
*mci
= data
;
604 unsigned int usb_status
;
607 mutex_lock(&mci
->chgdet_lock
);
609 dev_warn(mci
->dev
, "Received attach interrupt, bc12 disabled, ignore irq\n");
612 last_usb_type
= mci
->psy_usb_type
;
614 ret
= regmap_read(mci
->regmap
, MT6360_PMU_USB_STATUS1
, &usb_status
);
617 usb_status
&= MT6360_USB_STATUS_MASK
;
618 usb_status
>>= MT6360_USB_STATUS_SHFT
;
619 switch (usb_status
) {
620 case MT6360_CHG_TYPE_NOVBUS
:
621 dev_dbg(mci
->dev
, "Received attach interrupt, no vbus\n");
623 case MT6360_CHG_TYPE_UNDER_GOING
:
624 dev_dbg(mci
->dev
, "Received attach interrupt, under going...\n");
626 case MT6360_CHG_TYPE_SDP
:
627 mci
->psy_usb_type
= POWER_SUPPLY_USB_TYPE_SDP
;
629 case MT6360_CHG_TYPE_SDPNSTD
:
630 mci
->psy_usb_type
= POWER_SUPPLY_USB_TYPE_SDP
;
632 case MT6360_CHG_TYPE_CDP
:
633 mci
->psy_usb_type
= POWER_SUPPLY_USB_TYPE_CDP
;
635 case MT6360_CHG_TYPE_DCP
:
636 mci
->psy_usb_type
= POWER_SUPPLY_USB_TYPE_DCP
;
638 case MT6360_CHG_TYPE_DISABLE_BC12
:
639 dev_dbg(mci
->dev
, "Received attach interrupt, bc12 detect not enable\n");
642 mci
->psy_usb_type
= POWER_SUPPLY_USB_TYPE_UNKNOWN
;
643 dev_dbg(mci
->dev
, "Received attach interrupt, reserved address\n");
647 dev_dbg(mci
->dev
, "Received attach interrupt, chg_type = %d\n", mci
->psy_usb_type
);
648 if (last_usb_type
!= mci
->psy_usb_type
)
649 power_supply_changed(mci
->psy
);
651 mutex_unlock(&mci
->chgdet_lock
);
655 static void mt6360_handle_chrdet_ext_evt(struct mt6360_chg_info
*mci
)
660 mutex_lock(&mci
->chgdet_lock
);
661 ret
= mt6360_get_chrdet_ext_stat(mci
, &pwr_rdy
);
664 if (mci
->pwr_rdy
== pwr_rdy
) {
665 dev_dbg(mci
->dev
, "Received vbus interrupt, pwr_rdy is same(%d)\n", pwr_rdy
);
668 mci
->pwr_rdy
= pwr_rdy
;
669 dev_dbg(mci
->dev
, "Received vbus interrupt, pwr_rdy = %d\n", pwr_rdy
);
671 mci
->psy_usb_type
= POWER_SUPPLY_USB_TYPE_UNKNOWN
;
672 power_supply_changed(mci
->psy
);
675 ret
= regmap_update_bits(mci
->regmap
,
676 MT6360_PMU_DEVICE_TYPE
,
677 MT6360_USBCHGEN_MASK
,
678 pwr_rdy
? MT6360_USBCHGEN_MASK
: 0);
681 mci
->bc12_en
= pwr_rdy
;
683 mutex_unlock(&mci
->chgdet_lock
);
686 static void mt6360_chrdet_work(struct work_struct
*work
)
688 struct mt6360_chg_info
*mci
= (struct mt6360_chg_info
*)container_of(
689 work
, struct mt6360_chg_info
, chrdet_work
);
691 mt6360_handle_chrdet_ext_evt(mci
);
694 static irqreturn_t
mt6360_pmu_chrdet_ext_evt_handler(int irq
, void *data
)
696 struct mt6360_chg_info
*mci
= data
;
698 mt6360_handle_chrdet_ext_evt(mci
);
702 static int mt6360_chg_irq_register(struct platform_device
*pdev
)
706 irq_handler_t handler
;
708 { "attach_i", mt6360_pmu_attach_i_handler
},
709 { "chrdet_ext_evt", mt6360_pmu_chrdet_ext_evt_handler
}
713 for (i
= 0; i
< ARRAY_SIZE(irq_descs
); i
++) {
714 ret
= platform_get_irq_byname(pdev
, irq_descs
[i
].name
);
718 ret
= devm_request_threaded_irq(&pdev
->dev
, ret
, NULL
,
719 irq_descs
[i
].handler
,
720 IRQF_TRIGGER_FALLING
| IRQF_ONESHOT
,
722 platform_get_drvdata(pdev
));
724 return dev_err_probe(&pdev
->dev
, ret
, "Failed to request %s irq\n",
731 static u32
mt6360_vinovp_trans_to_sel(u32 val
)
733 u32 vinovp_tbl
[] = { 5500000, 6500000, 11000000, 14500000 };
736 /* Select the smaller and equal supported value */
737 for (i
= 0; i
< ARRAY_SIZE(vinovp_tbl
)-1; i
++) {
738 if (val
< vinovp_tbl
[i
+1])
744 static int mt6360_chg_init_setting(struct mt6360_chg_info
*mci
)
749 sel
= mt6360_vinovp_trans_to_sel(mci
->vinovp
);
750 ret
= regmap_update_bits(mci
->regmap
, MT6360_PMU_CHG_CTRL19
,
751 MT6360_VINOVP_MASK
, sel
<< MT6360_VINOVP_SHFT
);
753 return dev_err_probe(mci
->dev
, ret
, "%s: Failed to apply vinovp\n", __func__
);
754 ret
= regmap_update_bits(mci
->regmap
, MT6360_PMU_DEVICE_TYPE
,
755 MT6360_USBCHGEN_MASK
, 0);
757 return dev_err_probe(mci
->dev
, ret
, "%s: Failed to disable bc12\n", __func__
);
758 ret
= regmap_update_bits(mci
->regmap
, MT6360_PMU_CHG_CTRL2
,
759 MT6360_IINLMTSEL_MASK
,
760 MT6360_IINLMTSEL_AICR
<<
761 MT6360_IINLMTSEL_SHFT
);
763 return dev_err_probe(mci
->dev
, ret
,
764 "%s: Failed to switch iinlmtsel to aicr\n", __func__
);
765 usleep_range(5000, 6000);
766 ret
= regmap_update_bits(mci
->regmap
, MT6360_PMU_CHG_CTRL3
,
767 MT6360_ILIM_EN_MASK
, 0);
769 return dev_err_probe(mci
->dev
, ret
,
770 "%s: Failed to disable ilim\n", __func__
);
771 ret
= regmap_update_bits(mci
->regmap
, MT6360_PMU_CHG_CTRL10
,
772 MT6360_OTG_OC_MASK
, MT6360_OTG_OC_MASK
);
774 return dev_err_probe(mci
->dev
, ret
,
775 "%s: Failed to config otg oc to 3A\n", __func__
);
779 static int mt6360_charger_probe(struct platform_device
*pdev
)
781 struct mt6360_chg_info
*mci
;
782 struct power_supply_config charger_cfg
= {};
783 struct regulator_config config
= { };
786 mci
= devm_kzalloc(&pdev
->dev
, sizeof(*mci
), GFP_KERNEL
);
790 mci
->dev
= &pdev
->dev
;
791 mci
->vinovp
= 6500000;
792 mutex_init(&mci
->chgdet_lock
);
793 platform_set_drvdata(pdev
, mci
);
794 ret
= devm_work_autocancel(&pdev
->dev
, &mci
->chrdet_work
, mt6360_chrdet_work
);
796 return dev_err_probe(&pdev
->dev
, ret
, "Failed to set delayed work\n");
798 ret
= device_property_read_u32(&pdev
->dev
, "richtek,vinovp-microvolt", &mci
->vinovp
);
800 dev_warn(&pdev
->dev
, "Failed to parse vinovp in DT, keep default 6.5v\n");
802 mci
->regmap
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
804 return dev_err_probe(&pdev
->dev
, -ENODEV
, "Failed to get parent regmap\n");
806 ret
= mt6360_chg_init_setting(mci
);
808 return dev_err_probe(&pdev
->dev
, ret
, "Failed to initial setting\n");
810 memcpy(&mci
->psy_desc
, &mt6360_charger_desc
, sizeof(mci
->psy_desc
));
811 mci
->psy_desc
.name
= dev_name(&pdev
->dev
);
812 charger_cfg
.drv_data
= mci
;
813 charger_cfg
.of_node
= pdev
->dev
.of_node
;
814 mci
->psy
= devm_power_supply_register(&pdev
->dev
,
815 &mci
->psy_desc
, &charger_cfg
);
816 if (IS_ERR(mci
->psy
))
817 return dev_err_probe(&pdev
->dev
, PTR_ERR(mci
->psy
),
818 "Failed to register power supply dev\n");
821 ret
= mt6360_chg_irq_register(pdev
);
823 return dev_err_probe(&pdev
->dev
, ret
, "Failed to register irqs\n");
825 config
.dev
= &pdev
->dev
;
826 config
.regmap
= mci
->regmap
;
827 mci
->otg_rdev
= devm_regulator_register(&pdev
->dev
, &mt6360_otg_rdesc
,
829 if (IS_ERR(mci
->otg_rdev
))
830 return PTR_ERR(mci
->otg_rdev
);
832 schedule_work(&mci
->chrdet_work
);
837 static const struct of_device_id __maybe_unused mt6360_charger_of_id
[] = {
838 { .compatible
= "mediatek,mt6360-chg", },
841 MODULE_DEVICE_TABLE(of
, mt6360_charger_of_id
);
843 static const struct platform_device_id mt6360_charger_id
[] = {
847 MODULE_DEVICE_TABLE(platform
, mt6360_charger_id
);
849 static struct platform_driver mt6360_charger_driver
= {
851 .name
= "mt6360-chg",
852 .of_match_table
= of_match_ptr(mt6360_charger_of_id
),
854 .probe
= mt6360_charger_probe
,
855 .id_table
= mt6360_charger_id
,
857 module_platform_driver(mt6360_charger_driver
);
859 MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
860 MODULE_DESCRIPTION("MT6360 Charger Driver");
861 MODULE_LICENSE("GPL");