gemini: update usb driver and merge registers into one patch

Signed-off-by: Roman Yeryomin <roman@advem.lv>

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@43703 3c298f89-4303-0410-b956-a3cf2f4a3e73
master
John Crispin 2014-12-14 08:57:52 +00:00
parent e6ce5b6114
commit 426f76bc46
9 changed files with 546 additions and 741 deletions

View File

@ -0,0 +1,258 @@
/*
* Gemini EHCI Host Controller driver
*
* Copyright (C) 2014 Roman Yeryomin <roman@advem.lv>
* Copyright (C) 2012 Tobias Waldvogel
* based on GPLd code from Sony Computer Entertainment Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*/
#include <linux/kernel.h>
#include <linux/hrtimer.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/ehci_pdriver.h>
#include <mach/hardware.h>
#include <mach/global_reg.h>
#include "ehci.h"
#define DRV_NAME "ehci-fotg2"
#define HCD_MISC 0x40
#define OTGC_SCR 0x80
#define OTGC_INT_STS 0x84
#define OTGC_INT_EN 0x88
#define GLOBAL_ISR 0xC0
#define GLOBAL_ICR 0xC4
#define GLOBAL_INT_POLARITY (1 << 3)
#define GLOBAL_INT_MASK_HC (1 << 2)
#define GLOBAL_INT_MASK_OTG (1 << 1)
#define GLOBAL_INT_MASK_DEV (1 << 0)
#define OTGC_SCR_ID (1 << 21)
#define OTGC_SCR_CROLE (1 << 20)
#define OTGC_SCR_VBUS_VLD (1 << 19)
#define OTGC_SCR_A_SRP_RESP_TYPE (1 << 8)
#define OTGC_SCR_A_SRP_DET_EN (1 << 7)
#define OTGC_SCR_A_SET_B_HNP_EN (1 << 6)
#define OTGC_SCR_A_BUS_DROP (1 << 5)
#define OTGC_SCR_A_BUS_REQ (1 << 4)
#define OTGC_INT_APLGRMV (1 << 12)
#define OTGC_INT_BPLGRMV (1 << 11)
#define OTGC_INT_OVC (1 << 10)
#define OTGC_INT_IDCHG (1 << 9)
#define OTGC_INT_RLCHG (1 << 8)
#define OTGC_INT_AVBUSERR (1 << 5)
#define OTGC_INT_ASRPDET (1 << 4)
#define OTGC_INT_BSRPDN (1 << 0)
#define OTGC_INT_A_TYPE ( \
OTGC_INT_ASRPDET | \
OTGC_INT_AVBUSERR | \
OTGC_INT_OVC | \
OTGC_INT_RLCHG | \
OTGC_INT_IDCHG | \
OTGC_INT_APLGRMV \
)
#define OTGC_INT_B_TYPE ( \
OTGC_INT_AVBUSERR | \
OTGC_INT_OVC | \
OTGC_INT_RLCHG | \
OTGC_INT_IDCHG \
)
static void fotg2_otg_init(struct usb_hcd *hcd)
{
u32 val;
writel(GLOBAL_INT_POLARITY | GLOBAL_INT_MASK_HC |
GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV,
hcd->regs + GLOBAL_ICR);
val = readl(hcd->regs + OTGC_SCR);
val &= ~(OTGC_SCR_A_SRP_RESP_TYPE | OTGC_SCR_A_SRP_DET_EN |
OTGC_SCR_A_BUS_DROP | OTGC_SCR_A_SET_B_HNP_EN);
val |= OTGC_SCR_A_BUS_REQ;
writel(val, hcd->regs + OTGC_SCR);
writel(OTGC_INT_A_TYPE, hcd->regs + OTGC_INT_EN);
/* setup MISC register, fixes timing problems */
val = readl(hcd->regs + HCD_MISC);
val |= 0xD;
writel(val, hcd->regs + HCD_MISC);
writel(~0, hcd->regs + GLOBAL_ISR);
writel(~0, hcd->regs + OTGC_INT_STS);
}
static int fotg2_ehci_reset(struct usb_hcd *hcd)
{
int retval;
retval = ehci_setup(hcd);
if (retval)
return retval;
writel(GLOBAL_INT_POLARITY, hcd->regs + GLOBAL_ICR);
return 0;
}
static const struct hc_driver fotg2_ehci_hc_driver = {
.description = hcd_name,
.product_desc = "FOTG2 EHCI Host Controller",
.hcd_priv_size = sizeof(struct ehci_hcd),
.irq = ehci_irq,
.flags = HCD_MEMORY | HCD_USB2,
.reset = fotg2_ehci_reset,
.start = ehci_run,
.stop = ehci_stop,
.shutdown = ehci_shutdown,
.urb_enqueue = ehci_urb_enqueue,
.urb_dequeue = ehci_urb_dequeue,
.endpoint_disable = ehci_endpoint_disable,
.endpoint_reset = ehci_endpoint_reset,
.get_frame_number = ehci_get_frame,
.hub_status_data = ehci_hub_status_data,
.hub_control = ehci_hub_control,
#if defined(CONFIG_PM)
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
#endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
static irqreturn_t fotg2_ehci_irq(int irq, void *data)
{
struct usb_hcd *hcd = data;
u32 icr, sts;
irqreturn_t retval;
icr = readl(hcd->regs + GLOBAL_ICR);
writel(GLOBAL_INT_POLARITY | GLOBAL_INT_MASK_HC |
GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV,
hcd->regs + GLOBAL_ICR);
retval = IRQ_NONE;
sts = ~icr;
sts &= GLOBAL_INT_MASK_HC | GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV;
sts &= readl(hcd->regs + GLOBAL_ISR);
writel(sts, hcd->regs + GLOBAL_ISR);
if (unlikely(sts & GLOBAL_INT_MASK_DEV)) {
ehci_warn(hcd_to_ehci(hcd),
"Received unexpected irq for device role\n");
retval = IRQ_HANDLED;
}
if (unlikely(sts & GLOBAL_INT_MASK_OTG)) {
u32 otg_sts;
otg_sts = readl(hcd->regs + OTGC_INT_STS);
writel(otg_sts, hcd->regs + OTGC_INT_STS);
ehci_warn(hcd_to_ehci(hcd),
"Received unexpected irq for OTG management\n");
retval = IRQ_HANDLED;
}
if (sts & GLOBAL_INT_MASK_HC) {
retval = IRQ_NONE;
}
writel(icr, hcd->regs + GLOBAL_ICR);
return retval;
}
static int fotg2_ehci_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
struct resource *res;
int irq , err;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
pr_err("no irq provided");
return irq;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
pr_err("no memory resource provided");
return -ENXIO;
}
hcd = usb_create_hcd(&fotg2_ehci_hc_driver, &pdev->dev,
dev_name(&pdev->dev));
if (!hcd)
return -ENOMEM;
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
if (!hcd->regs) {
err = -ENOMEM;
goto err_put_hcd;
}
hcd->has_tt = 1;
hcd_to_ehci(hcd)->caps = hcd->regs;
fotg2_otg_init(hcd);
err = request_irq(irq, &fotg2_ehci_irq, IRQF_SHARED, "fotg2", hcd);
if (err)
goto err_put_hcd;
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
goto err_put_hcd;
platform_set_drvdata(pdev, hcd);
return 0;
err_put_hcd:
usb_put_hcd(hcd);
return err;
}
static int fotg2_ehci_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
writel(GLOBAL_INT_POLARITY | GLOBAL_INT_MASK_HC |
GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV,
hcd->regs + GLOBAL_ICR);
free_irq(hcd->irq, hcd);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
platform_set_drvdata(pdev, NULL);
return 0;
}
MODULE_ALIAS("platform:" DRV_NAME);
static struct platform_driver ehci_fotg2_driver = {
.probe = fotg2_ehci_probe,
.remove = fotg2_ehci_remove,
.driver.name = DRV_NAME,
};

View File

@ -0,0 +1,223 @@
--- a/arch/arm/mach-gemini/devices.c 2011-04-23 01:00:16.738137491 +0200
+++ b/arch/arm/mach-gemini/devices.c 2011-04-23 01:06:55.539299920 +0200
@@ -188,3 +188,64 @@
return platform_device_register(&ethernet_device);
}
+
+static struct resource usb0_resources[] = {
+ {
+ .start = GEMINI_USB0_BASE,
+ .end = GEMINI_USB0_BASE + 0xfff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_USB0,
+ .end = IRQ_USB0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource usb1_resources[] = {
+ {
+ .start = GEMINI_USB1_BASE,
+ .end = GEMINI_USB1_BASE + 0xfff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_USB1,
+ .end = IRQ_USB1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 usb0_dmamask = 0xffffffffUL;
+static u64 usb1_dmamask = 0xffffffffUL;
+
+static struct platform_device usb_device[] = {
+ {
+ .name = "ehci-fotg2",
+ .id = 0,
+ .dev = {
+ .dma_mask = &usb0_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(usb0_resources),
+ .resource = usb0_resources,
+ },
+ {
+ .name = "ehci-fotg2",
+ .id = 1,
+ .dev = {
+ .dma_mask = &usb1_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(usb1_resources),
+ .resource = usb1_resources,
+ },
+};
+
+int __init platform_register_usb(unsigned int id)
+{
+ if (id > 1)
+ return -EINVAL;
+
+ return platform_device_register(&usb_device[id]);
+}
+
--- a/arch/arm/mach-gemini/common.h 2011-04-23 01:09:31.413161153 +0200
+++ b/arch/arm/mach-gemini/common.h 2011-04-23 01:09:52.426358514 +0200
@@ -28,6 +28,7 @@
unsigned int nr_parts);
extern int platform_register_watchdog(void);
extern int platform_register_ethernet(struct gemini_gmac_platform_data *pdata);
+extern int platform_register_usb(unsigned int id);
extern void gemini_restart(char mode, const char *cmd);
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -39,6 +39,7 @@ config USB_ARCH_HAS_EHCI
default y if ARCH_MXC
default y if ARCH_MXS
default y if ARCH_OMAP3
+ default y if ARCH_GEMINI
default y if ARCH_CNS3XXX
default y if ARCH_VT8500
default y if PLAT_SPEAR
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -340,12 +340,14 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
spin_lock_irq(&ehci->lock);
ehci->rh_state = EHCI_RH_HALTED;
ehci_turn_off_all_ports(ehci);
+#ifndef CONFIG_ARCH_GEMINI
/* make BIOS/etc use companion controller during reboot */
ehci_writel(ehci, 0, &ehci->regs->configured_flag);
/* unblock posted writes */
ehci_readl(ehci, &ehci->regs->configured_flag);
+#endif
spin_unlock_irq(&ehci->lock);
}
@@ -600,7 +602,9 @@ static int ehci_run (struct usb_hcd *hcd)
// Philips, Intel, and maybe others need CMD_RUN before the
// root hub will detect new devices (why?); NEC doesn't
ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
+#ifndef CONFIG_ARCH_GEMINI
ehci->command |= CMD_RUN;
+#endif
ehci_writel(ehci, ehci->command, &ehci->regs->command);
dbg_cmd (ehci, "init", ehci->command);
@@ -620,9 +624,11 @@ static int ehci_run (struct usb_hcd *hcd)
*/
down_write(&ehci_cf_port_reset_rwsem);
ehci->rh_state = EHCI_RH_RUNNING;
+#ifndef CONFIG_ARCH_GEMINI
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
msleep(5);
+#endif
up_write(&ehci_cf_port_reset_rwsem);
ehci->last_periodic_enable = ktime_get_real();
@@ -763,9 +769,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
pcd_status = status;
/* resume root hub? */
+#ifndef CONFIG_ARCH_GEMINI
if (ehci->rh_state == EHCI_RH_SUSPENDED)
usb_hcd_resume_root_hub(hcd);
-
+#endif
/* get per-port change detect bits */
if (ehci->has_ppcd)
ppcd = status >> 16;
@@ -1228,6 +1241,11 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR (DRIVER_AUTHOR);
MODULE_LICENSE ("GPL");
+#ifdef CONFIG_ARCH_GEMINI
+#include "ehci-fotg2.c"
+#define PLATFORM_DRIVER ehci_fotg2_driver
+#endif
+
#ifdef CONFIG_USB_EHCI_FSL
#include "ehci-fsl.c"
#define PLATFORM_DRIVER ehci_fsl_driver
--- a/drivers/usb/host/ehci-timer.c 2012-12-24 18:35:19.695560879 +0100
+++ b/drivers/usb/host/ehci-timer.c 2012-12-24 18:39:39.813308000 +0100
@@ -207,7 +207,9 @@
/* Clean up the mess */
ehci->rh_state = EHCI_RH_HALTED;
+#ifndef CONFIG_ARCH_GEMINI
ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+#endif
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
ehci_work(ehci);
end_unlink_async(ehci);
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -600,7 +600,12 @@ static inline unsigned int
ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
{
if (ehci_is_TDI(ehci)) {
- switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) {
+#ifdef CONFIG_ARCH_GEMINI
+ portsc = readl(ehci_to_hcd(ehci)->regs + 0x80);
+ switch ((portsc>>22)&3) {
+#else
+ switch ((portsc>>26)&3) {
+#endif
case 0:
return 0;
case 1:
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -912,6 +912,11 @@ static int ehci_hub_control (
/* see what we found out */
temp = check_reset_complete (ehci, wIndex, status_reg,
ehci_readl(ehci, status_reg));
+#ifdef CONFIG_ARCH_GEMINI
+ /* restart schedule */
+ ehci->command |= CMD_RUN;
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
+#endif
}
if (!(temp & (PORT_RESUME|PORT_RESET))) {
--- a/include/linux/usb/ehci_def.h 2012-12-24 15:01:10.168320497 +0100
+++ b/include/linux/usb/ehci_def.h 2012-12-24 15:11:43.335575000 +0100
@@ -110,9 +110,14 @@
u32 frame_list; /* points to periodic list */
/* ASYNCLISTADDR: offset 0x18 */
u32 async_next; /* address of next async queue head */
-
+#ifndef CONFIG_ARCH_GEMINI
u32 reserved1[2];
-
+#else
+ u32 reserved1;
+ /* PORTSC: offset 0x20 for Faraday OTG */
+ u32 port_status[1];
+#endif
+
/* TXFILLTUNING: offset 0x24 */
u32 txfill_tuning; /* TX FIFO Tuning register */
#define TXFIFO_DEFAULT (8<<16) /* FIFO burst threshold 8 */
@@ -123,8 +128,11 @@
u32 configured_flag;
#define FLAG_CF (1<<0) /* true: we'll support "high speed" */
+#ifndef CONFIG_ARCH_GEMINI
/* PORTSC: offset 0x44 */
u32 port_status[0]; /* up to N_PORTS */
+#endif
+
/* EHCI 1.1 addendum */
#define PORTSC_SUSPEND_STS_ACK 0
#define PORTSC_SUSPEND_STS_NYET 1

View File

@ -1,611 +0,0 @@
--- /dev/null
+++ b/drivers/usb/host/ehci-fotg2xx.c
@@ -0,0 +1,459 @@
+/*
+ * EHCI Host Controller driver
+ *
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006 Sony Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+
+#define otg_set(port, bits) writel(readl(hcd->regs + port) | bits, hcd->regs + port)
+
+#define otg_clear(port, bits) writel(readl(hcd->regs + port) & ~bits, hcd->regs + port)
+
+#define GLOBAL_ISR 0xC0
+#define GLOBAL_ICR 0xC4
+
+#define HCD_MISC 0x40
+
+#define OTGC_SCR 0x80
+#define OTGC_INT_EN 0x88
+
+#define GLOBAL_INT_POLARITY (1 << 3)
+#define GLOBAL_INT_MASK_HC (1 << 2)
+#define GLOBAL_INT_MASK_OTG (1 << 1)
+#define GLOBAL_INT_MASK_DEV (1 << 0)
+
+#define OTGC_SCR_ID (1 << 21)
+#define OTGC_SCR_CROLE (1 << 20)
+#define OTGC_SCR_VBUS_VLD (1 << 19)
+#define OTGC_SCR_A_SRP_RESP_TYPE (1 << 8)
+#define OTGC_SCR_A_SRP_DET_EN (1 << 7)
+#define OTGC_SCR_A_SET_B_HNP_EN (1 << 6)
+#define OTGC_SCR_A_BUS_DROP (1 << 5)
+#define OTGC_SCR_A_BUS_REQ (1 << 4)
+
+#define OTGC_INT_APLGRMV (1 << 12)
+#define OTGC_INT_BPLGRMV (1 << 11)
+#define OTGC_INT_OVC (1 << 10)
+#define OTGC_INT_IDCHG (1 << 9)
+#define OTGC_INT_RLCHG (1 << 8)
+#define OTGC_INT_AVBUSERR (1 << 5)
+#define OTGC_INT_ASRPDET (1 << 4)
+#define OTGC_INT_BSRPDN (1 << 0)
+
+#define OTGC_INT_A_TYPE (OTGC_INT_ASRPDET|OTGC_INT_AVBUSERR|OTGC_INT_OVC|OTGC_INT_RLCHG|OTGC_INT_IDCHG|OTGC_INT_APLGRMV)
+#define OTGC_INT_B_TYPE (OTGC_INT_AVBUSERR|OTGC_INT_OVC|OTGC_INT_RLCHG|OTGC_INT_IDCHG)
+
+static void fotg2xx_otgc_role_change(struct usb_hcd *hcd);
+
+static void fotg2xx_otgc_init(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ unsigned int reg;
+
+ reg = __raw_readl(hcd->regs + OTGC_SCR);
+ ehci_info(ehci, "role detected: %s, ",
+ (reg & OTGC_SCR_CROLE) ? "Peripheral" : "Host");
+
+ if (reg & OTGC_SCR_ID)
+ ehci_info(ehci, "B-Device (may be unsupported!)\n");
+ else
+ ehci_info(ehci, "A-Device\n");
+
+ /* Enable the SRP detect */
+ reg &= ~OTGC_SCR_A_SRP_RESP_TYPE;
+ __raw_writel(reg, hcd->regs + OTGC_SCR);
+
+ reg = __raw_readl(hcd->regs + OTGC_INT_EN);
+ /* clear INT B: bits AVBUSERR | OVC | RLCHG | IDCHG */
+ reg &= ~OTGC_INT_B_TYPE;
+ /* set INT A: bits ASRPDET | AVBUSERR | OVC | RLCHG | IDCHG | APLGRMV */
+ reg |= OTGC_INT_A_TYPE;
+ __raw_writel(reg, hcd->regs + OTGC_INT_EN);
+
+ reg = __raw_readl(hcd->regs + GLOBAL_ICR);
+ reg &= ~GLOBAL_INT_MASK_OTG;
+ __raw_writel(reg, hcd->regs + GLOBAL_ICR);
+
+ /* setup MISC register, fixes timing problems */
+ reg = __raw_readl(hcd->regs + HCD_MISC);
+ reg |= 0xD;
+ __raw_writel(reg, hcd->regs + HCD_MISC);
+
+ fotg2xx_otgc_role_change(hcd);
+}
+
+static void fotg2xx_otgh_close(struct usb_hcd *hcd)
+{
+ unsigned int reg;
+
+ /* <1>.Enable Interrupt Mask */
+ reg = __raw_readl(hcd->regs + GLOBAL_ICR);
+ reg |= GLOBAL_INT_MASK_HC;
+ __raw_writel(reg, hcd->regs + GLOBAL_ICR);
+
+ /* <2>.Clear the Interrupt status */
+ reg = __raw_readl(hcd->regs + 0x18);
+ reg &= 0x0000003F;
+ __raw_writel(reg, hcd->regs + 0x14);
+}
+
+static void fotg2xx_otgh_open(struct usb_hcd *hcd)
+{
+ unsigned int reg;
+
+ reg = __raw_readl(hcd->regs + OTGC_SCR);
+ reg &= ~OTGC_SCR_A_SRP_DET_EN;
+ __raw_writel(reg, hcd->regs + OTGC_SCR);
+
+ reg = __raw_readl(hcd->regs + GLOBAL_ICR);
+ reg &= ~GLOBAL_INT_MASK_HC;
+ __raw_writel(reg, hcd->regs + GLOBAL_ICR);
+}
+
+/* change to host role */
+static void fotg2xx_otgc_role_change(struct usb_hcd *hcd)
+{
+
+ /* clear A_SET_B_HNP_EN */
+ otg_clear(0x80, BIT(6));
+
+ /*** Enable VBUS driving */
+ if (readl(hcd->regs + 0x80) & BIT(19))
+ printk(KERN_INFO "VBUS already enabled\n");
+ else {
+ int cnt = 0;
+
+ /* clear A_BUS_DROP */
+ otg_clear(0x80, BIT(5));
+
+ /* set A_BUS_REQ */
+ otg_set(0x80, BIT(4));
+
+ /* set global bus reg to VBUS on */
+ writel(readl(IO_ADDRESS(0x40000000) + 0x30) | ((BIT(21)|BIT(22))),
+ IO_ADDRESS(0x40000000) + 0x30);
+
+ if (readl(hcd->regs + 0x80) & (1<<19)) {
+ printk(KERN_INFO "Waiting for VBus");
+ while (!(readl(hcd->regs + 0x80) & (1<<19)) && (cnt < 80)) {
+ printk(KERN_CONT ".");
+ cnt++;
+ }
+ printk(KERN_CONT "\n");
+ } else
+ printk(KERN_INFO "VBUS enabled.\n");
+
+ mdelay(1);
+ }
+ fotg2xx_otgh_open(hcd);
+}
+
+static int fotg2xx_ehci_hc_reset(struct usb_hcd *hcd)
+{
+ int result;
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+ 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");
+
+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+ hcd->has_tt = 1;
+
+ result = ehci_halt(ehci);
+ if (result)
+ return result;
+
+ return ehci_init(hcd);
+}
+
+/*
+ * Name: OTGC_INT_ISR
+ * Description:This interrupt service routine belongs to the OTG-Controller
+ * <1>.Check for ID_Change
+ * <2>.Check for RL_Change
+ * <3>.Error Detect
+ * Input: wINTStatus
+ * Output:void
+ */
+void fotg2xx_int_isr(struct usb_hcd *hcd, u32 wINTStatus)
+{
+ /* <1>.Check for ID_Change */
+ if (wINTStatus&OTGC_INT_IDCHG) {
+ if ((readl(hcd->regs + 0x80) & BIT(21)) != 0)
+ fotg2xx_otgc_init(hcd); /* Change to B Type */
+ else
+ fotg2xx_otgc_init(hcd); /* Change to A Type */
+
+ return;
+ }
+
+ /* <2>.Check for RL_Change */
+ if (wINTStatus&OTGC_INT_RLCHG)
+ fotg2xx_otgc_role_change(hcd);
+
+ /* <3>.Error Detect */
+ if (wINTStatus&OTGC_INT_AVBUSERR)
+ printk(KERN_ERR "VBus error!\n");
+
+ if (wINTStatus&OTGC_INT_OVC)
+ printk(KERN_WARNING "Overcurrent detected!\n");
+
+ /* <3>.Check for Type-A/Type-B Interrupt */
+ if ((readl(hcd->regs + 0x80) & BIT(21)) == 0) { /*For Type-A Interrupt*/
+ if (wINTStatus & (OTGC_INT_A_TYPE | OTGC_INT_ASRPDET)) {
+ /* <1>.SRP detected => then set global variable */
+ printk(KERN_WARNING "SRP detected, but not implemented!\n");
+
+#if 0
+ u32 wTempCounter;
+ /* <2>.Turn on the V Bus */
+ pFTC_OTG->otg.state = OTG_STATE_A_WAIT_VRISE;
+ OTGC_enable_vbus_draw_storlink(1);
+ pFTC_OTG->otg.state = OTG_STATE_A_HOST;
+ /* <3>.Should waiting for Device-Connect Wait 300ms */
+ INFO(pFTC_OTG, ">>> OTG-A Waiting for OTG-B Connect,\n");
+ wTempCounter = 0;
+ while (mwHost20_PORTSC_ConnectStatus_Rd() == 0) {
+ mdelay(1);
+ wTempCounter++;
+ /* Waiting for 300 ms */
+ if (wTempCounter > 300) {
+ mdwOTGC_Control_A_SRP_DET_EN_Clr();
+ INFO(pFTC_OTG, ">>> OTG-B do not connect under 300 ms...\n");
+ break;
+ }
+ }
+ /* <4>.If Connect => issue quick Reset */
+ if (mwHost20_PORTSC_ConnectStatus_Rd() > 0) {
+ mdelay(300); /* For OPT-A Test */
+ OTGH_host_quick_Reset();
+ OTGH_Open();
+ pFTC_OTG->otg.host->A_Disable_Set_Feature_HNP = 0;
+ }
+#endif
+ }
+ } else { /* For Type-B Interrupt */
+ BUG();
+ }
+}
+
+static irqreturn_t fotg2xx_ehci_irq(int irq, void *devid)
+{
+ struct usb_hcd *hcd = devid;
+ u32 val;
+
+ /* OTG Interrupt Status Register */
+ val = readl(hcd->regs + 0x84);
+
+ /* OTG stuff */
+ if (val) {
+ /* supposed to do "INT STS Clr" - XXX */
+ writel(readl(hcd->regs + 0x84) | val, hcd->regs + 0x84);
+
+ fotg2xx_int_isr(hcd, val);
+
+ /* supposed to do "INT STS Clr" - XXX */
+ writel(readl(hcd->regs + 0x84) | val, hcd->regs + 0x84);
+
+ return IRQ_HANDLED;
+ }
+
+ if ((readl(hcd->regs + 0x80) & BIT(20)) == 0) { /* Role is HOST */
+ if (readl(hcd->regs + 0xC0) & BIT(2)) { /* INT STS HOST */
+ /* leave this for ehci irq handler */
+ return IRQ_NONE;
+ }
+ } else
+ printk(KERN_WARNING
+ "received irq for peripheral - don't know what to do!\n");
+
+ /* do not call the ehci irq handler */
+ return IRQ_HANDLED;
+}
+
+static int fotg2xx_ehci_run(struct usb_hcd *hcd)
+{
+ int retval;
+
+ retval = ehci_run(hcd);
+
+ fotg2xx_otgh_close(hcd);
+ fotg2xx_otgc_init(hcd);
+
+ return retval;
+}
+
+static const struct hc_driver fotg2xx_ehci_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "FOTG2XX EHCI Host Controller",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+ .reset = fotg2xx_ehci_hc_reset,
+ .start = fotg2xx_ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+ .endpoint_reset = ehci_endpoint_reset,
+
+ .get_frame_number = ehci_get_frame,
+
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+#if defined(CONFIG_PM)
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
+#endif
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static int fotg2xx_ehci_probe(struct platform_device *pdev)
+{
+ const struct hc_driver *driver = &fotg2xx_ehci_hc_driver;
+ struct usb_hcd *hcd;
+ struct resource *res;
+ int irq;
+ int retval;
+
+ pr_debug("initializing FOTG2XX-SOC USB Controller\n");
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev,
+ "Found HC with no IRQ. Check %s setup!\n",
+ dev_name(&pdev->dev));
+ return -ENODEV;
+ }
+
+ irq = res->start;
+
+ hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+ if (!hcd) {
+ retval = -ENOMEM;
+ goto err1;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev,
+ "Found HC with no register addr. Check %s setup!\n",
+ dev_name(&pdev->dev));
+ retval = -ENODEV;
+ goto err2;
+ }
+
+ hcd->rsrc_start = res->start;
+ hcd->rsrc_len = res->end - res->start + 1;
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+ driver->description)) {
+ dev_dbg(&pdev->dev, "controller already in use\n");
+ retval = -EBUSY;
+ goto err2;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (hcd->regs == NULL) {
+ dev_dbg(&pdev->dev, "error mapping memory\n");
+ retval = -EFAULT;
+ goto err3;
+ }
+
+
+ /* set global reg to mini-A host */
+ writel(readl(IO_ADDRESS(0x40000000) + 0x30) & ~(BIT(30)|BIT(29)),
+ IO_ADDRESS(0x40000000) + 0x30);
+
+ /* USB0&USB1 - VBUS off */
+ writel(readl(IO_ADDRESS(0x40000000) + 0x30) & ~(BIT(21)|BIT(22)),
+ IO_ADDRESS(0x40000000) + 0x30);
+
+ if ((readl(hcd->regs) == 0x01000010) &&
+ (readl(hcd->regs + 4) == 0x00000001) &&
+ (readl(hcd->regs + 8) == 0x00000006)) {
+ dev_info(&pdev->dev,
+ "Found Faraday OTG 2XX controller (base = 0x%08lX)\n",
+ (unsigned long) hcd->rsrc_start);
+ } else {
+ dev_err(&pdev->dev, "fotg2xx id mismatch: found %d.%d.%d\n",
+ readl(hcd->regs + 0x00),
+ readl(hcd->regs + 0x04),
+ readl(hcd->regs + 0x08));
+ retval = -ENODEV;
+ goto err4;
+ }
+
+ platform_set_drvdata(pdev, hcd);
+
+ /* mask interrupts - peripheral, otg, host, hi-active (bits 0,1,2,3) */
+ otg_set(0xc4, BIT(3)); /* hi active */
+
+ otg_set(0xc4, BIT(2)); /* host */
+ otg_set(0xc4, BIT(1)); /* otg */
+ otg_set(0xc4, BIT(0)); /* peripheral */
+
+ /* register additional interrupt - here we check otg status */
+ if ((request_irq(irq, &fotg2xx_ehci_irq, IRQF_SHARED | IRQF_DISABLED,
+ hcd->irq_descr, hcd)) != 0) {
+ dev_dbg(&pdev->dev, "error requesting irq %d\n", irq);
+ retval = -EFAULT;
+ goto err4;
+ }
+
+ retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (retval != 0)
+ goto err4;
+ return retval;
+
+err4:
+ iounmap(hcd->regs);
+err3:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err2:
+ usb_put_hcd(hcd);
+err1:
+ dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
+ return retval;
+}
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+int fotg2xx_ehci_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd =
+ (struct usb_hcd *)platform_get_drvdata(pdev);
+
+ usb_remove_hcd(hcd);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ iounmap(hcd->regs);
+ usb_put_hcd(hcd);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+MODULE_ALIAS("platform:ehci-fotg2xx");
+
+static struct platform_driver fotg2xx_ehci_driver = {
+ .probe = fotg2xx_ehci_probe,
+ .remove = fotg2xx_ehci_remove,
+ .driver = {
+ .name = "ehci-fotg2xx",
+ },
+};
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -603,7 +603,12 @@ static inline unsigned int
ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
{
if (ehci_is_TDI(ehci)) {
+#ifdef CONFIG_ARCH_GEMINI
+ portsc = readl(ehci_to_hcd(ehci)->regs + 0x80);
+ switch ((portsc>>22)&3) {
+#else
switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) {
+#endif
case 0:
return 0;
case 1:
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -204,10 +204,12 @@ static int ehci_halt (struct ehci_hcd *e
* This routine gets called during probe before ehci->command
* has been initialized, so we can't rely on its value.
*/
+#ifndef CONFIG_ARCH_GEMINI
ehci->command &= ~CMD_RUN;
temp = ehci_readl(ehci, &ehci->regs->command);
temp &= ~(CMD_RUN | CMD_IAAD);
ehci_writel(ehci, temp, &ehci->regs->command);
+#endif
spin_unlock_irq(&ehci->lock);
synchronize_irq(ehci_to_hcd(ehci)->irq);
@@ -257,13 +259,17 @@ static int ehci_reset (struct ehci_hcd *
if (ehci->has_hostpc) {
ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS,
&ehci->regs->usbmode_ex);
+#ifndef CONFIG_ARCH_GEMINI
ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning);
+#endif
}
if (retval)
return retval;
+#ifndef CONFIG_ARCH_GEMINI
if (ehci_is_TDI(ehci))
tdi_reset (ehci);
+#endif
if (ehci->debug)
dbgp_external_startup(ehci_to_hcd(ehci));
@@ -341,11 +347,14 @@ static void ehci_silence_controller(stru
ehci->rh_state = EHCI_RH_HALTED;
ehci_turn_off_all_ports(ehci);
+#ifndef CONFIG_ARCH_GEMINI
/* make BIOS/etc use companion controller during reboot */
ehci_writel(ehci, 0, &ehci->regs->configured_flag);
/* unblock posted writes */
ehci_readl(ehci, &ehci->regs->configured_flag);
+#endif
+
spin_unlock_irq(&ehci->lock);
}
@@ -603,7 +612,9 @@ static int ehci_run (struct usb_hcd *hcd
// Philips, Intel, and maybe others need CMD_RUN before the
// root hub will detect new devices (why?); NEC doesn't
ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
+#ifndef CONFIG_ARCH_GEMINI
ehci->command |= CMD_RUN;
+#endif
ehci_writel(ehci, ehci->command, &ehci->regs->command);
dbg_cmd (ehci, "init", ehci->command);
@@ -623,9 +634,11 @@ static int ehci_run (struct usb_hcd *hcd
*/
down_write(&ehci_cf_port_reset_rwsem);
ehci->rh_state = EHCI_RH_RUNNING;
+#ifndef CONFIG_ARCH_GEMINI
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
msleep(5);
+#endif /* !CONFIG_ARCH_GEMINI */
up_write(&ehci_cf_port_reset_rwsem);
ehci->last_periodic_enable = ktime_get_real();
@@ -1228,6 +1241,11 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR (DRIVER_AUTHOR);
MODULE_LICENSE ("GPL");
+#ifdef CONFIG_ARCH_GEMINI
+#include "ehci-fotg2xx.c"
+#define PLATFORM_DRIVER fotg2xx_ehci_driver
+#endif
+
#ifdef CONFIG_USB_EHCI_FSL
#include "ehci-fsl.c"
#define PLATFORM_DRIVER ehci_fsl_driver
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -914,6 +914,12 @@ static int ehci_hub_control (
/* see what we found out */
temp = check_reset_complete (ehci, wIndex, status_reg,
ehci_readl(ehci, status_reg));
+#ifdef CONFIG_ARCH_GEMINI
+ /* restart schedule */
+ ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) | CMD_RUN, &ehci->regs->command);
+
+// hcd->state = HC_STATE_RUNNING;
+#endif
}
if (!(temp & (PORT_RESUME|PORT_RESET))) {
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -47,6 +47,7 @@ config USB_ARCH_HAS_EHCI
default y if MICROBLAZE
default y if SPARC_LEON
default y if ARCH_MMP
+ default y if ARCH_GEMINI
default y if MACH_LOONGSON1
default y if PLAT_ORION
default PCI
@@ -96,7 +97,7 @@ config USB
traditional PC serial port. The bus supplies power to peripherals
and allows for hot swapping. Up to 127 USB peripherals can be
connected to a single USB host in a tree structure.
-
+
The USB host is the root of the tree, the peripherals are the
leaves and the inner nodes are special USB devices called hubs.
Most PCs now have USB host ports, used to connect peripherals
--- a/include/linux/usb/ehci_def.h
+++ b/include/linux/usb/ehci_def.h
@@ -111,6 +111,7 @@ struct ehci_regs {
/* ASYNCLISTADDR: offset 0x18 */
u32 async_next; /* address of next async queue head */
+#ifndef CONFIG_ARCH_GEMINI
u32 reserved1[2];
/* TXFILLTUNING: offset 0x24 */
@@ -118,6 +119,7 @@ struct ehci_regs {
#define TXFIFO_DEFAULT (8<<16) /* FIFO burst threshold 8 */
u32 reserved2[6];
+#endif /* !CONFIG_ARCH_GEMINI */
/* CONFIGFLAG: offset 0x40 */
u32 configured_flag;

View File

@ -1,75 +0,0 @@
--- a/arch/arm/mach-gemini/devices.c
+++ b/arch/arm/mach-gemini/devices.c
@@ -185,3 +185,62 @@ int __init platform_register_ethernet(st
return platform_device_register(&ethernet_device);
}
+
+static u64 usb0_dmamask = DMA_BIT_MASK(32);
+static struct resource usb0_resources[] = {
+ {
+ .start = 0x68000000,
+ .end = 0x68000fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_USB0,
+ .end = IRQ_USB0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 usb1_dmamask = DMA_BIT_MASK(32);
+static struct resource usb1_resources[] = {
+ {
+ .start = 0x69000000,
+ .end = 0x69000fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_USB1,
+ .end = IRQ_USB1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usb_device[] = {
+ {
+ .name = "ehci-fotg2xx",
+ .id = 0,
+ .dev = {
+ .dma_mask = &usb0_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(usb0_resources),
+ .resource = usb0_resources,
+ },
+ {
+ .name = "ehci-fotg2xx",
+ .id = 1,
+ .dev = {
+ .dma_mask = &usb1_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(usb1_resources),
+ .resource = usb1_resources,
+ },
+};
+
+int __init platform_register_usb(unsigned int id)
+{
+ if (id > 1)
+ return -EINVAL;
+
+ return platform_device_register(&usb_device[id]);
+}
--- a/arch/arm/mach-gemini/common.h
+++ b/arch/arm/mach-gemini/common.h
@@ -28,6 +28,7 @@ extern int platform_register_pflash(unsi
unsigned int nr_parts);
extern int platform_register_watchdog(void);
extern int platform_register_ethernet(struct gemini_gmac_platform_data *pdata);
+extern int platform_register_usb(unsigned int id);
extern void gemini_restart(char mode, const char *cmd);

View File

@ -0,0 +1,65 @@
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -145,6 +145,7 @@ static void __init wbd111_init(void)
platform_register_watchdog();
platform_device_register(&wbd111_phy_device);
platform_register_ethernet(&gmac_data);
+ platform_register_usb(0);
}
MACHINE_START(WBD111, "Wiliboard WBD-111")
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -147,6 +147,7 @@ static void __init wbd222_init(void)
platform_register_watchdog();
platform_device_register(&wbd222_phy_device);
platform_register_ethernet(&gmac_data);
+ platform_register_usb(0);
}
MACHINE_START(WBD222, "Wiliboard WBD-222")
--- a/arch/arm/mach-gemini/board-rut1xx.c
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -105,6 +105,7 @@ static void __init rut1xx_init(void)
platform_register_watchdog();
platform_device_register(&rut1xx_phy_device);
platform_register_ethernet(&gmac_data);
+ platform_register_usb(0);
}
MACHINE_START(RUT100, "Teltonika RUT100")
--- a/arch/arm/mach-gemini/board-nas4220b.c
+++ b/arch/arm/mach-gemini/board-nas4220b.c
@@ -134,10 +134,23 @@
GLOBAL_ARBITRATION1_CTRL));
}
+static void __init usb_ib4220b_init(void)
+{
+ unsigned int val;
+
+ val = readl((void __iomem*)(IO_ADDRESS(GEMINI_GLOBAL_BASE) +
+ GLOBAL_MISC_CTRL));
+ val &= ~(USB0_PLUG_MINIB | USB1_PLUG_MINIB);
+ val |= USB0_VBUS_ON | USB1_VBUS_ON;
+ writel(val, (void __iomem*)(IO_ADDRESS(GEMINI_GLOBAL_BASE) +
+ GLOBAL_MISC_CTRL));
+}
+
static void __init ib4220b_init(void)
{
gemini_gpio_init();
ib4220b_gmac_init();
+ usb_ib4220b_init();
platform_register_uart();
platform_register_pflash(SZ_16M, NULL, 0);
platform_device_register(&ib4220b_led_device);
@@ -168,6 +168,8 @@ static void __init ib4220b_init(void)
platform_register_watchdog();
platform_device_register(&ib4220b_phy_device);
platform_register_ethernet(&ib4220b_gmac_data);
+ platform_register_usb(0);
+ platform_register_usb(1);
}
MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")

View File

@ -1,24 +0,0 @@
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -145,6 +145,7 @@ static void __init wbd111_init(void)
platform_register_watchdog();
platform_device_register(&wbd111_phy_device);
platform_register_ethernet(&gmac_data);
+ platform_register_usb(0);
}
MACHINE_START(WBD111, "Wiliboard WBD-111")
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -99,7 +99,11 @@ module_param (park, uint, S_IRUGO);
MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
/* for flakey hardware, ignore overcurrent indicators */
+#ifdef CONFIG_ARCH_GEMINI
+static bool ignore_oc = 1;
+#else
static bool ignore_oc = 0;
+#endif
module_param (ignore_oc, bool, S_IRUGO);
MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");

View File

@ -1,10 +0,0 @@
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -147,6 +147,7 @@ static void __init wbd222_init(void)
platform_register_watchdog();
platform_device_register(&wbd222_phy_device);
platform_register_ethernet(&gmac_data);
+ platform_register_usb(0);
}
MACHINE_START(WBD222, "Wiliboard WBD-222")

View File

@ -1,10 +0,0 @@
--- a/arch/arm/mach-gemini/board-rut1xx.c
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -105,6 +105,7 @@ static void __init rut1xx_init(void)
platform_register_watchdog();
platform_device_register(&rut1xx_phy_device);
platform_register_ethernet(&gmac_data);
+ platform_register_usb(0);
}
MACHINE_START(RUT100, "Teltonika RUT100")

View File

@ -1,11 +0,0 @@
--- a/arch/arm/mach-gemini/board-nas4220b.c
+++ b/arch/arm/mach-gemini/board-nas4220b.c
@@ -146,6 +146,8 @@ static void __init ib4220b_init(void)
platform_register_watchdog();
platform_device_register(&ib4220b_phy_device);
platform_register_ethernet(&ib4220b_gmac_data);
+ platform_register_usb(0);
+ platform_register_usb(1);
}
MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")