Loading drivers/usb/phy/phy-msm-qusb.c +123 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <linux/regulator/machine.h> #include <linux/usb/phy.h> #include <linux/reset.h> #include <linux/power_supply.h> #define QUSB2PHY_PLL_PWR_CTL 0x18 #define REF_BUF_EN BIT(0) Loading Loading @@ -111,6 +112,7 @@ #define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */ #define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */ #define SOC_THRESHOLD_LEVEL 45 #define QUSB2PHY_REFCLK_ENABLE BIT(0) #define HSTX_TRIMSIZE 4 Loading Loading @@ -153,6 +155,7 @@ struct qusb_phy { struct regulator *vdda33; struct regulator *vdda18; int vdd_levels[3]; /* none, low, high */ int vdda33_levels[3]; /* low, min, max */ int init_seq_len; int *qusb_phy_init_seq; u32 major_rev; Loading @@ -169,7 +172,10 @@ struct qusb_phy { bool ulpi_mode; bool dpdm_enable; bool is_se_clk; bool low_soc; struct notifier_block psy_nb; struct work_struct soc_eval_work; struct regulator_desc dpdm_rdesc; struct regulator_dev *dpdm_rdev; Loading @@ -180,6 +186,7 @@ struct qusb_phy { bool vbus_active; bool id_state; struct power_supply *usb_psy; struct power_supply *batt_psy; struct delayed_work port_det_w; enum port_state port_state; unsigned int dcd_timeout; Loading Loading @@ -265,6 +272,34 @@ static int qusb_phy_config_vdd(struct qusb_phy *qphy, int high) return ret; } static int qusb_read_battery_soc(struct qusb_phy *qphy, int *soc_val) { union power_supply_propval val = {0,}; int ret = 0; if (!qphy->batt_psy) { qphy->batt_psy = power_supply_get_by_name("battery"); if (!qphy->batt_psy) { dev_err(qphy->phy.dev, "Could not get battery psy\n"); return -ENODEV; } } if (qphy->batt_psy) { ret = power_supply_get_property(qphy->batt_psy, POWER_SUPPLY_PROP_CAPACITY, &val); if (ret) { dev_err(qphy->phy.dev, "battery SoC read error\n"); return ret; } *soc_val = val.intval; } dev_dbg(qphy->phy.dev, "soc:%d\n", *soc_val); return ret; } static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on) { int ret = 0; Loading Loading @@ -314,8 +349,9 @@ static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on) goto disable_vdda18; } ret = regulator_set_voltage(qphy->vdda33, QUSB2PHY_3P3_VOL_MIN, QUSB2PHY_3P3_VOL_MAX); ret = regulator_set_voltage(qphy->vdda33, qphy->vdda33_levels[1], qphy->vdda33_levels[2]); if (ret) { dev_err(qphy->phy.dev, "Unable to set voltage for vdda33:%d\n", ret); Loading Loading @@ -628,6 +664,57 @@ static int qusb_phy_init(struct usb_phy *phy) return 0; } static int qusb_phy_battery_supply_cb(struct notifier_block *nb, unsigned long event, void *data) { struct qusb_phy *qphy = container_of(nb, struct qusb_phy, psy_nb); int soc_val = 0; if (event != PSY_EVENT_PROP_CHANGED) return NOTIFY_OK; if (qusb_read_battery_soc(qphy, &soc_val) < 0) { dev_err(qphy->phy.dev, "%s unable to read battery SoC\n", __func__); return NOTIFY_OK; } if (soc_val < SOC_THRESHOLD_LEVEL && !qphy->low_soc) { /* Reduce voltage to be set to 2.9V for low SoC */ qphy->vdda33_levels[1] = qphy->vdda33_levels[0]; qphy->vdda33_levels[2] = qphy->vdda33_levels[0]; qphy->low_soc = true; queue_work(system_freezable_wq, &qphy->soc_eval_work); return NOTIFY_OK; } if (soc_val > SOC_THRESHOLD_LEVEL && qphy->low_soc) { /* Reset voltage to be set to default for normal SoC */ qphy->vdda33_levels[1] = QUSB2PHY_3P3_VOL_MIN; qphy->vdda33_levels[2] = QUSB2PHY_3P3_VOL_MAX; qphy->low_soc = false; queue_work(system_freezable_wq, &qphy->soc_eval_work); } return NOTIFY_OK; } static void qusb_phy_evaluate_soc(struct work_struct *work) { struct qusb_phy *qphy = container_of(work, struct qusb_phy, soc_eval_work); int ret = 0; dev_dbg(qphy->phy.dev, "%s setting min voltage for vdda33 as %d\n", __func__, qphy->vdda33_levels[1]); ret = regulator_set_voltage(qphy->vdda33, qphy->vdda33_levels[1], qphy->vdda33_levels[2]); if (ret) { dev_err(qphy->phy.dev, "%s unable to set voltage for vdda33, ret = %d\n", __func__, ret); } } static void qusb_phy_shutdown(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); Loading Loading @@ -1796,9 +1883,30 @@ static int qusb_phy_probe(struct platform_device *pdev) if (ret) return ret; qphy->vdda33_levels[1] = QUSB2PHY_3P3_VOL_MIN; qphy->vdda33_levels[2] = QUSB2PHY_3P3_VOL_MAX; ret = of_property_read_u32(dev->of_node, "qcom,vdda33-voltage-level", (u32 *)&qphy->vdda33_levels[0]); if (!ret) { INIT_WORK(&qphy->soc_eval_work, qusb_phy_evaluate_soc); /* Register notifier to change gain based on state of charge */ qphy->psy_nb.notifier_call = qusb_phy_battery_supply_cb; ret = power_supply_reg_notifier(&qphy->psy_nb); if (ret) { dev_dbg(qphy->phy.dev, "%s: could not register pwr supply notifier\n", __func__); goto remove_phy; } qphy->low_soc = false; qusb_phy_battery_supply_cb(&qphy->psy_nb, PSY_EVENT_PROP_CHANGED, NULL); } ret = qusb_phy_regulator_init(qphy); if (ret) usb_remove_phy(&qphy->phy); goto unreg_notifier_and_put_batt_psy; /* de-assert clamp dig n to reduce leakage on 1p8 upon boot up */ qusb_phy_clear_tcsr_clamp(qphy, true); Loading Loading @@ -1838,7 +1946,14 @@ static int qusb_phy_probe(struct platform_device *pdev) } qusb_phy_create_debugfs(qphy); return 0; unreg_notifier_and_put_batt_psy: power_supply_unreg_notifier(&qphy->psy_nb); if (qphy->batt_psy) power_supply_put(qphy->batt_psy); remove_phy: usb_remove_phy(&qphy->phy); return ret; } Loading @@ -1846,6 +1961,11 @@ static int qusb_phy_remove(struct platform_device *pdev) { struct qusb_phy *qphy = platform_get_drvdata(pdev); power_supply_unreg_notifier(&qphy->psy_nb); if (qphy->batt_psy) power_supply_put(qphy->batt_psy); if (qphy->usb_psy) power_supply_put(qphy->usb_psy); debugfs_remove_recursive(qphy->root); usb_remove_phy(&qphy->phy); qphy->cable_connected = false; Loading Loading
drivers/usb/phy/phy-msm-qusb.c +123 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <linux/regulator/machine.h> #include <linux/usb/phy.h> #include <linux/reset.h> #include <linux/power_supply.h> #define QUSB2PHY_PLL_PWR_CTL 0x18 #define REF_BUF_EN BIT(0) Loading Loading @@ -111,6 +112,7 @@ #define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */ #define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */ #define SOC_THRESHOLD_LEVEL 45 #define QUSB2PHY_REFCLK_ENABLE BIT(0) #define HSTX_TRIMSIZE 4 Loading Loading @@ -153,6 +155,7 @@ struct qusb_phy { struct regulator *vdda33; struct regulator *vdda18; int vdd_levels[3]; /* none, low, high */ int vdda33_levels[3]; /* low, min, max */ int init_seq_len; int *qusb_phy_init_seq; u32 major_rev; Loading @@ -169,7 +172,10 @@ struct qusb_phy { bool ulpi_mode; bool dpdm_enable; bool is_se_clk; bool low_soc; struct notifier_block psy_nb; struct work_struct soc_eval_work; struct regulator_desc dpdm_rdesc; struct regulator_dev *dpdm_rdev; Loading @@ -180,6 +186,7 @@ struct qusb_phy { bool vbus_active; bool id_state; struct power_supply *usb_psy; struct power_supply *batt_psy; struct delayed_work port_det_w; enum port_state port_state; unsigned int dcd_timeout; Loading Loading @@ -265,6 +272,34 @@ static int qusb_phy_config_vdd(struct qusb_phy *qphy, int high) return ret; } static int qusb_read_battery_soc(struct qusb_phy *qphy, int *soc_val) { union power_supply_propval val = {0,}; int ret = 0; if (!qphy->batt_psy) { qphy->batt_psy = power_supply_get_by_name("battery"); if (!qphy->batt_psy) { dev_err(qphy->phy.dev, "Could not get battery psy\n"); return -ENODEV; } } if (qphy->batt_psy) { ret = power_supply_get_property(qphy->batt_psy, POWER_SUPPLY_PROP_CAPACITY, &val); if (ret) { dev_err(qphy->phy.dev, "battery SoC read error\n"); return ret; } *soc_val = val.intval; } dev_dbg(qphy->phy.dev, "soc:%d\n", *soc_val); return ret; } static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on) { int ret = 0; Loading Loading @@ -314,8 +349,9 @@ static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on) goto disable_vdda18; } ret = regulator_set_voltage(qphy->vdda33, QUSB2PHY_3P3_VOL_MIN, QUSB2PHY_3P3_VOL_MAX); ret = regulator_set_voltage(qphy->vdda33, qphy->vdda33_levels[1], qphy->vdda33_levels[2]); if (ret) { dev_err(qphy->phy.dev, "Unable to set voltage for vdda33:%d\n", ret); Loading Loading @@ -628,6 +664,57 @@ static int qusb_phy_init(struct usb_phy *phy) return 0; } static int qusb_phy_battery_supply_cb(struct notifier_block *nb, unsigned long event, void *data) { struct qusb_phy *qphy = container_of(nb, struct qusb_phy, psy_nb); int soc_val = 0; if (event != PSY_EVENT_PROP_CHANGED) return NOTIFY_OK; if (qusb_read_battery_soc(qphy, &soc_val) < 0) { dev_err(qphy->phy.dev, "%s unable to read battery SoC\n", __func__); return NOTIFY_OK; } if (soc_val < SOC_THRESHOLD_LEVEL && !qphy->low_soc) { /* Reduce voltage to be set to 2.9V for low SoC */ qphy->vdda33_levels[1] = qphy->vdda33_levels[0]; qphy->vdda33_levels[2] = qphy->vdda33_levels[0]; qphy->low_soc = true; queue_work(system_freezable_wq, &qphy->soc_eval_work); return NOTIFY_OK; } if (soc_val > SOC_THRESHOLD_LEVEL && qphy->low_soc) { /* Reset voltage to be set to default for normal SoC */ qphy->vdda33_levels[1] = QUSB2PHY_3P3_VOL_MIN; qphy->vdda33_levels[2] = QUSB2PHY_3P3_VOL_MAX; qphy->low_soc = false; queue_work(system_freezable_wq, &qphy->soc_eval_work); } return NOTIFY_OK; } static void qusb_phy_evaluate_soc(struct work_struct *work) { struct qusb_phy *qphy = container_of(work, struct qusb_phy, soc_eval_work); int ret = 0; dev_dbg(qphy->phy.dev, "%s setting min voltage for vdda33 as %d\n", __func__, qphy->vdda33_levels[1]); ret = regulator_set_voltage(qphy->vdda33, qphy->vdda33_levels[1], qphy->vdda33_levels[2]); if (ret) { dev_err(qphy->phy.dev, "%s unable to set voltage for vdda33, ret = %d\n", __func__, ret); } } static void qusb_phy_shutdown(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); Loading Loading @@ -1796,9 +1883,30 @@ static int qusb_phy_probe(struct platform_device *pdev) if (ret) return ret; qphy->vdda33_levels[1] = QUSB2PHY_3P3_VOL_MIN; qphy->vdda33_levels[2] = QUSB2PHY_3P3_VOL_MAX; ret = of_property_read_u32(dev->of_node, "qcom,vdda33-voltage-level", (u32 *)&qphy->vdda33_levels[0]); if (!ret) { INIT_WORK(&qphy->soc_eval_work, qusb_phy_evaluate_soc); /* Register notifier to change gain based on state of charge */ qphy->psy_nb.notifier_call = qusb_phy_battery_supply_cb; ret = power_supply_reg_notifier(&qphy->psy_nb); if (ret) { dev_dbg(qphy->phy.dev, "%s: could not register pwr supply notifier\n", __func__); goto remove_phy; } qphy->low_soc = false; qusb_phy_battery_supply_cb(&qphy->psy_nb, PSY_EVENT_PROP_CHANGED, NULL); } ret = qusb_phy_regulator_init(qphy); if (ret) usb_remove_phy(&qphy->phy); goto unreg_notifier_and_put_batt_psy; /* de-assert clamp dig n to reduce leakage on 1p8 upon boot up */ qusb_phy_clear_tcsr_clamp(qphy, true); Loading Loading @@ -1838,7 +1946,14 @@ static int qusb_phy_probe(struct platform_device *pdev) } qusb_phy_create_debugfs(qphy); return 0; unreg_notifier_and_put_batt_psy: power_supply_unreg_notifier(&qphy->psy_nb); if (qphy->batt_psy) power_supply_put(qphy->batt_psy); remove_phy: usb_remove_phy(&qphy->phy); return ret; } Loading @@ -1846,6 +1961,11 @@ static int qusb_phy_remove(struct platform_device *pdev) { struct qusb_phy *qphy = platform_get_drvdata(pdev); power_supply_unreg_notifier(&qphy->psy_nb); if (qphy->batt_psy) power_supply_put(qphy->batt_psy); if (qphy->usb_psy) power_supply_put(qphy->usb_psy); debugfs_remove_recursive(qphy->root); usb_remove_phy(&qphy->phy); qphy->cable_connected = false; Loading