Merge "phy: msm: usb: Check VBUS state before accessing registers in suspend"
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
a0e406a6f7
@@ -1420,6 +1420,7 @@ static irqreturn_t msm_otg_phy_irq_handler(int irq, void *data)
|
|||||||
|
|
||||||
static void msm_otg_set_vbus_state(int online);
|
static void msm_otg_set_vbus_state(int online);
|
||||||
static void msm_otg_perf_vote_update(struct msm_otg *motg, bool perf_mode);
|
static void msm_otg_perf_vote_update(struct msm_otg *motg, bool perf_mode);
|
||||||
|
static int get_psy_type(struct msm_otg *motg);
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int msm_otg_suspend(struct msm_otg *motg)
|
static int msm_otg_suspend(struct msm_otg *motg)
|
||||||
@@ -1458,7 +1459,11 @@ static int msm_otg_suspend(struct msm_otg *motg)
|
|||||||
msm_otg_perf_vote_update(motg, false);
|
msm_otg_perf_vote_update(motg, false);
|
||||||
|
|
||||||
host_pc_charger = (motg->chg_type == USB_SDP_CHARGER) ||
|
host_pc_charger = (motg->chg_type == USB_SDP_CHARGER) ||
|
||||||
(motg->chg_type == USB_CDP_CHARGER);
|
(motg->chg_type == USB_CDP_CHARGER) ||
|
||||||
|
(get_psy_type(motg) == POWER_SUPPLY_TYPE_USB) ||
|
||||||
|
(get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_CDP);
|
||||||
|
msm_otg_dbg_log_event(phy, "CHARGER CONNECTED",
|
||||||
|
host_pc_charger, motg->inputs);
|
||||||
|
|
||||||
/* !BSV, but its handling is in progress by otg sm_work */
|
/* !BSV, but its handling is in progress by otg sm_work */
|
||||||
sm_work_busy = !test_bit(B_SESS_VLD, &motg->inputs) &&
|
sm_work_busy = !test_bit(B_SESS_VLD, &motg->inputs) &&
|
||||||
@@ -1468,17 +1473,6 @@ static int msm_otg_suspend(struct msm_otg *motg)
|
|||||||
if (motg->err_event_seen)
|
if (motg->err_event_seen)
|
||||||
msm_otg_reset(phy);
|
msm_otg_reset(phy);
|
||||||
|
|
||||||
/* Enable line state difference wakeup fix for only device and host
|
|
||||||
* bus suspend scenarios. Otherwise PHY can not be suspended when
|
|
||||||
* a charger that pulls DP/DM high is connected.
|
|
||||||
*/
|
|
||||||
config2 = readl_relaxed(USB_GENCONFIG_2);
|
|
||||||
if (device_bus_suspend)
|
|
||||||
config2 |= GENCONFIG_2_LINESTATE_DIFF_WAKEUP_EN;
|
|
||||||
else
|
|
||||||
config2 &= ~GENCONFIG_2_LINESTATE_DIFF_WAKEUP_EN;
|
|
||||||
writel_relaxed(config2, USB_GENCONFIG_2);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Abort suspend when,
|
* Abort suspend when,
|
||||||
* 1. host mode activation in progress due to Micro-A cable insertion
|
* 1. host mode activation in progress due to Micro-A cable insertion
|
||||||
@@ -1496,6 +1490,17 @@ static int msm_otg_suspend(struct msm_otg *motg)
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enable line state difference wakeup fix for only device and host
|
||||||
|
* bus suspend scenarios. Otherwise PHY can not be suspended when
|
||||||
|
* a charger that pulls DP/DM high is connected.
|
||||||
|
*/
|
||||||
|
config2 = readl_relaxed(USB_GENCONFIG_2);
|
||||||
|
if (device_bus_suspend)
|
||||||
|
config2 |= GENCONFIG_2_LINESTATE_DIFF_WAKEUP_EN;
|
||||||
|
else
|
||||||
|
config2 &= ~GENCONFIG_2_LINESTATE_DIFF_WAKEUP_EN;
|
||||||
|
writel_relaxed(config2, USB_GENCONFIG_2);
|
||||||
|
|
||||||
if (motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED) {
|
if (motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED) {
|
||||||
/* put the controller in non-driving mode */
|
/* put the controller in non-driving mode */
|
||||||
func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
|
func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
|
||||||
@@ -2862,6 +2867,10 @@ static void check_for_sdp_connection(struct work_struct *w)
|
|||||||
msm_otg_set_vbus_state(motg->vbus_state);
|
msm_otg_set_vbus_state(motg->vbus_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DP_PULSE_WIDTH_MSEC 200
|
||||||
|
static int
|
||||||
|
msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width);
|
||||||
|
|
||||||
static void msm_otg_sm_work(struct work_struct *w)
|
static void msm_otg_sm_work(struct work_struct *w)
|
||||||
{
|
{
|
||||||
struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
|
struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
|
||||||
@@ -2905,6 +2914,9 @@ static void msm_otg_sm_work(struct work_struct *w)
|
|||||||
get_pm_runtime_counter(dev), 0);
|
get_pm_runtime_counter(dev), 0);
|
||||||
pm_runtime_put_sync(dev);
|
pm_runtime_put_sync(dev);
|
||||||
break;
|
break;
|
||||||
|
} else if (get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_CDP) {
|
||||||
|
pr_debug("Connected to CDP, pull DP up from sm_work\n");
|
||||||
|
msm_otg_phy_drive_dp_pulse(motg, DP_PULSE_WIDTH_MSEC);
|
||||||
}
|
}
|
||||||
pm_runtime_put(dev);
|
pm_runtime_put(dev);
|
||||||
/* FALL THROUGH */
|
/* FALL THROUGH */
|
||||||
@@ -3073,9 +3085,14 @@ msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
bool in_lpm = false;
|
||||||
|
|
||||||
msm_otg_dbg_log_event(&motg->phy, "DRIVE DP PULSE",
|
msm_otg_dbg_log_event(&motg->phy, "DRIVE DP PULSE",
|
||||||
motg->inputs, 0);
|
motg->inputs, 0);
|
||||||
|
if (atomic_read(&motg->in_lpm))
|
||||||
|
in_lpm = true;
|
||||||
|
|
||||||
|
if (in_lpm) {
|
||||||
ret = msm_hsusb_ldo_enable(motg, USB_PHY_REG_ON);
|
ret = msm_hsusb_ldo_enable(motg, USB_PHY_REG_ON);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -3086,6 +3103,7 @@ msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width)
|
|||||||
clk_prepare_enable(motg->phy_csr_clk);
|
clk_prepare_enable(motg->phy_csr_clk);
|
||||||
clk_prepare_enable(motg->core_clk);
|
clk_prepare_enable(motg->core_clk);
|
||||||
clk_prepare_enable(motg->pclk);
|
clk_prepare_enable(motg->pclk);
|
||||||
|
}
|
||||||
|
|
||||||
msm_otg_exit_phy_retention(motg);
|
msm_otg_exit_phy_retention(motg);
|
||||||
|
|
||||||
@@ -3131,6 +3149,7 @@ msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width)
|
|||||||
|
|
||||||
/* Make sure above writes are completed before clks off */
|
/* Make sure above writes are completed before clks off */
|
||||||
mb();
|
mb();
|
||||||
|
if (in_lpm) {
|
||||||
clk_disable_unprepare(motg->pclk);
|
clk_disable_unprepare(motg->pclk);
|
||||||
clk_disable_unprepare(motg->core_clk);
|
clk_disable_unprepare(motg->core_clk);
|
||||||
clk_disable_unprepare(motg->phy_csr_clk);
|
clk_disable_unprepare(motg->phy_csr_clk);
|
||||||
@@ -3138,17 +3157,19 @@ msm_otg_phy_drive_dp_pulse(struct msm_otg *motg, unsigned int pulse_width)
|
|||||||
regulator_disable(hsusb_vdd);
|
regulator_disable(hsusb_vdd);
|
||||||
msm_hsusb_config_vddcx(0);
|
msm_hsusb_config_vddcx(0);
|
||||||
msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
|
msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
|
||||||
|
} else {
|
||||||
|
msm_otg_reset(&motg->phy);
|
||||||
|
}
|
||||||
|
|
||||||
msm_otg_dbg_log_event(&motg->phy, "DP PULSE DRIVEN",
|
msm_otg_dbg_log_event(&motg->phy, "DP PULSE DRIVEN",
|
||||||
motg->inputs, 0);
|
motg->inputs, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DP_PULSE_WIDTH_MSEC 200
|
|
||||||
|
|
||||||
static void msm_otg_set_vbus_state(int online)
|
static void msm_otg_set_vbus_state(int online)
|
||||||
{
|
{
|
||||||
struct msm_otg *motg = the_msm_otg;
|
struct msm_otg *motg = the_msm_otg;
|
||||||
|
struct usb_otg *otg = motg->phy.otg;
|
||||||
|
|
||||||
motg->vbus_state = online;
|
motg->vbus_state = online;
|
||||||
|
|
||||||
@@ -3161,7 +3182,12 @@ static void msm_otg_set_vbus_state(int online)
|
|||||||
motg->inputs, 0);
|
motg->inputs, 0);
|
||||||
if (test_and_set_bit(B_SESS_VLD, &motg->inputs))
|
if (test_and_set_bit(B_SESS_VLD, &motg->inputs))
|
||||||
return;
|
return;
|
||||||
if (get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_CDP) {
|
/*
|
||||||
|
* It might race with block reset happening in sm_work, while
|
||||||
|
* state machine is in undefined state. Add check to avoid it.
|
||||||
|
*/
|
||||||
|
if ((get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_CDP) &&
|
||||||
|
(otg->state != OTG_STATE_UNDEFINED)) {
|
||||||
pr_debug("Connected to CDP, pull DP up\n");
|
pr_debug("Connected to CDP, pull DP up\n");
|
||||||
msm_otg_phy_drive_dp_pulse(motg, DP_PULSE_WIDTH_MSEC);
|
msm_otg_phy_drive_dp_pulse(motg, DP_PULSE_WIDTH_MSEC);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user