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 #define MT6360_LINEAR_RANGE(idx, _min, _min_sel, _max_sel, _step) \ 117 [idx] = REGULATOR_LINEAR_RANGE(_min, _min_sel, _max_sel, _step) 118 119 static const struct linear_range mt6360_chg_range[MT6360_RANGE_MAX] = { 120 MT6360_LINEAR_RANGE(MT6360_RANGE_VMIVR, 3900000, 0, 0x5F, 100000), 121 MT6360_LINEAR_RANGE(MT6360_RANGE_ICHG, 100000, 0, 0x31, 100000), 122 MT6360_LINEAR_RANGE(MT6360_RANGE_VOREG, 3900000, 0, 0x51, 10000), 123 MT6360_LINEAR_RANGE(MT6360_RANGE_AICR, 100000, 0, 0x3F, 50000), 124 MT6360_LINEAR_RANGE(MT6360_RANGE_IPREC, 100000, 0, 0x0F, 50000), 125 MT6360_LINEAR_RANGE(MT6360_RANGE_IEOC, 100000, 0, 0x0F, 50000), 126 }; 127 128 struct mt6360_chg_info { 129 struct device *dev; 130 struct regmap *regmap; 131 struct power_supply_desc psy_desc; 132 struct power_supply *psy; 133 struct regulator_dev *otg_rdev; 134 struct mutex chgdet_lock; 135 u32 vinovp; 136 bool pwr_rdy; 137 bool bc12_en; 138 int psy_usb_type; 139 struct work_struct chrdet_work; 140 }; 141 142 enum mt6360_iinlmtsel { 143 MT6360_IINLMTSEL_AICR_3250 = 0, 144 MT6360_IINLMTSEL_CHG_TYPE, 145 MT6360_IINLMTSEL_AICR, 146 MT6360_IINLMTSEL_LOWER_LEVEL, 147 }; 148 149 enum mt6360_pmu_chg_type { 150 MT6360_CHG_TYPE_NOVBUS = 0, 151 MT6360_CHG_TYPE_UNDER_GOING, 152 MT6360_CHG_TYPE_SDP, 153 MT6360_CHG_TYPE_SDPNSTD, 154 MT6360_CHG_TYPE_DCP, 155 MT6360_CHG_TYPE_CDP, 156 MT6360_CHG_TYPE_DISABLE_BC12, 157 MT6360_CHG_TYPE_MAX, 158 }; 159 160 static enum power_supply_usb_type mt6360_charger_usb_types[] = { 161 POWER_SUPPLY_USB_TYPE_UNKNOWN, 162 POWER_SUPPLY_USB_TYPE_SDP, 163 POWER_SUPPLY_USB_TYPE_DCP, 164 POWER_SUPPLY_USB_TYPE_CDP, 165 }; 166 167 static int mt6360_get_chrdet_ext_stat(struct mt6360_chg_info *mci, 168 bool *pwr_rdy) 169 { 170 int ret; 171 unsigned int regval; 172 173 ret = regmap_read(mci->regmap, MT6360_PMU_FOD_STAT, ®val); 174 if (ret < 0) 175 return ret; 176 *pwr_rdy = (regval & MT6360_CHRDET_EXT_MASK) ? true : false; 177 return 0; 178 } 179 180 static int mt6360_charger_get_online(struct mt6360_chg_info *mci, 181 union power_supply_propval *val) 182 { 183 int ret; 184 bool pwr_rdy; 185 186 ret = mt6360_get_chrdet_ext_stat(mci, &pwr_rdy); 187 if (ret < 0) 188 return ret; 189 val->intval = pwr_rdy ? true : false; 190 return 0; 191 } 192 193 static int mt6360_charger_get_status(struct mt6360_chg_info *mci, 194 union power_supply_propval *val) 195 { 196 int status, ret; 197 unsigned int regval; 198 bool pwr_rdy; 199 200 ret = mt6360_get_chrdet_ext_stat(mci, &pwr_rdy); 201 if (ret < 0) 202 return ret; 203 if (!pwr_rdy) { 204 status = POWER_SUPPLY_STATUS_DISCHARGING; 205 goto out; 206 } 207 208 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_STAT, ®val); 209 if (ret < 0) 210 return ret; 211 regval &= MT6360_CHG_STAT_MASK; 212 regval >>= MT6360_CHG_STAT_SHFT; 213 switch (regval) { 214 case 0x0: 215 status = POWER_SUPPLY_STATUS_NOT_CHARGING; 216 break; 217 case 0x1: 218 status = POWER_SUPPLY_STATUS_CHARGING; 219 break; 220 case 0x2: 221 status = POWER_SUPPLY_STATUS_FULL; 222 break; 223 default: 224 ret = -EIO; 225 } 226 out: 227 if (!ret) 228 val->intval = status; 229 return ret; 230 } 231 232 static int mt6360_charger_get_charge_type(struct mt6360_chg_info *mci, 233 union power_supply_propval *val) 234 { 235 int type, ret; 236 unsigned int regval; 237 u8 chg_stat; 238 239 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_STAT, ®val); 240 if (ret < 0) 241 return ret; 242 243 chg_stat = (regval & MT6360_CHG_STAT_MASK) >> MT6360_CHG_STAT_SHFT; 244 switch (chg_stat) { 245 case 0x01: /* Charge in Progress */ 246 if (regval & MT6360_VBAT_LVL_MASK) 247 type = POWER_SUPPLY_CHARGE_TYPE_FAST; 248 else 249 type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 250 break; 251 case 0x00: /* Not Charging */ 252 case 0x02: /* Charge Done */ 253 case 0x03: /* Charge Fault */ 254 default: 255 type = POWER_SUPPLY_CHARGE_TYPE_NONE; 256 break; 257 } 258 259 val->intval = type; 260 return 0; 261 } 262 263 static int mt6360_charger_get_ichg(struct mt6360_chg_info *mci, 264 union power_supply_propval *val) 265 { 266 int ret; 267 u32 sel, value; 268 269 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL7, &sel); 270 if (ret < 0) 271 return ret; 272 sel = (sel & MT6360_ICHG_MASK) >> MT6360_ICHG_SHFT; 273 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_ICHG], sel, &value); 274 if (!ret) 275 val->intval = value; 276 return ret; 277 } 278 279 static int mt6360_charger_get_max_ichg(struct mt6360_chg_info *mci, 280 union power_supply_propval *val) 281 { 282 val->intval = MT6360_ICHG_MAX; 283 return 0; 284 } 285 286 static int mt6360_charger_get_cv(struct mt6360_chg_info *mci, 287 union power_supply_propval *val) 288 { 289 int ret; 290 u32 sel, value; 291 292 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL4, &sel); 293 if (ret < 0) 294 return ret; 295 sel = (sel & MT6360_VOREG_MASK) >> MT6360_VOREG_SHFT; 296 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_VOREG], sel, &value); 297 if (!ret) 298 val->intval = value; 299 return ret; 300 } 301 302 static int mt6360_charger_get_max_cv(struct mt6360_chg_info *mci, 303 union power_supply_propval *val) 304 { 305 val->intval = MT6360_VOREG_MAX; 306 return 0; 307 } 308 309 static int mt6360_charger_get_aicr(struct mt6360_chg_info *mci, 310 union power_supply_propval *val) 311 { 312 int ret; 313 u32 sel, value; 314 315 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL3, &sel); 316 if (ret < 0) 317 return ret; 318 sel = (sel & MT6360_IAICR_MASK) >> MT6360_IAICR_SHFT; 319 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_AICR], sel, &value); 320 if (!ret) 321 val->intval = value; 322 return ret; 323 } 324 325 static int mt6360_charger_get_mivr(struct mt6360_chg_info *mci, 326 union power_supply_propval *val) 327 { 328 int ret; 329 u32 sel, value; 330 331 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL6, &sel); 332 if (ret < 0) 333 return ret; 334 sel = (sel & MT6360_VMIVR_MASK) >> MT6360_VMIVR_SHFT; 335 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_VMIVR], sel, &value); 336 if (!ret) 337 val->intval = value; 338 return ret; 339 } 340 341 static int mt6360_charger_get_iprechg(struct mt6360_chg_info *mci, 342 union power_supply_propval *val) 343 { 344 int ret; 345 u32 sel, value; 346 347 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL8, &sel); 348 if (ret < 0) 349 return ret; 350 sel = (sel & MT6360_IPREC_MASK) >> MT6360_IPREC_SHFT; 351 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_IPREC], sel, &value); 352 if (!ret) 353 val->intval = value; 354 return ret; 355 } 356 357 static int mt6360_charger_get_ieoc(struct mt6360_chg_info *mci, 358 union power_supply_propval *val) 359 { 360 int ret; 361 u32 sel, value; 362 363 ret = regmap_read(mci->regmap, MT6360_PMU_CHG_CTRL9, &sel); 364 if (ret < 0) 365 return ret; 366 sel = (sel & MT6360_IEOC_MASK) >> MT6360_IEOC_SHFT; 367 ret = linear_range_get_value(&mt6360_chg_range[MT6360_RANGE_IEOC], sel, &value); 368 if (!ret) 369 val->intval = value; 370 return ret; 371 } 372 373 static int mt6360_charger_set_online(struct mt6360_chg_info *mci, 374 const union power_supply_propval *val) 375 { 376 u8 force_sleep = val->intval ? 0 : 1; 377 378 return regmap_update_bits(mci->regmap, 379 MT6360_PMU_CHG_CTRL1, 380 MT6360_FSLP_MASK, 381 force_sleep << MT6360_FSLP_SHFT); 382 } 383 384 static int mt6360_charger_set_ichg(struct mt6360_chg_info *mci, 385 const union power_supply_propval *val) 386 { 387 u32 sel; 388 389 linear_range_get_selector_within(&mt6360_chg_range[MT6360_RANGE_ICHG], val->intval, &sel); 390 return regmap_update_bits(mci->regmap, 391 MT6360_PMU_CHG_CTRL7, 392 MT6360_ICHG_MASK, 393 sel << MT6360_ICHG_SHFT); 394 } 395 396 static int mt6360_charger_set_cv(struct mt6360_chg_info *mci, 397 const union power_supply_propval *val) 398 { 399 u32 sel; 400 401 linear_range_get_selector_within(&mt6360_chg_range[MT6360_RANGE_VOREG], val->intval, &sel); 402 return regmap_update_bits(mci->regmap, 403 MT6360_PMU_CHG_CTRL4, 404 MT6360_VOREG_MASK, 405 sel << MT6360_VOREG_SHFT); 406 } 407 408 static int mt6360_charger_set_aicr(struct mt6360_chg_info *mci, 409 const union power_supply_propval *val) 410 { 411 u32 sel; 412 413 linear_range_get_selector_within(&mt6360_chg_range[MT6360_RANGE_AICR], val->intval, &sel); 414 return regmap_update_bits(mci->regmap, 415 MT6360_PMU_CHG_CTRL3, 416 MT6360_IAICR_MASK, 417 sel << MT6360_IAICR_SHFT); 418 } 419 420 static int mt6360_charger_set_mivr(struct mt6360_chg_info *mci, 421 const union power_supply_propval *val) 422 { 423 u32 sel; 424 425 linear_range_get_selector_within(&mt6360_chg_range[MT6360_RANGE_VMIVR], val->intval, &sel); 426 return regmap_update_bits(mci->regmap, 427 MT6360_PMU_CHG_CTRL3, 428 MT6360_VMIVR_MASK, 429 sel << MT6360_VMIVR_SHFT); 430 } 431 432 static int mt6360_charger_set_iprechg(struct mt6360_chg_info *mci, 433 const union power_supply_propval *val) 434 { 435 u32 sel; 436 437 linear_range_get_selector_within(&mt6360_chg_range[MT6360_RANGE_IPREC], val->intval, &sel); 438 return regmap_update_bits(mci->regmap, 439 MT6360_PMU_CHG_CTRL8, 440 MT6360_IPREC_MASK, 441 sel << MT6360_IPREC_SHFT); 442 } 443 444 static int mt6360_charger_set_ieoc(struct mt6360_chg_info *mci, 445 const union power_supply_propval *val) 446 { 447 u32 sel; 448 449 linear_range_get_selector_within(&mt6360_chg_range[MT6360_RANGE_IEOC], val->intval, &sel); 450 return regmap_update_bits(mci->regmap, 451 MT6360_PMU_CHG_CTRL9, 452 MT6360_IEOC_MASK, 453 sel << MT6360_IEOC_SHFT); 454 } 455 456 static int mt6360_charger_get_property(struct power_supply *psy, 457 enum power_supply_property psp, 458 union power_supply_propval *val) 459 { 460 struct mt6360_chg_info *mci = power_supply_get_drvdata(psy); 461 int ret = 0; 462 463 switch (psp) { 464 case POWER_SUPPLY_PROP_ONLINE: 465 ret = mt6360_charger_get_online(mci, val); 466 break; 467 case POWER_SUPPLY_PROP_STATUS: 468 ret = mt6360_charger_get_status(mci, val); 469 break; 470 case POWER_SUPPLY_PROP_CHARGE_TYPE: 471 ret = mt6360_charger_get_charge_type(mci, val); 472 break; 473 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 474 ret = mt6360_charger_get_ichg(mci, val); 475 break; 476 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: 477 ret = mt6360_charger_get_max_ichg(mci, val); 478 break; 479 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 480 ret = mt6360_charger_get_cv(mci, val); 481 break; 482 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 483 ret = mt6360_charger_get_max_cv(mci, val); 484 break; 485 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 486 ret = mt6360_charger_get_aicr(mci, val); 487 break; 488 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 489 ret = mt6360_charger_get_mivr(mci, val); 490 break; 491 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 492 ret = mt6360_charger_get_iprechg(mci, val); 493 break; 494 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 495 ret = mt6360_charger_get_ieoc(mci, val); 496 break; 497 case POWER_SUPPLY_PROP_USB_TYPE: 498 val->intval = mci->psy_usb_type; 499 break; 500 default: 501 ret = -ENODATA; 502 } 503 return ret; 504 } 505 506 static int mt6360_charger_set_property(struct power_supply *psy, 507 enum power_supply_property psp, 508 const union power_supply_propval *val) 509 { 510 struct mt6360_chg_info *mci = power_supply_get_drvdata(psy); 511 int ret; 512 513 switch (psp) { 514 case POWER_SUPPLY_PROP_ONLINE: 515 ret = mt6360_charger_set_online(mci, val); 516 break; 517 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 518 ret = mt6360_charger_set_ichg(mci, val); 519 break; 520 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 521 ret = mt6360_charger_set_cv(mci, val); 522 break; 523 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 524 ret = mt6360_charger_set_aicr(mci, val); 525 break; 526 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 527 ret = mt6360_charger_set_mivr(mci, val); 528 break; 529 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 530 ret = mt6360_charger_set_iprechg(mci, val); 531 break; 532 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 533 ret = mt6360_charger_set_ieoc(mci, val); 534 break; 535 default: 536 ret = -EINVAL; 537 } 538 return ret; 539 } 540 541 static int mt6360_charger_property_is_writeable(struct power_supply *psy, 542 enum power_supply_property psp) 543 { 544 switch (psp) { 545 case POWER_SUPPLY_PROP_ONLINE: 546 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 547 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: 548 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: 549 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT: 550 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT: 551 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: 552 return 1; 553 default: 554 return 0; 555 } 556 } 557 558 static enum power_supply_property mt6360_charger_properties[] = { 559 POWER_SUPPLY_PROP_ONLINE, 560 POWER_SUPPLY_PROP_STATUS, 561 POWER_SUPPLY_PROP_CHARGE_TYPE, 562 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 563 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, 564 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, 565 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 566 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 567 POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, 568 POWER_SUPPLY_PROP_PRECHARGE_CURRENT, 569 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, 570 POWER_SUPPLY_PROP_USB_TYPE, 571 }; 572 573 static const struct power_supply_desc mt6360_charger_desc = { 574 .type = POWER_SUPPLY_TYPE_USB, 575 .properties = mt6360_charger_properties, 576 .num_properties = ARRAY_SIZE(mt6360_charger_properties), 577 .get_property = mt6360_charger_get_property, 578 .set_property = mt6360_charger_set_property, 579 .property_is_writeable = mt6360_charger_property_is_writeable, 580 .usb_types = mt6360_charger_usb_types, 581 .num_usb_types = ARRAY_SIZE(mt6360_charger_usb_types), 582 }; 583 584 static const struct regulator_ops mt6360_chg_otg_ops = { 585 .list_voltage = regulator_list_voltage_linear, 586 .enable = regulator_enable_regmap, 587 .disable = regulator_disable_regmap, 588 .is_enabled = regulator_is_enabled_regmap, 589 .set_voltage_sel = regulator_set_voltage_sel_regmap, 590 .get_voltage_sel = regulator_get_voltage_sel_regmap, 591 }; 592 593 static const struct regulator_desc mt6360_otg_rdesc = { 594 .of_match = "usb-otg-vbus", 595 .name = "usb-otg-vbus", 596 .ops = &mt6360_chg_otg_ops, 597 .owner = THIS_MODULE, 598 .type = REGULATOR_VOLTAGE, 599 .min_uV = 4425000, 600 .uV_step = 25000, 601 .n_voltages = 57, 602 .vsel_reg = MT6360_PMU_CHG_CTRL5, 603 .vsel_mask = MT6360_VOBST_MASK, 604 .enable_reg = MT6360_PMU_CHG_CTRL1, 605 .enable_mask = MT6360_OPA_MODE_MASK, 606 }; 607 608 static irqreturn_t mt6360_pmu_attach_i_handler(int irq, void *data) 609 { 610 struct mt6360_chg_info *mci = data; 611 int ret; 612 unsigned int usb_status; 613 int last_usb_type; 614 615 mutex_lock(&mci->chgdet_lock); 616 if (!mci->bc12_en) { 617 dev_warn(mci->dev, "Received attach interrupt, bc12 disabled, ignore irq\n"); 618 goto out; 619 } 620 last_usb_type = mci->psy_usb_type; 621 /* Plug in */ 622 ret = regmap_read(mci->regmap, MT6360_PMU_USB_STATUS1, &usb_status); 623 if (ret < 0) 624 goto out; 625 usb_status &= MT6360_USB_STATUS_MASK; 626 usb_status >>= MT6360_USB_STATUS_SHFT; 627 switch (usb_status) { 628 case MT6360_CHG_TYPE_NOVBUS: 629 dev_dbg(mci->dev, "Received attach interrupt, no vbus\n"); 630 goto out; 631 case MT6360_CHG_TYPE_UNDER_GOING: 632 dev_dbg(mci->dev, "Received attach interrupt, under going...\n"); 633 goto out; 634 case MT6360_CHG_TYPE_SDP: 635 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP; 636 break; 637 case MT6360_CHG_TYPE_SDPNSTD: 638 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP; 639 break; 640 case MT6360_CHG_TYPE_CDP: 641 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_CDP; 642 break; 643 case MT6360_CHG_TYPE_DCP: 644 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_DCP; 645 break; 646 case MT6360_CHG_TYPE_DISABLE_BC12: 647 dev_dbg(mci->dev, "Received attach interrupt, bc12 detect not enable\n"); 648 goto out; 649 default: 650 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; 651 dev_dbg(mci->dev, "Received attach interrupt, reserved address\n"); 652 goto out; 653 } 654 655 dev_dbg(mci->dev, "Received attach interrupt, chg_type = %d\n", mci->psy_usb_type); 656 if (last_usb_type != mci->psy_usb_type) 657 power_supply_changed(mci->psy); 658 out: 659 mutex_unlock(&mci->chgdet_lock); 660 return IRQ_HANDLED; 661 } 662 663 static void mt6360_handle_chrdet_ext_evt(struct mt6360_chg_info *mci) 664 { 665 int ret; 666 bool pwr_rdy; 667 668 mutex_lock(&mci->chgdet_lock); 669 ret = mt6360_get_chrdet_ext_stat(mci, &pwr_rdy); 670 if (ret < 0) 671 goto out; 672 if (mci->pwr_rdy == pwr_rdy) { 673 dev_dbg(mci->dev, "Received vbus interrupt, pwr_rdy is same(%d)\n", pwr_rdy); 674 goto out; 675 } 676 mci->pwr_rdy = pwr_rdy; 677 dev_dbg(mci->dev, "Received vbus interrupt, pwr_rdy = %d\n", pwr_rdy); 678 if (!pwr_rdy) { 679 mci->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN; 680 power_supply_changed(mci->psy); 681 682 } 683 ret = regmap_update_bits(mci->regmap, 684 MT6360_PMU_DEVICE_TYPE, 685 MT6360_USBCHGEN_MASK, 686 pwr_rdy ? MT6360_USBCHGEN_MASK : 0); 687 if (ret < 0) 688 goto out; 689 mci->bc12_en = pwr_rdy; 690 out: 691 mutex_unlock(&mci->chgdet_lock); 692 } 693 694 static void mt6360_chrdet_work(struct work_struct *work) 695 { 696 struct mt6360_chg_info *mci = (struct mt6360_chg_info *)container_of( 697 work, struct mt6360_chg_info, chrdet_work); 698 699 mt6360_handle_chrdet_ext_evt(mci); 700 } 701 702 static irqreturn_t mt6360_pmu_chrdet_ext_evt_handler(int irq, void *data) 703 { 704 struct mt6360_chg_info *mci = data; 705 706 mt6360_handle_chrdet_ext_evt(mci); 707 return IRQ_HANDLED; 708 } 709 710 static int mt6360_chg_irq_register(struct platform_device *pdev) 711 { 712 const struct { 713 const char *name; 714 irq_handler_t handler; 715 } irq_descs[] = { 716 { "attach_i", mt6360_pmu_attach_i_handler }, 717 { "chrdet_ext_evt", mt6360_pmu_chrdet_ext_evt_handler } 718 }; 719 int i, ret; 720 721 for (i = 0; i < ARRAY_SIZE(irq_descs); i++) { 722 ret = platform_get_irq_byname(pdev, irq_descs[i].name); 723 if (ret < 0) 724 return ret; 725 726 ret = devm_request_threaded_irq(&pdev->dev, ret, NULL, 727 irq_descs[i].handler, 728 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 729 irq_descs[i].name, 730 platform_get_drvdata(pdev)); 731 if (ret < 0) 732 return dev_err_probe(&pdev->dev, ret, "Failed to request %s irq\n", 733 irq_descs[i].name); 734 } 735 736 return 0; 737 } 738 739 static u32 mt6360_vinovp_trans_to_sel(u32 val) 740 { 741 u32 vinovp_tbl[] = { 5500000, 6500000, 11000000, 14500000 }; 742 int i; 743 744 /* Select the smaller and equal supported value */ 745 for (i = 0; i < ARRAY_SIZE(vinovp_tbl)-1; i++) { 746 if (val < vinovp_tbl[i+1]) 747 break; 748 } 749 return i; 750 } 751 752 static int mt6360_chg_init_setting(struct mt6360_chg_info *mci) 753 { 754 int ret; 755 u32 sel; 756 757 sel = mt6360_vinovp_trans_to_sel(mci->vinovp); 758 ret = regmap_update_bits(mci->regmap, MT6360_PMU_CHG_CTRL19, 759 MT6360_VINOVP_MASK, sel << MT6360_VINOVP_SHFT); 760 if (ret) 761 return dev_err_probe(mci->dev, ret, "%s: Failed to apply vinovp\n", __func__); 762 ret = regmap_update_bits(mci->regmap, MT6360_PMU_DEVICE_TYPE, 763 MT6360_USBCHGEN_MASK, 0); 764 if (ret) 765 return dev_err_probe(mci->dev, ret, "%s: Failed to disable bc12\n", __func__); 766 ret = regmap_update_bits(mci->regmap, MT6360_PMU_CHG_CTRL2, 767 MT6360_IINLMTSEL_MASK, 768 MT6360_IINLMTSEL_AICR << 769 MT6360_IINLMTSEL_SHFT); 770 if (ret) 771 return dev_err_probe(mci->dev, ret, 772 "%s: Failed to switch iinlmtsel to aicr\n", __func__); 773 usleep_range(5000, 6000); 774 ret = regmap_update_bits(mci->regmap, MT6360_PMU_CHG_CTRL3, 775 MT6360_ILIM_EN_MASK, 0); 776 if (ret) 777 return dev_err_probe(mci->dev, ret, 778 "%s: Failed to disable ilim\n", __func__); 779 ret = regmap_update_bits(mci->regmap, MT6360_PMU_CHG_CTRL10, 780 MT6360_OTG_OC_MASK, MT6360_OTG_OC_MASK); 781 if (ret) 782 return dev_err_probe(mci->dev, ret, 783 "%s: Failed to config otg oc to 3A\n", __func__); 784 return 0; 785 } 786 787 static int mt6360_charger_probe(struct platform_device *pdev) 788 { 789 struct mt6360_chg_info *mci; 790 struct power_supply_config charger_cfg = {}; 791 struct regulator_config config = { }; 792 int ret; 793 794 mci = devm_kzalloc(&pdev->dev, sizeof(*mci), GFP_KERNEL); 795 if (!mci) 796 return -ENOMEM; 797 798 mci->dev = &pdev->dev; 799 mci->vinovp = 6500000; 800 mutex_init(&mci->chgdet_lock); 801 platform_set_drvdata(pdev, mci); 802 devm_work_autocancel(&pdev->dev, &mci->chrdet_work, mt6360_chrdet_work); 803 804 ret = device_property_read_u32(&pdev->dev, "richtek,vinovp-microvolt", &mci->vinovp); 805 if (ret) 806 dev_warn(&pdev->dev, "Failed to parse vinovp in DT, keep default 6.5v\n"); 807 808 mci->regmap = dev_get_regmap(pdev->dev.parent, NULL); 809 if (!mci->regmap) 810 return dev_err_probe(&pdev->dev, -ENODEV, "Failed to get parent regmap\n"); 811 812 ret = mt6360_chg_init_setting(mci); 813 if (ret) 814 return dev_err_probe(&pdev->dev, ret, "Failed to initial setting\n"); 815 816 memcpy(&mci->psy_desc, &mt6360_charger_desc, sizeof(mci->psy_desc)); 817 mci->psy_desc.name = dev_name(&pdev->dev); 818 charger_cfg.drv_data = mci; 819 charger_cfg.of_node = pdev->dev.of_node; 820 mci->psy = devm_power_supply_register(&pdev->dev, 821 &mci->psy_desc, &charger_cfg); 822 if (IS_ERR(mci->psy)) 823 return dev_err_probe(&pdev->dev, PTR_ERR(mci->psy), 824 "Failed to register power supply dev\n"); 825 826 827 ret = mt6360_chg_irq_register(pdev); 828 if (ret) 829 return dev_err_probe(&pdev->dev, ret, "Failed to register irqs\n"); 830 831 config.dev = &pdev->dev; 832 config.regmap = mci->regmap; 833 mci->otg_rdev = devm_regulator_register(&pdev->dev, &mt6360_otg_rdesc, 834 &config); 835 if (IS_ERR(mci->otg_rdev)) 836 return PTR_ERR(mci->otg_rdev); 837 838 schedule_work(&mci->chrdet_work); 839 840 return 0; 841 } 842 843 static const struct of_device_id __maybe_unused mt6360_charger_of_id[] = { 844 { .compatible = "mediatek,mt6360-chg", }, 845 {}, 846 }; 847 MODULE_DEVICE_TABLE(of, mt6360_charger_of_id); 848 849 static const struct platform_device_id mt6360_charger_id[] = { 850 { "mt6360-chg", 0 }, 851 {}, 852 }; 853 MODULE_DEVICE_TABLE(platform, mt6360_charger_id); 854 855 static struct platform_driver mt6360_charger_driver = { 856 .driver = { 857 .name = "mt6360-chg", 858 .of_match_table = of_match_ptr(mt6360_charger_of_id), 859 }, 860 .probe = mt6360_charger_probe, 861 .id_table = mt6360_charger_id, 862 }; 863 module_platform_driver(mt6360_charger_driver); 864 865 MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>"); 866 MODULE_DESCRIPTION("MT6360 Charger Driver"); 867 MODULE_LICENSE("GPL"); 868