aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc2/core.c')
-rw-r--r--drivers/usb/dwc2/core.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 55d5ae2a7ec7..01ac4a064feb 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -1020,6 +1020,196 @@ int dwc2_hsotg_wait_bit_clear(struct dwc2_hsotg *hsotg, u32 offset, u32 mask,
1020 return -ETIMEDOUT; 1020 return -ETIMEDOUT;
1021} 1021}
1022 1022
1023/*
1024 * Initializes the FSLSPClkSel field of the HCFG register depending on the
1025 * PHY type
1026 */
1027void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
1028{
1029 u32 hcfg, val;
1030
1031 if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
1032 hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
1033 hsotg->params.ulpi_fs_ls) ||
1034 hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
1035 /* Full speed PHY */
1036 val = HCFG_FSLSPCLKSEL_48_MHZ;
1037 } else {
1038 /* High speed PHY running at full speed or high speed */
1039 val = HCFG_FSLSPCLKSEL_30_60_MHZ;
1040 }
1041
1042 dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val);
1043 hcfg = dwc2_readl(hsotg, HCFG);
1044 hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
1045 hcfg |= val << HCFG_FSLSPCLKSEL_SHIFT;
1046 dwc2_writel(hsotg, hcfg, HCFG);
1047}
1048
1049static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
1050{
1051 u32 usbcfg, ggpio, i2cctl;
1052 int retval = 0;
1053
1054 /*
1055 * core_init() is now called on every switch so only call the
1056 * following for the first time through
1057 */
1058 if (select_phy) {
1059 dev_dbg(hsotg->dev, "FS PHY selected\n");
1060
1061 usbcfg = dwc2_readl(hsotg, GUSBCFG);
1062 if (!(usbcfg & GUSBCFG_PHYSEL)) {
1063 usbcfg |= GUSBCFG_PHYSEL;
1064 dwc2_writel(hsotg, usbcfg, GUSBCFG);
1065
1066 /* Reset after a PHY select */
1067 retval = dwc2_core_reset(hsotg, false);
1068
1069 if (retval) {
1070 dev_err(hsotg->dev,
1071 "%s: Reset failed, aborting", __func__);
1072 return retval;
1073 }
1074 }
1075
1076 if (hsotg->params.activate_stm_fs_transceiver) {
1077 ggpio = dwc2_readl(hsotg, GGPIO);
1078 if (!(ggpio & GGPIO_STM32_OTG_GCCFG_PWRDWN)) {
1079 dev_dbg(hsotg->dev, "Activating transceiver\n");
1080 /*
1081 * STM32F4x9 uses the GGPIO register as general
1082 * core configuration register.
1083 */
1084 ggpio |= GGPIO_STM32_OTG_GCCFG_PWRDWN;
1085 dwc2_writel(hsotg, ggpio, GGPIO);
1086 }
1087 }
1088 }
1089
1090 /*
1091 * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
1092 * do this on HNP Dev/Host mode switches (done in dev_init and
1093 * host_init).
1094 */
1095 if (dwc2_is_host_mode(hsotg))
1096 dwc2_init_fs_ls_pclk_sel(hsotg);
1097
1098 if (hsotg->params.i2c_enable) {
1099 dev_dbg(hsotg->dev, "FS PHY enabling I2C\n");
1100
1101 /* Program GUSBCFG.OtgUtmiFsSel to I2C */
1102 usbcfg = dwc2_readl(hsotg, GUSBCFG);
1103 usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL;
1104 dwc2_writel(hsotg, usbcfg, GUSBCFG);
1105
1106 /* Program GI2CCTL.I2CEn */
1107 i2cctl = dwc2_readl(hsotg, GI2CCTL);
1108 i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK;
1109 i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT;
1110 i2cctl &= ~GI2CCTL_I2CEN;
1111 dwc2_writel(hsotg, i2cctl, GI2CCTL);
1112 i2cctl |= GI2CCTL_I2CEN;
1113 dwc2_writel(hsotg, i2cctl, GI2CCTL);
1114 }
1115
1116 return retval;
1117}
1118
1119static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
1120{
1121 u32 usbcfg, usbcfg_old;
1122 int retval = 0;
1123
1124 if (!select_phy)
1125 return 0;
1126
1127 usbcfg = dwc2_readl(hsotg, GUSBCFG);
1128 usbcfg_old = usbcfg;
1129
1130 /*
1131 * HS PHY parameters. These parameters are preserved during soft reset
1132 * so only program the first time. Do a soft reset immediately after
1133 * setting phyif.
1134 */
1135 switch (hsotg->params.phy_type) {
1136 case DWC2_PHY_TYPE_PARAM_ULPI:
1137 /* ULPI interface */
1138 dev_dbg(hsotg->dev, "HS ULPI PHY selected\n");
1139 usbcfg |= GUSBCFG_ULPI_UTMI_SEL;
1140 usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
1141 if (hsotg->params.phy_ulpi_ddr)
1142 usbcfg |= GUSBCFG_DDRSEL;
1143
1144 /* Set external VBUS indicator as needed. */
1145 if (hsotg->params.oc_disable)
1146 usbcfg |= (GUSBCFG_ULPI_INT_VBUS_IND |
1147 GUSBCFG_INDICATORPASSTHROUGH);
1148 break;
1149 case DWC2_PHY_TYPE_PARAM_UTMI:
1150 /* UTMI+ interface */
1151 dev_dbg(hsotg->dev, "HS UTMI+ PHY selected\n");
1152 usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16);
1153 if (hsotg->params.phy_utmi_width == 16)
1154 usbcfg |= GUSBCFG_PHYIF16;
1155 break;
1156 default:
1157 dev_err(hsotg->dev, "FS PHY selected at HS!\n");
1158 break;
1159 }
1160
1161 if (usbcfg != usbcfg_old) {
1162 dwc2_writel(hsotg, usbcfg, GUSBCFG);
1163
1164 /* Reset after setting the PHY parameters */
1165 retval = dwc2_core_reset(hsotg, false);
1166 if (retval) {
1167 dev_err(hsotg->dev,
1168 "%s: Reset failed, aborting", __func__);
1169 return retval;
1170 }
1171 }
1172
1173 return retval;
1174}
1175
1176int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
1177{
1178 u32 usbcfg;
1179 int retval = 0;
1180
1181 if ((hsotg->params.speed == DWC2_SPEED_PARAM_FULL ||
1182 hsotg->params.speed == DWC2_SPEED_PARAM_LOW) &&
1183 hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
1184 /* If FS/LS mode with FS/LS PHY */
1185 retval = dwc2_fs_phy_init(hsotg, select_phy);
1186 if (retval)
1187 return retval;
1188 } else {
1189 /* High speed PHY */
1190 retval = dwc2_hs_phy_init(hsotg, select_phy);
1191 if (retval)
1192 return retval;
1193 }
1194
1195 if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
1196 hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
1197 hsotg->params.ulpi_fs_ls) {
1198 dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
1199 usbcfg = dwc2_readl(hsotg, GUSBCFG);
1200 usbcfg |= GUSBCFG_ULPI_FS_LS;
1201 usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M;
1202 dwc2_writel(hsotg, usbcfg, GUSBCFG);
1203 } else {
1204 usbcfg = dwc2_readl(hsotg, GUSBCFG);
1205 usbcfg &= ~GUSBCFG_ULPI_FS_LS;
1206 usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M;
1207 dwc2_writel(hsotg, usbcfg, GUSBCFG);
1208 }
1209
1210 return retval;
1211}
1212
1023MODULE_DESCRIPTION("DESIGNWARE HS OTG Core"); 1213MODULE_DESCRIPTION("DESIGNWARE HS OTG Core");
1024MODULE_AUTHOR("Synopsys, Inc."); 1214MODULE_AUTHOR("Synopsys, Inc.");
1025MODULE_LICENSE("Dual BSD/GPL"); 1215MODULE_LICENSE("Dual BSD/GPL");