Loading Documentation/devicetree/bindings/usb/msm-phy.txt +3 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ Optional properties: - qcom,primary-phy: If present, indicates this is a secondary PHY and is dependent on the primary PHY referenced by this phandle. - qcom,set-pllbtune: If present, PLL tune is required in PHY initialization. - qcom,num_ports: Indicates the number of ports that supported by the HS PHY. If omitted, defaults to 1 Example: hsphy@f9200000 { Loading @@ -41,6 +43,7 @@ Example: vdd-supply = <&pm8841_s2_corner>; vdda18-supply = <&pm8941_l6>; vdda33-supply = <&pm8941_l24>; qcom,num_of_ports = <3>; qcom,vdd-voltage-level = <1 5 7>; }; Loading drivers/usb/phy/phy-msm-hsusb.c +108 −80 Original line number Diff line number Diff line Loading @@ -28,15 +28,19 @@ static int override_phy_init; module_param(override_phy_init, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq"); #define PORT_OFFSET(i) ((i == 0) ? 0x0 : ((i == 1) ? 0x6c : 0x88)) /* QSCRATCH register settings differ based on MSM core ver */ #define MSM_CORE_VER_120 0x10020061 /* QSCRATCH register offsets */ #define GENERAL_CFG_REG (0x08) #define HS_PHY_CTRL_REG (0x10) #define PARAMETER_OVERRIDE_X_REG (0x14) #define ALT_INTERRUPT_EN_REG (0x20) #define HS_PHY_IRQ_STAT_REG (0x24) #define HS_PHY_CTRL_REG(i) (0x10 + PORT_OFFSET(i)) #define PARAMETER_OVERRIDE_X_REG(i) (0x14 + PORT_OFFSET(i)) #define ALT_INTERRUPT_EN_REG(i) (0x20 + PORT_OFFSET(i)) #define HS_PHY_IRQ_STAT_REG(i) (0x24 + PORT_OFFSET(i)) #define HS_PHY_CTRL_COMMON_REG (0xEC) /* ver >= MSM_CORE_VER_120 */ /* GENERAL_CFG_REG bits */ Loading Loading @@ -123,6 +127,7 @@ struct msm_hsphy { /* Using external VBUS/ID notification */ bool ext_vbus_id; int num_ports; }; static int msm_hsusb_config_vdd(struct msm_hsphy *phy, int high) Loading Loading @@ -266,7 +271,7 @@ static int msm_hsphy_init(struct usb_phy *uphy) * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs, * and disable RETENTION (power-on default is ENABLED) */ val = readl_relaxed(phy->base + HS_PHY_CTRL_REG); val = readl_relaxed(phy->base + HS_PHY_CTRL_REG(0)); val |= (USB2_UTMI_CLK_EN | CLAMP_MPM_DPSE_DMSE_EN_N | RETENABLEN); if (uphy->flags & ENABLE_SECONDARY_PHY) { Loading @@ -274,7 +279,7 @@ static int msm_hsphy_init(struct usb_phy *uphy) val |= FREECLK_DIS_WHEN_SUSP; } writel_relaxed(val, phy->base + HS_PHY_CTRL_REG); writel_relaxed(val, phy->base + HS_PHY_CTRL_REG(0)); usleep_range(2000, 2200); if (uphy->flags & ENABLE_SECONDARY_PHY) Loading Loading @@ -306,7 +311,7 @@ static int msm_hsphy_init(struct usb_phy *uphy) phy->hsphy_init_seq = override_phy_init; if (phy->hsphy_init_seq) msm_usb_write_readback(phy->base, PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF, PARAMETER_OVERRIDE_X_REG(0), 0x03FFFFFF, phy->hsphy_init_seq & 0x03FFFFFF); return 0; Loading @@ -317,6 +322,7 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy); bool host = uphy->flags & PHY_HOST_MODE; bool chg_connected = uphy->flags & PHY_CHARGER_CONNECTED; int i; if (!!suspend == phy->suspended) { dev_dbg(uphy->dev, "%s\n", suspend ? "already suspended" Loading @@ -325,22 +331,24 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) } if (suspend) { for (i = 0; i < phy->num_ports; i++) { /* Clear interrupt latch register */ writel_relaxed(ALT_INTERRUPT_MASK, phy->base + HS_PHY_IRQ_STAT_REG); phy->base + HS_PHY_IRQ_STAT_REG(i)); if (host) { /* Enable DP and DM HV interrupts */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG, ALT_INTERRUPT_EN_REG(i), LINESTATE_INTEN, LINESTATE_INTEN); else msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG, ALT_INTERRUPT_EN_REG(i), DPDMHV_INT_MASK, DPDMHV_INT_MASK); udelay(5); } else { /* set the following: Loading @@ -354,10 +362,11 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) COMMON_OTGDISABLE0); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, HS_PHY_CTRL_REG(i), OTGDISABLE0, OTGDISABLE0); msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), (USB2_SUSPEND_N_SEL | USB2_SUSPEND_N), USB2_SUSPEND_N_SEL); /* Loading @@ -372,17 +381,20 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) COMMON_PLLITUNE_1); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, HS_PHY_CTRL_REG(i), RETENABLEN, 0); } } if (!phy->ext_vbus_id) /* Enable PHY-based IDHV and OTGSESSVLD HV interrupts */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, /* Enable PHY-based IDHV and *OTGSESSVLD HV interrupts */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), (OTGSESSVLDHV_INTEN | IDHV_INTEN), (OTGSESSVLDHV_INTEN | IDHV_INTEN)); } /* can turn off regulators if disconnected in device mode */ if (!host && !chg_connected) { if (phy->ext_vbus_id) Loading @@ -407,23 +419,25 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) FSEL_MASK, FSEL_DEFAULT); } } for (i = 0; i < phy->num_ports; i++) { if (!phy->ext_vbus_id) /* Disable HV interrupts */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, (OTGSESSVLDHV_INTEN | IDHV_INTEN), 0); msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), (OTGSESSVLDHV_INTEN | IDHV_INTEN), 0); if (host) { /* Clear interrupt latch register */ writel_relaxed(0x0, phy->base + HS_PHY_IRQ_STAT_REG); writel_relaxed(0x0, phy->base + HS_PHY_IRQ_STAT_REG(i)); /* Disable DP and DM HV interrupt */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG, ALT_INTERRUPT_EN_REG(i), LINESTATE_INTEN, 0); else msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG, ALT_INTERRUPT_EN_REG(i), DPDMHV_INT_MASK, 0); } else { /* Disable PHY retention */ Loading @@ -433,11 +447,12 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) COMMON_PLLITUNE_1, 0); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, HS_PHY_CTRL_REG(i), RETENABLEN, RETENABLEN); /* Bring PHY out of suspend */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), USB2_SUSPEND_N_SEL, 0); if (phy->core_ver >= MSM_CORE_VER_120) Loading @@ -447,10 +462,11 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) 0); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, HS_PHY_CTRL_REG(i), OTGDISABLE0, 0); } } } phy->suspended = !!suspend; /* double-NOT coerces to bool value */ return 0; Loading @@ -473,21 +489,24 @@ static int msm_hsphy_notify_connect(struct usb_phy *uphy, COMMON_VBUSVLDEXTSEL0, COMMON_VBUSVLDEXTSEL0); } else { msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), VBUSVLDEXTSEL0, VBUSVLDEXTSEL0); } /* Enable D+ pull-up resistor */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), VBUSVLDEXT0, VBUSVLDEXT0); /* Set OTG VBUS Valid from HSPHY to controller */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, UTMI_OTG_VBUS_VALID, UTMI_OTG_VBUS_VALID); msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), UTMI_OTG_VBUS_VALID, UTMI_OTG_VBUS_VALID); /* Indicate value is driven by UTMI_OTG_VBUS_VALID bit */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), SW_SESSVLD_SEL, SW_SESSVLD_SEL); return 0; Loading @@ -505,15 +524,16 @@ static int msm_hsphy_notify_disconnect(struct usb_phy *uphy, return 0; /* Clear OTG VBUS Valid to Controller */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), UTMI_OTG_VBUS_VALID, 0); /* Disable D+ pull-up resistor */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, VBUSVLDEXT0, 0); msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), VBUSVLDEXT0, 0); /* Indicate value is no longer driven by UTMI_OTG_VBUS_VALID bit */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), SW_SESSVLD_SEL, 0); return 0; Loading Loading @@ -622,6 +642,14 @@ static int msm_hsphy_probe(struct platform_device *pdev) else if (!phy->hsphy_init_seq) dev_warn(dev, "hsphy init seq cannot be 0. Using POR value\n"); if (of_property_read_u32(dev->of_node, "qcom,num-ports", &phy->num_ports)) phy->num_ports = 1; else if (phy->num_ports > 3) { dev_err(dev, " number of ports more that 3 is not supported\n"); goto disable_hs_vdd; } phy->set_pllbtune = of_property_read_bool(dev->of_node, "qcom,set-pllbtune"); Loading Loading
Documentation/devicetree/bindings/usb/msm-phy.txt +3 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,8 @@ Optional properties: - qcom,primary-phy: If present, indicates this is a secondary PHY and is dependent on the primary PHY referenced by this phandle. - qcom,set-pllbtune: If present, PLL tune is required in PHY initialization. - qcom,num_ports: Indicates the number of ports that supported by the HS PHY. If omitted, defaults to 1 Example: hsphy@f9200000 { Loading @@ -41,6 +43,7 @@ Example: vdd-supply = <&pm8841_s2_corner>; vdda18-supply = <&pm8941_l6>; vdda33-supply = <&pm8941_l24>; qcom,num_of_ports = <3>; qcom,vdd-voltage-level = <1 5 7>; }; Loading
drivers/usb/phy/phy-msm-hsusb.c +108 −80 Original line number Diff line number Diff line Loading @@ -28,15 +28,19 @@ static int override_phy_init; module_param(override_phy_init, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq"); #define PORT_OFFSET(i) ((i == 0) ? 0x0 : ((i == 1) ? 0x6c : 0x88)) /* QSCRATCH register settings differ based on MSM core ver */ #define MSM_CORE_VER_120 0x10020061 /* QSCRATCH register offsets */ #define GENERAL_CFG_REG (0x08) #define HS_PHY_CTRL_REG (0x10) #define PARAMETER_OVERRIDE_X_REG (0x14) #define ALT_INTERRUPT_EN_REG (0x20) #define HS_PHY_IRQ_STAT_REG (0x24) #define HS_PHY_CTRL_REG(i) (0x10 + PORT_OFFSET(i)) #define PARAMETER_OVERRIDE_X_REG(i) (0x14 + PORT_OFFSET(i)) #define ALT_INTERRUPT_EN_REG(i) (0x20 + PORT_OFFSET(i)) #define HS_PHY_IRQ_STAT_REG(i) (0x24 + PORT_OFFSET(i)) #define HS_PHY_CTRL_COMMON_REG (0xEC) /* ver >= MSM_CORE_VER_120 */ /* GENERAL_CFG_REG bits */ Loading Loading @@ -123,6 +127,7 @@ struct msm_hsphy { /* Using external VBUS/ID notification */ bool ext_vbus_id; int num_ports; }; static int msm_hsusb_config_vdd(struct msm_hsphy *phy, int high) Loading Loading @@ -266,7 +271,7 @@ static int msm_hsphy_init(struct usb_phy *uphy) * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs, * and disable RETENTION (power-on default is ENABLED) */ val = readl_relaxed(phy->base + HS_PHY_CTRL_REG); val = readl_relaxed(phy->base + HS_PHY_CTRL_REG(0)); val |= (USB2_UTMI_CLK_EN | CLAMP_MPM_DPSE_DMSE_EN_N | RETENABLEN); if (uphy->flags & ENABLE_SECONDARY_PHY) { Loading @@ -274,7 +279,7 @@ static int msm_hsphy_init(struct usb_phy *uphy) val |= FREECLK_DIS_WHEN_SUSP; } writel_relaxed(val, phy->base + HS_PHY_CTRL_REG); writel_relaxed(val, phy->base + HS_PHY_CTRL_REG(0)); usleep_range(2000, 2200); if (uphy->flags & ENABLE_SECONDARY_PHY) Loading Loading @@ -306,7 +311,7 @@ static int msm_hsphy_init(struct usb_phy *uphy) phy->hsphy_init_seq = override_phy_init; if (phy->hsphy_init_seq) msm_usb_write_readback(phy->base, PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF, PARAMETER_OVERRIDE_X_REG(0), 0x03FFFFFF, phy->hsphy_init_seq & 0x03FFFFFF); return 0; Loading @@ -317,6 +322,7 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) struct msm_hsphy *phy = container_of(uphy, struct msm_hsphy, phy); bool host = uphy->flags & PHY_HOST_MODE; bool chg_connected = uphy->flags & PHY_CHARGER_CONNECTED; int i; if (!!suspend == phy->suspended) { dev_dbg(uphy->dev, "%s\n", suspend ? "already suspended" Loading @@ -325,22 +331,24 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) } if (suspend) { for (i = 0; i < phy->num_ports; i++) { /* Clear interrupt latch register */ writel_relaxed(ALT_INTERRUPT_MASK, phy->base + HS_PHY_IRQ_STAT_REG); phy->base + HS_PHY_IRQ_STAT_REG(i)); if (host) { /* Enable DP and DM HV interrupts */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG, ALT_INTERRUPT_EN_REG(i), LINESTATE_INTEN, LINESTATE_INTEN); else msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG, ALT_INTERRUPT_EN_REG(i), DPDMHV_INT_MASK, DPDMHV_INT_MASK); udelay(5); } else { /* set the following: Loading @@ -354,10 +362,11 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) COMMON_OTGDISABLE0); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, HS_PHY_CTRL_REG(i), OTGDISABLE0, OTGDISABLE0); msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), (USB2_SUSPEND_N_SEL | USB2_SUSPEND_N), USB2_SUSPEND_N_SEL); /* Loading @@ -372,17 +381,20 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) COMMON_PLLITUNE_1); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, HS_PHY_CTRL_REG(i), RETENABLEN, 0); } } if (!phy->ext_vbus_id) /* Enable PHY-based IDHV and OTGSESSVLD HV interrupts */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, /* Enable PHY-based IDHV and *OTGSESSVLD HV interrupts */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), (OTGSESSVLDHV_INTEN | IDHV_INTEN), (OTGSESSVLDHV_INTEN | IDHV_INTEN)); } /* can turn off regulators if disconnected in device mode */ if (!host && !chg_connected) { if (phy->ext_vbus_id) Loading @@ -407,23 +419,25 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) FSEL_MASK, FSEL_DEFAULT); } } for (i = 0; i < phy->num_ports; i++) { if (!phy->ext_vbus_id) /* Disable HV interrupts */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, (OTGSESSVLDHV_INTEN | IDHV_INTEN), 0); msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), (OTGSESSVLDHV_INTEN | IDHV_INTEN), 0); if (host) { /* Clear interrupt latch register */ writel_relaxed(0x0, phy->base + HS_PHY_IRQ_STAT_REG); writel_relaxed(0x0, phy->base + HS_PHY_IRQ_STAT_REG(i)); /* Disable DP and DM HV interrupt */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG, ALT_INTERRUPT_EN_REG(i), LINESTATE_INTEN, 0); else msm_usb_write_readback(phy->base, ALT_INTERRUPT_EN_REG, ALT_INTERRUPT_EN_REG(i), DPDMHV_INT_MASK, 0); } else { /* Disable PHY retention */ Loading @@ -433,11 +447,12 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) COMMON_PLLITUNE_1, 0); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, HS_PHY_CTRL_REG(i), RETENABLEN, RETENABLEN); /* Bring PHY out of suspend */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(i), USB2_SUSPEND_N_SEL, 0); if (phy->core_ver >= MSM_CORE_VER_120) Loading @@ -447,10 +462,11 @@ static int msm_hsphy_set_suspend(struct usb_phy *uphy, int suspend) 0); else msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, HS_PHY_CTRL_REG(i), OTGDISABLE0, 0); } } } phy->suspended = !!suspend; /* double-NOT coerces to bool value */ return 0; Loading @@ -473,21 +489,24 @@ static int msm_hsphy_notify_connect(struct usb_phy *uphy, COMMON_VBUSVLDEXTSEL0, COMMON_VBUSVLDEXTSEL0); } else { msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), VBUSVLDEXTSEL0, VBUSVLDEXTSEL0); } /* Enable D+ pull-up resistor */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), VBUSVLDEXT0, VBUSVLDEXT0); /* Set OTG VBUS Valid from HSPHY to controller */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, UTMI_OTG_VBUS_VALID, UTMI_OTG_VBUS_VALID); msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), UTMI_OTG_VBUS_VALID, UTMI_OTG_VBUS_VALID); /* Indicate value is driven by UTMI_OTG_VBUS_VALID bit */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), SW_SESSVLD_SEL, SW_SESSVLD_SEL); return 0; Loading @@ -505,15 +524,16 @@ static int msm_hsphy_notify_disconnect(struct usb_phy *uphy, return 0; /* Clear OTG VBUS Valid to Controller */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), UTMI_OTG_VBUS_VALID, 0); /* Disable D+ pull-up resistor */ msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, VBUSVLDEXT0, 0); msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), VBUSVLDEXT0, 0); /* Indicate value is no longer driven by UTMI_OTG_VBUS_VALID bit */ if (phy->core_ver >= MSM_CORE_VER_120) msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG, msm_usb_write_readback(phy->base, HS_PHY_CTRL_REG(0), SW_SESSVLD_SEL, 0); return 0; Loading Loading @@ -622,6 +642,14 @@ static int msm_hsphy_probe(struct platform_device *pdev) else if (!phy->hsphy_init_seq) dev_warn(dev, "hsphy init seq cannot be 0. Using POR value\n"); if (of_property_read_u32(dev->of_node, "qcom,num-ports", &phy->num_ports)) phy->num_ports = 1; else if (phy->num_ports > 3) { dev_err(dev, " number of ports more that 3 is not supported\n"); goto disable_hs_vdd; } phy->set_pllbtune = of_property_read_bool(dev->of_node, "qcom,set-pllbtune"); Loading