|
|
@ -1,12 +1,15 @@ |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* EHCI HCD (Host Controller Driver) for USB. |
|
|
|
* Bus Glue for Atheros AR71xx built-in EHCI controller. |
|
|
|
* |
|
|
|
* |
|
|
|
* Copyright (C) 2007 Atheros Communications, Inc. |
|
|
|
|
|
|
|
* Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> |
|
|
|
* Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> |
|
|
|
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> |
|
|
|
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> |
|
|
|
* |
|
|
|
* |
|
|
|
* Bus Glue for Atheros AR71xx built-in EHCI controller |
|
|
|
* Parts of this file are based on Atheros' 2.6.15 BSP |
|
|
|
|
|
|
|
* Copyright (C) 2007 Atheros Communications, Inc. |
|
|
|
* |
|
|
|
* |
|
|
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify it |
|
|
|
|
|
|
|
* under the terms of the GNU General Public License version 2 as published |
|
|
|
|
|
|
|
* by the Free Software Foundation. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#include <linux/platform_device.h> |
|
|
|
#include <linux/platform_device.h> |
|
|
@ -14,14 +17,14 @@ |
|
|
|
|
|
|
|
|
|
|
|
extern int usb_disabled(void); |
|
|
|
extern int usb_disabled(void); |
|
|
|
|
|
|
|
|
|
|
|
static void ar71xx_start_ehci(struct platform_device *pdev) |
|
|
|
static void ehci_ar71xx_setup(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* TODO: implement |
|
|
|
* TODO: implement |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int usb_ehci_ar71xx_probe(const struct hc_driver *driver, |
|
|
|
static int ehci_ar71xx_probe(const struct hc_driver *driver, |
|
|
|
struct usb_hcd **hcd_out, |
|
|
|
struct usb_hcd **hcd_out, |
|
|
|
struct platform_device *pdev) |
|
|
|
struct platform_device *pdev) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -39,17 +42,17 @@ static int usb_ehci_ar71xx_probe(const struct hc_driver *driver, |
|
|
|
} |
|
|
|
} |
|
|
|
irq = res->start; |
|
|
|
irq = res->start; |
|
|
|
|
|
|
|
|
|
|
|
hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); |
|
|
|
|
|
|
|
if (!hcd) |
|
|
|
|
|
|
|
return -ENOMEM; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|
|
|
if (!res) { |
|
|
|
if (!res) { |
|
|
|
dev_dbg(&pdev->dev, "no base address specified for %s\n", |
|
|
|
dev_dbg(&pdev->dev, "no base address specified for %s\n", |
|
|
|
pdev->dev.bus_id); |
|
|
|
pdev->dev.bus_id); |
|
|
|
ret = -ENODEV; |
|
|
|
return -ENODEV; |
|
|
|
goto err_put_hcd; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); |
|
|
|
|
|
|
|
if (!hcd) |
|
|
|
|
|
|
|
return -ENOMEM; |
|
|
|
|
|
|
|
|
|
|
|
hcd->rsrc_start = res->start; |
|
|
|
hcd->rsrc_start = res->start; |
|
|
|
hcd->rsrc_len = res->end - res->start + 1; |
|
|
|
hcd->rsrc_len = res->end - res->start + 1; |
|
|
|
|
|
|
|
|
|
|
@ -68,10 +71,11 @@ static int usb_ehci_ar71xx_probe(const struct hc_driver *driver, |
|
|
|
|
|
|
|
|
|
|
|
ehci = hcd_to_ehci(hcd); |
|
|
|
ehci = hcd_to_ehci(hcd); |
|
|
|
ehci->caps = hcd->regs; |
|
|
|
ehci->caps = hcd->regs; |
|
|
|
ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); |
|
|
|
ehci->regs = hcd->regs + |
|
|
|
ehci->hcs_params = readl(&ehci->caps->hcs_params); |
|
|
|
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); |
|
|
|
|
|
|
|
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); |
|
|
|
|
|
|
|
|
|
|
|
ar71xx_start_ehci(pdev); |
|
|
|
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) |
|
|
@ -89,7 +93,7 @@ static int usb_ehci_ar71xx_probe(const struct hc_driver *driver, |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void usb_ehci_ar71xx_remove(struct usb_hcd *hcd, |
|
|
|
static void ehci_ar71xx_remove(struct usb_hcd *hcd, |
|
|
|
struct platform_device *pdev) |
|
|
|
struct platform_device *pdev) |
|
|
|
{ |
|
|
|
{ |
|
|
|
usb_remove_hcd(hcd); |
|
|
|
usb_remove_hcd(hcd); |
|
|
@ -140,32 +144,30 @@ static const struct hc_driver ehci_ar71xx_hc_driver = { |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static int ehci_hcd_ar71xx_drv_probe(struct platform_device *pdev) |
|
|
|
static int ehci_ar71xx_driver_probe(struct platform_device *pdev) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct usb_hcd *hcd = NULL; |
|
|
|
struct usb_hcd *hcd = NULL; |
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ret = -ENODEV; |
|
|
|
if (usb_disabled()) |
|
|
|
if (!usb_disabled()) |
|
|
|
return -ENODEV; |
|
|
|
ret = usb_ehci_ar71xx_probe(&ehci_ar71xx_hc_driver, &hcd, pdev); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
return ehci_ar71xx_probe(&ehci_ar71xx_hc_driver, &hcd, pdev); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int ehci_hcd_ar71xx_drv_remove(struct platform_device *pdev) |
|
|
|
static int ehci_ar71xx_driver_remove(struct platform_device *pdev) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct usb_hcd *hcd = platform_get_drvdata(pdev); |
|
|
|
struct usb_hcd *hcd = platform_get_drvdata(pdev); |
|
|
|
|
|
|
|
|
|
|
|
usb_ehci_ar71xx_remove(hcd, pdev); |
|
|
|
ehci_ar71xx_remove(hcd, pdev); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static struct platform_driver ehci_hcd_ar71xx_driver = { |
|
|
|
MODULE_ALIAS("platform:ar71xx-ehci"); |
|
|
|
.probe = ehci_hcd_ar71xx_drv_probe, |
|
|
|
|
|
|
|
.remove = ehci_hcd_ar71xx_drv_remove, |
|
|
|
static struct platform_driver ehci_ar71xx_driver = { |
|
|
|
|
|
|
|
.probe = ehci_ar71xx_driver_probe, |
|
|
|
|
|
|
|
.remove = ehci_ar71xx_driver_remove, |
|
|
|
.driver = { |
|
|
|
.driver = { |
|
|
|
.name = "ar71xx-ehci", |
|
|
|
.name = "ar71xx-ehci", |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
MODULE_ALIAS("platform:ar71xx-ehci"); |
|
|
|
|
|
|
|