diff options
Diffstat (limited to 'drivers/usb/host/ehci-fsl.c')
| -rw-r--r-- | drivers/usb/host/ehci-fsl.c | 405 | 
1 files changed, 323 insertions, 82 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 86e42892016..cf2734b532a 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -1,6 +1,6 @@  /*   * Copyright 2005-2009 MontaVista Software, Inc. - * Copyright 2008      Freescale Semiconductor, Inc. + * Copyright 2008,2012      Freescale Semiconductor, Inc.   *   * This program is free software; you can redistribute it and/or modify it   * under the terms of the GNU General Public License as published by the @@ -27,6 +27,7 @@  #include <linux/types.h>  #include <linux/delay.h>  #include <linux/pm.h> +#include <linux/err.h>  #include <linux/platform_device.h>  #include <linux/fsl_devices.h> @@ -52,12 +53,11 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,  	struct resource *res;  	int irq;  	int retval; -	unsigned int temp;  	pr_debug("initializing FSL-SOC USB Controller\n");  	/* Need platform data for setup */ -	pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data; +	pdata = dev_get_platdata(&pdev->dev);  	if (!pdata) {  		dev_err(&pdev->dev,  			"No platform data for %s.\n", dev_name(&pdev->dev)); @@ -101,58 +101,61 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,  		goto err2;  	}  	hcd->rsrc_start = res->start; -	hcd->rsrc_len = res->end - res->start + 1; -	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, -				driver->description)) { -		dev_dbg(&pdev->dev, "controller already in use\n"); -		retval = -EBUSY; +	hcd->rsrc_len = resource_size(res); +	hcd->regs = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(hcd->regs)) { +		retval = PTR_ERR(hcd->regs);  		goto err2;  	} -	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - -	if (hcd->regs == NULL) { -		dev_dbg(&pdev->dev, "error mapping memory\n"); -		retval = -EFAULT; -		goto err3; -	}  	pdata->regs = hcd->regs; +	if (pdata->power_budget) +		hcd->power_budget = pdata->power_budget; +  	/*  	 * do platform specific init: check the clock, grab/config pins, etc.  	 */  	if (pdata->init && pdata->init(pdev)) {  		retval = -ENODEV; -		goto err3; +		goto err2;  	} -	/* -	 * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs -	 * flag for 83xx or 8536 system interface registers. -	 */ -	if (pdata->big_endian_mmio) -		temp = in_be32(hcd->regs + FSL_SOC_USB_ID); -	else -		temp = in_le32(hcd->regs + FSL_SOC_USB_ID); - -	if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK)) -		pdata->have_sysif_regs = 1; -  	/* Enable USB controller, 83xx or 8536 */ -	if (pdata->have_sysif_regs) +	if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)  		setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);  	/* Don't need to set host mode here. It will be done by tdi_reset() */ -	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); +	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);  	if (retval != 0) -		goto err4; +		goto err2; +	device_wakeup_enable(hcd->self.controller); + +#ifdef CONFIG_USB_OTG +	if (pdata->operating_mode == FSL_USB2_DR_OTG) { +		struct ehci_hcd *ehci = hcd_to_ehci(hcd); + +		hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2); +		dev_dbg(&pdev->dev, "hcd=0x%p  ehci=0x%p, phy=0x%p\n", +			hcd, ehci, hcd->phy); + +		if (!IS_ERR_OR_NULL(hcd->phy)) { +			retval = otg_set_host(hcd->phy->otg, +					      &ehci_to_hcd(ehci)->self); +			if (retval) { +				usb_put_phy(hcd->phy); +				goto err2; +			} +		} else { +			dev_err(&pdev->dev, "can't find phy\n"); +			retval = -ENODEV; +			goto err2; +		} +	} +#endif  	return retval; -      err4: -	iounmap(hcd->regs); -      err3: -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);        err2:  	usb_put_hcd(hcd);        err1: @@ -176,7 +179,12 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,  static void usb_hcd_fsl_remove(struct usb_hcd *hcd,  			       struct platform_device *pdev)  { -	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; +	struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); + +	if (!IS_ERR_OR_NULL(hcd->phy)) { +		otg_set_host(hcd->phy->otg, NULL); +		usb_put_phy(hcd->phy); +	}  	usb_remove_hcd(hcd); @@ -186,22 +194,35 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,  	 */  	if (pdata->exit)  		pdata->exit(pdev); -	iounmap(hcd->regs); -	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);  	usb_put_hcd(hcd);  } -static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, +static int ehci_fsl_setup_phy(struct usb_hcd *hcd,  			       enum fsl_usb2_phy_modes phy_mode,  			       unsigned int port_offset)  {  	u32 portsc; +	struct ehci_hcd *ehci = hcd_to_ehci(hcd); +	void __iomem *non_ehci = hcd->regs; +	struct device *dev = hcd->self.controller; +	struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); + +	if (pdata->controller_ver < 0) { +		dev_warn(hcd->self.controller, "Could not get controller version\n"); +		return -ENODEV; +	}  	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);  	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);  	switch (phy_mode) {  	case FSL_USB2_PHY_ULPI: +		if (pdata->have_sysif_regs && pdata->controller_ver) { +			/* controller version 1.6 or above */ +			clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); +			setbits32(non_ehci + FSL_SOC_USB_CTRL, +				ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN); +		}  		portsc |= PORT_PTS_ULPI;  		break;  	case FSL_USB2_PHY_SERIAL: @@ -211,46 +232,67 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,  		portsc |= PORT_PTS_PTW;  		/* fall through */  	case FSL_USB2_PHY_UTMI: +		if (pdata->have_sysif_regs && pdata->controller_ver) { +			/* controller version 1.6 or above */ +			setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); +			mdelay(FSL_UTMI_PHY_DLY);  /* Delay for UTMI PHY CLK to +						become stable - 10ms*/ +		} +		/* enable UTMI PHY */ +		if (pdata->have_sysif_regs) +			setbits32(non_ehci + FSL_SOC_USB_CTRL, +				  CTRL_UTMI_PHY_EN);  		portsc |= PORT_PTS_UTMI;  		break;  	case FSL_USB2_PHY_NONE:  		break;  	} + +	if (pdata->have_sysif_regs && +	    pdata->controller_ver > FSL_USB_VER_1_6 && +	    (phy_mode == FSL_USB2_PHY_ULPI)) { +		/* 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) || +				in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) { +			dev_warn(hcd->self.controller, "USB PHY clock invalid\n"); +			return -EINVAL; +		} +	} +  	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); + +	if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs) +		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 fsl_usb2_platform_data *pdata;  	void __iomem *non_ehci = hcd->regs; -	u32 temp; -	pdata = hcd->self.controller->platform_data; +	pdata = dev_get_platdata(hcd->self.controller); -	/* Enable PHY interface in the control reg. */  	if (pdata->have_sysif_regs) { -		temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); -		out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); -		out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); +		/* +		* Turn on cache snooping hardware, since some PowerPC platforms +		* wholly rely on hardware to deal with cache coherent +		*/ + +		/* Setup Snooping for all the 4GB space */ +		/* SNOOP1 starts from 0x0, size 2G */ +		out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB); +		/* SNOOP2 starts from 0x80000000, size 2G */ +		out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);  	} -#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) -	/* -	 * Turn on cache snooping hardware, since some PowerPC platforms -	 * wholly rely on hardware to deal with cache coherent -	 */ - -	/* Setup Snooping for all the 4GB space */ -	/* SNOOP1 starts from 0x0, size 2G */ -	out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB); -	/* SNOOP2 starts from 0x80000000, size 2G */ -	out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); -#endif -  	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||  			(pdata->operating_mode == FSL_USB2_DR_OTG)) -		ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); +		if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) +			return -EINVAL;  	if (pdata->operating_mode == FSL_USB2_MPH_HOST) {  		unsigned int chip, rev, svr; @@ -264,13 +306,16 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)  			ehci->has_fsl_port_bug = 1;  		if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) -			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0); +			if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) +				return -EINVAL; +  		if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) -			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1); +			if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1)) +				return -EINVAL;  	}  	if (pdata->have_sysif_regs) { -#ifdef CONFIG_PPC_85xx +#ifdef CONFIG_FSL_SOC_BOOKE  		out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);  		out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);  #else @@ -279,13 +324,15 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)  #endif  		out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);  	} + +	return 0;  }  /* called after powerup, by probe or system-pm "wakeup" */  static int ehci_fsl_reinit(struct ehci_hcd *ehci)  { -	ehci_fsl_usb_setup(ehci); -	ehci_port_power(ehci, 0); +	if (ehci_fsl_usb_setup(ehci)) +		return -EINVAL;  	return 0;  } @@ -296,35 +343,40 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)  	struct ehci_hcd *ehci = hcd_to_ehci(hcd);  	int retval;  	struct fsl_usb2_platform_data *pdata; +	struct device *dev; -	pdata = hcd->self.controller->platform_data; +	dev = hcd->self.controller; +	pdata = dev_get_platdata(hcd->self.controller);  	ehci->big_endian_desc = pdata->big_endian_desc;  	ehci->big_endian_mmio = pdata->big_endian_mmio;  	/* EHCI registers start at offset 0x100 */  	ehci->caps = hcd->regs + 0x100; -	ehci->regs = hcd->regs + 0x100 + -	    HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); -	dbg_hcs_params(ehci, "reset"); -	dbg_hcc_params(ehci, "reset"); -	/* cache this readonly data; minimize chip reads */ -	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); +#ifdef CONFIG_PPC_83xx +	/* +	 * Deal with MPC834X that need port power to be cycled after the power +	 * fault condition is removed. Otherwise the state machine does not +	 * reflect PORTSC[CSC] correctly. +	 */ +	ehci->need_oc_pp_cycle = 1; +#endif  	hcd->has_tt = 1; -	retval = ehci_halt(ehci); +	retval = ehci_setup(hcd);  	if (retval)  		return retval; -	/* data structure init */ -	retval = ehci_init(hcd); -	if (retval) -		return retval; - -	ehci->sbrn = 0x20; - -	ehci_reset(ehci); +	if (of_device_is_compatible(dev->parent->of_node, +				    "fsl,mpc5121-usb2-dr")) { +		/* +		 * set SBUSCFG:AHBBRST so that control msgs don't +		 * fail when doing heavy PATA writes. +		 */ +		ehci_writel(ehci, SBUSCFG_INCR8, +			    hcd->regs + FSL_SOC_USB_SBUSCFG); +	}  	retval = ehci_fsl_reinit(ehci);  	return retval; @@ -341,6 +393,151 @@ struct ehci_fsl {  #ifdef CONFIG_PM +#ifdef CONFIG_PPC_MPC512x +static int ehci_fsl_mpc512x_drv_suspend(struct device *dev) +{ +	struct usb_hcd *hcd = dev_get_drvdata(dev); +	struct ehci_hcd *ehci = hcd_to_ehci(hcd); +	struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); +	u32 tmp; + +#ifdef CONFIG_DYNAMIC_DEBUG +	u32 mode = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBMODE); +	mode &= USBMODE_CM_MASK; +	tmp = ehci_readl(ehci, hcd->regs + 0x140);	/* usbcmd */ + +	dev_dbg(dev, "suspend=%d already_suspended=%d " +		"mode=%d  usbcmd %08x\n", pdata->suspended, +		pdata->already_suspended, mode, tmp); +#endif + +	/* +	 * If the controller is already suspended, then this must be a +	 * PM suspend.  Remember this fact, so that we will leave the +	 * controller suspended at PM resume time. +	 */ +	if (pdata->suspended) { +		dev_dbg(dev, "already suspended, leaving early\n"); +		pdata->already_suspended = 1; +		return 0; +	} + +	dev_dbg(dev, "suspending...\n"); + +	ehci->rh_state = EHCI_RH_SUSPENDED; +	dev->power.power_state = PMSG_SUSPEND; + +	/* ignore non-host interrupts */ +	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + +	/* stop the controller */ +	tmp = ehci_readl(ehci, &ehci->regs->command); +	tmp &= ~CMD_RUN; +	ehci_writel(ehci, tmp, &ehci->regs->command); + +	/* save EHCI registers */ +	pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); +	pdata->pm_command &= ~CMD_RUN; +	pdata->pm_status  = ehci_readl(ehci, &ehci->regs->status); +	pdata->pm_intr_enable  = ehci_readl(ehci, &ehci->regs->intr_enable); +	pdata->pm_frame_index  = ehci_readl(ehci, &ehci->regs->frame_index); +	pdata->pm_segment  = ehci_readl(ehci, &ehci->regs->segment); +	pdata->pm_frame_list  = ehci_readl(ehci, &ehci->regs->frame_list); +	pdata->pm_async_next  = ehci_readl(ehci, &ehci->regs->async_next); +	pdata->pm_configured_flag  = +		ehci_readl(ehci, &ehci->regs->configured_flag); +	pdata->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]); +	pdata->pm_usbgenctrl = ehci_readl(ehci, +					  hcd->regs + FSL_SOC_USB_USBGENCTRL); + +	/* clear the W1C bits */ +	pdata->pm_portsc &= cpu_to_hc32(ehci, ~PORT_RWC_BITS); + +	pdata->suspended = 1; + +	/* clear PP to cut power to the port */ +	tmp = ehci_readl(ehci, &ehci->regs->port_status[0]); +	tmp &= ~PORT_POWER; +	ehci_writel(ehci, tmp, &ehci->regs->port_status[0]); + +	return 0; +} + +static int ehci_fsl_mpc512x_drv_resume(struct device *dev) +{ +	struct usb_hcd *hcd = dev_get_drvdata(dev); +	struct ehci_hcd *ehci = hcd_to_ehci(hcd); +	struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); +	u32 tmp; + +	dev_dbg(dev, "suspend=%d already_suspended=%d\n", +		pdata->suspended, pdata->already_suspended); + +	/* +	 * If the controller was already suspended at suspend time, +	 * then don't resume it now. +	 */ +	if (pdata->already_suspended) { +		dev_dbg(dev, "already suspended, leaving early\n"); +		pdata->already_suspended = 0; +		return 0; +	} + +	if (!pdata->suspended) { +		dev_dbg(dev, "not suspended, leaving early\n"); +		return 0; +	} + +	pdata->suspended = 0; + +	dev_dbg(dev, "resuming...\n"); + +	/* set host mode */ +	tmp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0); +	ehci_writel(ehci, tmp, hcd->regs + FSL_SOC_USB_USBMODE); + +	ehci_writel(ehci, pdata->pm_usbgenctrl, +		    hcd->regs + FSL_SOC_USB_USBGENCTRL); +	ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE, +		    hcd->regs + FSL_SOC_USB_ISIPHYCTRL); + +	ehci_writel(ehci, SBUSCFG_INCR8, hcd->regs + FSL_SOC_USB_SBUSCFG); + +	/* restore EHCI registers */ +	ehci_writel(ehci, pdata->pm_command, &ehci->regs->command); +	ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable); +	ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index); +	ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment); +	ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list); +	ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next); +	ehci_writel(ehci, pdata->pm_configured_flag, +		    &ehci->regs->configured_flag); +	ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]); + +	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); +	ehci->rh_state = EHCI_RH_RUNNING; +	dev->power.power_state = PMSG_ON; + +	tmp = ehci_readl(ehci, &ehci->regs->command); +	tmp |= CMD_RUN; +	ehci_writel(ehci, tmp, &ehci->regs->command); + +	usb_hcd_resume_root_hub(hcd); + +	return 0; +} +#else +static inline int ehci_fsl_mpc512x_drv_suspend(struct device *dev) +{ +	return 0; +} + +static inline int ehci_fsl_mpc512x_drv_resume(struct device *dev) +{ +	return 0; +} +#endif /* CONFIG_PPC_MPC512x */ +  static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd)  {  	struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -354,6 +551,11 @@ static int ehci_fsl_drv_suspend(struct device *dev)  	struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);  	void __iomem *non_ehci = hcd->regs; +	if (of_device_is_compatible(dev->parent->of_node, +				    "fsl,mpc5121-usb2-dr")) { +		return ehci_fsl_mpc512x_drv_suspend(dev); +	} +  	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),  			device_may_wakeup(dev));  	if (!fsl_deep_sleep()) @@ -370,6 +572,11 @@ static int ehci_fsl_drv_resume(struct device *dev)  	struct ehci_hcd *ehci = hcd_to_ehci(hcd);  	void __iomem *non_ehci = hcd->regs; +	if (of_device_is_compatible(dev->parent->of_node, +				    "fsl,mpc5121-usb2-dr")) { +		return ehci_fsl_mpc512x_drv_resume(dev); +	} +  	ehci_prepare_ports_for_controller_resume(ehci);  	if (!fsl_deep_sleep())  		return 0; @@ -404,6 +611,38 @@ static struct dev_pm_ops ehci_fsl_pm_ops = {  #define EHCI_FSL_PM_OPS		NULL  #endif /* CONFIG_PM */ +#ifdef CONFIG_USB_OTG +static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port) +{ +	struct ehci_hcd *ehci = hcd_to_ehci(hcd); +	u32 status; + +	if (!port) +		return -EINVAL; + +	port--; + +	/* start port reset before HNP protocol time out */ +	status = readl(&ehci->regs->port_status[port]); +	if (!(status & PORT_CONNECT)) +		return -ENODEV; + +	/* khubd will finish the reset later */ +	if (ehci_is_TDI(ehci)) { +		writel(PORT_RESET | +		       (status & ~(PORT_CSC | PORT_PEC | PORT_OCC)), +		       &ehci->regs->port_status[port]); +	} else { +		writel(PORT_RESET, &ehci->regs->port_status[port]); +	} + +	return 0; +} +#else +#define ehci_start_port_reset	NULL +#endif /* CONFIG_USB_OTG */ + +  static const struct hc_driver ehci_fsl_hc_driver = {  	.description = hcd_name,  	.product_desc = "Freescale On-Chip EHCI Host Controller", @@ -413,7 +652,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {  	 * generic hardware linkage  	 */  	.irq = ehci_irq, -	.flags = HCD_USB2 | HCD_MEMORY, +	.flags = HCD_USB2 | HCD_MEMORY | HCD_BH,  	/*  	 * basic lifecycle operations @@ -443,6 +682,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {  	.hub_control = ehci_hub_control,  	.bus_suspend = ehci_bus_suspend,  	.bus_resume = ehci_bus_resume, +	.start_port_reset = ehci_start_port_reset,  	.relinquish_port = ehci_relinquish_port,  	.port_handed_over = ehci_port_handed_over, @@ -475,6 +715,7 @@ static struct platform_driver ehci_fsl_driver = {  	.shutdown = usb_hcd_platform_shutdown,  	.driver = {  		.name = "fsl-ehci", +		.owner	= THIS_MODULE,  		.pm = EHCI_FSL_PM_OPS,  	},  };  | 
