From 519e16d75181169331a86cd650531419fde56937 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Wed, 25 Oct 2006 21:38:51 +0300 Subject: [PATCH] [PATCH] Initial USB support on OMAP2 Initial full speed USB support on OMAP2 platform. Remaining issues include: - only usb0 port tested (not usb1, usb2) - only peripheral/gadget controller tested (not ohci, otg) - UDC DMA is not working - clocks are not turned off Board support is in separate patches. Also minor omap_udc updates: whitespace fixes, syncing with a few changes from upstream, warning removal. Signed-off-by: Kyungmin Park Signed-off-by: David Brownell --- arch/arm/mach-omap2/Kconfig | 1 + arch/arm/plat-omap/usb.c | 199 ++++++++++++++++++++++++------- drivers/usb/gadget/Kconfig | 2 +- drivers/usb/gadget/omap_udc.c | 149 ++++++++++++++++------- include/asm-arm/arch-omap/irqs.h | 6 + include/asm-arm/arch-omap/usb.h | 40 ++++++- 6 files changed, 305 insertions(+), 92 deletions(-) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 417cfbabfc3..42e04369db4 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -9,6 +9,7 @@ config ARCH_OMAP2420 bool "OMAP2420 support" depends on ARCH_OMAP24XX select OMAP_DM_TIMER + select ARCH_OMAP_OTG comment "OMAP Board Type" depends on ARCH_OMAP2 diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index 7e8096809be..25489aafb11 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c @@ -37,9 +37,27 @@ #include #include +#ifdef CONFIG_ARCH_OMAP1 + +#define INT_USB_IRQ_GEN IH2_BASE + 20 +#define INT_USB_IRQ_NISO IH2_BASE + 30 +#define INT_USB_IRQ_ISO IH2_BASE + 29 +#define INT_USB_IRQ_HGEN INT_USB_HHC_1 +#define INT_USB_IRQ_OTG IH2_BASE + 8 + +#else + +#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN +#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO +#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO +#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN +#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG + +#endif + + /* These routines should handle the standard chip-specific modes * for usb0/1/2 ports, covering basic mux and transceiver setup. - * Call omap_usb_init() once, from INIT_MACHINE(). * * Some board-*.c files will need to set up additional mux options, * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. @@ -96,19 +114,26 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) { u32 syscon1 = 0; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL); + if (nwires == 0) { - if (!cpu_is_omap15xx()) { + if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { /* pulldown D+/D- */ USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); } return 0; } - if (is_device) - omap_cfg_reg(W4_USB_PUEN); + if (is_device) { + if (cpu_is_omap24xx()) + omap_cfg_reg(J20_24XX_USB0_PUEN); + else + omap_cfg_reg(W4_USB_PUEN); + } - /* internal transceiver */ - if (nwires == 2) { + /* internal transceiver (unavailable on 17xx, 24xx) */ + if (!cpu_class_is_omap2() && nwires == 2) { // omap_cfg_reg(P9_USB_DP); // omap_cfg_reg(R8_USB_DM); @@ -136,29 +161,50 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) return 0; } - omap_cfg_reg(V6_USB0_TXD); - omap_cfg_reg(W9_USB0_TXEN); - omap_cfg_reg(W5_USB0_SE0); + if (cpu_is_omap24xx()) { + omap_cfg_reg(K18_24XX_USB0_DAT); + omap_cfg_reg(K19_24XX_USB0_TXEN); + omap_cfg_reg(J14_24XX_USB0_SE0); + if (nwires != 3) + omap_cfg_reg(J18_24XX_USB0_RCV); + } else { + omap_cfg_reg(V6_USB0_TXD); + omap_cfg_reg(W9_USB0_TXEN); + omap_cfg_reg(W5_USB0_SE0); + if (nwires != 3) + omap_cfg_reg(Y5_USB0_RCV); + } - /* NOTE: SPEED and SUSP aren't configured here */ + /* NOTE: SPEED and SUSP aren't configured here. OTG hosts + * may be able to use I2C requests to set those bits along + * with VBUS switching and overcurrent detction. + */ - if (nwires != 3) - omap_cfg_reg(Y5_USB0_RCV); - if (nwires != 6) + if (cpu_class_is_omap1() && nwires != 6) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; switch (nwires) { case 3: syscon1 = 2; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); break; case 6: syscon1 = 3; - omap_cfg_reg(AA9_USB0_VP); - omap_cfg_reg(R9_USB0_VM); - USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; + if (cpu_is_omap24xx()) { + omap_cfg_reg(J19_24XX_USB0_VP); + omap_cfg_reg(K20_24XX_USB0_VM); + CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR); + } else { + omap_cfg_reg(AA9_USB0_VP); + omap_cfg_reg(R9_USB0_VM); + USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; + } break; default: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", @@ -171,14 +217,22 @@ static u32 __init omap_usb1_init(unsigned nwires) { u32 syscon1 = 0; - if (nwires != 6 && !cpu_is_omap15xx()) + if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL); + if (nwires == 0) return 0; /* external transceiver */ - omap_cfg_reg(USB1_TXD); - omap_cfg_reg(USB1_TXEN); + if (cpu_class_is_omap1()) { + omap_cfg_reg(USB1_TXD); + omap_cfg_reg(USB1_TXEN); + if (nwires != 3) + omap_cfg_reg(USB1_RCV); + } + if (cpu_is_omap15xx()) { omap_cfg_reg(USB1_SEO); omap_cfg_reg(USB1_SPEED); @@ -190,20 +244,38 @@ static u32 __init omap_usb1_init(unsigned nwires) } else if (cpu_is_omap1710()) { omap_cfg_reg(R13_1710_USB1_SE0); // SUSP + } else if (cpu_is_omap24xx()) { + /* NOTE: board-specific code must set up pin muxing for usb1, + * since each signal could come out on either of two balls. + */ } else { - pr_debug("usb unrecognized\n"); + pr_debug("usb%d cpu unrecognized\n", 1); + return 0; } - if (nwires != 3) - omap_cfg_reg(USB1_RCV); switch (nwires) { + case 2: + if (!cpu_is_omap24xx()) + goto bad; + /* NOTE: board-specific code must override this setting if + * this TLL link is not using DP/DM + */ + syscon1 = 1; + CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL); + break; case 3: syscon1 = 2; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); break; case 6: + if (cpu_is_omap24xx()) + goto bad; syscon1 = 3; omap_cfg_reg(USB1_VP); omap_cfg_reg(USB1_VM); @@ -211,6 +283,7 @@ static u32 __init omap_usb1_init(unsigned nwires) USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; break; default: +bad: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 1, nwires); } @@ -221,10 +294,17 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) { u32 syscon1 = 0; - /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */ + if (cpu_is_omap24xx()) { + CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL) + | USBT2TLL5PI); + alt_pingroup = 0; + } + + /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ if (alt_pingroup || nwires == 0) return 0; - if (nwires != 6 && !cpu_is_omap15xx()) + + if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; /* external transceiver */ @@ -242,19 +322,54 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) if (nwires != 3) omap_cfg_reg(Y5_USB2_RCV); // FIXME omap_cfg_reg(USB2_SPEED); + } else if (cpu_is_omap24xx()) { + omap_cfg_reg(Y11_24XX_USB2_DAT); + omap_cfg_reg(AA10_24XX_USB2_SE0); + if (nwires > 2) + omap_cfg_reg(AA12_24XX_USB2_TXEN); + if (nwires > 3) + omap_cfg_reg(AA6_24XX_USB2_RCV); } else { - pr_debug("usb unrecognized\n"); + pr_debug("usb%d cpu unrecognized\n", 1); + return 0; } - // omap_cfg_reg(USB2_SUSP); + // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP); switch (nwires) { + case 2: + if (!cpu_is_omap24xx()) + goto bad; + /* NOTE: board-specific code must override this setting if + * this TLL link is not using DP/DM + */ + syscon1 = 1; + CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL); + break; case 3: syscon1 = 2; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); + break; + case 5: + if (!cpu_is_omap24xx()) + goto bad; + omap_cfg_reg(AA4_24XX_USB2_TLLSE0); + /* NOTE: board-specific code must override this setting if + * this TLL link is not using DP/DM. Something must also + * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} + */ + syscon1 = 3; + CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL) + | USBT2TLL5PI; break; case 6: + if (cpu_is_omap24xx()) + goto bad; syscon1 = 3; if (cpu_is_omap15xx()) { omap_cfg_reg(USB2_VP); @@ -266,6 +381,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) } break; default: +bad: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 2, nwires); } @@ -294,13 +410,13 @@ static struct resource udc_resources[] = { .end = UDC_BASE + 0xff, .flags = IORESOURCE_MEM, }, { /* general IRQ */ - .start = IH2_BASE + 20, + .start = INT_USB_IRQ_GEN, .flags = IORESOURCE_IRQ, }, { /* PIO IRQ */ - .start = IH2_BASE + 30, + .start = INT_USB_IRQ_NISO, .flags = IORESOURCE_IRQ, }, { /* SOF IRQ */ - .start = IH2_BASE + 29, + .start = INT_USB_IRQ_ISO, .flags = IORESOURCE_IRQ, }, }; @@ -329,11 +445,11 @@ static u64 ohci_dmamask = ~(u32)0; static struct resource ohci_resources[] = { { .start = OMAP_OHCI_BASE, - .end = OMAP_OHCI_BASE + 4096 - 1, + .end = OMAP_OHCI_BASE + 0xff, .flags = IORESOURCE_MEM, }, { - .start = INT_USB_HHC_1, + .start = INT_USB_IRQ_HGEN, .flags = IORESOURCE_IRQ, }, }; @@ -361,7 +477,7 @@ static struct resource otg_resources[] = { .end = OTG_BASE + 0xff, .flags = IORESOURCE_MEM, }, { - .start = IH2_BASE + 8, + .start = INT_USB_IRQ_OTG, .flags = IORESOURCE_IRQ, }, }; @@ -385,7 +501,7 @@ static struct platform_device otg_device = { // FIXME correct answer depends on hmc_mode, -// as does any nonzero value for config->otg port number +// as does (on omap1) any nonzero value for config->otg port number #ifdef CONFIG_USB_GADGET_OMAP #define is_usb0_device(config) 1 #else @@ -426,12 +542,13 @@ omap_otg_init(struct omap_usb_config *config) if (config->otg) syscon |= OTG_EN; #endif - pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); + if (cpu_class_is_omap1()) + pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); OTG_SYSCON_2_REG = syscon; printk("USB: hmc %d", config->hmc_mode); - if (alt_pingroup) + if (!alt_pingroup) printk(", usb2 alt %d wires", config->pins[2]); else if (config->pins[0]) printk(", usb0 %d wires%s", config->pins[0], @@ -444,10 +561,12 @@ omap_otg_init(struct omap_usb_config *config) printk(", Mini-AB on usb%d", config->otg - 1); printk("\n"); - /* leave USB clocks/controllers off until needed */ - ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; - ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; - ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; + if (cpu_class_is_omap1()) { + /* leave USB clocks/controllers off until needed */ + ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; + ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; + ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; + } syscon = OTG_SYSCON_1_REG; syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; @@ -585,7 +704,7 @@ omap_usb_init(void) } platform_data = *config; - if (cpu_is_omap730() || cpu_is_omap16xx()) + if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx()) omap_otg_init(&platform_data); else if (cpu_is_omap15xx()) omap_1510_usb_init(&platform_data); diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 7b7b68b839d..6fb770c499d 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -167,7 +167,7 @@ config USB_GADGET_MUSB_HDRC config USB_GADGET_OMAP boolean "OMAP USB Device Controller" - depends on ARCH_OMAP1 + depends on ARCH_OMAP select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 help Many Texas Instruments OMAP processors have flexible full diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 80aa0e2fe9a..ceba0a4d383 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -61,6 +61,11 @@ /* bulk DMA seems to be behaving for both IN and OUT */ #define USE_DMA +/* FIXME: OMAP2 currently has some problem in DMA mode */ +#ifdef CONFIG_ARCH_OMAP2 +#undef USE_DMA +#endif + /* ISO too */ #define USE_ISO @@ -100,7 +105,7 @@ static unsigned fifo_mode = 0; * boot parameter "omap_udc:fifo_mode=42" */ module_param (fifo_mode, uint, 0); -MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)"); +MODULE_PARM_DESC (fifo_mode, "endpoint configuration"); #ifdef USE_DMA static unsigned use_dma = 1; @@ -123,7 +128,7 @@ static const char driver_desc [] = DRIVER_DESC; /*-------------------------------------------------------------------------*/ /* there's a notion of "current endpoint" for modifying endpoint - * state, and PIO access to its FIFO. + * state, and PIO access to its FIFO. */ static void use_ep(struct omap_ep *ep, u16 select) @@ -392,7 +397,7 @@ done(struct omap_ep *ep, struct omap_req *req, int status) #define FIFO_EMPTY (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY) #define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY) -static inline int +static inline int write_packet(u8 *buf, struct omap_req *req, unsigned max) { unsigned len; @@ -457,7 +462,7 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req) return is_last; } -static inline int +static inline int read_packet(u8 *buf, struct omap_req *req, unsigned avail) { unsigned len; @@ -625,7 +630,7 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) } else { length = min(length / ep->maxpacket, (unsigned) UDC_TXN_TSC + 1); - txdma_ctrl = length; + txdma_ctrl = length; omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, ep->ep.maxpacket >> 1, length, sync_mode, 0, 0); @@ -1124,7 +1129,7 @@ static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) */ dma_channel_release(ep); dma_channel_claim(ep, channel); - } else + } else done(ep, req, -ECONNRESET); spin_unlock_irqrestore(&ep->udc->lock, flags); return 0; @@ -1160,7 +1165,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) /* IN endpoints must already be idle */ if ((ep->bEndpointAddress & USB_DIR_IN) - && !list_empty(&ep->queue)) { + && !list_empty(&ep->queue)) { status = -EAGAIN; goto done; } @@ -1477,7 +1482,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) } } - /* IN/OUT packets mean we're in the DATA or STATUS stage. + /* IN/OUT packets mean we're in the DATA or STATUS stage. * This driver uses only uses protocol stalls (ep0 never halts), * and if we got this far the gadget driver already had a * chance to stall. Tries to be forgiving of host oddities. @@ -1545,7 +1550,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) } else if (stat == 0) UDC_CTRL_REG = UDC_SET_FIFO_EN; UDC_EP_NUM_REG = 0; - + /* activate status stage */ if (stat == 1) { done(ep0, req, 0); @@ -1916,10 +1921,8 @@ static void pio_out_timer(unsigned long _ep) UDC_EP_NUM_REG = ep->bEndpointAddress; UDC_CTRL_REG = UDC_SET_FIFO_EN; ep->ackwait = 1 + ep->double_buf; - } - else { - deselect_ep(); - } + } else + deselect_ep(); } mod_timer(&ep->timer, PIO_OUT_TIMEOUT); spin_unlock_irqrestore(&ep->udc->lock, flags); @@ -2066,6 +2069,16 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) /*-------------------------------------------------------------------------*/ +static inline int machine_needs_vbus_session(void) +{ + return (machine_is_omap_innovator() + || machine_is_omap_osk() + || machine_is_omap_apollon() +#ifndef CONFIG_MACH_OMAP_H4_OTG + || machine_is_omap_h4() +#endif + ); +} int usb_gadget_register_driver (struct usb_gadget_driver *driver) { @@ -2142,7 +2155,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) /* boards that don't have VBUS sensing can't autogate 48MHz; * can't enter deep sleep while a gadget driver is active. */ - if (machine_is_omap_innovator() || machine_is_omap_osk()) + if (machine_needs_vbus_session()) omap_vbus_session(&udc->gadget, 1); done: @@ -2165,7 +2178,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) if (udc->dc_clk != NULL) omap_udc_enable_clock(1); - if (machine_is_omap_innovator() || machine_is_omap_osk()) + if (machine_needs_vbus_session()) omap_vbus_session(&udc->gadget, 0); if (udc->transceiver) @@ -2265,7 +2278,7 @@ static char *trx_mode(unsigned m, int enabled) case 0: return enabled ? "*6wire" : "unused"; case 1: return "4wire"; case 2: return "3wire"; - case 3: return "6wire"; + case 3: return "6wire"; default: return "unknown"; } } @@ -2274,11 +2287,18 @@ static int proc_otg_show(struct seq_file *s) { u32 tmp; u32 trans; + char *ctrl_name; tmp = OTG_REV_REG; - trans = USB_TRANSCEIVER_CTRL_REG; - seq_printf(s, "\nOTG rev %d.%d, transceiver_ctrl %05x\n", - tmp >> 4, tmp & 0xf, trans); + if (cpu_is_omap24xx()) { + ctrl_name = "control_devconf"; + trans = CONTROL_DEVCONF_REG; + } else { + ctrl_name = "tranceiver_ctrl"; + trans = USB_TRANSCEIVER_CTRL_REG; + } + seq_printf(s, "\nOTG rev %d.%d, %s %05x\n", + tmp >> 4, tmp & 0xf, ctrl_name, trans); tmp = OTG_SYSCON_1_REG; seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s," FOURBITS "\n", tmp, @@ -2353,7 +2373,7 @@ static int proc_udc_show(struct seq_file *s, void *_) driver_desc, use_dma ? " (dma)" : ""); - tmp = UDC_REV_REG & 0xff; + tmp = UDC_REV_REG & 0xff; seq_printf(s, "UDC rev %d.%d, fifo mode %d, gadget %s\n" "hmc %d, transceiver %s\n", @@ -2361,11 +2381,16 @@ static int proc_udc_show(struct seq_file *s, void *_) fifo_mode, udc->driver ? udc->driver->driver.name : "(none)", HMC, - udc->transceiver ? udc->transceiver->label : "(none)"); - seq_printf(s, "ULPD control %04x req %04x status %04x\n", - __REG16(ULPD_CLOCK_CTRL), - __REG16(ULPD_SOFT_REQ), - __REG16(ULPD_STATUS_REQ)); + udc->transceiver + ? udc->transceiver->label + : ((cpu_is_omap1710() || cpu_is_omap24xx()) + ? "external" : "(none)")); + if (cpu_class_is_omap1()) { + seq_printf(s, "ULPD control %04x req %04x status %04x\n", + __REG16(ULPD_CLOCK_CTRL), + __REG16(ULPD_SOFT_REQ), + __REG16(ULPD_STATUS_REQ)); + } /* OTG controller registers */ if (!cpu_is_omap15xx()) @@ -2550,9 +2575,11 @@ omap_ep_setup(char *name, u8 addr, u8 type, dbuf = 1; } else { /* double-buffering "not supported" on 15xx, - * and ignored for PIO-IN on 16xx + * and ignored for PIO-IN on newer chips + * (for more reliable behavior) */ - if (!use_dma || cpu_is_omap15xx()) + if ((!use_dma && (addr & USB_DIR_IN)) + || cpu_is_omap15xx()) dbuf = 0; switch (maxp) { @@ -2595,7 +2622,7 @@ omap_ep_setup(char *name, u8 addr, u8 type, ep->bEndpointAddress = addr; ep->bmAttributes = type; ep->double_buf = dbuf; - ep->udc = udc; + ep->udc = udc; ep->ep.name = ep->name; ep->ep.ops = &omap_ep_ops; @@ -2759,7 +2786,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) struct clk *hhc_clk; /* NOTE: "knows" the order of the resources! */ - if (!request_mem_region(pdev->resource[0].start, + if (!request_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1, driver_name)) { DBG("request_mem_region failed\n"); @@ -2776,6 +2803,16 @@ static int __init omap_udc_probe(struct platform_device *pdev) udelay(100); } + if (cpu_is_omap24xx()) { + dc_clk = clk_get(&pdev->dev, "usb_fck"); + hhc_clk = clk_get(&pdev->dev, "usb_l4_ick"); + BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk)); + /* can't use omap_udc_enable_clock yet */ + clk_enable(dc_clk); + clk_enable(hhc_clk); + udelay(100); + } + INFO("OMAP UDC rev %d.%d%s\n", UDC_REV_REG >> 4, UDC_REV_REG & 0xf, config->otg ? ", Mini-AB" : ""); @@ -2814,6 +2851,15 @@ static int __init omap_udc_probe(struct platform_device *pdev) } hmc = HMC_1610; + + if (cpu_is_omap24xx()) { + /* this could be transceiverless in one of the + * "we don't need to know" modes. + */ + type = "external"; + goto known; + } + switch (hmc) { case 0: /* POWERUP DEFAULT == 0 */ case 4: @@ -2852,6 +2898,7 @@ bad_on_1710: goto cleanup0; } } +known: INFO("hmc mode %d, %s transceiver\n", hmc, type); /* a "gadget" abstracts/virtualizes the controller */ @@ -2876,8 +2923,8 @@ bad_on_1710: status = request_irq(pdev->resource[1].start, omap_udc_irq, IRQF_SAMPLE_RANDOM, driver_name, udc); if (status != 0) { - ERR( "can't get irq %ld, err %d\n", - pdev->resource[1].start, status); + ERR("can't get irq %d, err %d\n", + (int) pdev->resource[1].start, status); goto cleanup1; } @@ -2885,16 +2932,16 @@ bad_on_1710: status = request_irq(pdev->resource[2].start, omap_udc_pio_irq, IRQF_SAMPLE_RANDOM, "omap_udc pio", udc); if (status != 0) { - ERR( "can't get irq %ld, err %d\n", - pdev->resource[2].start, status); + ERR("can't get irq %d, err %d\n", + (int) pdev->resource[2].start, status); goto cleanup2; } #ifdef USE_ISO status = request_irq(pdev->resource[3].start, omap_udc_iso_irq, IRQF_DISABLED, "omap_udc iso", udc); if (status != 0) { - ERR("can't get irq %ld, err %d\n", - pdev->resource[3].start, status); + ERR("can't get irq %d, err %d\n", + (int) pdev->resource[3].start, status); goto cleanup3; } #endif @@ -2905,6 +2952,16 @@ bad_on_1710: clk_disable(dc_clk); } + if (cpu_is_omap24xx()) { + udc->dc_clk = dc_clk; + udc->hhc_clk = hhc_clk; + /* FIXME OMAP2 don't release hhc & dc clock */ +#if 0 + clk_disable(hhc_clk); + clk_disable(dc_clk); +#endif + } + create_proc_file(); device_add(&udc->gadget.dev); return 0; @@ -2925,12 +2982,12 @@ cleanup0: if (xceiv) put_device(xceiv->dev); - if (cpu_is_omap16xx()) { - clk_disable(hhc_clk); - clk_disable(dc_clk); - clk_put(hhc_clk); - clk_put(dc_clk); - } + if (cpu_is_omap16xx() || cpu_is_omap24xx()) { + clk_disable(hhc_clk); + clk_disable(dc_clk); + clk_put(hhc_clk); + clk_put(dc_clk); + } release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); @@ -2963,11 +3020,11 @@ static int __exit omap_udc_remove(struct platform_device *pdev) free_irq(pdev->resource[1].start, udc); if (udc->dc_clk) { - if (udc->clk_requested) - omap_udc_enable_clock(0); - clk_put(udc->hhc_clk); - clk_put(udc->dc_clk); - } + if (udc->clk_requested) + omap_udc_enable_clock(0); + clk_put(udc->hhc_clk); + clk_put(udc->dc_clk); + } release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h index db940fbafe8..812f96f2be8 100644 --- a/include/asm-arm/arch-omap/irqs.h +++ b/include/asm-arm/arch-omap/irqs.h @@ -269,6 +269,12 @@ #define INT_24XX_UART1_IRQ 72 #define INT_24XX_UART2_IRQ 73 #define INT_24XX_UART3_IRQ 74 +#define INT_24XX_USB_IRQ_GEN 75 +#define INT_24XX_USB_IRQ_NISO 76 +#define INT_24XX_USB_IRQ_ISO 77 +#define INT_24XX_USB_IRQ_HGEN 78 +#define INT_24XX_USB_IRQ_HSOF 79 +#define INT_24XX_USB_IRQ_OTG 80 #define INT_24XX_MMC_IRQ 83 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and diff --git a/include/asm-arm/arch-omap/usb.h b/include/asm-arm/arch-omap/usb.h index 054fb9a8e0c..99ae9eabaf7 100644 --- a/include/asm-arm/arch-omap/usb.h +++ b/include/asm-arm/arch-omap/usb.h @@ -7,9 +7,27 @@ /*-------------------------------------------------------------------------*/ -#define OTG_BASE 0xfffb0400 -#define UDC_BASE 0xfffb4000 -#define OMAP_OHCI_BASE 0xfffba000 +#define OMAP1_OTG_BASE 0xfffb0400 +#define OMAP1_UDC_BASE 0xfffb4000 +#define OMAP1_OHCI_BASE 0xfffba000 + +#define OMAP2_OHCI_BASE 0x4805e000 +#define OMAP2_UDC_BASE 0x4805e200 +#define OMAP2_OTG_BASE 0x4805e300 + +#ifdef CONFIG_ARCH_OMAP1 + +#define OTG_BASE OMAP1_OTG_BASE +#define UDC_BASE OMAP1_UDC_BASE +#define OMAP_OHCI_BASE OMAP1_OHCI_BASE + +#else + +#define OTG_BASE OMAP2_OTG_BASE +#define UDC_BASE OMAP2_UDC_BASE +#define OMAP_OHCI_BASE OMAP2_OHCI_BASE + +#endif /*-------------------------------------------------------------------------*/ @@ -28,6 +46,7 @@ # define HST_IDLE_EN (1 << 14) # define DEV_IDLE_EN (1 << 13) # define OTG_RESET_DONE (1 << 2) +# define OTG_SOFT_RESET (1 << 1) #define OTG_SYSCON_2_REG OTG_REG32(0x08) # define OTG_EN (1 << 31) # define USBX_SYNCHRO (1 << 30) @@ -103,6 +122,7 @@ /*-------------------------------------------------------------------------*/ +/* OMAP1 */ #define USB_TRANSCEIVER_CTRL_REG __REG32(0xfffe1000 + 0x0064) # define CONF_USB2_UNI_R (1 << 8) # define CONF_USB1_UNI_R (1 << 7) @@ -111,7 +131,17 @@ # define CONF_USB_PWRDN_DM_R (1 << 2) # define CONF_USB_PWRDN_DP_R (1 << 1) - - +/* OMAP2 */ +#define CONTROL_DEVCONF_REG __REG32(L4_24XX_BASE + 0x0274) +# define USB_UNIDIR 0x0 +# define USB_UNIDIR_TLL 0x1 +# define USB_BIDIR 0x2 +# define USB_BIDIR_TLL 0x3 +# define USBT0WRMODEI(x) ((x) << 22) +# define USBT1WRMODEI(x) ((x) << 20) +# define USBT2WRMODEI(x) ((x) << 18) +# define USBT2TLL5PI (1 << 17) +# define USB0PUENACTLOI (1 << 16) +# define USBSTANDBYCTRL (1 << 15) #endif /* __ASM_ARCH_OMAP_USB_H */ -- 2.41.1