power: pm8921-charger: support dc charging while in usb host mode
The current code disables charging when the usb is operating in host
mode. This unnecessarily stops charging from the DC path. The board
layout (the ovp fet and otg path) is assumed to support host mode and
charging from dc path.
Also make the usb driver change the power supply framework's scope
property instead of calling 8921 charger apis directly.
CRs-Fixed: 373365
Change-Id: I2a9fb32de22cbe68e26078b97a7d83c40272a370
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index a2eb39e..dc40c8e 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -265,6 +265,7 @@
enum pm8921_chg_hot_thr hot_thr;
int rconn_mohm;
enum pm8921_chg_led_src_config led_src_config;
+ bool host_mode;
};
/* user space parameter to limit usb current */
@@ -1141,6 +1142,7 @@
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_SCOPE,
};
static enum power_supply_property pm_power_props_mains[] = {
@@ -1196,6 +1198,67 @@
return 0;
}
+static int switch_usb_to_charge_mode(struct pm8921_chg_chip *chip)
+{
+ int rc;
+
+ if (!chip->host_mode)
+ return 0;
+
+ /* enable usbin valid comparator and remove force usb ovp fet off */
+ rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, 0xB2);
+ if (rc < 0) {
+ pr_err("Failed to write 0xB2 to USB_OVP_TEST rc = %d\n", rc);
+ return rc;
+ }
+
+ chip->host_mode = 0;
+
+ return 0;
+}
+
+static int switch_usb_to_host_mode(struct pm8921_chg_chip *chip)
+{
+ int rc;
+
+ if (chip->host_mode)
+ return 0;
+
+ /* disable usbin valid comparator and force usb ovp fet off */
+ rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, 0xB3);
+ if (rc < 0) {
+ pr_err("Failed to write 0xB3 to USB_OVP_TEST rc = %d\n", rc);
+ return rc;
+ }
+
+ chip->host_mode = 1;
+
+ return 0;
+}
+
+static int pm_power_set_property_usb(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ /* Check if called before init */
+ if (!the_chip)
+ return -EINVAL;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_SCOPE:
+ if (val->intval == POWER_SUPPLY_SCOPE_SYSTEM)
+ return switch_usb_to_host_mode(the_chip);
+ if (val->intval == POWER_SUPPLY_SCOPE_DEVICE)
+ return switch_usb_to_charge_mode(the_chip);
+ else
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int pm_power_get_property_usb(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -1234,6 +1297,13 @@
else
return 0;
break;
+
+ case POWER_SUPPLY_PROP_SCOPE:
+ if (the_chip->host_mode)
+ val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
+ else
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
default:
return -EINVAL;
}
@@ -3851,6 +3921,7 @@
chip->usb_psy.properties = pm_power_props_usb,
chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props_usb),
chip->usb_psy.get_property = pm_power_get_property_usb,
+ chip->usb_psy.set_property = pm_power_set_property_usb,
chip->dc_psy.name = "pm8921-dc",
chip->dc_psy.type = POWER_SUPPLY_TYPE_MAINS,
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 1d9c84f..5b85d98 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -972,6 +972,21 @@
}
#endif
+static int msm_otg_notify_host_mode(struct msm_otg *motg, bool host_mode)
+{
+ if (!psy)
+ goto psy_not_supported;
+
+ if (host_mode)
+ power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_SYSTEM);
+ else
+ power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_DEVICE);
+
+psy_not_supported:
+ dev_dbg(motg->phy.dev, "Power Supply doesn't support USB charger\n");
+ return -ENXIO;
+}
+
static int msm_otg_notify_chg_type(struct msm_otg *motg)
{
static int charger_type;
@@ -1220,7 +1235,7 @@
* current from the source.
*/
if (on) {
- pm8921_disable_source_current(on);
+ msm_otg_notify_host_mode(motg, on);
ret = regulator_enable(vbus_otg);
if (ret) {
pr_err("unable to enable vbus_otg\n");
@@ -1233,7 +1248,7 @@
pr_err("unable to disable vbus_otg\n");
return;
}
- pm8921_disable_source_current(on);
+ msm_otg_notify_host_mode(motg, on);
vbus_is_on = false;
}
}