1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2021 MediaTek Inc. 4 */ 5 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> 12 #include <linux/of.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> 18 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 34 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) 80 81 /* uV */ 82 #define MT6360_VMIVR_MIN 3900000 83 #define MT6360_VMIVR_MAX 13400000 84 #define MT6360_VMIVR_STEP 100000 85 /* uA */ 86 #define MT6360_ICHG_MIN 100000 87 #define MT6360_ICHG_MAX 5000000 88 #define MT6360_ICHG_STEP 100000 89 /* uV */ 90 #define MT6360_VOREG_MIN 3900000 91 #define MT6360_VOREG_MAX 4710000 92 #define MT6360_VOREG_STEP 10000 93 /* uA */ 94 #define MT6360_AICR_MIN 100000 95 #define MT6360_AICR_MAX 3250000 96 #define MT6360_AICR_STEP 50000 97 /* uA */ 98 #define MT6360_IPREC_MIN 100000 99 #define MT6360_IPREC_MAX 850000 100 #define MT6360_IPREC_STEP 50000 101 /* uA */ 102 #define MT6360_IEOC_MIN 100000 103 #define MT6360_IEOC_MAX 850000 104 #define MT6360_IEOC_STEP 50000 105 106 enum { 107 MT6360_RANGE_VMIVR, 108 MT6360_RANGE_ICHG, 109 MT6360_RANGE_VOREG, 110 MT6360_RANGE_AICR, 111 MT6360_RANGE_IPREC, 112 MT6360_RANGE_IEOC, 113 MT6360_RANGE_MAX, 114 }; 115 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), 123 }; 124 125 struct mt6360_chg_info { 126 struct device *dev; 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; 132 u32 vinovp; 133 bool pwr_rdy; 134 bool bc12_en; 135 int psy_usb_type; 136 struct work_struct chrdet_work; 137 }; 138 139 enum mt6360_iinlmtsel { 140 MT6360_IINLMTSEL_AICR_3250 = 0, 141 MT6360_IINLMTSEL_CHG_TYPE, 142 MT6360_IINLMTSEL_AICR, 143 MT6360_IINLMTSEL_LOWER_LEVEL, 144 }; 145 146 enum mt6360_pmu_chg_type { 147 MT6360_CHG_TYPE_NOVBUS = 0, 148 MT6360_CHG_TYPE_UNDER_GOING, 149 MT6360_CHG_TYPE_SDP, 150 MT6360_CHG_TYPE_SDPNSTD, 151 MT6360_CHG_TYPE_DCP, 152 MT6360_CHG_TYPE_CDP, 153 MT6360_CHG_TYPE_DISABLE_BC12, 154 MT6360_CHG_TYPE_MAX, 155 }; 156 157 static int mt6360_get_chrdet_ext_stat(struct mt6360_chg_info *mci, 158 bool *pwr_rdy) 159 { 160 int ret; 161 unsigned int regval; 162 163 ret = regmap_read(mci->regmap, MT6360_PMU_FOD_STAT, ®val); 164 if (ret < 0) 165 return ret; 166 *pwr_rdy = (regval & MT6360_CHRDET_EXT_MASK) ? true : false; 167 return 0; 168 } 169 170 static int mt6360_charger_get_online(struct mt6360_chg_info *mci, 171 union power_supply_propval *val) 172 { 173 int ret; 174 bool pwr_rdy; 175 176 ret = mt6360_get_chrdet_ext_stat(mci, &pwr_rdy); 177 if (ret < 0) 178 return ret; 179 val->intval = pwr_rdy ? true : false; 180 return 0; 181 } 182 183 static int mt6360_charger_get_status(struct mt6360_chg_info *mci, 184 union power_supply_propval *val) 185 { 186 int status, ret; 187 unsigned int regval; 188 bool pwr_rdy; 189 190 ret = mt6360_get_chrdet_ext_stat(mci, &pwr_rdy); 191 if (ret < 0) 192 return ret; 193 if (!pwr_rdy) { 194 status = POWER_SUPPLY_STATUS_DISCHARGING; 195 goto out; 196 } 197 198 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_STAT, ®val); 199 if (ret < 0) 200 return ret; 201 regval &= MT6360_CHG_STAT_MASK; 202 regval >>= MT6360_CHG_STAT_SHFT; 203 switch (regval) { 204 case 0x0: 205 status = POWER_SUPPLY_STATUS_NOT_CHARGING; 206 break; 207 case 0x1: 208 status = POWER_SUPPLY_STATUS_CHARGING; 209 break; 210 case 0x2: 211 status = POWER_SUPPLY_STATUS_FULL; 212 break; 213 default: 214 ret = -EIO; 215 } 216 out: 217 if (!ret) 218 val->intval = status; 219 return ret; 220 } 221 222 static int mt6360_charger_get_charge_type(struct mt6360_chg_info *mci, 223 union power_supply_propval *val) 224 { 225 int type, ret; 226 unsigned int regval; 227 u8 chg_stat; 228 229 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_STAT, ®val); 230 if (ret < 0) 231 return ret; 232 233 chg_stat = (regval & MT6360_CHG_STAT_MASK) >> MT6360_CHG_STAT_SHFT; 234 switch (chg_stat) { 235 case 0x01: /* Charge in Progress */ 236 if (regval & MT6360_VBAT_LVL_MASK) 237 type = POWER_SUPPLY_CHARGE_TYPE_FAST; 238 else 239 type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 240 break; 241 case 0x00: /* Not Charging */ 242 case 0x02: /* Charge Done */ 243 case 0x03: /* Charge Fault */ 244 default: 245 type = POWER_SUPPLY_CHARGE_TYPE_NONE; 246 break; 247 } 248 249 val->intval = type; 250 return 0; 251 } 252 253 static int mt6360_charger_get_ichg(struct mt6360_chg_info *mci, 254 union power_supply_propval *val) 255 { 256 int ret; 257 u32 sel, value; 258 259 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL7, &sel); 260 if (ret < 0) 261 return ret; 262 sel = (sel & MT6360_ICHG_MASK) >> MT6360_ICHG_SHFT; 263 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_ICHG], sel, &value); 264 if (!ret) 265 val->intval = value; 266 return ret; 267 } 268 269 static int mt6360_charger_get_max_ichg(struct mt6360_chg_info *mci, 270 union power_supply_propval *val) 271 { 272 val->intval = MT6360_ICHG_MAX; 273 return 0; 274 } 275 276 static int mt6360_charger_get_cv(struct mt6360_chg_info *mci, 277 union power_supply_propval *val) 278 { 279 int ret; 280 u32 sel, value; 281 282 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL4, &sel); 283 if (ret < 0) 284 return ret; 285 sel = (sel & MT6360_VOREG_MASK) >> MT6360_VOREG_SHFT; 286 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_VOREG], sel, &value); 287 if (!ret) 288 val->intval = value; 289 return ret; 290 } 291 292 static int mt6360_charger_get_max_cv(struct mt6360_chg_info *mci, 293 union power_supply_propval *val) 294 { 295 val->intval = MT6360_VOREG_MAX; 296 return 0; 297 } 298 299 static int mt6360_charger_get_aicr(struct mt6360_chg_info *mci, 300 union power_supply_propval *val) 301 { 302 int ret; 303 u32 sel, value; 304 305 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL3, &sel); 306 if (ret < 0) 307 return ret; 308 sel = (sel & MT6360_IAICR_MASK) >> MT6360_IAICR_SHFT; 309 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_AICR], sel, &value); 310 if (!ret) 311 val->intval = value; 312 return ret; 313 } 314 315 static int mt6360_charger_get_mivr(struct mt6360_chg_info *mci, 316 union power_supply_propval *val) 317 { 318 int ret; 319 u32 sel, value; 320 321 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL6, &sel); 322 if (ret < 0) 323 return ret; 324 sel = (sel & MT6360_VMIVR_MASK) >> MT6360_VMIVR_SHFT; 325 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_VMIVR], sel, &value); 326 if (!ret) 327 val->intval = value; 328 return ret; 329 } 330 331 static int mt6360_charger_get_iprechg(struct mt6360_chg_info *mci, 332 union power_supply_propval *val) 333 { 334 int ret; 335 u32 sel, value; 336 337 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL8, &sel); 338 if (ret < 0) 339 return ret; 340 sel = (sel & MT6360_IPREC_MASK) >> MT6360_IPREC_SHFT; 341 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_IPREC], sel, &value); 342 if (!ret) 343 val->intval = value; 344 return ret; 345 } 346 347 static int mt6360_charger_get_ieoc(struct mt6360_chg_info *mci, 348 union power_supply_propval *val) 349 { 350 int ret; 351 u32 sel, value; 352 353 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL9, &sel); 354 if (ret < 0) 355 return ret; 356 sel = (sel & MT6360_IEOC_MASK) >> MT6360_IEOC_SHFT; 357 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_IEOC], sel, &value); 358 if (!ret) 359 val->intval = value; 360 return ret; 361 } 362 363 static int mt6360_charger_set_online(struct mt6360_chg_info *mci, 364 const union power_supply_propval *val) 365 { 366 u8 force_sleep = val->intval ? 0 : 1; 367 368 return regmap_update_bits(mci->regmap, 369 MT6360_PMU_CHG_CTRL1, 370 MT6360_FSLP_MASK, 371 force_sleep << MT6360_FSLP_SHFT); 372 } 373 374 static int mt6360_charger_set_ichg(struct mt6360_chg_info *mci, 375 const union power_supply_propval *val) 376 { 377 u32 sel; 378 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, 382 MT6360_ICHG_MASK, 383 sel << MT6360_ICHG_SHFT); 384 } 385 386 static int mt6360_charger_set_cv(struct mt6360_chg_info *mci, 387 const union power_supply_propval *val) 388 { 389 u32 sel; 390 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, 394 MT6360_VOREG_MASK, 395 sel << MT6360_VOREG_SHFT); 396 } 397 398 static int mt6360_charger_set_aicr(struct mt6360_chg_info *mci, 399 const union power_supply_propval *val) 400 { 401 u32 sel; 402 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, 406 MT6360_IAICR_MASK, 407 sel << MT6360_IAICR_SHFT); 408 } 409 410 static int mt6360_charger_set_mivr(struct mt6360_chg_info *mci, 411 const union power_supply_propval *val) 412 { 413 u32 sel; 414 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, 418 MT6360_VMIVR_MASK, 419 sel << MT6360_VMIVR_SHFT); 420 } 421 422 static int mt6360_charger_set_iprechg(struct mt6360_chg_info *mci, 423 const union power_supply_propval *val) 424 { 425 u32 sel; 426 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, 430 MT6360_IPREC_MASK, 431 sel << MT6360_IPREC_SHFT); 432 } 433 434 static int mt6360_charger_set_ieoc(struct mt6360_chg_info *mci, 435 const union power_supply_propval *val) 436 { 437 u32 sel; 438 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, 442 MT6360_IEOC_MASK, 443 sel << MT6360_IEOC_SHFT); 444 } 445 446 static int mt6360_charger_get_property(struct power_supply *psy, 447 enum power_supply_property psp, 448 union power_supply_propval *val) 449 { 450 struct mt6360_chg_info *mci = power_supply_get_drvdata(psy); 451 int ret = 0; 452 453 switch (psp) { 454 case POWER_SUPPLY_PROP_ONLINE: 455 ret = mt6360_charger_get_online(mci, val); 456 break; 457 case POWER_SUPPLY_PROP_STATUS: 458 ret = mt6360_charger_get_status(mci, val); 459 break; 460 case POWER_SUPPLY_PROP_CHARGE_TYPE: 461 ret = mt6360_charger_get_charge_type(mci, val); 462 break; 463 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 464 ret = mt6360_charger_get_ichg(mci, val); 465 break; 466 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 467 ret = mt6360_charger_get_max_ichg(mci, val); 468 break; 469 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 470 ret = mt6360_charger_get_cv(mci, val); 471 break; 472 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 473 ret = mt6360_charger_get_max_cv(mci, val); 474 break; 475 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 476 ret = mt6360_charger_get_aicr(mci, val); 477 break; 478 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 479 ret = mt6360_charger_get_mivr(mci, val); 480 break; 481 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 482 ret = mt6360_charger_get_iprechg(mci, val); 483 break; 484 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 485 ret = mt6360_charger_get_ieoc(mci, val); 486 break; 487 case POWER_SUPPLY_PROP_USB_TYPE: 488 val->intval = mci->psy_usb_type; 489 break; 490 default: 491 ret = -ENODATA; 492 } 493 return ret; 494 } 495 496 static int mt6360_charger_set_property(struct power_supply *psy, 497 enum power_supply_property psp, 498 const union power_supply_propval *val) 499 { 500 struct mt6360_chg_info *mci = power_supply_get_drvdata(psy); 501 int ret; 502 503 switch (psp) { 504 case POWER_SUPPLY_PROP_ONLINE: 505 ret = mt6360_charger_set_online(mci, val); 506 break; 507 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 508 ret = mt6360_charger_set_ichg(mci, val); 509 break; 510 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 511 ret = mt6360_charger_set_cv(mci, val); 512 break; 513 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 514 ret = mt6360_charger_set_aicr(mci, val); 515 break; 516 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 517 ret = mt6360_charger_set_mivr(mci, val); 518 break; 519 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 520 ret = mt6360_charger_set_iprechg(mci, val); 521 break; 522 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 523 ret = mt6360_charger_set_ieoc(mci, val); 524 break; 525 default: 526 ret = -EINVAL; 527 } 528 return ret; 529 } 530 531 static int mt6360_charger_property_is_writeable(struct power_supply *psy, 532 enum power_supply_property psp) 533 { 534 switch (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: 542 return 1; 543 default: 544 return 0; 545 } 546 } 547 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, 561 }; 562 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), 574 }; 575 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, 583 }; 584 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, 591 .min_uV = 4425000, 592 .uV_step = 25000, 593 .n_voltages = 57, 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, 598 }; 599 600 static irqreturn_t mt6360_pmu_attach_i_handler(int irq, void *data) 601 { 602 struct mt6360_chg_info *mci = data; 603 int ret; 604 unsigned int usb_status; 605 int last_usb_type; 606 607 mutex_lock(&mci->chgdet_lock); 608 if (!mci->bc12_en) { 609 dev_warn(mci->dev, "Received attach interrupt, bc12 disabled, ignore irq\n"); 610 goto out; 611 } 612 last_usb_type = mci->psy_usb_type; 613 /* Plug in */ 614 ret = regmap_read(mci->regmap, MT6360_PMU_USB_STATUS1, &usb_status); 615 if (ret < 0) 616 goto out; 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"); 622 goto out; 623 case MT6360_CHG_TYPE_UNDER_GOING: 624 dev_dbg(mci->dev, "Received attach interrupt, under going...\n"); 625 goto out; 626 case MT6360_CHG_TYPE_SDP: 627 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP; 628 break; 629 case MT6360_CHG_TYPE_SDPNSTD: 630 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP; 631 break; 632 case MT6360_CHG_TYPE_CDP: 633 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_CDP; 634 break; 635 case MT6360_CHG_TYPE_DCP: 636 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_DCP; 637 break; 638 case MT6360_CHG_TYPE_DISABLE_BC12: 639 dev_dbg(mci->dev, "Received attach interrupt, bc12 detect not enable\n"); 640 goto out; 641 default: 642 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; 643 dev_dbg(mci->dev, "Received attach interrupt, reserved address\n"); 644 goto out; 645 } 646 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); 650 out: 651 mutex_unlock(&mci->chgdet_lock); 652 return IRQ_HANDLED; 653 } 654 655 static void mt6360_handle_chrdet_ext_evt(struct mt6360_chg_info *mci) 656 { 657 int ret; 658 bool pwr_rdy; 659 660 mutex_lock(&mci->chgdet_lock); 661 ret = mt6360_get_chrdet_ext_stat(mci, &pwr_rdy); 662 if (ret < 0) 663 goto out; 664 if (mci->pwr_rdy == pwr_rdy) { 665 dev_dbg(mci->dev, "Received vbus interrupt, pwr_rdy is same(%d)\n", pwr_rdy); 666 goto out; 667 } 668 mci->pwr_rdy = pwr_rdy; 669 dev_dbg(mci->dev, "Received vbus interrupt, pwr_rdy = %d\n", pwr_rdy); 670 if (!pwr_rdy) { 671 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; 672 power_supply_changed(mci->psy); 673 674 } 675 ret = regmap_update_bits(mci->regmap, 676 MT6360_PMU_DEVICE_TYPE, 677 MT6360_USBCHGEN_MASK, 678 pwr_rdy ? MT6360_USBCHGEN_MASK : 0); 679 if (ret < 0) 680 goto out; 681 mci->bc12_en = pwr_rdy; 682 out: 683 mutex_unlock(&mci->chgdet_lock); 684 } 685 686 static void mt6360_chrdet_work(struct work_struct *work) 687 { 688 struct mt6360_chg_info *mci = (struct mt6360_chg_info *)container_of( 689 work, struct mt6360_chg_info, chrdet_work); 690 691 mt6360_handle_chrdet_ext_evt(mci); 692 } 693 694 static irqreturn_t mt6360_pmu_chrdet_ext_evt_handler(int irq, void *data) 695 { 696 struct mt6360_chg_info *mci = data; 697 698 mt6360_handle_chrdet_ext_evt(mci); 699 return IRQ_HANDLED; 700 } 701 702 static int mt6360_chg_irq_register(struct platform_device *pdev) 703 { 704 const struct { 705 const char *name; 706 irq_handler_t handler; 707 } irq_descs[] = { 708 { "attach_i", mt6360_pmu_attach_i_handler }, 709 { "chrdet_ext_evt", mt6360_pmu_chrdet_ext_evt_handler } 710 }; 711 int i, ret; 712 713 for (i = 0; i < ARRAY_SIZE(irq_descs); i++) { 714 ret = platform_get_irq_byname(pdev, irq_descs[i].name); 715 if (ret < 0) 716 return ret; 717 718 ret = devm_request_threaded_irq(&pdev->dev, ret, NULL, 719 irq_descs[i].handler, 720 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 721 irq_descs[i].name, 722 platform_get_drvdata(pdev)); 723 if (ret < 0) 724 return dev_err_probe(&pdev->dev, ret, "Failed to request %s irq\n", 725 irq_descs[i].name); 726 } 727 728 return 0; 729 } 730 731 static u32 mt6360_vinovp_trans_to_sel(u32 val) 732 { 733 u32 vinovp_tbl[] = { 5500000, 6500000, 11000000, 14500000 }; 734 int i; 735 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]) 739 break; 740 } 741 return i; 742 } 743 744 static int mt6360_chg_init_setting(struct mt6360_chg_info *mci) 745 { 746 int ret; 747 u32 sel; 748 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); 752 if (ret) 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); 756 if (ret) 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); 762 if (ret) 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); 768 if (ret) 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); 773 if (ret) 774 return dev_err_probe(mci->dev, ret, 775 "%s: Failed to config otg oc to 3A\n", __func__); 776 return 0; 777 } 778 779 static int mt6360_charger_probe(struct platform_device *pdev) 780 { 781 struct mt6360_chg_info *mci; 782 struct power_supply_config charger_cfg = {}; 783 struct regulator_config config = { }; 784 int ret; 785 786 mci = devm_kzalloc(&pdev->dev, sizeof(*mci), GFP_KERNEL); 787 if (!mci) 788 return -ENOMEM; 789 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); 795 if (ret) 796 return dev_err_probe(&pdev->dev, ret, "Failed to set delayed work\n"); 797 798 ret = device_property_read_u32(&pdev->dev, "richtek,vinovp-microvolt", &mci->vinovp); 799 if (ret) 800 dev_warn(&pdev->dev, "Failed to parse vinovp in DT, keep default 6.5v\n"); 801 802 mci->regmap = dev_get_regmap(pdev->dev.parent, NULL); 803 if (!mci->regmap) 804 return dev_err_probe(&pdev->dev, -ENODEV, "Failed to get parent regmap\n"); 805 806 ret = mt6360_chg_init_setting(mci); 807 if (ret) 808 return dev_err_probe(&pdev->dev, ret, "Failed to initial setting\n"); 809 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"); 819 820 821 ret = mt6360_chg_irq_register(pdev); 822 if (ret) 823 return dev_err_probe(&pdev->dev, ret, "Failed to register irqs\n"); 824 825 config.dev = &pdev->dev; 826 config.regmap = mci->regmap; 827 mci->otg_rdev = devm_regulator_register(&pdev->dev, &mt6360_otg_rdesc, 828 &config); 829 if (IS_ERR(mci->otg_rdev)) 830 return PTR_ERR(mci->otg_rdev); 831 832 schedule_work(&mci->chrdet_work); 833 834 return 0; 835 } 836 837 static const struct of_device_id __maybe_unused mt6360_charger_of_id[] = { 838 { .compatible = "mediatek,mt6360-chg", }, 839 {}, 840 }; 841 MODULE_DEVICE_TABLE(of, mt6360_charger_of_id); 842 843 static const struct platform_device_id mt6360_charger_id[] = { 844 { "mt6360-chg", 0 }, 845 {}, 846 }; 847 MODULE_DEVICE_TABLE(platform, mt6360_charger_id); 848 849 static struct platform_driver mt6360_charger_driver = { 850 .driver = { 851 .name = "mt6360-chg", 852 .of_match_table = of_match_ptr(mt6360_charger_of_id), 853 }, 854 .probe = mt6360_charger_probe, 855 .id_table = mt6360_charger_id, 856 }; 857 module_platform_driver(mt6360_charger_driver); 858 859 MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>"); 860 MODULE_DESCRIPTION("MT6360 Charger Driver"); 861 MODULE_LICENSE("GPL"); 862