Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

power: supply: axp20x_usb_power: enable usb_type reporting

The axp803 and axp813 chips can report the detected USB BC mode. SDP,
CDP, and DCP are supported.

Signed-off-by: Aren Moynihan <aren@peacevolution.org>
Link: https://lore.kernel.org/r/20240130203714.3020464-5-aren@peacevolution.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

Aren Moynihan and committed by
Sebastian Reichel
aa08a0d1 06a807e6

+72 -1
+72 -1
drivers/power/supply/axp20x_usb_power.c
··· 55 55 struct reg_field vbus_valid_bit; 56 56 struct reg_field vbus_mon_bit; 57 57 struct reg_field usb_bc_en_bit; 58 + struct reg_field usb_bc_det_fld; 58 59 struct reg_field vbus_disable_bit; 59 60 bool vbus_needs_polling: 1; 60 61 }; ··· 67 66 struct regmap_field *vbus_valid_bit; 68 67 struct regmap_field *vbus_mon_bit; 69 68 struct regmap_field *usb_bc_en_bit; 69 + struct regmap_field *usb_bc_det_fld; 70 70 struct regmap_field *vbus_disable_bit; 71 71 struct power_supply *supply; 72 72 const struct axp_data *axp_data; ··· 134 132 out: 135 133 if (axp20x_usb_vbus_needs_polling(power)) 136 134 mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME); 135 + } 136 + 137 + static int axp20x_get_usb_type(struct axp20x_usb_power *power, 138 + union power_supply_propval *val) 139 + { 140 + unsigned int reg; 141 + int ret; 142 + 143 + if (!power->usb_bc_det_fld) 144 + return -EINVAL; 145 + 146 + ret = regmap_field_read(power->usb_bc_det_fld, &reg); 147 + if (ret) 148 + return ret; 149 + 150 + switch (reg) { 151 + case 1: 152 + val->intval = POWER_SUPPLY_USB_TYPE_SDP; 153 + break; 154 + case 2: 155 + val->intval = POWER_SUPPLY_USB_TYPE_CDP; 156 + break; 157 + case 3: 158 + val->intval = POWER_SUPPLY_USB_TYPE_DCP; 159 + break; 160 + default: 161 + val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN; 162 + break; 163 + } 164 + 165 + return 0; 137 166 } 138 167 139 168 static int axp20x_usb_power_get_property(struct power_supply *psy, ··· 237 204 238 205 val->intval = ret * 375; /* 1 step = 0.375 mA */ 239 206 return 0; 207 + 208 + case POWER_SUPPLY_PROP_USB_TYPE: 209 + return axp20x_get_usb_type(power, val); 240 210 default: 241 211 break; 242 212 } ··· 403 367 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 404 368 }; 405 369 370 + static enum power_supply_property axp813_usb_power_properties[] = { 371 + POWER_SUPPLY_PROP_HEALTH, 372 + POWER_SUPPLY_PROP_PRESENT, 373 + POWER_SUPPLY_PROP_ONLINE, 374 + POWER_SUPPLY_PROP_VOLTAGE_MIN, 375 + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, 376 + POWER_SUPPLY_PROP_USB_TYPE, 377 + }; 378 + 379 + static enum power_supply_usb_type axp813_usb_types[] = { 380 + POWER_SUPPLY_USB_TYPE_SDP, 381 + POWER_SUPPLY_USB_TYPE_DCP, 382 + POWER_SUPPLY_USB_TYPE_CDP, 383 + POWER_SUPPLY_USB_TYPE_UNKNOWN, 384 + }; 385 + 406 386 static const struct power_supply_desc axp20x_usb_power_desc = { 407 387 .name = "axp20x-usb", 408 388 .type = POWER_SUPPLY_TYPE_USB, ··· 437 385 .property_is_writeable = axp20x_usb_power_prop_writeable, 438 386 .get_property = axp20x_usb_power_get_property, 439 387 .set_property = axp20x_usb_power_set_property, 388 + }; 389 + 390 + static const struct power_supply_desc axp813_usb_power_desc = { 391 + .name = "axp20x-usb", 392 + .type = POWER_SUPPLY_TYPE_USB, 393 + .properties = axp813_usb_power_properties, 394 + .num_properties = ARRAY_SIZE(axp813_usb_power_properties), 395 + .property_is_writeable = axp20x_usb_power_prop_writeable, 396 + .get_property = axp20x_usb_power_get_property, 397 + .set_property = axp20x_usb_power_set_property, 398 + .usb_types = axp813_usb_types, 399 + .num_usb_types = ARRAY_SIZE(axp813_usb_types), 440 400 }; 441 401 442 402 static const char * const axp20x_irq_names[] = { ··· 539 475 }; 540 476 541 477 static const struct axp_data axp813_data = { 542 - .power_desc = &axp22x_usb_power_desc, 478 + .power_desc = &axp813_usb_power_desc, 543 479 .irq_names = axp22x_irq_names, 544 480 .num_irq_names = ARRAY_SIZE(axp22x_irq_names), 545 481 .curr_lim_table = axp813_usb_curr_lim_table, 546 482 .curr_lim_table_size = ARRAY_SIZE(axp813_usb_curr_lim_table), 547 483 .curr_lim_fld = REG_FIELD(AXP22X_CHRG_CTRL3, 4, 7), 548 484 .usb_bc_en_bit = REG_FIELD(AXP288_BC_GLOBAL, 0, 0), 485 + .usb_bc_det_fld = REG_FIELD(AXP288_BC_DET_STAT, 5, 7), 549 486 .vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7), 550 487 .vbus_needs_polling = true, 551 488 }; ··· 691 626 ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap, 692 627 axp_data->usb_bc_en_bit, 693 628 &power->usb_bc_en_bit); 629 + if (ret) 630 + return ret; 631 + 632 + ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap, 633 + axp_data->usb_bc_det_fld, 634 + &power->usb_bc_det_fld); 694 635 if (ret) 695 636 return ret; 696 637