aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorShengzhou Liu <Shengzhou.Liu@freescale.com>2012-08-22 06:17:00 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-05 19:52:08 -0400
commit3735ba8db8e6ea22ad3ff524328926d8d780a884 (patch)
tree002b17dc5fe22c4c437f4f79ac8657c343587243 /drivers/usb
parent67990472c77b06cc591dd59923542f64da91453d (diff)
powerpc/usb: fix bug of CPU hang when missing USB PHY clock
when missing USB PHY clock, kernel booting up will hang during USB initialization. We should check USBGP[PHY_CLK_VALID] bit to avoid CPU hanging in this case. Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ehci-fsl.c58
-rw-r--r--drivers/usb/host/ehci-fsl.h1
2 files changed, 41 insertions, 18 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index b7451b29c5a..11ff4b4dc7a 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -210,11 +210,11 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
210 usb_put_hcd(hcd); 210 usb_put_hcd(hcd);
211} 211}
212 212
213static void ehci_fsl_setup_phy(struct usb_hcd *hcd, 213static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
214 enum fsl_usb2_phy_modes phy_mode, 214 enum fsl_usb2_phy_modes phy_mode,
215 unsigned int port_offset) 215 unsigned int port_offset)
216{ 216{
217 u32 portsc, temp; 217 u32 portsc;
218 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 218 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
219 void __iomem *non_ehci = hcd->regs; 219 void __iomem *non_ehci = hcd->regs;
220 struct device *dev = hcd->self.controller; 220 struct device *dev = hcd->self.controller;
@@ -232,9 +232,15 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
232 case FSL_USB2_PHY_ULPI: 232 case FSL_USB2_PHY_ULPI:
233 if (pdata->controller_ver) { 233 if (pdata->controller_ver) {
234 /* controller version 1.6 or above */ 234 /* controller version 1.6 or above */
235 temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); 235 setbits32(non_ehci + FSL_SOC_USB_CTRL,
236 out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 236 ULPI_PHY_CLK_SEL);
237 USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL); 237 /*
238 * Due to controller issue of PHY_CLK_VALID in ULPI
239 * mode, we set USB_CTRL_USB_EN before checking
240 * PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work.
241 */
242 clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
243 UTMI_PHY_EN, USB_CTRL_USB_EN);
238 } 244 }
239 portsc |= PORT_PTS_ULPI; 245 portsc |= PORT_PTS_ULPI;
240 break; 246 break;
@@ -247,9 +253,7 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
247 case FSL_USB2_PHY_UTMI: 253 case FSL_USB2_PHY_UTMI:
248 if (pdata->controller_ver) { 254 if (pdata->controller_ver) {
249 /* controller version 1.6 or above */ 255 /* controller version 1.6 or above */
250 temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); 256 setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
251 out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
252 UTMI_PHY_EN | USB_CTRL_USB_EN);
253 mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to 257 mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to
254 become stable - 10ms*/ 258 become stable - 10ms*/
255 } 259 }
@@ -262,23 +266,34 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
262 case FSL_USB2_PHY_NONE: 266 case FSL_USB2_PHY_NONE:
263 break; 267 break;
264 } 268 }
269
270 if ((pdata->controller_ver) && ((phy_mode == FSL_USB2_PHY_ULPI) ||
271 (phy_mode == FSL_USB2_PHY_UTMI))) {
272 /* check PHY_CLK_VALID to get phy clk valid */
273 if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
274 PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) {
275 printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
276 return -EINVAL;
277 }
278 }
279
265 ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); 280 ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
281
282 if (phy_mode != FSL_USB2_PHY_ULPI)
283 setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN);
284
285 return 0;
266} 286}
267 287
268static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) 288static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
269{ 289{
270 struct usb_hcd *hcd = ehci_to_hcd(ehci); 290 struct usb_hcd *hcd = ehci_to_hcd(ehci);
271 struct fsl_usb2_platform_data *pdata; 291 struct fsl_usb2_platform_data *pdata;
272 void __iomem *non_ehci = hcd->regs; 292 void __iomem *non_ehci = hcd->regs;
273 u32 temp;
274 293
275 pdata = hcd->self.controller->platform_data; 294 pdata = hcd->self.controller->platform_data;
276 295
277 /* Enable PHY interface in the control reg. */
278 if (pdata->have_sysif_regs) { 296 if (pdata->have_sysif_regs) {
279 temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
280 out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
281
282 /* 297 /*
283 * Turn on cache snooping hardware, since some PowerPC platforms 298 * Turn on cache snooping hardware, since some PowerPC platforms
284 * wholly rely on hardware to deal with cache coherent 299 * wholly rely on hardware to deal with cache coherent
@@ -293,7 +308,8 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
293 308
294 if ((pdata->operating_mode == FSL_USB2_DR_HOST) || 309 if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
295 (pdata->operating_mode == FSL_USB2_DR_OTG)) 310 (pdata->operating_mode == FSL_USB2_DR_OTG))
296 ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); 311 if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
312 return -EINVAL;
297 313
298 if (pdata->operating_mode == FSL_USB2_MPH_HOST) { 314 if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
299 unsigned int chip, rev, svr; 315 unsigned int chip, rev, svr;
@@ -307,9 +323,12 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
307 ehci->has_fsl_port_bug = 1; 323 ehci->has_fsl_port_bug = 1;
308 324
309 if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) 325 if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
310 ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); 326 if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
327 return -EINVAL;
328
311 if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) 329 if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
312 ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1); 330 if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1))
331 return -EINVAL;
313 } 332 }
314 333
315 if (pdata->have_sysif_regs) { 334 if (pdata->have_sysif_regs) {
@@ -322,12 +341,15 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
322#endif 341#endif
323 out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); 342 out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
324 } 343 }
344
345 return 0;
325} 346}
326 347
327/* called after powerup, by probe or system-pm "wakeup" */ 348/* called after powerup, by probe or system-pm "wakeup" */
328static int ehci_fsl_reinit(struct ehci_hcd *ehci) 349static int ehci_fsl_reinit(struct ehci_hcd *ehci)
329{ 350{
330 ehci_fsl_usb_setup(ehci); 351 if (ehci_fsl_usb_setup(ehci))
352 return -EINVAL;
331 ehci_port_power(ehci, 0); 353 ehci_port_power(ehci, 0);
332 354
333 return 0; 355 return 0;
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 88403684d10..dbd292e9f0a 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -61,4 +61,5 @@
61#define PLL_RESET (1<<8) 61#define PLL_RESET (1<<8)
62#define UTMI_PHY_EN (1<<9) 62#define UTMI_PHY_EN (1<<9)
63#define ULPI_PHY_CLK_SEL (1<<10) 63#define ULPI_PHY_CLK_SEL (1<<10)
64#define PHY_CLK_VALID (1<<17)
64#endif /* _EHCI_FSL_H */ 65#endif /* _EHCI_FSL_H */