--- a/arch/arm/mach-gemini/devices.c +++ b/arch/arm/mach-gemini/devices.c @@ -188,3 +188,64 @@ int platform_register_ethernet(struct ge return platform_device_register(ðernet_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 +++ 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(enum reboot_mode mode, const char *cmd); --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -346,11 +346,13 @@ 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); } @@ -602,7 +604,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); @@ -622,9 +626,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(); @@ -762,9 +768,10 @@ static irqreturn_t ehci_irq (struct usb_ 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; @@ -1243,6 +1250,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 +++ b/drivers/usb/host/ehci-timer.c @@ -208,7 +208,9 @@ static void ehci_handle_controller_death /* 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 @@ -656,7 +656,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 @@ -1075,6 +1075,11 @@ 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 } /* transfer dedicated ports to the companion hc */ --- a/include/linux/usb/ehci_def.h +++ b/include/linux/usb/ehci_def.h @@ -110,8 +110,13 @@ struct ehci_regs { 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 */ @@ -123,8 +128,11 @@ struct ehci_regs { 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