EHCI: centralize controller initialization
This patch (as1564c) converts the EHCI platform drivers to use the central ehci_setup() routine for generic controller initialization rather than each having its own idiosyncratic approach. The major point of difficulty lies in ehci-pci's many vendor- and device-specific workarounds. Some of them have to be applied before calling ehci_setup() and some after, which necessitates a fair amount of code motion. The other platform drivers require much smaller changes. One point not addressed by the patch is whether ports should be powered on or off following initialization. The different drivers appear to handle this pretty much at random. In fact it shouldn't matter, because the hub driver turns on power to all ports when it binds to the root hub. Straightening that out will be left for another day. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
1530280084
commit
1a49e2ac96
@ -53,30 +53,15 @@ static void atmel_stop_ehci(struct platform_device *pdev)
|
||||
static int ehci_atmel_setup(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval = 0;
|
||||
int retval;
|
||||
|
||||
/* registers start at offset 0x0 */
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, 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);
|
||||
|
||||
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);
|
||||
ehci_port_power(ehci, 0);
|
||||
|
||||
return retval;
|
||||
|
@ -20,10 +20,12 @@ extern int usb_disabled(void);
|
||||
static int au1xxx_ehci_setup(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int ret = ehci_init(hcd);
|
||||
int ret;
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
ret = ehci_setup(hcd);
|
||||
|
||||
ehci->need_io_watchdog = 0;
|
||||
ehci_reset(ehci);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -78,7 +80,6 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
|
||||
static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
struct ehci_hcd *ehci;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
@ -116,13 +117,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
|
||||
goto err3;
|
||||
}
|
||||
|
||||
ehci = hcd_to_ehci(hcd);
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = readl(&ehci->caps->hcs_params);
|
||||
|
||||
ret = usb_add_hcd(hcd, pdev->resource[1].start,
|
||||
IRQF_SHARED);
|
||||
if (ret == 0) {
|
||||
|
@ -33,14 +33,10 @@ static int cns3xxx_ehci_init(struct usb_hcd *hcd)
|
||||
}
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs
|
||||
+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
hcd->has_tt = 0;
|
||||
ehci_reset(ehci);
|
||||
|
||||
retval = ehci_init(hcd);
|
||||
retval = ehci_setup(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
@ -348,29 +348,13 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
|
||||
|
||||
/* EHCI registers start at offset 0x100 */
|
||||
ehci->caps = hcd->regs + 0x100;
|
||||
ehci->regs = hcd->regs + 0x100 +
|
||||
HC_LENGTH(ehci, 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);
|
||||
|
||||
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")) {
|
||||
/*
|
||||
|
@ -40,18 +40,13 @@ static int ehci_grlib_setup(struct usb_hcd *hcd)
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval;
|
||||
|
||||
retval = ehci_halt(ehci);
|
||||
retval = ehci_setup(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = ehci_init(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci->sbrn = 0x20;
|
||||
ehci_port_power(ehci, 1);
|
||||
|
||||
return ehci_reset(ehci);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@ -164,12 +159,6 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
|
||||
ehci->big_endian_capbase = 1;
|
||||
}
|
||||
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
rv = usb_add_hcd(hcd, irq, 0);
|
||||
if (rv)
|
||||
goto err_ehci;
|
||||
|
@ -808,7 +808,7 @@ static int ehci_run (struct usb_hcd *hcd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
|
||||
static int ehci_setup(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval;
|
||||
@ -832,6 +832,9 @@ static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (ehci_is_TDI(ehci))
|
||||
tdi_reset(ehci);
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
return 0;
|
||||
|
@ -22,14 +22,10 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd)
|
||||
ehci->big_endian_mmio = 1;
|
||||
|
||||
ehci->caps = hcd->regs + 0x100;
|
||||
ehci->regs = hcd->regs + 0x100
|
||||
+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
hcd->has_tt = 1;
|
||||
ehci_reset(ehci);
|
||||
|
||||
retval = ehci_init(hcd);
|
||||
retval = ehci_setup(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
@ -77,7 +77,6 @@ static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv)
|
||||
|
||||
static int mv_ehci_reset(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
struct device *dev = hcd->self.controller;
|
||||
struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev);
|
||||
int retval;
|
||||
@ -87,25 +86,13 @@ static int mv_ehci_reset(struct usb_hcd *hcd)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* data structure init
|
||||
*/
|
||||
retval = ehci_init(hcd);
|
||||
if (retval) {
|
||||
dev_err(dev, "ehci_init failed %d\n", retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
hcd->has_tt = 1;
|
||||
ehci->sbrn = 0x20;
|
||||
|
||||
retval = ehci_reset(ehci);
|
||||
if (retval) {
|
||||
dev_err(dev, "ehci_reset failed %d\n", retval);
|
||||
return retval;
|
||||
}
|
||||
retval = ehci_setup(hcd);
|
||||
if (retval)
|
||||
dev_err(dev, "ehci_setup failed %d\n", retval);
|
||||
|
||||
return 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const struct hc_driver mv_ehci_hc_driver = {
|
||||
@ -248,8 +235,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
|
||||
|
||||
ehci = hcd_to_ehci(hcd);
|
||||
ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs;
|
||||
ehci->regs = (struct ehci_regs *) ehci_mv->op_regs;
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
ehci_mv->mode = pdata->mode;
|
||||
if (ehci_mv->mode == MV_USB_MODE_OTG) {
|
||||
|
@ -42,27 +42,12 @@ static int ehci_mxc_setup(struct usb_hcd *hcd)
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
ehci_port_power(ehci, 0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ static const struct hc_driver ehci_octeon_hc_driver = {
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.reset = ehci_init,
|
||||
.reset = ehci_setup,
|
||||
.start = ehci_run,
|
||||
.stop = ehci_stop,
|
||||
.shutdown = ehci_shutdown,
|
||||
@ -150,12 +150,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
|
||||
#endif
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
||||
if (ret) {
|
||||
|
@ -145,6 +145,56 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port)
|
||||
}
|
||||
}
|
||||
|
||||
static int omap_ehci_init(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int rc;
|
||||
struct ehci_hcd_omap_platform_data *pdata;
|
||||
|
||||
pdata = hcd->self.controller->platform_data;
|
||||
if (pdata->phy_reset) {
|
||||
if (gpio_is_valid(pdata->reset_gpio_port[0]))
|
||||
gpio_request_one(pdata->reset_gpio_port[0],
|
||||
GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
|
||||
|
||||
if (gpio_is_valid(pdata->reset_gpio_port[1]))
|
||||
gpio_request_one(pdata->reset_gpio_port[1],
|
||||
GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
|
||||
|
||||
/* Hold the PHY in RESET for enough time till DIR is high */
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/* Soft reset the PHY using PHY reset command over ULPI */
|
||||
if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
|
||||
omap_ehci_soft_phy_reset(pdev, 0);
|
||||
if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
|
||||
omap_ehci_soft_phy_reset(pdev, 1);
|
||||
|
||||
/* we know this is the memory we want, no need to ioremap again */
|
||||
ehci->caps = hcd->regs;
|
||||
|
||||
rc = ehci_setup(hcd);
|
||||
|
||||
if (pdata->phy_reset) {
|
||||
/* Hold the PHY in RESET for enough time till
|
||||
* PHY is settled and ready
|
||||
*/
|
||||
udelay(10);
|
||||
|
||||
if (gpio_is_valid(pdata->reset_gpio_port[0]))
|
||||
gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
|
||||
|
||||
if (gpio_is_valid(pdata->reset_gpio_port[1]))
|
||||
gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
|
||||
}
|
||||
|
||||
/* root ports should always stay powered */
|
||||
ehci_port_power(ehci, 1);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int omap_ehci_hub_control(
|
||||
struct usb_hcd *hcd,
|
||||
u16 typeReq,
|
||||
@ -219,7 +269,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
struct usb_hcd *hcd;
|
||||
void __iomem *regs;
|
||||
struct ehci_hcd *omap_ehci;
|
||||
int ret = -ENODEV;
|
||||
int irq;
|
||||
int i;
|
||||
@ -281,19 +330,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
if (pdata->phy_reset) {
|
||||
if (gpio_is_valid(pdata->reset_gpio_port[0]))
|
||||
gpio_request_one(pdata->reset_gpio_port[0],
|
||||
GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
|
||||
|
||||
if (gpio_is_valid(pdata->reset_gpio_port[1]))
|
||||
gpio_request_one(pdata->reset_gpio_port[1],
|
||||
GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
|
||||
|
||||
/* Hold the PHY in RESET for enough time till DIR is high */
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
@ -309,50 +345,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
|
||||
ehci_write(regs, EHCI_INSNREG04,
|
||||
EHCI_INSNREG04_DISABLE_UNSUSPEND);
|
||||
|
||||
/* Soft reset the PHY using PHY reset command over ULPI */
|
||||
if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
|
||||
omap_ehci_soft_phy_reset(pdev, 0);
|
||||
if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
|
||||
omap_ehci_soft_phy_reset(pdev, 1);
|
||||
|
||||
omap_ehci = hcd_to_ehci(hcd);
|
||||
omap_ehci->sbrn = 0x20;
|
||||
|
||||
/* we know this is the memory we want, no need to ioremap again */
|
||||
omap_ehci->caps = hcd->regs;
|
||||
omap_ehci->regs = hcd->regs
|
||||
+ HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase));
|
||||
|
||||
dbg_hcs_params(omap_ehci, "reset");
|
||||
dbg_hcc_params(omap_ehci, "reset");
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);
|
||||
|
||||
ehci_reset(omap_ehci);
|
||||
|
||||
if (pdata->phy_reset) {
|
||||
/* Hold the PHY in RESET for enough time till
|
||||
* PHY is settled and ready
|
||||
*/
|
||||
udelay(10);
|
||||
|
||||
if (gpio_is_valid(pdata->reset_gpio_port[0]))
|
||||
gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
|
||||
|
||||
if (gpio_is_valid(pdata->reset_gpio_port[1]))
|
||||
gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
|
||||
}
|
||||
|
||||
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to add hcd with err %d\n", ret);
|
||||
goto err_pm_runtime;
|
||||
}
|
||||
|
||||
/* root ports should always stay powered */
|
||||
ehci_port_power(omap_ehci, 1);
|
||||
|
||||
/* get clocks */
|
||||
utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
|
||||
if (IS_ERR(utmi_p1_fck)) {
|
||||
@ -512,7 +510,7 @@ static const struct hc_driver ehci_omap_hc_driver = {
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.reset = ehci_init,
|
||||
.reset = omap_ehci_init,
|
||||
.start = ehci_run,
|
||||
.stop = ehci_stop,
|
||||
.shutdown = ehci_shutdown,
|
||||
|
@ -106,21 +106,10 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval;
|
||||
|
||||
hcd->has_tt = 1;
|
||||
|
||||
retval = ehci_halt(ehci);
|
||||
retval = ehci_setup(ehci);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* data structure init
|
||||
*/
|
||||
retval = ehci_init(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
ehci_port_power(ehci, 0);
|
||||
|
||||
return retval;
|
||||
@ -261,11 +250,7 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev)
|
||||
|
||||
ehci = hcd_to_ehci(hcd);
|
||||
ehci->caps = hcd->regs + 0x100;
|
||||
ehci->regs = hcd->regs + 0x100 +
|
||||
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
hcd->has_tt = 1;
|
||||
ehci->sbrn = 0x20;
|
||||
|
||||
/*
|
||||
* (Re-)program MBUS remapping windows if we are asked to.
|
||||
|
@ -54,6 +54,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
u32 temp;
|
||||
int retval;
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
|
||||
/*
|
||||
* ehci_init() causes memory for DMA transfers to be
|
||||
* allocated. Thus, any vendor-specific workarounds based on
|
||||
* limiting the type of memory used for DMA transfers must
|
||||
* happen before ehci_setup() is called.
|
||||
*
|
||||
* Most other workarounds can be done either before or after
|
||||
* init and reset; they are located here too.
|
||||
*/
|
||||
switch (pdev->vendor) {
|
||||
case PCI_VENDOR_ID_TOSHIBA_2:
|
||||
/* celleb's companion chip */
|
||||
@ -66,20 +77,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
|
||||
dbg_hcs_params(ehci, "reset");
|
||||
dbg_hcc_params(ehci, "reset");
|
||||
|
||||
/* ehci_init() causes memory for DMA transfers to be
|
||||
* allocated. Thus, any vendor-specific workarounds based on
|
||||
* limiting the type of memory used for DMA transfers must
|
||||
* happen before ehci_init() is called. */
|
||||
switch (pdev->vendor) {
|
||||
case PCI_VENDOR_ID_NVIDIA:
|
||||
/* NVidia reports that certain chips don't handle
|
||||
* QH, ITD, or SITD addresses above 2GB. (But TD,
|
||||
@ -95,61 +92,28 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
ehci_warn(ehci, "can't enable NVidia "
|
||||
"workaround for >2GB RAM\n");
|
||||
break;
|
||||
|
||||
/* Some NForce2 chips have problems with selective suspend;
|
||||
* fixed in newer silicon.
|
||||
*/
|
||||
case 0x0068:
|
||||
if (pdev->revision < 0xa4)
|
||||
ehci->no_selective_suspend = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
retval = ehci_halt(ehci);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if ((pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x7808) ||
|
||||
(pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x4396)) {
|
||||
/* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
|
||||
* read/write memory space which does not belong to it when
|
||||
* there is NULL pointer with T-bit set to 1 in the frame list
|
||||
* table. To avoid the issue, the frame list link pointer
|
||||
* should always contain a valid pointer to a inactive qh.
|
||||
*/
|
||||
ehci->use_dummy_qh = 1;
|
||||
ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI "
|
||||
"dummy qh workaround\n");
|
||||
}
|
||||
|
||||
/* data structure init */
|
||||
retval = ehci_init(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
switch (pdev->vendor) {
|
||||
case PCI_VENDOR_ID_NEC:
|
||||
ehci->need_io_watchdog = 0;
|
||||
break;
|
||||
case PCI_VENDOR_ID_INTEL:
|
||||
ehci->need_io_watchdog = 0;
|
||||
ehci->fs_i_thresh = 1;
|
||||
if (pdev->device == 0x27cc) {
|
||||
ehci->broken_periodic = 1;
|
||||
ehci_info(ehci, "using broken periodic workaround\n");
|
||||
}
|
||||
if (pdev->device == 0x0806 || pdev->device == 0x0811
|
||||
|| pdev->device == 0x0829) {
|
||||
ehci_info(ehci, "disable lpm for langwell/penwell\n");
|
||||
ehci->has_lpm = 0;
|
||||
}
|
||||
if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) {
|
||||
if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB)
|
||||
hcd->has_tt = 1;
|
||||
tdi_reset(ehci);
|
||||
}
|
||||
break;
|
||||
case PCI_VENDOR_ID_TDI:
|
||||
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
|
||||
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI)
|
||||
hcd->has_tt = 1;
|
||||
tdi_reset(ehci);
|
||||
}
|
||||
break;
|
||||
case PCI_VENDOR_ID_AMD:
|
||||
/* AMD PLL quirk */
|
||||
@ -161,28 +125,17 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
retval = -EIO;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case PCI_VENDOR_ID_NVIDIA:
|
||||
switch (pdev->device) {
|
||||
/* Some NForce2 chips have problems with selective suspend;
|
||||
* fixed in newer silicon.
|
||||
*/
|
||||
case 0x0068:
|
||||
if (pdev->revision < 0xa4)
|
||||
ehci->no_selective_suspend = 1;
|
||||
break;
|
||||
|
||||
/* MCP89 chips on the MacBookAir3,1 give EPROTO when
|
||||
* fetching device descriptors unless LPM is disabled.
|
||||
* There are also intermittent problems enumerating
|
||||
* devices with PPCD enabled.
|
||||
/*
|
||||
* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
|
||||
* read/write memory space which does not belong to it when
|
||||
* there is NULL pointer with T-bit set to 1 in the frame list
|
||||
* table. To avoid the issue, the frame list link pointer
|
||||
* should always contain a valid pointer to a inactive qh.
|
||||
*/
|
||||
case 0x0d9d:
|
||||
ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
|
||||
ehci->has_lpm = 0;
|
||||
ehci->has_ppcd = 0;
|
||||
ehci->command &= ~CMD_PPCEE;
|
||||
break;
|
||||
if (pdev->device == 0x7808) {
|
||||
ehci->use_dummy_qh = 1;
|
||||
ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n");
|
||||
}
|
||||
break;
|
||||
case PCI_VENDOR_ID_VIA:
|
||||
@ -203,6 +156,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
/* AMD PLL quirk */
|
||||
if (usb_amd_find_chipset_info())
|
||||
ehci->amd_pll_fix = 1;
|
||||
|
||||
/*
|
||||
* EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may
|
||||
* read/write memory space which does not belong to it when
|
||||
* there is NULL pointer with T-bit set to 1 in the frame list
|
||||
* table. To avoid the issue, the frame list link pointer
|
||||
* should always contain a valid pointer to a inactive qh.
|
||||
*/
|
||||
if (pdev->device == 0x4396) {
|
||||
ehci->use_dummy_qh = 1;
|
||||
ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n");
|
||||
}
|
||||
/* SB600 and old version of SB700 have a bug in EHCI controller,
|
||||
* which causes usb devices lose response in some cases.
|
||||
*/
|
||||
@ -231,6 +196,40 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
break;
|
||||
}
|
||||
|
||||
retval = ehci_setup(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* These workarounds need to be applied after ehci_setup() */
|
||||
switch (pdev->vendor) {
|
||||
case PCI_VENDOR_ID_NEC:
|
||||
ehci->need_io_watchdog = 0;
|
||||
break;
|
||||
case PCI_VENDOR_ID_INTEL:
|
||||
ehci->need_io_watchdog = 0;
|
||||
if (pdev->device == 0x0806 || pdev->device == 0x0811
|
||||
|| pdev->device == 0x0829) {
|
||||
ehci_info(ehci, "disable lpm for langwell/penwell\n");
|
||||
ehci->has_lpm = 0;
|
||||
}
|
||||
break;
|
||||
case PCI_VENDOR_ID_NVIDIA:
|
||||
switch (pdev->device) {
|
||||
/* MCP89 chips on the MacBookAir3,1 give EPROTO when
|
||||
* fetching device descriptors unless LPM is disabled.
|
||||
* There are also intermittent problems enumerating
|
||||
* devices with PPCD enabled.
|
||||
*/
|
||||
case 0x0d9d:
|
||||
ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89");
|
||||
ehci->has_lpm = 0;
|
||||
ehci->has_ppcd = 0;
|
||||
ehci->command &= ~CMD_PPCEE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* optional debug port, normally in the first BAR */
|
||||
temp = pci_find_capability(pdev, 0x0a);
|
||||
if (temp) {
|
||||
@ -238,7 +237,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
temp >>= 16;
|
||||
if ((temp & (3 << 13)) == (1 << 13)) {
|
||||
temp &= 0x1fff;
|
||||
ehci->debug = ehci_to_hcd(ehci)->regs + temp;
|
||||
ehci->debug = hcd->regs + temp;
|
||||
temp = ehci_readl(ehci, &ehci->debug->control);
|
||||
ehci_info(ehci, "debug port %d%s\n",
|
||||
HCS_DEBUG_PORT(ehci->hcs_params),
|
||||
@ -250,8 +249,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
}
|
||||
}
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
/* at least the Genesys GL880S needs fixup here */
|
||||
temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
|
||||
temp &= 0x0f;
|
||||
@ -275,10 +272,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
}
|
||||
|
||||
/* Serial Bus Release Number is at PCI 0x60 offset */
|
||||
pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
|
||||
if (pdev->vendor == PCI_VENDOR_ID_STMICRO
|
||||
&& pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
|
||||
ehci->sbrn = 0x20; /* ConneXT has no sbrn register */
|
||||
; /* ConneXT has no sbrn register */
|
||||
else
|
||||
pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
|
||||
|
||||
/* Keep this around for a while just in case some EHCI
|
||||
* implementation uses legacy PCI PM support. This test
|
||||
|
@ -78,27 +78,14 @@ static int ehci_msp_setup(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval;
|
||||
|
||||
ehci->big_endian_mmio = 1;
|
||||
ehci->big_endian_desc = 1;
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, 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);
|
||||
hcd->has_tt = 1;
|
||||
|
||||
retval = ehci_halt(ehci);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
/* data structure init */
|
||||
retval = ehci_init(hcd);
|
||||
retval = ehci_setup(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
@ -17,24 +17,6 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
/* called during probe() after chip reset completes */
|
||||
static int ehci_ppc_of_setup(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval;
|
||||
|
||||
retval = ehci_halt(ehci);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = ehci_init(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci->sbrn = 0x20;
|
||||
return ehci_reset(ehci);
|
||||
}
|
||||
|
||||
|
||||
static const struct hc_driver ehci_ppc_of_hc_driver = {
|
||||
.description = hcd_name,
|
||||
@ -50,7 +32,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.reset = ehci_ppc_of_setup,
|
||||
.reset = ehci_setup,
|
||||
.start = ehci_run,
|
||||
.stop = ehci_stop,
|
||||
.shutdown = ehci_shutdown,
|
||||
@ -178,11 +160,6 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
|
||||
ehci->big_endian_desc = 1;
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
|
||||
rv = ppc44x_enable_bmt(dn);
|
||||
|
@ -55,28 +55,12 @@ static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
|
||||
ehci->big_endian_mmio = 1;
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
|
||||
&ehci->caps->hc_capbase));
|
||||
|
||||
dbg_hcs_params(ehci, "reset");
|
||||
dbg_hcc_params(ehci, "reset");
|
||||
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
result = ehci_halt(ehci);
|
||||
|
||||
result = ehci_setup(hcd);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = ehci_init(hcd);
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
ps3_ehci_setup_insnreg(ehci);
|
||||
|
||||
return result;
|
||||
|
@ -40,7 +40,7 @@ static const struct hc_driver s5p_ehci_hc_driver = {
|
||||
.irq = ehci_irq,
|
||||
.flags = HCD_MEMORY | HCD_USB2,
|
||||
|
||||
.reset = ehci_init,
|
||||
.reset = ehci_setup,
|
||||
.start = ehci_run,
|
||||
.stop = ehci_stop,
|
||||
.shutdown = ehci_shutdown,
|
||||
@ -134,20 +134,10 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)
|
||||
|
||||
ehci = hcd_to_ehci(hcd);
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
|
||||
|
||||
/* DMA burst Enable */
|
||||
writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
|
||||
|
||||
dbg_hcs_params(ehci, "reset");
|
||||
dbg_hcc_params(ehci, "reset");
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = readl(&ehci->caps->hcs_params);
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to add USB HCD\n");
|
||||
|
@ -24,25 +24,11 @@ static int ehci_sh_reset(struct usb_hcd *hcd)
|
||||
int ret;
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
|
||||
&ehci->caps->hc_capbase));
|
||||
|
||||
dbg_hcs_params(ehci, "reset");
|
||||
dbg_hcc_params(ehci, "reset");
|
||||
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
ret = ehci_halt(ehci);
|
||||
ret = ehci_setup(hcd);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
ret = ehci_init(hcd);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
ehci->sbrn = 0x20;
|
||||
|
||||
ehci_reset(ehci);
|
||||
ehci_port_power(ehci, 0);
|
||||
|
||||
return ret;
|
||||
|
@ -41,19 +41,11 @@ static int ehci_spear_setup(struct usb_hcd *hcd)
|
||||
|
||||
/* registers start at offset 0x0 */
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
|
||||
&ehci->caps->hc_capbase));
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
retval = ehci_halt(ehci);
|
||||
|
||||
retval = ehci_setup(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = ehci_init(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci_reset(ehci);
|
||||
ehci_port_power(ehci, 0);
|
||||
|
||||
return retval;
|
||||
|
@ -281,30 +281,14 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
|
||||
|
||||
/* EHCI registers start at offset 0x100 */
|
||||
ehci->caps = hcd->regs + 0x100;
|
||||
ehci->regs = hcd->regs + 0x100 +
|
||||
HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
|
||||
|
||||
dbg_hcs_params(ehci, "reset");
|
||||
dbg_hcc_params(ehci, "reset");
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = readl(&ehci->caps->hcs_params);
|
||||
|
||||
/* switch to host mode */
|
||||
hcd->has_tt = 1;
|
||||
ehci_reset(ehci);
|
||||
|
||||
retval = ehci_halt(ehci);
|
||||
retval = ehci_setup(ehci);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* data structure init */
|
||||
retval = ehci_init(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci->sbrn = 0x20;
|
||||
|
||||
ehci_port_power(ehci, 1);
|
||||
return retval;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.reset = ehci_init,
|
||||
.reset = ehci_setup,
|
||||
.start = ehci_run,
|
||||
.stop = ehci_stop,
|
||||
.shutdown = ehci_shutdown,
|
||||
@ -121,18 +121,6 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev)
|
||||
|
||||
ehci = hcd_to_ehci(hcd);
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
|
||||
|
||||
dbg_hcs_params(ehci, "reset");
|
||||
dbg_hcc_params(ehci, "reset");
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = readl(&ehci->caps->hcs_params);
|
||||
|
||||
ehci_port_power(ehci, 1);
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
ret = usb_add_hcd(hcd, pdev->resource[1].start,
|
||||
IRQF_SHARED);
|
||||
|
@ -71,21 +71,14 @@ static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
|
||||
val |= ENPHY;
|
||||
__raw_writel(val, ehci->regs+PHY1_CTR);
|
||||
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
ehci->sbrn = 0x20;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
goto err4;
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
||||
if (retval != 0)
|
||||
goto err4;
|
||||
|
||||
ehci_writel(ehci, 1, &ehci->regs->configured_flag);
|
||||
|
||||
return retval;
|
||||
err4:
|
||||
iounmap(hcd->regs);
|
||||
@ -120,7 +113,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = {
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.reset = ehci_init,
|
||||
.reset = ehci_setup,
|
||||
.start = ehci_run,
|
||||
|
||||
.stop = ehci_stop,
|
||||
|
@ -31,30 +31,6 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
/**
|
||||
* ehci_xilinx_of_setup - Initialize the device for ehci_reset()
|
||||
* @hcd: Pointer to the usb_hcd device to which the host controller bound
|
||||
*
|
||||
* called during probe() after chip reset completes.
|
||||
*/
|
||||
static int ehci_xilinx_of_setup(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval;
|
||||
|
||||
retval = ehci_halt(ehci);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
retval = ehci_init(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci->sbrn = 0x20;
|
||||
|
||||
return ehci_reset(ehci);
|
||||
}
|
||||
|
||||
/**
|
||||
* ehci_xilinx_port_handed_over - hand the port out if failed to enable it
|
||||
* @hcd: Pointer to the usb_hcd device to which the host controller bound
|
||||
@ -107,7 +83,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.reset = ehci_xilinx_of_setup,
|
||||
.reset = ehci_setup,
|
||||
.start = ehci_run,
|
||||
.stop = ehci_stop,
|
||||
.shutdown = ehci_shutdown,
|
||||
@ -219,11 +195,6 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
|
||||
/* Debug registers are at the first 0x100 region
|
||||
*/
|
||||
ehci->caps = hcd->regs + 0x100;
|
||||
ehci->regs = hcd->regs + 0x100 +
|
||||
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
rv = usb_add_hcd(hcd, irq, 0);
|
||||
if (rv == 0)
|
||||
|
@ -14,30 +14,11 @@
|
||||
|
||||
static int ehci_xls_setup(struct usb_hcd *hcd)
|
||||
{
|
||||
int retval;
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci, 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);
|
||||
|
||||
retval = ehci_halt(ehci);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* data structure init */
|
||||
retval = ehci_init(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
return retval;
|
||||
return ehci_setup(ehci);
|
||||
}
|
||||
|
||||
int ehci_xls_probe_internal(const struct hc_driver *driver,
|
||||
|
Loading…
Reference in New Issue
Block a user