|
|
@ -19,11 +19,51 @@ |
|
|
|
|
|
|
|
|
|
|
|
extern int usb_disabled(void); |
|
|
|
extern int usb_disabled(void); |
|
|
|
|
|
|
|
|
|
|
|
static void ehci_ar71xx_setup(void) |
|
|
|
static int ehci_ar71xx_init(struct usb_hcd *hcd) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/*
|
|
|
|
struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
|
|
|
* TODO: implement |
|
|
|
int ret; |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
ehci->caps = hcd->regs; |
|
|
|
|
|
|
|
ehci->regs = hcd->regs + |
|
|
|
|
|
|
|
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); |
|
|
|
|
|
|
|
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ehci->sbrn = 0x20; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ehci_reset(ehci); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ret = ehci_init(hcd); |
|
|
|
|
|
|
|
if (ret) |
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ehci_port_power(ehci, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int ehci_ar91xx_init(struct usb_hcd *hcd) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
|
|
|
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ehci->caps = hcd->regs + 0x100; |
|
|
|
|
|
|
|
ehci->regs = hcd->regs + 0x100 + |
|
|
|
|
|
|
|
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); |
|
|
|
|
|
|
|
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hcd->has_tt = 1; |
|
|
|
|
|
|
|
ehci->sbrn = 0x20; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ehci_reset(ehci); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ret = ehci_init(hcd); |
|
|
|
|
|
|
|
if (ret) |
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ehci_port_power(ehci, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int ehci_ar71xx_probe(const struct hc_driver *driver, |
|
|
|
static int ehci_ar71xx_probe(const struct hc_driver *driver, |
|
|
@ -31,7 +71,6 @@ static int ehci_ar71xx_probe(const struct hc_driver *driver, |
|
|
|
struct platform_device *pdev) |
|
|
|
struct platform_device *pdev) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct usb_hcd *hcd; |
|
|
|
struct usb_hcd *hcd; |
|
|
|
struct ehci_hcd *ehci; |
|
|
|
|
|
|
|
struct resource *res; |
|
|
|
struct resource *res; |
|
|
|
int irq; |
|
|
|
int irq; |
|
|
|
int ret; |
|
|
|
int ret; |
|
|
@ -71,14 +110,6 @@ static int ehci_ar71xx_probe(const struct hc_driver *driver, |
|
|
|
goto err_release_region; |
|
|
|
goto err_release_region; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ehci = hcd_to_ehci(hcd); |
|
|
|
|
|
|
|
ehci->caps = hcd->regs; |
|
|
|
|
|
|
|
ehci->regs = hcd->regs + |
|
|
|
|
|
|
|
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); |
|
|
|
|
|
|
|
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ehci_ar71xx_setup(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); |
|
|
|
ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); |
|
|
|
if (ret) |
|
|
|
if (ret) |
|
|
|
goto err_iounmap; |
|
|
|
goto err_iounmap; |
|
|
@ -109,51 +140,80 @@ static const struct hc_driver ehci_ar71xx_hc_driver = { |
|
|
|
.product_desc = "Atheros AR71xx built-in EHCI controller", |
|
|
|
.product_desc = "Atheros AR71xx built-in EHCI controller", |
|
|
|
.hcd_priv_size = sizeof(struct ehci_hcd), |
|
|
|
.hcd_priv_size = sizeof(struct ehci_hcd), |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* generic hardware linkage |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
.irq = ehci_irq, |
|
|
|
.irq = ehci_irq, |
|
|
|
.flags = HCD_MEMORY | HCD_USB2, |
|
|
|
.flags = HCD_MEMORY | HCD_USB2, |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
.reset = ehci_ar71xx_init, |
|
|
|
* basic lifecycle operations |
|
|
|
.start = ehci_run, |
|
|
|
*/ |
|
|
|
.stop = ehci_stop, |
|
|
|
.reset = ehci_init, |
|
|
|
.shutdown = ehci_shutdown, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.urb_enqueue = ehci_urb_enqueue, |
|
|
|
|
|
|
|
.urb_dequeue = ehci_urb_dequeue, |
|
|
|
|
|
|
|
.endpoint_disable = ehci_endpoint_disable, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.get_frame_number = ehci_get_frame, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.hub_status_data = ehci_hub_status_data, |
|
|
|
|
|
|
|
.hub_control = ehci_hub_control, |
|
|
|
|
|
|
|
#ifdef CONFIG_PM |
|
|
|
|
|
|
|
.hub_suspend = ehci_hub_suspend, |
|
|
|
|
|
|
|
.hub_resume = ehci_hub_resume, |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
.relinquish_port = ehci_relinquish_port, |
|
|
|
|
|
|
|
.port_handed_over = ehci_port_handed_over, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const struct hc_driver ehci_ar91xx_hc_driver = { |
|
|
|
|
|
|
|
.description = hcd_name, |
|
|
|
|
|
|
|
.product_desc = "Atheros AR91xx built-in EHCI controller", |
|
|
|
|
|
|
|
.hcd_priv_size = sizeof(struct ehci_hcd), |
|
|
|
|
|
|
|
.irq = ehci_irq, |
|
|
|
|
|
|
|
.flags = HCD_MEMORY | HCD_USB2, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.reset = ehci_ar91xx_init, |
|
|
|
.start = ehci_run, |
|
|
|
.start = ehci_run, |
|
|
|
.stop = ehci_stop, |
|
|
|
.stop = ehci_stop, |
|
|
|
.shutdown = ehci_shutdown, |
|
|
|
.shutdown = ehci_shutdown, |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* managing i/o requests and associated device resources |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
.urb_enqueue = ehci_urb_enqueue, |
|
|
|
.urb_enqueue = ehci_urb_enqueue, |
|
|
|
.urb_dequeue = ehci_urb_dequeue, |
|
|
|
.urb_dequeue = ehci_urb_dequeue, |
|
|
|
.endpoint_disable = ehci_endpoint_disable, |
|
|
|
.endpoint_disable = ehci_endpoint_disable, |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* scheduling support |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
.get_frame_number = ehci_get_frame, |
|
|
|
.get_frame_number = ehci_get_frame, |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* root hub support |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
.hub_status_data = ehci_hub_status_data, |
|
|
|
.hub_status_data = ehci_hub_status_data, |
|
|
|
.hub_control = ehci_hub_control, |
|
|
|
.hub_control = ehci_hub_control, |
|
|
|
#ifdef CONFIG_PM |
|
|
|
#ifdef CONFIG_PM |
|
|
|
.hub_suspend = ehci_hub_suspend, |
|
|
|
.hub_suspend = ehci_hub_suspend, |
|
|
|
.hub_resume = ehci_hub_resume, |
|
|
|
.hub_resume = ehci_hub_resume, |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
.relinquish_port = ehci_relinquish_port, |
|
|
|
|
|
|
|
.port_handed_over = ehci_port_handed_over, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static int ehci_ar71xx_driver_probe(struct platform_device *pdev) |
|
|
|
static int ehci_ar71xx_driver_probe(struct platform_device *pdev) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
struct ar71xx_ehci_platform_data *pdata; |
|
|
|
struct usb_hcd *hcd = NULL; |
|
|
|
struct usb_hcd *hcd = NULL; |
|
|
|
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
|
|
if (usb_disabled()) |
|
|
|
if (usb_disabled()) |
|
|
|
return -ENODEV; |
|
|
|
return -ENODEV; |
|
|
|
|
|
|
|
|
|
|
|
return ehci_ar71xx_probe(&ehci_ar71xx_hc_driver, &hcd, pdev); |
|
|
|
pdata = pdev->dev.platform_data; |
|
|
|
|
|
|
|
if (!pdata) { |
|
|
|
|
|
|
|
dev_err(&pdev->dev, "no platform data specified for %s\n", |
|
|
|
|
|
|
|
pdev->dev.bus_id); |
|
|
|
|
|
|
|
return -ENODEV; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pdata->is_ar91xx) |
|
|
|
|
|
|
|
ret = ehci_ar71xx_probe(&ehci_ar91xx_hc_driver, &hcd, pdev); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
ret = ehci_ar71xx_probe(&ehci_ar71xx_hc_driver, &hcd, pdev); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int ehci_ar71xx_driver_remove(struct platform_device *pdev) |
|
|
|
static int ehci_ar71xx_driver_remove(struct platform_device *pdev) |
|
|
|