aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJules Maselbas <jmaselbas@kalray.eu>2019-04-05 09:35:32 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2019-05-03 02:13:48 -0400
commit059d8d528718407435216251eff8b49935b92b34 (patch)
tree3ddddd060d835412252dafd04e3af8ebb095d3ab
parent707d80f0a3c5fb58e61404277f6b103955fac294 (diff)
usb: dwc2: Move phy init into core
As the phy initialization is almost the same in host and gadget mode. This only move the phy initialization functions into core.c for now, the goal is to share theses functions between the two modes. Acked-by: Minas Harutyunyan <hminas@synopsys.com> Signed-off-by: Jules Maselbas <jmaselbas@kalray.eu> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r--drivers/usb/dwc2/core.c190
-rw-r--r--drivers/usb/dwc2/core.h2
-rw-r--r--drivers/usb/dwc2/hcd.c190
3 files changed, 192 insertions, 190 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");
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 8e3edf10d76d..9f3fc8e18277 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1286,6 +1286,8 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore);
1286int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg, int is_host); 1286int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg, int is_host);
1287int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, 1287int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
1288 int reset, int is_host); 1288 int reset, int is_host);
1289void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg);
1290int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy);
1289 1291
1290void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host); 1292void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host);
1291void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg); 1293void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 978232a9e4a8..7ac7b524243d 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -97,196 +97,6 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
97 dwc2_writel(hsotg, intmsk, GINTMSK); 97 dwc2_writel(hsotg, intmsk, GINTMSK);
98} 98}
99 99
100/*
101 * Initializes the FSLSPClkSel field of the HCFG register depending on the
102 * PHY type
103 */
104static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
105{
106 u32 hcfg, val;
107
108 if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
109 hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
110 hsotg->params.ulpi_fs_ls) ||
111 hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
112 /* Full speed PHY */
113 val = HCFG_FSLSPCLKSEL_48_MHZ;
114 } else {
115 /* High speed PHY running at full speed or high speed */
116 val = HCFG_FSLSPCLKSEL_30_60_MHZ;
117 }
118
119 dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val);
120 hcfg = dwc2_readl(hsotg, HCFG);
121 hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
122 hcfg |= val << HCFG_FSLSPCLKSEL_SHIFT;
123 dwc2_writel(hsotg, hcfg, HCFG);
124}
125
126static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
127{
128 u32 usbcfg, ggpio, i2cctl;
129 int retval = 0;
130
131 /*
132 * core_init() is now called on every switch so only call the
133 * following for the first time through
134 */
135 if (select_phy) {
136 dev_dbg(hsotg->dev, "FS PHY selected\n");
137
138 usbcfg = dwc2_readl(hsotg, GUSBCFG);
139 if (!(usbcfg & GUSBCFG_PHYSEL)) {
140 usbcfg |= GUSBCFG_PHYSEL;
141 dwc2_writel(hsotg, usbcfg, GUSBCFG);
142
143 /* Reset after a PHY select */
144 retval = dwc2_core_reset(hsotg, false);
145
146 if (retval) {
147 dev_err(hsotg->dev,
148 "%s: Reset failed, aborting", __func__);
149 return retval;
150 }
151 }
152
153 if (hsotg->params.activate_stm_fs_transceiver) {
154 ggpio = dwc2_readl(hsotg, GGPIO);
155 if (!(ggpio & GGPIO_STM32_OTG_GCCFG_PWRDWN)) {
156 dev_dbg(hsotg->dev, "Activating transceiver\n");
157 /*
158 * STM32F4x9 uses the GGPIO register as general
159 * core configuration register.
160 */
161 ggpio |= GGPIO_STM32_OTG_GCCFG_PWRDWN;
162 dwc2_writel(hsotg, ggpio, GGPIO);
163 }
164 }
165 }
166
167 /*
168 * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
169 * do this on HNP Dev/Host mode switches (done in dev_init and
170 * host_init).
171 */
172 if (dwc2_is_host_mode(hsotg))
173 dwc2_init_fs_ls_pclk_sel(hsotg);
174
175 if (hsotg->params.i2c_enable) {
176 dev_dbg(hsotg->dev, "FS PHY enabling I2C\n");
177
178 /* Program GUSBCFG.OtgUtmiFsSel to I2C */
179 usbcfg = dwc2_readl(hsotg, GUSBCFG);
180 usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL;
181 dwc2_writel(hsotg, usbcfg, GUSBCFG);
182
183 /* Program GI2CCTL.I2CEn */
184 i2cctl = dwc2_readl(hsotg, GI2CCTL);
185 i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK;
186 i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT;
187 i2cctl &= ~GI2CCTL_I2CEN;
188 dwc2_writel(hsotg, i2cctl, GI2CCTL);
189 i2cctl |= GI2CCTL_I2CEN;
190 dwc2_writel(hsotg, i2cctl, GI2CCTL);
191 }
192
193 return retval;
194}
195
196static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
197{
198 u32 usbcfg, usbcfg_old;
199 int retval = 0;
200
201 if (!select_phy)
202 return 0;
203
204 usbcfg = dwc2_readl(hsotg, GUSBCFG);
205 usbcfg_old = usbcfg;
206
207 /*
208 * HS PHY parameters. These parameters are preserved during soft reset
209 * so only program the first time. Do a soft reset immediately after
210 * setting phyif.
211 */
212 switch (hsotg->params.phy_type) {
213 case DWC2_PHY_TYPE_PARAM_ULPI:
214 /* ULPI interface */
215 dev_dbg(hsotg->dev, "HS ULPI PHY selected\n");
216 usbcfg |= GUSBCFG_ULPI_UTMI_SEL;
217 usbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL);
218 if (hsotg->params.phy_ulpi_ddr)
219 usbcfg |= GUSBCFG_DDRSEL;
220
221 /* Set external VBUS indicator as needed. */
222 if (hsotg->params.oc_disable)
223 usbcfg |= (GUSBCFG_ULPI_INT_VBUS_IND |
224 GUSBCFG_INDICATORPASSTHROUGH);
225 break;
226 case DWC2_PHY_TYPE_PARAM_UTMI:
227 /* UTMI+ interface */
228 dev_dbg(hsotg->dev, "HS UTMI+ PHY selected\n");
229 usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16);
230 if (hsotg->params.phy_utmi_width == 16)
231 usbcfg |= GUSBCFG_PHYIF16;
232 break;
233 default:
234 dev_err(hsotg->dev, "FS PHY selected at HS!\n");
235 break;
236 }
237
238 if (usbcfg != usbcfg_old) {
239 dwc2_writel(hsotg, usbcfg, GUSBCFG);
240
241 /* Reset after setting the PHY parameters */
242 retval = dwc2_core_reset(hsotg, false);
243 if (retval) {
244 dev_err(hsotg->dev,
245 "%s: Reset failed, aborting", __func__);
246 return retval;
247 }
248 }
249
250 return retval;
251}
252
253static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
254{
255 u32 usbcfg;
256 int retval = 0;
257
258 if ((hsotg->params.speed == DWC2_SPEED_PARAM_FULL ||
259 hsotg->params.speed == DWC2_SPEED_PARAM_LOW) &&
260 hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
261 /* If FS/LS mode with FS/LS PHY */
262 retval = dwc2_fs_phy_init(hsotg, select_phy);
263 if (retval)
264 return retval;
265 } else {
266 /* High speed PHY */
267 retval = dwc2_hs_phy_init(hsotg, select_phy);
268 if (retval)
269 return retval;
270 }
271
272 if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
273 hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
274 hsotg->params.ulpi_fs_ls) {
275 dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
276 usbcfg = dwc2_readl(hsotg, GUSBCFG);
277 usbcfg |= GUSBCFG_ULPI_FS_LS;
278 usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M;
279 dwc2_writel(hsotg, usbcfg, GUSBCFG);
280 } else {
281 usbcfg = dwc2_readl(hsotg, GUSBCFG);
282 usbcfg &= ~GUSBCFG_ULPI_FS_LS;
283 usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M;
284 dwc2_writel(hsotg, usbcfg, GUSBCFG);
285 }
286
287 return retval;
288}
289
290static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) 100static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
291{ 101{
292 u32 ahbcfg = dwc2_readl(hsotg, GAHBCFG); 102 u32 ahbcfg = dwc2_readl(hsotg, GAHBCFG);