diff options
Diffstat (limited to 'drivers/usb/host/ehci-ps3.c')
| -rw-r--r-- | drivers/usb/host/ehci-ps3.c | 52 | 
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 1dee33b9139..7934ff9b35e 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -21,33 +21,47 @@  #include <asm/firmware.h>  #include <asm/ps3.h> -static int ps3_ehci_hc_reset(struct usb_hcd *hcd) +static void ps3_ehci_setup_insnreg(struct ehci_hcd *ehci)  { -	int result; -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); +	/* PS3 HC internal setup register offsets. */ -	ehci->big_endian_mmio = 1; +	enum ps3_ehci_hc_insnreg { +		ps3_ehci_hc_insnreg01 = 0x084, +		ps3_ehci_hc_insnreg02 = 0x088, +		ps3_ehci_hc_insnreg03 = 0x08c, +	}; -	ehci->caps = hcd->regs; -	ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, -		&ehci->caps->hc_capbase)); +	/* PS3 EHCI HC errata fix 316 - The PS3 EHCI HC will reset its +	 * internal INSNREGXX setup regs back to the chip default values +	 * on Host Controller Reset (CMD_RESET) or Light Host Controller +	 * Reset (CMD_LRESET).  The work-around for this is for the HC +	 * driver to re-initialise these regs when ever the HC is reset. +	 */ -	dbg_hcs_params(ehci, "reset"); -	dbg_hcc_params(ehci, "reset"); +	/* Set burst transfer counts to 256 out, 32 in. */ -	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); +	writel_be(0x01000020, (void __iomem *)ehci->regs + +		ps3_ehci_hc_insnreg01); -	result = ehci_halt(ehci); +	/* Enable burst transfer counts. */ -	if (result) -		return result; +	writel_be(0x00000001, (void __iomem *)ehci->regs + +		ps3_ehci_hc_insnreg03); +} -	result = ehci_init(hcd); +static int ps3_ehci_hc_reset(struct usb_hcd *hcd) +{ +	int result; +	struct ehci_hcd *ehci = hcd_to_ehci(hcd); + +	ehci->big_endian_mmio = 1; +	ehci->caps = hcd->regs; +	result = ehci_setup(hcd);  	if (result)  		return result; -	ehci_reset(ehci); +	ps3_ehci_setup_insnreg(ehci);  	return result;  } @@ -57,7 +71,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {  	.product_desc		= "PS3 EHCI Host Controller",  	.hcd_priv_size		= sizeof(struct ehci_hcd),  	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, +	.flags			= HCD_MEMORY | HCD_USB2 | HCD_BH,  	.reset			= ps3_ehci_hc_reset,  	.start			= ehci_run,  	.stop			= ehci_stop, @@ -79,7 +93,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {  	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,  }; -static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev) +static int ps3_ehci_probe(struct ps3_system_bus_device *dev)  {  	int result;  	struct usb_hcd *hcd; @@ -167,7 +181,7 @@ static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)  	ps3_system_bus_set_drvdata(dev, hcd); -	result = usb_add_hcd(hcd, virq, IRQF_DISABLED); +	result = usb_add_hcd(hcd, virq, 0);  	if (result) {  		dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", @@ -175,6 +189,7 @@ static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)  		goto fail_add_hcd;  	} +	device_wakeup_enable(hcd->self.controller);  	return result;  fail_add_hcd: @@ -207,7 +222,6 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev)  	tmp = hcd->irq; -	ehci_shutdown(hcd);  	usb_remove_hcd(hcd);  	ps3_system_bus_set_drvdata(dev, NULL);  | 
