diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 34439f0250e9..948c8a6f6870 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -287,13 +287,6 @@ enum dwc3_id_state { DWC3_ID_FLOAT, }; -/* for type c cable */ -enum plug_orientation { - ORIENTATION_NONE, - ORIENTATION_CC1, - ORIENTATION_CC2, -}; - enum msm_usb_irq { HS_PHY_IRQ, PWR_EVNT_IRQ, @@ -476,7 +469,6 @@ struct dwc3_msm { atomic_t in_p3; unsigned int lpm_to_suspend_delay; - enum plug_orientation typec_orientation; u32 num_gsi_event_buffers; struct dwc3_event_buffer **gsi_ev_buff; int pm_qos_latency; @@ -2683,6 +2675,45 @@ static void dwc3_set_phy_speed_flags(struct dwc3_msm *mdwc) } } +static void dwc3_set_ssphy_orientation_flag(struct dwc3_msm *mdwc) +{ + struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); + union extcon_property_value val; + struct extcon_dev *edev = NULL; + unsigned int extcon_id; + int ret; + + mdwc->ss_phy->flags &= ~(PHY_LANE_A | PHY_LANE_B); + + if (mdwc->orientation_override) { + mdwc->ss_phy->flags |= mdwc->orientation_override; + } else if (mdwc->ss_redriver_node) { + ret = redriver_orientation_get(mdwc->ss_redriver_node); + if (ret == 0) + mdwc->ss_phy->flags |= PHY_LANE_A; + else + mdwc->ss_phy->flags |= PHY_LANE_B; + } else { + if (mdwc->extcon && mdwc->vbus_active && !mdwc->in_restart) { + extcon_id = EXTCON_USB; + edev = mdwc->extcon[mdwc->ext_idx].edev; + } else if (mdwc->extcon && mdwc->id_state == DWC3_ID_GROUND) { + extcon_id = EXTCON_USB_HOST; + edev = mdwc->extcon[mdwc->ext_idx].edev; + } + + if (edev && extcon_get_state(edev, extcon_id)) { + ret = extcon_get_property(edev, extcon_id, + EXTCON_PROP_USB_TYPEC_POLARITY, &val); + if (ret == 0) + mdwc->ss_phy->flags |= val.intval ? + PHY_LANE_B : PHY_LANE_A; + } + } + + dbg_event(0xFF, "ss_flag", mdwc->ss_phy->flags); +} + static void msm_dwc3_perf_vote_update(struct dwc3_msm *mdwc, bool perf_mode); @@ -3094,13 +3125,7 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) /* Resume SS PHY */ if (dwc->maximum_speed >= USB_SPEED_SUPER && mdwc->lpm_flags & MDWC3_SS_PHY_SUSPEND) { - mdwc->ss_phy->flags &= ~(PHY_LANE_A | PHY_LANE_B); - if (mdwc->orientation_override) - mdwc->ss_phy->flags |= mdwc->orientation_override; - else if (mdwc->typec_orientation == ORIENTATION_CC1) - mdwc->ss_phy->flags |= PHY_LANE_A; - else if (mdwc->typec_orientation == ORIENTATION_CC2) - mdwc->ss_phy->flags |= PHY_LANE_B; + dwc3_set_ssphy_orientation_flag(mdwc); usb_phy_set_suspend(mdwc->ss_phy, 0); mdwc->ss_phy->flags &= ~DEVICE_IN_SS_MODE; mdwc->lpm_flags &= ~MDWC3_SS_PHY_SUSPEND; @@ -3284,25 +3309,18 @@ static void dwc3_resume_work(struct work_struct *w) } dwc->maximum_speed = dwc->max_hw_supp_speed; - /* Check speed and Type-C polarity values in order to configure PHY */ + if (edev && extcon_get_state(edev, extcon_id)) { ret = extcon_get_property(edev, extcon_id, EXTCON_PROP_USB_SS, &val); if (!ret && val.intval == 0) dwc->maximum_speed = USB_SPEED_HIGH; - - ret = extcon_get_property(edev, extcon_id, - EXTCON_PROP_USB_TYPEC_POLARITY, &val); - if (ret) - mdwc->typec_orientation = ORIENTATION_NONE; - else - mdwc->typec_orientation = val.intval ? - ORIENTATION_CC2 : ORIENTATION_CC1; - - dbg_event(0xFF, "cc_state", mdwc->typec_orientation); } + if (dwc->maximum_speed >= USB_SPEED_SUPER) + dwc3_set_ssphy_orientation_flag(mdwc); + skip_update: dbg_log_string("max_speed:%d hw_supp_speed:%d override_speed:%d", dwc->maximum_speed, dwc->max_hw_supp_speed, @@ -3820,7 +3838,7 @@ static ssize_t orientation_store(struct device *dev, else if (sysfs_streq(buf, "B")) mdwc->orientation_override = PHY_LANE_B; else - mdwc->orientation_override = ORIENTATION_NONE; + mdwc->orientation_override = 0; return count; } diff --git a/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c b/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c index 9ca119f5a6bc..3849f2dab9ee 100644 --- a/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c +++ b/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c @@ -85,7 +85,6 @@ struct ssusb_redriver { struct i2c_client *client; int orientation_gpio; - bool orientation_gpio_enable; enum plug_orientation typec_orientation; enum operation_mode op_mode; @@ -403,40 +402,15 @@ err: static int ssusb_redriver_read_orientation(struct ssusb_redriver *redriver) { - struct device *dev = redriver->dev; - struct pinctrl *orientation_pinctrl; - struct pinctrl_state *gpio_state; int ret; - if (!redriver->orientation_gpio_enable) + if (!gpio_is_valid(redriver->orientation_gpio)) return -EINVAL; - orientation_pinctrl = pinctrl_get(dev); - if (IS_ERR_OR_NULL(orientation_pinctrl)) { - dev_err(dev, "Failed to get pinctrl\n"); - return -EINVAL; - } - - gpio_state = pinctrl_lookup_state(orientation_pinctrl, "enable_gpio"); - if (IS_ERR_OR_NULL(gpio_state)) { - dev_err(dev, "Failed to get gpio state\n"); - ret = -ENODEV; - goto put_pinctrl; - } - - ret = pinctrl_select_state(orientation_pinctrl, gpio_state); - if (ret) { - dev_err(redriver->dev, "fail to enable gpio state\n"); - ret = -EINVAL; - goto put_pinctrl; - } - - /* wait for some time ??? */ ret = gpio_get_value(redriver->orientation_gpio); if (ret < 0) { dev_err(redriver->dev, "fail to read gpio value\n"); - ret = -EINVAL; - goto put_pinctrl; + return -EINVAL; } if (ret == 0) @@ -444,14 +418,32 @@ static int ssusb_redriver_read_orientation(struct ssusb_redriver *redriver) else redriver->typec_orientation = ORIENTATION_CC2; - ret = 0; - -put_pinctrl: - pinctrl_put(orientation_pinctrl); - - return ret; + return 0; } +int redriver_orientation_get(struct device_node *node) +{ + struct ssusb_redriver *redriver; + struct i2c_client *client; + + if (!node) + return -ENODEV; + + client = of_find_i2c_device_by_node(node); + if (!client) + return -ENODEV; + + redriver = i2c_get_clientdata(client); + if (!redriver) + return -EINVAL; + + if (!gpio_is_valid(redriver->orientation_gpio)) + return -EINVAL; + + return gpio_get_value(redriver->orientation_gpio); +} +EXPORT_SYMBOL(redriver_orientation_get); + static int ssusb_redriver_ucsi_notifier(struct notifier_block *nb, unsigned long action, void *data) { @@ -669,9 +661,8 @@ static void ssusb_redriver_orientation_gpio_init( struct device *dev = redriver->dev; int rc; - redriver->orientation_gpio = - of_get_named_gpio(dev->of_node, "orientation_gpio", 0); - if (redriver->orientation_gpio < 0) { + redriver->orientation_gpio = of_get_gpio(dev->of_node, 0); + if (!gpio_is_valid(redriver->orientation_gpio)) { dev_err(dev, "Failed to get gpio\n"); return; } @@ -679,10 +670,9 @@ static void ssusb_redriver_orientation_gpio_init( rc = devm_gpio_request(dev, redriver->orientation_gpio, "redriver"); if (rc < 0) { dev_err(dev, "Failed to request gpio\n"); + redriver->orientation_gpio = -EINVAL; return; } - - redriver->orientation_gpio_enable = true; } static const struct regmap_config redriver_regmap = { diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c index f33c7726c0ba..dc9767bb52de 100644 --- a/drivers/usb/phy/phy-msm-ssusb-qmp.c +++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c @@ -370,51 +370,6 @@ static void msm_ssphy_qmp_setmode(struct msm_ssphy_qmp *phy, u32 mode) readl_relaxed(phy->base + phy->phy_reg[USB3_DP_COM_PHY_MODE_CTRL]); } -static void usb_qmp_update_hw_portselect(struct msm_ssphy_qmp *phy) -{ - struct pinctrl *portselect_pinctrl; - struct pinctrl_state *portselect_state; - u32 status; - - if (phy->phy.dev->pins) { - portselect_pinctrl = phy->phy.dev->pins->p; - portselect_state = phy->phy.dev->pins->default_state; - } else { - portselect_pinctrl = pinctrl_get(phy->phy.dev); - if (IS_ERR_OR_NULL(portselect_pinctrl)) { - dev_dbg(phy->phy.dev, "failed to get pinctrl\n"); - return; - } - - portselect_state = - pinctrl_lookup_state(portselect_pinctrl, "portselect"); - if (IS_ERR_OR_NULL(portselect_state)) { - dev_dbg(phy->phy.dev, - "failed to find portselect state\n"); - pinctrl_put(portselect_pinctrl); - return; - } - } - - writel_relaxed(0x01, - phy->base + phy->phy_reg[USB3_DP_COM_SW_RESET]); - - pinctrl_select_state(portselect_pinctrl, portselect_state); - - writel_relaxed(0x00, - phy->base + phy->phy_reg[USB3_DP_COM_SW_RESET]); - - if (!phy->phy.dev->pins) - pinctrl_put(portselect_pinctrl); - - if (phy->phy_reg[USB3_DP_COM_TYPEC_STATUS]) { - status = readl_relaxed(phy->base + - phy->phy_reg[USB3_DP_COM_TYPEC_STATUS]); - dev_dbg(phy->phy.dev, "hw port select %s\n", - status & PORTSELECT_RAW ? "CC2" : "CC1"); - } -} - static void usb_qmp_update_portselect_phymode(struct msm_ssphy_qmp *phy) { int val; @@ -431,7 +386,16 @@ static void usb_qmp_update_portselect_phymode(struct msm_ssphy_qmp *phy) switch (phy->phy_type) { case USB3_AND_DP: - usb_qmp_update_hw_portselect(phy); + if (phy->phy.dev->pins) { + writel_relaxed(0x01, + phy->base + phy->phy_reg[USB3_DP_COM_SW_RESET]); + + pinctrl_select_state(phy->phy.dev->pins->p, + phy->phy.dev->pins->default_state); + + writel_relaxed(0x00, + phy->base + phy->phy_reg[USB3_DP_COM_SW_RESET]); + } /* override hardware control for reset of qmp phy */ writel_relaxed(SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | diff --git a/include/linux/usb/redriver.h b/include/linux/usb/redriver.h index 2ad09e9a4d57..0ad48a87a725 100644 --- a/include/linux/usb/redriver.h +++ b/include/linux/usb/redriver.h @@ -12,6 +12,7 @@ int redriver_release_usb_lanes(struct device_node *node); int redriver_gadget_pullup(struct device_node *node, int is_on); int redriver_notify_connect(struct device_node *node); int redriver_notify_disconnect(struct device_node *node); +int redriver_orientation_get(struct device_node *node); #else @@ -35,6 +36,11 @@ static inline int redriver_notify_disconnect(struct device_node *node) return 0; } +static inline int redriver_orientation_get(struct device_node *node) +{ + return -ENODEV; +} + #endif #endif /*__LINUX_USB_REDRIVER_H */