Skip to content

Commit

Permalink
EHCI: centralize controller initialization
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Jul 9, 2012
1 parent 1530280 commit 1a49e2a
Show file tree
Hide file tree
Showing 24 changed files with 164 additions and 439 deletions.
19 changes: 2 additions & 17 deletions drivers/usb/host/ehci-atmel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
if (retval)
return retval;

/* data structure init */
retval = ehci_init(hcd);
retval = ehci_setup(hcd);
if (retval)
return retval;

ehci->sbrn = 0x20;

ehci_reset(ehci);
ehci_port_power(ehci, 0);

return retval;
Expand Down
14 changes: 4 additions & 10 deletions drivers/usb/host/ehci-au1xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/host/ehci-cns3xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
18 changes: 1 addition & 17 deletions drivers/usb/host/ehci-fsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
if (retval)
return retval;

/* data structure init */
retval = ehci_init(hcd);
retval = ehci_setup(hcd);
if (retval)
return retval;

ehci->sbrn = 0x20;

ehci_reset(ehci);

if (of_device_is_compatible(dev->parent->of_node,
"fsl,mpc5121-usb2-dr")) {
/*
Expand Down
15 changes: 2 additions & 13 deletions drivers/usb/host/ehci-grlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/host/ehci-ixp4xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
23 changes: 4 additions & 19 deletions drivers/usb/host/ehci-mv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 = {
Expand Down Expand Up @@ -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) {
Expand Down
17 changes: 1 addition & 16 deletions drivers/usb/host/ehci-mxc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
8 changes: 1 addition & 7 deletions drivers/usb/host/ehci-octeon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit 1a49e2a

Please sign in to comment.