Loading drivers/usb/dwc3/dwc3-msm.c +12 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -3104,6 +3104,7 @@ static int dwc3_cpu_notifier_cb(struct notifier_block *nfb, } static void dwc3_otg_sm_work(struct work_struct *w); static int get_psy_type(struct dwc3_msm *mdwc); static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) { Loading Loading @@ -3258,6 +3259,8 @@ static void check_for_sdp_connection(struct work_struct *w) } } #define DP_PULSE_WIDTH_MSEC 200 static int dwc3_msm_vbus_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { Loading @@ -3270,6 +3273,14 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb, return NOTIFY_DONE; mdwc->vbus_active = event; if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_CDP && mdwc->vbus_active) { dev_dbg(mdwc->dev, "Connected to CDP, pull DP up\n"); usb_phy_drive_dp_pulse(mdwc->hs_phy, DP_PULSE_WIDTH_MSEC); } if (dwc->is_drd && !mdwc->in_restart) queue_work(mdwc->dwc3_wq, &mdwc->resume_work); Loading drivers/usb/phy/phy-msm-qusb-v2.c +69 −1 Original line number Diff line number Diff line /* * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2014-2018, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -32,6 +32,7 @@ /* QUSB2PHY_PWR_CTRL1 register related bits */ #define PWR_CTRL1_POWR_DOWN BIT(0) #define CLAMP_N_EN BIT(1) /* QUSB2PHY_PLL_COMMON_STATUS_ONE register related bits */ #define CORE_READY_STATUS BIT(0) Loading Loading @@ -82,6 +83,10 @@ /* STAT5 register bits */ #define VSTATUS_PLL_LOCK_STATUS_MASK BIT(0) /* DEBUG_CTRL4 register bits */ #define FORCED_UTMI_DPPULLDOWN BIT(2) #define FORCED_UTMI_DMPULLDOWN BIT(3) enum qusb_phy_reg { PORT_TUNE1, PLL_COMMON_STATUS_ONE, Loading @@ -94,6 +99,8 @@ enum qusb_phy_reg { SQ_CTRL2, DEBUG_CTRL1, DEBUG_CTRL2, DEBUG_CTRL3, DEBUG_CTRL4, STAT5, USB2_PHY_REG_MAX, }; Loading Loading @@ -452,6 +459,24 @@ static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt, usleep_range(delay, (delay + 2000)); } } static void msm_usb_write_readback(void __iomem *base, u32 offset, const u32 mask, u32 val) { u32 write_val, tmp = readl_relaxed(base + offset); tmp &= ~mask; /* retain other bits */ write_val = tmp | val; writel_relaxed(write_val, base + offset); /* Read back to see if val was written */ tmp = readl_relaxed(base + offset); tmp &= mask; /* clear other bits */ if (tmp != val) pr_err("%s: write: %x to QSCRATCH: %x FAILED\n", __func__, val, offset); } static void qusb_phy_reset(struct qusb_phy *qphy) { Loading Loading @@ -889,6 +914,48 @@ static int qusb_phy_disable_chirp(struct usb_phy *phy, bool disable) mutex_unlock(&qphy->lock); return ret; } static int msm_qusb_phy_drive_dp_pulse(struct usb_phy *phy, unsigned int interval_ms) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); qusb_phy_enable_clocks(qphy, true); msm_usb_write_readback(qphy->base, qphy->phy_reg[PWR_CTRL1], PWR_CTRL1_POWR_DOWN, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL4], FORCED_UTMI_DPPULLDOWN, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL4], FORCED_UTMI_DMPULLDOWN, FORCED_UTMI_DMPULLDOWN); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL3], 0xd1, 0xd1); msm_usb_write_readback(qphy->base, qphy->phy_reg[PWR_CTRL1], CLAMP_N_EN, CLAMP_N_EN); msm_usb_write_readback(qphy->base, qphy->phy_reg[INTR_CTRL], DPSE_INTR_HIGH_SEL, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[INTR_CTRL], DPSE_INTR_EN, DPSE_INTR_EN); msleep(interval_ms); msm_usb_write_readback(qphy->base, qphy->phy_reg[INTR_CTRL], DPSE_INTR_HIGH_SEL | DPSE_INTR_EN, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL3], 0xd1, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL4], FORCED_UTMI_DPPULLDOWN | FORCED_UTMI_DMPULLDOWN, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[PWR_CTRL1], PWR_CTRL1_POWR_DOWN | CLAMP_N_EN, 0x00); msleep(20); qusb_phy_enable_clocks(qphy, false); return 0; } static int qusb_phy_dpdm_regulator_enable(struct regulator_dev *rdev) { Loading Loading @@ -1332,6 +1399,7 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.type = USB_PHY_TYPE_USB2; qphy->phy.notify_connect = qusb_phy_notify_connect; qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; qphy->phy.drive_dp_pulse = msm_qusb_phy_drive_dp_pulse; /* * qusb_phy_disable_chirp is not required if soc version is Loading include/linux/usb/phy.h +10 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ struct usb_phy { /* reset the PHY clocks */ int (*reset)(struct usb_phy *x); int (*drive_dp_pulse)(struct usb_phy *x, unsigned int pulse_width); /* for notification of usb_phy_dbg_events */ void (*dbg_event)(struct usb_phy *x, Loading Loading @@ -241,6 +242,15 @@ usb_phy_reset(struct usb_phy *x) return 0; } static inline int usb_phy_drive_dp_pulse(struct usb_phy *x, unsigned int pulse_width) { if (x && x->drive_dp_pulse) return x->drive_dp_pulse(x, pulse_width); return 0; } /* for usb host and peripheral controller drivers */ #if IS_ENABLED(CONFIG_USB_PHY) extern struct usb_phy *usb_get_phy(enum usb_phy_type type); Loading Loading
drivers/usb/dwc3/dwc3-msm.c +12 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -3104,6 +3104,7 @@ static int dwc3_cpu_notifier_cb(struct notifier_block *nfb, } static void dwc3_otg_sm_work(struct work_struct *w); static int get_psy_type(struct dwc3_msm *mdwc); static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) { Loading Loading @@ -3258,6 +3259,8 @@ static void check_for_sdp_connection(struct work_struct *w) } } #define DP_PULSE_WIDTH_MSEC 200 static int dwc3_msm_vbus_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { Loading @@ -3270,6 +3273,14 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb, return NOTIFY_DONE; mdwc->vbus_active = event; if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_CDP && mdwc->vbus_active) { dev_dbg(mdwc->dev, "Connected to CDP, pull DP up\n"); usb_phy_drive_dp_pulse(mdwc->hs_phy, DP_PULSE_WIDTH_MSEC); } if (dwc->is_drd && !mdwc->in_restart) queue_work(mdwc->dwc3_wq, &mdwc->resume_work); Loading
drivers/usb/phy/phy-msm-qusb-v2.c +69 −1 Original line number Diff line number Diff line /* * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2014-2018, 2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -32,6 +32,7 @@ /* QUSB2PHY_PWR_CTRL1 register related bits */ #define PWR_CTRL1_POWR_DOWN BIT(0) #define CLAMP_N_EN BIT(1) /* QUSB2PHY_PLL_COMMON_STATUS_ONE register related bits */ #define CORE_READY_STATUS BIT(0) Loading Loading @@ -82,6 +83,10 @@ /* STAT5 register bits */ #define VSTATUS_PLL_LOCK_STATUS_MASK BIT(0) /* DEBUG_CTRL4 register bits */ #define FORCED_UTMI_DPPULLDOWN BIT(2) #define FORCED_UTMI_DMPULLDOWN BIT(3) enum qusb_phy_reg { PORT_TUNE1, PLL_COMMON_STATUS_ONE, Loading @@ -94,6 +99,8 @@ enum qusb_phy_reg { SQ_CTRL2, DEBUG_CTRL1, DEBUG_CTRL2, DEBUG_CTRL3, DEBUG_CTRL4, STAT5, USB2_PHY_REG_MAX, }; Loading Loading @@ -452,6 +459,24 @@ static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt, usleep_range(delay, (delay + 2000)); } } static void msm_usb_write_readback(void __iomem *base, u32 offset, const u32 mask, u32 val) { u32 write_val, tmp = readl_relaxed(base + offset); tmp &= ~mask; /* retain other bits */ write_val = tmp | val; writel_relaxed(write_val, base + offset); /* Read back to see if val was written */ tmp = readl_relaxed(base + offset); tmp &= mask; /* clear other bits */ if (tmp != val) pr_err("%s: write: %x to QSCRATCH: %x FAILED\n", __func__, val, offset); } static void qusb_phy_reset(struct qusb_phy *qphy) { Loading Loading @@ -889,6 +914,48 @@ static int qusb_phy_disable_chirp(struct usb_phy *phy, bool disable) mutex_unlock(&qphy->lock); return ret; } static int msm_qusb_phy_drive_dp_pulse(struct usb_phy *phy, unsigned int interval_ms) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); qusb_phy_enable_clocks(qphy, true); msm_usb_write_readback(qphy->base, qphy->phy_reg[PWR_CTRL1], PWR_CTRL1_POWR_DOWN, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL4], FORCED_UTMI_DPPULLDOWN, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL4], FORCED_UTMI_DMPULLDOWN, FORCED_UTMI_DMPULLDOWN); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL3], 0xd1, 0xd1); msm_usb_write_readback(qphy->base, qphy->phy_reg[PWR_CTRL1], CLAMP_N_EN, CLAMP_N_EN); msm_usb_write_readback(qphy->base, qphy->phy_reg[INTR_CTRL], DPSE_INTR_HIGH_SEL, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[INTR_CTRL], DPSE_INTR_EN, DPSE_INTR_EN); msleep(interval_ms); msm_usb_write_readback(qphy->base, qphy->phy_reg[INTR_CTRL], DPSE_INTR_HIGH_SEL | DPSE_INTR_EN, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL3], 0xd1, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[DEBUG_CTRL4], FORCED_UTMI_DPPULLDOWN | FORCED_UTMI_DMPULLDOWN, 0x00); msm_usb_write_readback(qphy->base, qphy->phy_reg[PWR_CTRL1], PWR_CTRL1_POWR_DOWN | CLAMP_N_EN, 0x00); msleep(20); qusb_phy_enable_clocks(qphy, false); return 0; } static int qusb_phy_dpdm_regulator_enable(struct regulator_dev *rdev) { Loading Loading @@ -1332,6 +1399,7 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.type = USB_PHY_TYPE_USB2; qphy->phy.notify_connect = qusb_phy_notify_connect; qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; qphy->phy.drive_dp_pulse = msm_qusb_phy_drive_dp_pulse; /* * qusb_phy_disable_chirp is not required if soc version is Loading
include/linux/usb/phy.h +10 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ struct usb_phy { /* reset the PHY clocks */ int (*reset)(struct usb_phy *x); int (*drive_dp_pulse)(struct usb_phy *x, unsigned int pulse_width); /* for notification of usb_phy_dbg_events */ void (*dbg_event)(struct usb_phy *x, Loading Loading @@ -241,6 +242,15 @@ usb_phy_reset(struct usb_phy *x) return 0; } static inline int usb_phy_drive_dp_pulse(struct usb_phy *x, unsigned int pulse_width) { if (x && x->drive_dp_pulse) return x->drive_dp_pulse(x, pulse_width); return 0; } /* for usb host and peripheral controller drivers */ #if IS_ENABLED(CONFIG_USB_PHY) extern struct usb_phy *usb_get_phy(enum usb_phy_type type); Loading