forked from mirrors/linux
		
	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>
This commit is contained in:
		
							parent
							
								
									67990472c7
								
							
						
					
					
						commit
						3735ba8db8
					
				
					 3 changed files with 42 additions and 18 deletions
				
			
		| 
						 | 
					@ -210,11 +210,11 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
 | 
				
			||||||
	usb_put_hcd(hcd);
 | 
						usb_put_hcd(hcd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
 | 
					static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
 | 
				
			||||||
			       enum fsl_usb2_phy_modes phy_mode,
 | 
								       enum fsl_usb2_phy_modes phy_mode,
 | 
				
			||||||
			       unsigned int port_offset)
 | 
								       unsigned int port_offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 portsc, temp;
 | 
						u32 portsc;
 | 
				
			||||||
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 | 
						struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 | 
				
			||||||
	void __iomem *non_ehci = hcd->regs;
 | 
						void __iomem *non_ehci = hcd->regs;
 | 
				
			||||||
	struct device *dev = hcd->self.controller;
 | 
						struct device *dev = hcd->self.controller;
 | 
				
			||||||
| 
						 | 
					@ -232,9 +232,15 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
 | 
				
			||||||
	case FSL_USB2_PHY_ULPI:
 | 
						case FSL_USB2_PHY_ULPI:
 | 
				
			||||||
		if (pdata->controller_ver) {
 | 
							if (pdata->controller_ver) {
 | 
				
			||||||
			/* controller version 1.6 or above */
 | 
								/* controller version 1.6 or above */
 | 
				
			||||||
			temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
 | 
								setbits32(non_ehci + FSL_SOC_USB_CTRL,
 | 
				
			||||||
			out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
 | 
										ULPI_PHY_CLK_SEL);
 | 
				
			||||||
				USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL);
 | 
								/*
 | 
				
			||||||
 | 
								 * Due to controller issue of PHY_CLK_VALID in ULPI
 | 
				
			||||||
 | 
								 * mode, we set USB_CTRL_USB_EN before checking
 | 
				
			||||||
 | 
								 * PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
 | 
				
			||||||
 | 
										UTMI_PHY_EN, USB_CTRL_USB_EN);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		portsc |= PORT_PTS_ULPI;
 | 
							portsc |= PORT_PTS_ULPI;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -247,9 +253,7 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
 | 
				
			||||||
	case FSL_USB2_PHY_UTMI:
 | 
						case FSL_USB2_PHY_UTMI:
 | 
				
			||||||
		if (pdata->controller_ver) {
 | 
							if (pdata->controller_ver) {
 | 
				
			||||||
			/* controller version 1.6 or above */
 | 
								/* controller version 1.6 or above */
 | 
				
			||||||
			temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
 | 
								setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
 | 
				
			||||||
			out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
 | 
					 | 
				
			||||||
				UTMI_PHY_EN | USB_CTRL_USB_EN);
 | 
					 | 
				
			||||||
			mdelay(FSL_UTMI_PHY_DLY);  /* Delay for UTMI PHY CLK to
 | 
								mdelay(FSL_UTMI_PHY_DLY);  /* Delay for UTMI PHY CLK to
 | 
				
			||||||
						become stable - 10ms*/
 | 
											become stable - 10ms*/
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -262,23 +266,34 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
 | 
				
			||||||
	case FSL_USB2_PHY_NONE:
 | 
						case FSL_USB2_PHY_NONE:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((pdata->controller_ver) && ((phy_mode == FSL_USB2_PHY_ULPI) ||
 | 
				
			||||||
 | 
								(phy_mode == FSL_USB2_PHY_UTMI))) {
 | 
				
			||||||
 | 
							/* check PHY_CLK_VALID to get phy clk valid */
 | 
				
			||||||
 | 
							if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
 | 
				
			||||||
 | 
									PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) {
 | 
				
			||||||
 | 
								printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 | 
						ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (phy_mode != FSL_USB2_PHY_ULPI)
 | 
				
			||||||
 | 
							setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 | 
					static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct usb_hcd *hcd = ehci_to_hcd(ehci);
 | 
						struct usb_hcd *hcd = ehci_to_hcd(ehci);
 | 
				
			||||||
	struct fsl_usb2_platform_data *pdata;
 | 
						struct fsl_usb2_platform_data *pdata;
 | 
				
			||||||
	void __iomem *non_ehci = hcd->regs;
 | 
						void __iomem *non_ehci = hcd->regs;
 | 
				
			||||||
	u32 temp;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pdata = hcd->self.controller->platform_data;
 | 
						pdata = hcd->self.controller->platform_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enable PHY interface in the control reg. */
 | 
					 | 
				
			||||||
	if (pdata->have_sysif_regs) {
 | 
						if (pdata->have_sysif_regs) {
 | 
				
			||||||
		temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
 | 
					 | 
				
			||||||
		out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		* Turn on cache snooping hardware, since some PowerPC platforms
 | 
							* Turn on cache snooping hardware, since some PowerPC platforms
 | 
				
			||||||
		* wholly rely on hardware to deal with cache coherent
 | 
							* wholly rely on hardware to deal with cache coherent
 | 
				
			||||||
| 
						 | 
					@ -293,7 +308,8 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
 | 
						if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
 | 
				
			||||||
			(pdata->operating_mode == FSL_USB2_DR_OTG))
 | 
								(pdata->operating_mode == FSL_USB2_DR_OTG))
 | 
				
			||||||
		ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
 | 
							if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
 | 
						if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
 | 
				
			||||||
		unsigned int chip, rev, svr;
 | 
							unsigned int chip, rev, svr;
 | 
				
			||||||
| 
						 | 
					@ -307,9 +323,12 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 | 
				
			||||||
			ehci->has_fsl_port_bug = 1;
 | 
								ehci->has_fsl_port_bug = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
 | 
							if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
 | 
				
			||||||
			ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
 | 
								if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
 | 
							if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
 | 
				
			||||||
			ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1);
 | 
								if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1))
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pdata->have_sysif_regs) {
 | 
						if (pdata->have_sysif_regs) {
 | 
				
			||||||
| 
						 | 
					@ -322,12 +341,15 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
 | 
							out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* called after powerup, by probe or system-pm "wakeup" */
 | 
					/* called after powerup, by probe or system-pm "wakeup" */
 | 
				
			||||||
static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 | 
					static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ehci_fsl_usb_setup(ehci);
 | 
						if (ehci_fsl_usb_setup(ehci))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
	ehci_port_power(ehci, 0);
 | 
						ehci_port_power(ehci, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,4 +61,5 @@
 | 
				
			||||||
#define PLL_RESET               (1<<8)
 | 
					#define PLL_RESET               (1<<8)
 | 
				
			||||||
#define UTMI_PHY_EN             (1<<9)
 | 
					#define UTMI_PHY_EN             (1<<9)
 | 
				
			||||||
#define ULPI_PHY_CLK_SEL        (1<<10)
 | 
					#define ULPI_PHY_CLK_SEL        (1<<10)
 | 
				
			||||||
 | 
					#define PHY_CLK_VALID		(1<<17)
 | 
				
			||||||
#endif				/* _EHCI_FSL_H */
 | 
					#endif				/* _EHCI_FSL_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FSL_UTMI_PHY_DLY	10	/*As per P1010RM, delay for UTMI
 | 
					#define FSL_UTMI_PHY_DLY	10	/*As per P1010RM, delay for UTMI
 | 
				
			||||||
				PHY CLK to become stable - 10ms*/
 | 
									PHY CLK to become stable - 10ms*/
 | 
				
			||||||
 | 
					#define FSL_USB_PHY_CLK_TIMEOUT	1000	/* uSec */
 | 
				
			||||||
#define FSL_USB_VER_OLD		0
 | 
					#define FSL_USB_VER_OLD		0
 | 
				
			||||||
#define FSL_USB_VER_1_6		1
 | 
					#define FSL_USB_VER_1_6		1
 | 
				
			||||||
#define FSL_USB_VER_2_2		2
 | 
					#define FSL_USB_VER_2_2		2
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue