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

power: supply: cpcap-charger: Enable vbus boost voltage

We are currently not enabling VBUS boost for cpcap when in host mode.
This means the VBUS is fed at the battery voltage level, which can cause
flakeyness enumerating devices.

Looks like the boost control for VBUS is CPCAP_BIT_VBUS_SWITCH that we
must enable in the charger for nice 4.92 V VBUS output. And looks like
we must not use the STBY pin enabling but must instead use manual VBUS
control in phy-cpcap-usb.

We want to do this in cpcap_charger_vbus_work() and also set a flag for
feeding_vbus to avoid races between USB detection and charger detection,
and disable charging if feeding_vbus is set.

Cc: Jacopo Mondi <jacopo@jmondi.org>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Marcel Partap <mpartap@gmx.net>
Cc: Merlijn Wajer <merlijn@wizzup.org>
Cc: Michael Scott <hashcode0f@gmail.com>
Cc: NeKit <nekit1000@gmail.com>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

Tony Lindgren and committed by
Sebastian Reichel
7f737861 7cfd33d9

+25 -6
+5 -3
drivers/phy/motorola/phy-cpcap-usb.c
··· 231 231 goto out_err; 232 232 233 233 error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3, 234 - CPCAP_BIT_VBUSSTBY_EN, 235 - CPCAP_BIT_VBUSSTBY_EN); 234 + CPCAP_BIT_VBUSSTBY_EN | 235 + CPCAP_BIT_VBUSEN_SPI, 236 + CPCAP_BIT_VBUSEN_SPI); 236 237 if (error) 237 238 goto out_err; 238 239 ··· 241 240 } 242 241 243 242 error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3, 244 - CPCAP_BIT_VBUSSTBY_EN, 0); 243 + CPCAP_BIT_VBUSSTBY_EN | 244 + CPCAP_BIT_VBUSEN_SPI, 0); 245 245 if (error) 246 246 goto out_err; 247 247
+20 -3
drivers/power/supply/cpcap-charger.c
··· 108 108 #define CPCAP_REG_CRM_ICHRG_1A596 CPCAP_REG_CRM_ICHRG(0xe) 109 109 #define CPCAP_REG_CRM_ICHRG_NO_LIMIT CPCAP_REG_CRM_ICHRG(0xf) 110 110 111 + /* CPCAP_REG_VUSBC register bits needed for VBUS */ 112 + #define CPCAP_BIT_VBUS_SWITCH BIT(0) /* VBUS boost to 5V */ 113 + 111 114 enum { 112 115 CPCAP_CHARGER_IIO_BATTDET, 113 116 CPCAP_CHARGER_IIO_VOLTAGE, ··· 133 130 struct power_supply *usb; 134 131 135 132 struct phy_companion comparator; /* For USB VBUS */ 136 - bool vbus_enabled; 133 + unsigned int vbus_enabled:1; 134 + unsigned int feeding_vbus:1; 137 135 atomic_t active; 138 136 139 137 int status; ··· 329 325 } 330 326 331 327 /* VBUS control functions for the USB PHY companion */ 332 - 333 328 static void cpcap_charger_vbus_work(struct work_struct *work) 334 329 { 335 330 struct cpcap_charger_ddata *ddata; ··· 346 343 return; 347 344 } 348 345 346 + ddata->feeding_vbus = true; 349 347 cpcap_charger_set_cable_path(ddata, false); 350 348 cpcap_charger_set_inductive_path(ddata, false); 351 349 352 350 error = cpcap_charger_set_state(ddata, 0, 0, 0); 351 + if (error) 352 + goto out_err; 353 + 354 + error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC, 355 + CPCAP_BIT_VBUS_SWITCH, 356 + CPCAP_BIT_VBUS_SWITCH); 353 357 if (error) 354 358 goto out_err; 355 359 ··· 366 356 if (error) 367 357 goto out_err; 368 358 } else { 359 + error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC, 360 + CPCAP_BIT_VBUS_SWITCH, 0); 361 + if (error) 362 + goto out_err; 363 + 369 364 error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM, 370 365 CPCAP_REG_CRM_RVRSMODE, 0); 371 366 if (error) ··· 378 363 379 364 cpcap_charger_set_cable_path(ddata, true); 380 365 cpcap_charger_set_inductive_path(ddata, true); 366 + ddata->feeding_vbus = false; 381 367 } 382 368 383 369 return; ··· 447 431 if (error) 448 432 return; 449 433 450 - if (cpcap_charger_vbus_valid(ddata) && s.chrgcurr1) { 434 + if (!ddata->feeding_vbus && cpcap_charger_vbus_valid(ddata) && 435 + s.chrgcurr1) { 451 436 int max_current; 452 437 453 438 if (cpcap_charger_battery_found(ddata))