aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-03-16 13:05:30 +0000
committerArnd Bergmann <arnd@arndb.de>2012-03-16 13:05:46 +0000
commit2a9f23d82a79d2785429aba43b02683abf103c0b (patch)
tree16fc44dc26a0af5b08ac668ee02f4022737c33ae /drivers/usb
parentMerge branch 'dt-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/dt (diff)
parentARM: at91: dt: enable usb ehci for sam9g45 and sam9x5 (diff)
downloadlinux-dev-2a9f23d82a79d2785429aba43b02683abf103c0b.tar.xz
linux-dev-2a9f23d82a79d2785429aba43b02683abf103c0b.zip
Merge branch 'at91-3.4-cleanup2-DT2' of git://github.com/at91linux/linux-at91 into next/dt
* 'at91-3.4-cleanup2-DT2' of git://github.com/at91linux/linux-at91: (23 commits) ARM: at91: dt: enable usb ehci for sam9g45 and sam9x5 ARM: at91: usb ehci add dt support ARM: at91: dt: enable usb ohci for sam9g20, sam9g45 amd sam9x5 ARM: at91: usb ohci add dt support ARM: at91: add Shutdown Controller (SHDWC) DT support ARM: at91: add ram controller DT support ARM: at91: add RSTC (Reset Controller) dt support ARM: at91: always enable sam9 restart ARM: at91: add pmc DT support ARM: at91/dt: add specific DT soc init ARM: at91/dt: add Calao DAB-MMX daugther board support for USB-A9G20 ARM: at91: sam9x5 add i2c DT support ARM: at91: sam9g45 add i2c DT support ARM: at91: usb_a9g20 add DT i2c support ARM: at91: sam9g20 add i2c DT support i2c/gpio: add DT support ARM: at91: sam9x5 add nand support atmel/nand: add DT support of/mtd/nand: add generic bindings and helpers of: introduce helper to manage boolean ...
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Kconfig2
-rw-r--r--drivers/usb/host/ehci-atmel.c24
-rw-r--r--drivers/usb/host/ohci-at91.c101
3 files changed, 124 insertions, 3 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 75823a1abeb6..7fe4902d9e51 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -65,7 +65,7 @@ config USB_ARCH_HAS_EHCI
default y if PPC_MPC512x
default y if ARCH_IXP4XX
default y if ARCH_W90X900
- default y if ARCH_AT91SAM9G45
+ default y if ARCH_AT91
default y if ARCH_MXC
default y if ARCH_OMAP3
default y if ARCH_CNS3XXX
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index a5a3ef1f0096..19f318ababa2 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -13,6 +13,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
/* interface and function clocks */
static struct clk *iclk, *fclk;
@@ -115,6 +116,8 @@ static const struct hc_driver ehci_atmel_hc_driver = {
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
+static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
+
static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
@@ -137,6 +140,13 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
goto fail_create_hcd;
}
+ /* Right now device-tree probed devices don't get dma_mask set.
+ * Since shared usb code relies on it, set it here for now.
+ * Once we have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &at91_ehci_dma_mask;
+
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
retval = -ENOMEM;
@@ -225,9 +235,21 @@ static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_ehci_dt_ids[] = {
+ { .compatible = "atmel,at91sam9g45-ehci" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids);
+#endif
+
static struct platform_driver ehci_atmel_driver = {
.probe = ehci_atmel_drv_probe,
.remove = __devexit_p(ehci_atmel_drv_remove),
.shutdown = usb_hcd_platform_shutdown,
- .driver.name = "atmel-ehci",
+ .driver = {
+ .name = "atmel-ehci",
+ .of_match_table = of_match_ptr(atmel_ehci_dt_ids),
+ },
};
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 8e855eb0bf89..db8963f5fbce 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -14,6 +14,8 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
#include <mach/hardware.h>
#include <asm/gpio.h>
@@ -477,13 +479,109 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
return IRQ_HANDLED;
}
+#ifdef CONFIG_OF
+static const struct of_device_id at91_ohci_dt_ids[] = {
+ { .compatible = "atmel,at91rm9200-ohci" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
+
+static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32);
+
+static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int i, ret, gpio;
+ enum of_gpio_flags flags;
+ struct at91_usbh_data *pdata;
+ u32 ports;
+
+ if (!np)
+ return 0;
+
+ /* Right now device-tree probed devices don't get dma_mask set.
+ * Since shared usb code relies on it, set it here for now.
+ * Once we have dma capability bindings this can go away.
+ */
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &at91_ohci_dma_mask;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ if (!of_property_read_u32(np, "num-ports", &ports))
+ pdata->ports = ports;
+
+ for (i = 0; i < 2; i++) {
+ gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags);
+ pdata->vbus_pin[i] = gpio;
+ if (!gpio_is_valid(gpio))
+ continue;
+ pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
+ ret = gpio_request(gpio, "ohci_vbus");
+ if (ret) {
+ dev_warn(&pdev->dev, "can't request vbus gpio %d", gpio);
+ continue;
+ }
+ ret = gpio_direction_output(gpio, !(flags & OF_GPIO_ACTIVE_LOW) ^ 1);
+ if (ret)
+ dev_warn(&pdev->dev, "can't put vbus gpio %d as output %d",
+ !(flags & OF_GPIO_ACTIVE_LOW) ^ 1, gpio);
+ }
+
+ for (i = 0; i < 2; i++) {
+ gpio = of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
+ pdata->overcurrent_pin[i] = gpio;
+ if (!gpio_is_valid(gpio))
+ continue;
+ ret = gpio_request(gpio, "ohci_overcurrent");
+ if (ret) {
+ dev_err(&pdev->dev, "can't request overcurrent gpio %d", gpio);
+ continue;
+ }
+
+ ret = gpio_direction_input(gpio);
+ if (ret) {
+ dev_err(&pdev->dev, "can't configure overcurrent gpio %d as input", gpio);
+ continue;
+ }
+
+ ret = request_irq(gpio_to_irq(gpio),
+ ohci_hcd_at91_overcurrent_irq,
+ IRQF_SHARED, "ohci_overcurrent", pdev);
+ if (ret) {
+ gpio_free(gpio);
+ dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n");
+ }
+ }
+
+ pdev->dev.platform_data = pdata;
+
+ return 0;
+}
+#else
+static int __devinit ohci_at91_of_init(struct platform_device *pdev)
+{
+ return 0;
+}
+#endif
+
/*-------------------------------------------------------------------------*/
static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
{
- struct at91_usbh_data *pdata = pdev->dev.platform_data;
+ struct at91_usbh_data *pdata;
int i;
+ i = ohci_at91_of_init(pdev);
+
+ if (i)
+ return i;
+
+ pdata = pdev->dev.platform_data;
+
if (pdata) {
for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
if (!gpio_is_valid(pdata->vbus_pin[i]))
@@ -596,5 +694,6 @@ static struct platform_driver ohci_hcd_at91_driver = {
.driver = {
.name = "at91_ohci",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(at91_ohci_dt_ids),
},
};