power: supply: cpcap-charger: Enable vbus boost voltage
diff mbox series

Message ID 20190830232316.53750-1-tony@atomide.com
State New
Headers show
Series
  • power: supply: cpcap-charger: Enable vbus boost voltage
Related show

Commit Message

Tony Lindgren Aug. 30, 2019, 11:23 p.m. UTC
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>
---
 drivers/phy/motorola/phy-cpcap-usb.c |  8 +++++---
 drivers/power/supply/cpcap-charger.c | 23 ++++++++++++++++++++---
 2 files changed, 25 insertions(+), 6 deletions(-)

Comments

Pavel Machek Sept. 2, 2019, 7:59 a.m. UTC | #1
Hi!

> 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.

I did not know phone is supposed to provide voltage on USB. USB mouse
works for me.. in stock android, provided I conect USB hub and
external power.

This does not seem to work for me.. and it does not even work on stock
kernel. What is going on here?

Is there some kind of debug ineterface where I could test just the
vbus switch? I do have voltmeter for the usb port...

Best regards,
								Pavel

> diff --git a/drivers/phy/motorola/phy-cpcap-usb.c b/drivers/phy/motorola/phy-cpcap-usb.c
> --- a/drivers/phy/motorola/phy-cpcap-usb.c
> +++ b/drivers/phy/motorola/phy-cpcap-usb.c
> @@ -231,8 +231,9 @@ static void cpcap_usb_detect(struct work_struct *work)
>  			goto out_err;
>  
>  		error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
> -					   CPCAP_BIT_VBUSSTBY_EN,
> -					   CPCAP_BIT_VBUSSTBY_EN);
> +					   CPCAP_BIT_VBUSSTBY_EN |
> +					   CPCAP_BIT_VBUSEN_SPI,
> +					   CPCAP_BIT_VBUSEN_SPI);
>  		if (error)
>  			goto out_err;
>  
> @@ -240,7 +241,8 @@ static void cpcap_usb_detect(struct work_struct *work)
>  	}
>  
>  	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
> -				   CPCAP_BIT_VBUSSTBY_EN, 0);
> +				   CPCAP_BIT_VBUSSTBY_EN |
> +				   CPCAP_BIT_VBUSEN_SPI, 0);
>  	if (error)
>  		goto out_err;
>  
> diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c
> --- a/drivers/power/supply/cpcap-charger.c
> +++ b/drivers/power/supply/cpcap-charger.c
> @@ -108,6 +108,9 @@
>  #define CPCAP_REG_CRM_ICHRG_1A596	CPCAP_REG_CRM_ICHRG(0xe)
>  #define CPCAP_REG_CRM_ICHRG_NO_LIMIT	CPCAP_REG_CRM_ICHRG(0xf)
>  
> +/* CPCAP_REG_VUSBC register bits needed for VBUS */
> +#define CPCAP_BIT_VBUS_SWITCH		BIT(0)	/* VBUS boost to 5V */
> +
>  enum {
>  	CPCAP_CHARGER_IIO_BATTDET,
>  	CPCAP_CHARGER_IIO_VOLTAGE,
> @@ -130,7 +133,8 @@ struct cpcap_charger_ddata {
>  	struct power_supply *usb;
>  
>  	struct phy_companion comparator;	/* For USB VBUS */
> -	bool vbus_enabled;
> +	unsigned int vbus_enabled:1;
> +	unsigned int feeding_vbus:1;
>  	atomic_t active;
>  
>  	int status;
> @@ -325,7 +329,6 @@ static bool cpcap_charger_vbus_valid(struct cpcap_charger_ddata *ddata)
>  }
>  
>  /* VBUS control functions for the USB PHY companion */
> -
>  static void cpcap_charger_vbus_work(struct work_struct *work)
>  {
>  	struct cpcap_charger_ddata *ddata;
> @@ -343,6 +346,7 @@ static void cpcap_charger_vbus_work(struct work_struct *work)
>  			return;
>  		}
>  
> +		ddata->feeding_vbus = true;
>  		cpcap_charger_set_cable_path(ddata, false);
>  		cpcap_charger_set_inductive_path(ddata, false);
>  
> @@ -350,12 +354,23 @@ static void cpcap_charger_vbus_work(struct work_struct *work)
>  		if (error)
>  			goto out_err;
>  
> +		error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC,
> +					   CPCAP_BIT_VBUS_SWITCH,
> +					   CPCAP_BIT_VBUS_SWITCH);
> +		if (error)
> +			goto out_err;
> +
>  		error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM,
>  					   CPCAP_REG_CRM_RVRSMODE,
>  					   CPCAP_REG_CRM_RVRSMODE);
>  		if (error)
>  			goto out_err;
>  	} else {
> +		error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC,
> +					   CPCAP_BIT_VBUS_SWITCH, 0);
> +		if (error)
> +			goto out_err;
> +
>  		error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM,
>  					   CPCAP_REG_CRM_RVRSMODE, 0);
>  		if (error)
> @@ -363,6 +378,7 @@ static void cpcap_charger_vbus_work(struct work_struct *work)
>  
>  		cpcap_charger_set_cable_path(ddata, true);
>  		cpcap_charger_set_inductive_path(ddata, true);
> +		ddata->feeding_vbus = false;
>  	}
>  
>  	return;
> @@ -431,7 +447,8 @@ static void cpcap_usb_detect(struct work_struct *work)
>  	if (error)
>  		return;
>  
> -	if (cpcap_charger_vbus_valid(ddata) && s.chrgcurr1) {
> +	if (!ddata->feeding_vbus && cpcap_charger_vbus_valid(ddata) &&
> +	    s.chrgcurr1) {
>  		int max_current;
>  
>  		if (cpcap_charger_battery_found(ddata))
Tony Lindgren Sept. 2, 2019, 4:20 p.m. UTC | #2
* Pavel Machek <pavel@ucw.cz> [190902 08:00]:
> Hi!
> 
> > 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.
> 
> I did not know phone is supposed to provide voltage on USB. USB mouse
> works for me.. in stock android, provided I conect USB hub and
> external power.

Yup that's standard USB OTG feature when ID pin is grounded.

> This does not seem to work for me.. and it does not even work on stock
> kernel. What is going on here?

Sounds like you're missing a USB micro-B cable with ID pin grounded
and trying to use debugfs/sysfs instead to force the host mode.

> Is there some kind of debug ineterface where I could test just the
> vbus switch? I do have voltmeter for the usb port...

Yeah well.. just ground the ID pin :) No debug interface should be
needed here.

If you really wanted to add some kind of debugfs interface for forcing
host mode without ID pin grounded, you could try to have the USB phy
driver enable ID pin pull-down via sysfs. That's the cpcap PMIC in this
case, I think some combination of CPCAP_BIT_ID* bits might do the
trick.

Regards,

Tony
Sebastian Reichel Sept. 2, 2019, 9:12 p.m. UTC | #3
Hi,

On Fri, Aug 30, 2019 at 04:23:16PM -0700, Tony Lindgren wrote:
> 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>
> ---

Thanks, queued.

-- Sebastian

>  drivers/phy/motorola/phy-cpcap-usb.c |  8 +++++---
>  drivers/power/supply/cpcap-charger.c | 23 ++++++++++++++++++++---
>  2 files changed, 25 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/phy/motorola/phy-cpcap-usb.c b/drivers/phy/motorola/phy-cpcap-usb.c
> --- a/drivers/phy/motorola/phy-cpcap-usb.c
> +++ b/drivers/phy/motorola/phy-cpcap-usb.c
> @@ -231,8 +231,9 @@ static void cpcap_usb_detect(struct work_struct *work)
>  			goto out_err;
>  
>  		error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
> -					   CPCAP_BIT_VBUSSTBY_EN,
> -					   CPCAP_BIT_VBUSSTBY_EN);
> +					   CPCAP_BIT_VBUSSTBY_EN |
> +					   CPCAP_BIT_VBUSEN_SPI,
> +					   CPCAP_BIT_VBUSEN_SPI);
>  		if (error)
>  			goto out_err;
>  
> @@ -240,7 +241,8 @@ static void cpcap_usb_detect(struct work_struct *work)
>  	}
>  
>  	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
> -				   CPCAP_BIT_VBUSSTBY_EN, 0);
> +				   CPCAP_BIT_VBUSSTBY_EN |
> +				   CPCAP_BIT_VBUSEN_SPI, 0);
>  	if (error)
>  		goto out_err;
>  
> diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c
> --- a/drivers/power/supply/cpcap-charger.c
> +++ b/drivers/power/supply/cpcap-charger.c
> @@ -108,6 +108,9 @@
>  #define CPCAP_REG_CRM_ICHRG_1A596	CPCAP_REG_CRM_ICHRG(0xe)
>  #define CPCAP_REG_CRM_ICHRG_NO_LIMIT	CPCAP_REG_CRM_ICHRG(0xf)
>  
> +/* CPCAP_REG_VUSBC register bits needed for VBUS */
> +#define CPCAP_BIT_VBUS_SWITCH		BIT(0)	/* VBUS boost to 5V */
> +
>  enum {
>  	CPCAP_CHARGER_IIO_BATTDET,
>  	CPCAP_CHARGER_IIO_VOLTAGE,
> @@ -130,7 +133,8 @@ struct cpcap_charger_ddata {
>  	struct power_supply *usb;
>  
>  	struct phy_companion comparator;	/* For USB VBUS */
> -	bool vbus_enabled;
> +	unsigned int vbus_enabled:1;
> +	unsigned int feeding_vbus:1;
>  	atomic_t active;
>  
>  	int status;
> @@ -325,7 +329,6 @@ static bool cpcap_charger_vbus_valid(struct cpcap_charger_ddata *ddata)
>  }
>  
>  /* VBUS control functions for the USB PHY companion */
> -
>  static void cpcap_charger_vbus_work(struct work_struct *work)
>  {
>  	struct cpcap_charger_ddata *ddata;
> @@ -343,6 +346,7 @@ static void cpcap_charger_vbus_work(struct work_struct *work)
>  			return;
>  		}
>  
> +		ddata->feeding_vbus = true;
>  		cpcap_charger_set_cable_path(ddata, false);
>  		cpcap_charger_set_inductive_path(ddata, false);
>  
> @@ -350,12 +354,23 @@ static void cpcap_charger_vbus_work(struct work_struct *work)
>  		if (error)
>  			goto out_err;
>  
> +		error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC,
> +					   CPCAP_BIT_VBUS_SWITCH,
> +					   CPCAP_BIT_VBUS_SWITCH);
> +		if (error)
> +			goto out_err;
> +
>  		error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM,
>  					   CPCAP_REG_CRM_RVRSMODE,
>  					   CPCAP_REG_CRM_RVRSMODE);
>  		if (error)
>  			goto out_err;
>  	} else {
> +		error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC,
> +					   CPCAP_BIT_VBUS_SWITCH, 0);
> +		if (error)
> +			goto out_err;
> +
>  		error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM,
>  					   CPCAP_REG_CRM_RVRSMODE, 0);
>  		if (error)
> @@ -363,6 +378,7 @@ static void cpcap_charger_vbus_work(struct work_struct *work)
>  
>  		cpcap_charger_set_cable_path(ddata, true);
>  		cpcap_charger_set_inductive_path(ddata, true);
> +		ddata->feeding_vbus = false;
>  	}
>  
>  	return;
> @@ -431,7 +447,8 @@ static void cpcap_usb_detect(struct work_struct *work)
>  	if (error)
>  		return;
>  
> -	if (cpcap_charger_vbus_valid(ddata) && s.chrgcurr1) {
> +	if (!ddata->feeding_vbus && cpcap_charger_vbus_valid(ddata) &&
> +	    s.chrgcurr1) {
>  		int max_current;
>  
>  		if (cpcap_charger_battery_found(ddata))
> -- 
> 2.23.0

Patch
diff mbox series

diff --git a/drivers/phy/motorola/phy-cpcap-usb.c b/drivers/phy/motorola/phy-cpcap-usb.c
--- a/drivers/phy/motorola/phy-cpcap-usb.c
+++ b/drivers/phy/motorola/phy-cpcap-usb.c
@@ -231,8 +231,9 @@  static void cpcap_usb_detect(struct work_struct *work)
 			goto out_err;
 
 		error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
-					   CPCAP_BIT_VBUSSTBY_EN,
-					   CPCAP_BIT_VBUSSTBY_EN);
+					   CPCAP_BIT_VBUSSTBY_EN |
+					   CPCAP_BIT_VBUSEN_SPI,
+					   CPCAP_BIT_VBUSEN_SPI);
 		if (error)
 			goto out_err;
 
@@ -240,7 +241,8 @@  static void cpcap_usb_detect(struct work_struct *work)
 	}
 
 	error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
-				   CPCAP_BIT_VBUSSTBY_EN, 0);
+				   CPCAP_BIT_VBUSSTBY_EN |
+				   CPCAP_BIT_VBUSEN_SPI, 0);
 	if (error)
 		goto out_err;
 
diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c
--- a/drivers/power/supply/cpcap-charger.c
+++ b/drivers/power/supply/cpcap-charger.c
@@ -108,6 +108,9 @@ 
 #define CPCAP_REG_CRM_ICHRG_1A596	CPCAP_REG_CRM_ICHRG(0xe)
 #define CPCAP_REG_CRM_ICHRG_NO_LIMIT	CPCAP_REG_CRM_ICHRG(0xf)
 
+/* CPCAP_REG_VUSBC register bits needed for VBUS */
+#define CPCAP_BIT_VBUS_SWITCH		BIT(0)	/* VBUS boost to 5V */
+
 enum {
 	CPCAP_CHARGER_IIO_BATTDET,
 	CPCAP_CHARGER_IIO_VOLTAGE,
@@ -130,7 +133,8 @@  struct cpcap_charger_ddata {
 	struct power_supply *usb;
 
 	struct phy_companion comparator;	/* For USB VBUS */
-	bool vbus_enabled;
+	unsigned int vbus_enabled:1;
+	unsigned int feeding_vbus:1;
 	atomic_t active;
 
 	int status;
@@ -325,7 +329,6 @@  static bool cpcap_charger_vbus_valid(struct cpcap_charger_ddata *ddata)
 }
 
 /* VBUS control functions for the USB PHY companion */
-
 static void cpcap_charger_vbus_work(struct work_struct *work)
 {
 	struct cpcap_charger_ddata *ddata;
@@ -343,6 +346,7 @@  static void cpcap_charger_vbus_work(struct work_struct *work)
 			return;
 		}
 
+		ddata->feeding_vbus = true;
 		cpcap_charger_set_cable_path(ddata, false);
 		cpcap_charger_set_inductive_path(ddata, false);
 
@@ -350,12 +354,23 @@  static void cpcap_charger_vbus_work(struct work_struct *work)
 		if (error)
 			goto out_err;
 
+		error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC,
+					   CPCAP_BIT_VBUS_SWITCH,
+					   CPCAP_BIT_VBUS_SWITCH);
+		if (error)
+			goto out_err;
+
 		error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM,
 					   CPCAP_REG_CRM_RVRSMODE,
 					   CPCAP_REG_CRM_RVRSMODE);
 		if (error)
 			goto out_err;
 	} else {
+		error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC,
+					   CPCAP_BIT_VBUS_SWITCH, 0);
+		if (error)
+			goto out_err;
+
 		error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM,
 					   CPCAP_REG_CRM_RVRSMODE, 0);
 		if (error)
@@ -363,6 +378,7 @@  static void cpcap_charger_vbus_work(struct work_struct *work)
 
 		cpcap_charger_set_cable_path(ddata, true);
 		cpcap_charger_set_inductive_path(ddata, true);
+		ddata->feeding_vbus = false;
 	}
 
 	return;
@@ -431,7 +447,8 @@  static void cpcap_usb_detect(struct work_struct *work)
 	if (error)
 		return;
 
-	if (cpcap_charger_vbus_valid(ddata) && s.chrgcurr1) {
+	if (!ddata->feeding_vbus && cpcap_charger_vbus_valid(ddata) &&
+	    s.chrgcurr1) {
 		int max_current;
 
 		if (cpcap_charger_battery_found(ddata))