]> git.neil.brown.name Git - history.git/commitdiff
[ARM PATCH] 2007/1: OMAP update 3/6: Arch files
authorTony Lindgren <tony@com.rmk.(none)>
Sat, 14 Aug 2004 18:27:39 +0000 (19:27 +0100)
committerRussell King <rmk@flint.arm.linux.org.uk>
Sat, 14 Aug 2004 18:27:39 +0000 (19:27 +0100)
Patch from Tony Lindgren

This patch syncs the mainline kernel with the linux-omap tree.
The highlights of the patch are:
- DMA fixes from Samuel Ortiz
- USB low level configuration from David Brownell
- H3 support from Nishant Kamat
- TPS65010 power management interface from Dirk Behme

16 files changed:
arch/arm/mach-omap/Makefile
arch/arm/mach-omap/board-generic.c
arch/arm/mach-omap/board-innovator.c
arch/arm/mach-omap/board-osk.c
arch/arm/mach-omap/board-perseus2.c
arch/arm/mach-omap/clocks.c
arch/arm/mach-omap/common.c
arch/arm/mach-omap/common.h
arch/arm/mach-omap/dma.c
arch/arm/mach-omap/fpga.c
arch/arm/mach-omap/gpio.c
arch/arm/mach-omap/irq.c
arch/arm/mach-omap/leds.c
arch/arm/mach-omap/leds.h
arch/arm/mach-omap/ocpi.c
arch/arm/mach-omap/usb.c [new file with mode: 0644]

index 5fcb1e5c76270d5f0e7b6e72e1d502aa1aa576cb..b483092dd2832eed4d85119e424c39bc8fd7c7c3 100644 (file)
@@ -3,25 +3,29 @@
 #
 
 # Common support
-obj-y := common.o irq.o dma.o clocks.o mux.o bus.o gpio.o time.o
+obj-y := common.o time.o irq.o dma.o clocks.o mux.o gpio.o mcbsp.o
 obj-m :=
 obj-n :=
 obj-  :=
 led-y := leds.o
 
 # Specific board support
+obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o
 obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
 obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
 obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
 obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
+obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
 
-# OCPI interconnect support for 1610 and 5912
+# OCPI interconnect support for 1710, 1610 and 5912
+obj-$(CONFIG_ARCH_OMAP1710) += ocpi.o
 obj-$(CONFIG_ARCH_OMAP1610) += ocpi.o
 obj-$(CONFIG_ARCH_OMAP5912) += ocpi.o
 
 # LEDs support
+led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o
 led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o
-led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-perseus2.o
+led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o
 obj-$(CONFIG_LEDS) += $(led-y)
 
 # Power Management
index 447046b24a082dd59ae04b328c2828c6056f897c..03da924c7786772a7ef54a0d6b6d65c93e795745 100644 (file)
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 static void __init omap_generic_init_irq(void)
 {
        omap_init_irq();
@@ -36,17 +40,49 @@ static void __init omap_generic_init_irq(void)
 /*
  * Muxes the serial ports on
  */
+#ifdef CONFIG_ARCH_OMAP1510
 static void __init omap_early_serial_init(void)
 {
+#ifdef CONFIG_OMAP_LL_DEBUG_UART1
        omap_cfg_reg(UART1_TX);
        omap_cfg_reg(UART1_RTS);
+#endif
 
+#ifdef CONFIG_OMAP_LL_DEBUG_UART2
        omap_cfg_reg(UART2_TX);
        omap_cfg_reg(UART2_RTS);
+#endif
 
+#ifdef CONFIG_OMAP_LL_DEBUG_UART1
        omap_cfg_reg(UART3_TX);
        omap_cfg_reg(UART3_RX);
+#endif
 }
+#endif
+
+/* assume no Mini-AB port */
+
+#ifdef CONFIG_ARCH_OMAP1510
+static struct omap_usb_config generic1510_usb_config __initdata = {
+       .register_host  = 1,
+       .register_dev   = 1,
+       .hmc_mode       = 16,
+       .pins[0]        = 3,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1610
+static struct omap_usb_config generic1610_usb_config __initdata = {
+       .register_host  = 1,
+       .register_dev   = 1,
+       .hmc_mode       = 16,
+       .pins[0]        = 6,
+};
+#endif
+
+static struct omap_board_config_kernel generic_config[] = {
+       { OMAP_TAG_USB,           NULL },
+};
 
 static void __init omap_generic_init(void)
 {
@@ -55,9 +91,19 @@ static void __init omap_generic_init(void)
         * You have to mux them off in device drivers later on
         * if not needed.
         */
+#ifdef CONFIG_ARCH_OMAP1510
        if (cpu_is_omap1510()) {
                omap_early_serial_init();
+               generic_config[0].data = &generic1510_usb_config;
        }
+#endif
+#ifdef CONFIG_ARCH_OMAP1610
+       if (!cpu_is_omap1510()) {
+               generic_config[0].data = &generic1610_usb_config;
+       }
+#endif
+       omap_board_config = generic_config;
+       omap_board_config_size = ARRAY_SIZE(generic_config);
 }
 
 static void __init omap_generic_map_io(void)
@@ -65,18 +111,12 @@ static void __init omap_generic_map_io(void)
        omap_map_io();
 }
 
-static void __init omap_generic_init_time(void)
-{
-       omap_init_time();
-}
-
-MACHINE_START(OMAP_GENERIC, "Generic OMAP-1510/1610/1710")
+MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
        MAINTAINER("Tony Lindgren <tony@atomide.com>")
        BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
        BOOT_PARAMS(0x10000100)
        MAPIO(omap_generic_map_io)
        INITIRQ(omap_generic_init_irq)
        INIT_MACHINE(omap_generic_init)
-       INITTIME(omap_generic_init_time)
+       INITTIME(omap_init_time)
 MACHINE_END
-
index 6ef4d8dcf9039860b0a21a402ad5da83229c74c7..8fd97e7af54972aae7e34e2136eeded0973eee37 100644 (file)
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/fpga.h>
+#include <asm/arch/usb.h>
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 #ifdef CONFIG_ARCH_OMAP1510
 
 extern int omap_gpio_init(void);
@@ -49,8 +52,8 @@ static struct resource innovator1510_smc91x_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = INT_ETHER,
-               .end    = INT_ETHER,
+               .start  = OMAP1510_INT_ETHER,
+               .end    = OMAP1510_INT_ETHER,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -108,11 +111,43 @@ void innovator_init_irq(void)
 #ifdef CONFIG_ARCH_OMAP1510
        if (cpu_is_omap1510()) {
                omap_gpio_init();
-               fpga_init_irq();
+               omap1510_fpga_init_irq();
        }
 #endif
 }
 
+#ifdef CONFIG_ARCH_OMAP1510
+static struct omap_usb_config innovator1510_usb_config __initdata = {
+       /* has usb host and device, but no Mini-AB port */
+       .register_host  = 1,
+       .register_dev   = 1,
+       /* Assume bad Innovator wiring; Use internal host only with custom cable */
+       .hmc_mode       = 16,
+       .pins[0]        = 2,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1610
+static struct omap_usb_config h2_usb_config __initdata = {
+       /* usb1 has a Mini-AB port and external isp1301 transceiver */
+       .otg            = 2,
+
+#ifdef CONFIG_USB_GADGET_OMAP
+       .hmc_mode       = 19,   // 0:host(off) 1:dev|otg 2:disabled
+       // .hmc_mode    = 21,   // 0:host(off) 1:dev(loopback) 2:host(loopback)
+#elif  defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+       /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
+       .hmc_mode       = 20,   // 1:dev|otg(off) 1:host 2:disabled
+#endif
+
+       .pins[1]        = 3,
+};
+#endif
+
+static struct omap_board_config_kernel innovator_config[] = {
+       { OMAP_TAG_USB,         NULL },
+};
+
 static void __init innovator_init(void)
 {
 #ifdef CONFIG_ARCH_OMAP1510
@@ -121,10 +156,21 @@ static void __init innovator_init(void)
        }
 #endif
 #ifdef CONFIG_ARCH_OMAP1610
-       if (cpu_is_omap1610()) {
+       if (!cpu_is_omap1510()) {
                platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices));
        }
 #endif
+
+#ifdef CONFIG_ARCH_OMAP1510
+       if (cpu_is_omap1510())
+               innovator_config[0].data = &innovator1510_usb_config;
+#endif
+#ifdef CONFIG_ARCH_OMAP1610
+       if (cpu_is_omap1610())
+               innovator_config[0].data = &h2_usb_config;
+#endif
+       omap_board_config = innovator_config;
+       omap_board_config_size = ARRAY_SIZE(innovator_config);
 }
 
 static void __init innovator_map_io(void)
@@ -144,7 +190,7 @@ static void __init innovator_map_io(void)
        }
 #endif
 #ifdef CONFIG_ARCH_OMAP1610
-       if (cpu_is_omap1610()) {
+       if (!cpu_is_omap1510()) {
                iotable_init(innovator1610_io_desc, ARRAY_SIZE(innovator1610_io_desc));
        }
 #endif
@@ -156,6 +202,6 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
        BOOT_PARAMS(0x10000100)
        MAPIO(innovator_map_io)
        INITIRQ(innovator_init_irq)
-       INITTIME(omap_init_time)
        INIT_MACHINE(innovator_init)
+       INITTIME(omap_init_time)
 MACHINE_END
index 16ecd6be5a6099c6541049bea420a54de79bf357..85d9a0ac33e32d5291a23f69bf579d4d174dec05 100644 (file)
@@ -41,6 +41,8 @@
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 static struct map_desc osk5912_io_desc[] __initdata = {
 { OMAP_OSK_ETHR_BASE, OMAP_OSK_ETHR_START, OMAP_OSK_ETHR_SIZE,MT_DEVICE },
 { OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
@@ -94,6 +96,6 @@ MACHINE_START(OMAP_OSK, "TI-OSK")
        BOOT_PARAMS(0x10000100)
        MAPIO(osk_map_io)
        INITIRQ(osk_init_irq)
-       INITTIME(omap_init_time)
        INIT_MACHINE(osk_init)
+       INITTIME(omap_init_time)
 MACHINE_END
index 8015d10fc75e30f63e7e9d5d2c9ffff5ec7dd3df..95833f3b942325ff17990a947e98a9f3fe76abb9 100644 (file)
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
+#include <asm/arch/fpga.h>
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 void omap_perseus2_init_irq(void)
 {
        omap_init_irq();
@@ -33,14 +36,14 @@ void omap_perseus2_init_irq(void)
 
 static struct resource smc91x_resources[] = {
        [0] = {
-               .start  = OMAP730_FPGA_ETHR_START,      /* Physical */
-               .end    = OMAP730_FPGA_ETHR_START + SZ_4K,
+               .start  = H2P2_DBG_FPGA_ETHR_START,     /* Physical */
+               .end    = H2P2_DBG_FPGA_ETHR_START + SZ_4K,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = 0,
+               .start  = INT_730_MPU_EXT_NIRQ,
                .end    = 0,
-               .flags  = INT_ETHER,
+               .flags  = IORESOURCE_IRQ,
        },
 };
 
@@ -62,7 +65,7 @@ static void __init omap_perseus2_init(void)
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
-       {OMAP730_FPGA_BASE, OMAP730_FPGA_START, OMAP730_FPGA_SIZE,
+       {H2P2_DBG_FPGA_BASE, H2P2_DBG_FPGA_START, H2P2_DBG_FPGA_SIZE,
         MT_DEVICE},
 };
 
@@ -111,6 +114,6 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
        BOOT_PARAMS(0x10000100)
        MAPIO(omap_perseus2_map_io)
        INITIRQ(omap_perseus2_init_irq)
-       INITTIME(omap_init_time)
        INIT_MACHINE(omap_perseus2_init)
+       INITTIME(omap_init_time)
 MACHINE_END
index bda7c6f381ee3c92d3f147f672a3988eaad085ad..b507856597321c438d32ac3d5e1ddde61114b99c 100644 (file)
@@ -36,6 +36,8 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/board.h>
 
+extern void start_mputimer1(unsigned long load_val);
+
 /* Input clock in MHz */
 static unsigned int source_clock = 12;
 
@@ -239,7 +241,7 @@ int ck_auto_unclock = 1;
 int ck_debug = 0;
 
 #define CK_MAX_PLL_FREQ                OMAP_CK_MAX_RATE
-static __u8 ck_valid_table[CK_MAX_PLL_FREQ / 8 + 1];
+static __u32 ck_valid_table[CK_MAX_PLL_FREQ / 32 + 1];
 static __u8 ck_lookup_table[CK_MAX_PLL_FREQ];
 
 int
@@ -615,11 +617,11 @@ __ck_make_lookup_table(void)
 int __init
 init_ck(void)
 {
-       const struct omap_clock_info *info;
+       const struct omap_clock_config *info;
        int crystal_type = 0; /* Default 12 MHz */
 
        __ck_make_lookup_table();
-       info = omap_get_per_info(OMAP_TAG_CLOCK, struct omap_clock_info);
+       info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
        if (info != NULL) {
                if (!cpu_is_omap1510())
                        crystal_type = info->system_clock_type;
@@ -645,7 +647,8 @@ init_ck(void)
 #elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
        omap_writew(0x250E, ARM_CKCTL);
        omap_writew(0x2710, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912))
+#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+                                         || defined(CONFIG_ARCH_OMAP1710))
        omap_writew(0x150f, ARM_CKCTL);
        if (crystal_type == 2) {
                source_clock = 13;      /* MHz */
index 43aaa1c6c5458b2a4c999e7761df611c5ddbcc4b..17d82a7f3a3f8d4b7bb1b71c9808d5fabdd5bb29 100644 (file)
@@ -104,7 +104,7 @@ static struct map_desc omap1510_io_desc[] __initdata = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1610
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
 static struct map_desc omap1610_io_desc[] __initdata = {
  { OMAP1610_DSP_BASE,    OMAP1610_DSP_START,    OMAP1610_DSP_SIZE,    MT_DEVICE },
  { OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE },
@@ -147,8 +147,8 @@ static void __init _omap_map_io(void)
                iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
        }
 #endif
-#ifdef CONFIG_ARCH_OMAP1610
-       if (cpu_is_omap1610()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+       if (cpu_is_omap1610() || cpu_is_omap1710()) {
                iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
        }
 #endif
@@ -181,13 +181,18 @@ void omap_map_io(void)
 extern int omap_bootloader_tag_len;
 extern u8 omap_bootloader_tag[];
 
-const void *__omap_get_per_info(u16 tag, size_t len)
+struct omap_board_config_kernel *omap_board_config;
+int omap_board_config_size = 0;
+
+const void *__omap_get_config(u16 tag, size_t len)
 {
-       struct omap_board_info_entry *info = NULL;
+       struct omap_board_config_entry *info = NULL;
+       struct omap_board_config_kernel *kinfo = NULL;
+       int i;
 
 #ifdef CONFIG_OMAP_BOOT_TAG
        if (omap_bootloader_tag_len > 4)
-               info = (struct omap_board_info_entry *) omap_bootloader_tag;
+               info = (struct omap_board_config_entry *) omap_bootloader_tag;
        while (info != NULL) {
                u8 *next;
 
@@ -198,26 +203,38 @@ const void *__omap_get_per_info(u16 tag, size_t len)
                if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
                        info = NULL;
                else
-                       info = (struct omap_board_info_entry *) next;
+                       info = (struct omap_board_config_entry *) next;
+       }
+       if (info != NULL) {
+               /* Check the length as a lame attempt to check for
+                * binary inconsistancy. */
+               if (info->len != len) {
+                       printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
+                              tag, len, info->len);
+                       return NULL;
+               }
+               return info->data;
        }
 #endif
-       if (info == NULL)
-               return NULL;
-       if (info->len != len) {
-               printk(KERN_ERR "OMAP per_info: Length mismatch with tag %x (want %d, got %d)\n",
-                      tag, len, info->len);
-               return NULL;
+       /* Try to find the config from the board-specific structures
+        * in the kernel. */
+       for (i = 0; i < omap_board_config_size; i++) {
+               if (omap_board_config[i].tag == tag) {
+                       kinfo = &omap_board_config[i];
+                       break;
+               }
        }
-
-       return info->data;
+       if (kinfo == NULL)
+               return NULL;
+       return kinfo->data;
 }
-EXPORT_SYMBOL(__omap_get_per_info);
+EXPORT_SYMBOL(__omap_get_config);
 
 static int __init omap_add_serial_console(void)
 {
-       const struct omap_uart_info *info;
+       const struct omap_uart_config *info;
 
-       info = omap_get_per_info(OMAP_TAG_UART, struct omap_uart_info);
+       info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
        if (info != NULL && info->console_uart) {
                static char speed[11], *opt = NULL;
 
index 96dcb3c5397360b46582f517e38d9873838e37fd..1cc559dd2f81726d86f15091264708e0424d7bfc 100644 (file)
@@ -28,7 +28,6 @@
 #define __ARCH_ARM_MACH_OMAP_COMMON_H
 
 extern void omap_map_io(void);
-extern void omap_init_time(void);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
 
index 385b4d1cc055c90617fbabe0cf422d28b0a12a32..cfb23d894a958af55e8fb40214f9aaf319d6ba7c 100644 (file)
@@ -118,7 +118,7 @@ void omap_set_dma_constant_fill(int lch, u32 color)
        u16 w;
 
 #ifdef CONFIG_DEBUG_KERNEL
-       if (omap_dma_in_1510_mode) {
+       if (omap_dma_in_1510_mode()) {
                printk(KERN_ERR "OMAP DMA constant fill not available in 1510 mode.");
                BUG();
                return;
@@ -141,7 +141,7 @@ void omap_set_dma_transparent_copy(int lch, u32 color)
        u16 w;
 
 #ifdef CONFIG_DEBUG_KERNEL
-       if (omap_dma_in_1510_mode) {
+       if (omap_dma_in_1510_mode()) {
                printk(KERN_ERR "OMAP DMA transparent copy not available in 1510 mode.");
                BUG();
        }
@@ -266,46 +266,78 @@ void omap_set_dma_dest_burst_mode(int lch, int burst_mode)
        omap_writew(w, OMAP_DMA_CSDP(lch));
 }
 
-void omap_start_dma(int lch)
+static inline void init_intr(int lch)
 {
        u16 w;
 
-       if (!omap_dma_in_1510_mode()) {
-               int next_lch;
-
-               next_lch = dma_chan[lch].next_lch;
-
-               /* Enable the queue, if needed so. */
-               if (next_lch != -1) {
-                       /* Clear the STOP_LNK bits */
-                       w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
-                       w &= ~(1 << 14);
-                       omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
-                       w = omap_readw(OMAP_DMA_CLNK_CTRL(next_lch));
-                       w &= ~(1 << 14);
-                       omap_writew(w, OMAP_DMA_CLNK_CTRL(next_lch));
-
-                       /* And set the ENABLE_LNK bits */
-                       omap_writew(next_lch | (1 << 15),
-                                   OMAP_DMA_CLNK_CTRL(lch));
-                       /* The loop case */
-                       if (dma_chan[next_lch].next_lch == lch)
-                               omap_writew(lch | (1 << 15),
-                                           OMAP_DMA_CLNK_CTRL(next_lch));
-
-                       /* Read CSR to make sure it's cleared. */
-                       w = omap_readw(OMAP_DMA_CSR(next_lch));
-                       /* Enable some nice interrupts. */
-                       omap_writew(dma_chan[next_lch].enabled_irqs,
-                                   OMAP_DMA_CICR(next_lch));
-                       dma_chan[next_lch].flags |= OMAP_DMA_ACTIVE;
-               }
-       }
-
        /* Read CSR to make sure it's cleared. */
        w = omap_readw(OMAP_DMA_CSR(lch));
        /* Enable some nice interrupts. */
        omap_writew(dma_chan[lch].enabled_irqs, OMAP_DMA_CICR(lch));
+       dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
+}
+
+static inline void enable_lnk(int lch)
+{
+       u16 w;
+
+       /* Clear the STOP_LNK bits */
+       w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
+       w &= ~(1 << 14);
+       omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
+
+       /* And set the ENABLE_LNK bits */
+       if (dma_chan[lch].next_lch != -1)
+               omap_writew(dma_chan[lch].next_lch | (1 << 15),
+                           OMAP_DMA_CLNK_CTRL(lch));
+}
+
+static inline void disable_lnk(int lch)
+{
+       u16 w;
+
+       /* Disable interrupts */
+       omap_writew(0, OMAP_DMA_CICR(lch));
+
+       /* Set the STOP_LNK bit */
+       w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
+       w |= (1 << 14);
+       w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
+
+       dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
+}
+
+void omap_start_dma(int lch)
+{
+       u16 w;
+
+       if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
+               int next_lch, cur_lch;
+               char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT];
+
+               dma_chan_link_map[lch] = 1;
+               /* Set the link register of the first channel */
+               enable_lnk(lch);
+
+               memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
+               cur_lch = dma_chan[lch].next_lch;
+               do {
+                       next_lch = dma_chan[cur_lch].next_lch;
+
+                        /* The loop case: we've been here already */
+                       if (dma_chan_link_map[cur_lch])
+                               break;
+                       /* Mark the current channel */
+                       dma_chan_link_map[cur_lch] = 1;
+
+                       enable_lnk(cur_lch);
+                       init_intr(cur_lch);
+
+                       cur_lch = next_lch;
+               } while (next_lch != -1);
+       }
+
+       init_intr(lch);
 
        w = omap_readw(OMAP_DMA_CCR(lch));
        w |= OMAP_DMA_CCR_EN;
@@ -316,37 +348,34 @@ void omap_start_dma(int lch)
 void omap_stop_dma(int lch)
 {
        u16 w;
-       int next_lch;
 
-       /* Disable all interrupts on the channel */
-       omap_writew(0, OMAP_DMA_CICR(lch));
+       if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
+               int next_lch, cur_lch = lch;
+               char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT];
 
-       if (omap_dma_in_1510_mode()) {
-               w = omap_readw(OMAP_DMA_CCR(lch));
-               w &= ~OMAP_DMA_CCR_EN;
-               omap_writew(w, OMAP_DMA_CCR(lch));
-               dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
-               return;
-       }
+               memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
+               do {
+                       /* The loop case: we've been here already */
+                       if (dma_chan_link_map[cur_lch])
+                               break;
+                       /* Mark the current channel */
+                       dma_chan_link_map[cur_lch] = 1;
 
-       next_lch = dma_chan[lch].next_lch;
+                       disable_lnk(cur_lch);
 
-       /*
-        * According to thw HW spec, enabling the STOP_LNK bit
-        * resets the CCR_EN bit at the same time.
-        */
-       w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
-       w |= (1 << 14);
-       w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
-       dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
+                       next_lch = dma_chan[cur_lch].next_lch;
+                       cur_lch = next_lch;
+               } while (next_lch != -1);
 
-       if (next_lch != -1) {
-               omap_writew(0, OMAP_DMA_CICR(next_lch));
-               w = omap_readw(OMAP_DMA_CLNK_CTRL(next_lch));
-               w |= (1 << 14);
-               w = omap_writew(w, OMAP_DMA_CLNK_CTRL(next_lch));
-               dma_chan[next_lch].flags &= ~OMAP_DMA_ACTIVE;
+               return;
        }
+       /* Disable all interrupts on the channel */
+       omap_writew(0, OMAP_DMA_CICR(lch));
+
+       w = omap_readw(OMAP_DMA_CCR(lch));
+       w &= ~OMAP_DMA_CCR_EN;
+       omap_writew(w, OMAP_DMA_CCR(lch));
+       dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
 void omap_enable_dma_irq(int lch, u16 bits)
@@ -445,7 +474,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
        chan->data = data;
        chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
 
-       if (cpu_is_omap1610() || cpu_is_omap5912()) {
+       if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
                /* If the sync device is set, configure it dynamically. */
                if (dev_id != 0) {
                        set_gdma_dev(free_ch + 1, dev_id);
@@ -533,7 +562,6 @@ void omap_dma_unlink_lch (int lch_head, int lch_queue)
        }
 
        dma_chan[lch_head].next_lch = -1;
-       dma_chan[lch_queue].next_lch = -1;
 }
 
 
@@ -713,7 +741,7 @@ static int __init omap_init_dma(void)
                printk(KERN_INFO "DMA support for OMAP1510 initialized\n");
                dma_chan_count = 9;
                enable_1510_mode = 1;
-       } else if (cpu_is_omap1610() || cpu_is_omap5912()) {
+       } else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
                printk(KERN_INFO "OMAP DMA hardware version %d\n",
                       omap_readw(OMAP_DMA_HW_ID));
                printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
@@ -771,6 +799,8 @@ EXPORT_SYMBOL(omap_request_dma);
 EXPORT_SYMBOL(omap_free_dma);
 EXPORT_SYMBOL(omap_start_dma);
 EXPORT_SYMBOL(omap_stop_dma);
+EXPORT_SYMBOL(omap_enable_dma_irq);
+EXPORT_SYMBOL(omap_disable_dma_irq);
 
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 EXPORT_SYMBOL(omap_set_dma_constant_fill);
index d9246b1dcc1e61047cd0099809dd8b22e642b7eb..f0ce5c12a2ad96298ef7454cfeeb32655fa11af5 100644 (file)
 #include <asm/arch/fpga.h>
 #include <asm/arch/gpio.h>
 
-unsigned char fpga_read(int reg)
-{
-       return __raw_readb(reg);
-}
-
-void fpga_write(unsigned char val, int reg)
-{
-       __raw_writeb(val, reg);
-}
-
 static void fpga_mask_irq(unsigned int irq)
 {
-       irq -= IH_FPGA_BASE;
+       irq -= OMAP1510_IH_FPGA_BASE;
 
        if (irq < 8)
                __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO)
@@ -76,7 +66,7 @@ static void fpga_ack_irq(unsigned int irq)
 
 static void fpga_unmask_irq(unsigned int irq)
 {
-       irq -= IH_FPGA_BASE;
+       irq -= OMAP1510_IH_FPGA_BASE;
 
        if (irq < 8)
                __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) | (1 << irq)),
@@ -114,8 +104,8 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
                        break;
                }
 
-               for (fpga_irq = IH_FPGA_BASE;
-                       (fpga_irq < (IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
+               for (fpga_irq = OMAP1510_IH_FPGA_BASE;
+                       (fpga_irq < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
                        fpga_irq++, stat >>= 1) {
                        if (stat & 1) {
                                d = irq_desc + fpga_irq;
@@ -162,7 +152,7 @@ static struct irqchip omap_fpga_irq = {
  * interrupts at the interrupt controller via disable_irq/enable_irq
  * could pose a problem.
  */
-void fpga_init_irq(void)
+void omap1510_fpga_init_irq(void)
 {
        int i;
 
@@ -170,9 +160,9 @@ void fpga_init_irq(void)
        __raw_writeb(0, OMAP1510_FPGA_IMR_HI);
        __raw_writeb(0, INNOVATOR_FPGA_IMR2);
 
-       for (i = IH_FPGA_BASE; i < (IH_FPGA_BASE + NR_FPGA_IRQS); i++) {
+       for (i = OMAP1510_IH_FPGA_BASE; i < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS); i++) {
 
-               if (i == INT_FPGA_TS) {
+               if (i == OMAP1510_INT_FPGA_TS) {
                        /*
                         * The touchscreen interrupt is level-sensitive, so
                         * we'll use the regular mask_ack routine for it.
@@ -201,9 +191,7 @@ void fpga_init_irq(void)
        omap_request_gpio(13);
        omap_set_gpio_direction(13, 1);
        omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE);
-       set_irq_chained_handler(INT_FPGA, innovator_fpga_IRQ_demux);
+       set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
 }
 
-EXPORT_SYMBOL(fpga_init_irq);
-EXPORT_SYMBOL(fpga_read);
-EXPORT_SYMBOL(fpga_write);
+EXPORT_SYMBOL(omap1510_fpga_init_irq);
index 2f052a959af17873cbaa5b2f62217b4900de1b5f..206bee968329f26b7f321e92e86b88a77d7c802c 100644 (file)
@@ -94,7 +94,7 @@ struct gpio_bank {
 #define METHOD_GPIO_1610       2
 #define METHOD_GPIO_730                3
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
 static struct gpio_bank gpio_bank_1610[5] = {
        { OMAP_MPUIO_BASE,     INT_MPUIO,           IH_MPUIO_BASE,     METHOD_MPUIO},
        { OMAP1610_GPIO1_BASE, INT_GPIO_BANK1,      IH_GPIO_BASE,      METHOD_GPIO_1610 },
@@ -113,7 +113,7 @@ static struct gpio_bank gpio_bank_1510[2] = {
 
 #ifdef CONFIG_ARCH_OMAP730
 static struct gpio_bank gpio_bank_730[7] = {
-       { OMAP_MPUIO_BASE,     INT_MPUIO,           IH_MPUIO_BASE,      METHOD_MPUIO },
+       { OMAP_MPUIO_BASE,     INT_730_MPUIO,       IH_MPUIO_BASE,      METHOD_MPUIO },
        { OMAP730_GPIO1_BASE,  INT_GPIO_BANK1,      IH_GPIO_BASE,       METHOD_GPIO_730 },
        { OMAP730_GPIO2_BASE,  INT_730_GPIO_BANK2,  IH_GPIO_BASE + 32,  METHOD_GPIO_730 },
        { OMAP730_GPIO3_BASE,  INT_730_GPIO_BANK3,  IH_GPIO_BASE + 64,  METHOD_GPIO_730 },
@@ -135,8 +135,8 @@ static inline struct gpio_bank *get_gpio_bank(int gpio)
                return &gpio_bank[1];
        }
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-       if (cpu_is_omap1610() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+       if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
                if (OMAP_GPIO_IS_MPUIO(gpio))
                        return &gpio_bank[0];
                return &gpio_bank[1 + (gpio >> 4)];
@@ -172,8 +172,8 @@ static inline int gpio_valid(int gpio)
        if (cpu_is_omap1510() && gpio < 16)
                return 0;
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-       if ((cpu_is_omap1610() || cpu_is_omap5912()) && gpio < 64)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+       if ((cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) && gpio < 64)
                return 0;
 #endif
 #ifdef CONFIG_ARCH_OMAP730
@@ -554,7 +554,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
        if (bank->method == METHOD_GPIO_1510)
                isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
        if (bank->method == METHOD_GPIO_1610)
                isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
 #endif
@@ -588,7 +588,7 @@ static void gpio_ack_irq(unsigned int irq)
        if (bank->method == METHOD_GPIO_1510)
                __raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1510_GPIO_INT_STATUS);
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
        if (bank->method == METHOD_GPIO_1610)
                __raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1610_GPIO_IRQSTATUS1);
 #endif
@@ -629,7 +629,7 @@ static void mpuio_mask_irq(unsigned int irq)
        unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
        struct gpio_bank *bank = get_gpio_bank(gpio);
 
-       _set_gpio_irqenable(bank, gpio, 0);
+       _set_gpio_irqenable(bank, get_gpio_index(gpio), 0);
 }
 
 static void mpuio_unmask_irq(unsigned int irq)
@@ -637,7 +637,7 @@ static void mpuio_unmask_irq(unsigned int irq)
        unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
        struct gpio_bank *bank = get_gpio_bank(gpio);
 
-       _set_gpio_irqenable(bank, gpio, 1);
+       _set_gpio_irqenable(bank, get_gpio_index(gpio), 1);
 }
 
 static struct irqchip gpio_irq_chip = {
@@ -668,8 +668,8 @@ static int __init _omap_gpio_init(void)
                gpio_bank = gpio_bank_1510;
        }
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-       if (cpu_is_omap1610() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+       if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
                int rev;
 
                gpio_bank_count = 5;
@@ -702,7 +702,7 @@ static int __init _omap_gpio_init(void)
                        __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
                }
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
                if (bank->method == METHOD_GPIO_1610) {
                        __raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
                        __raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
@@ -731,7 +731,7 @@ static int __init _omap_gpio_init(void)
 
        /* Enable system clock for GPIO module.
         * The CAM_CLK_CTRL *is* really the right place. */
-       if (cpu_is_omap1610())
+       if (cpu_is_omap1610() || cpu_is_omap1710())
                omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
 
        return 0;
index 18da117f6c1c1c172a3905f88f4c9f4368866577..3eec2986b40bae9969334ea0d50782b3b93d4222 100644 (file)
@@ -140,7 +140,9 @@ static struct omap_irq_bank omap1510_irq_banks[] = {
 };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+                                 || defined(CONFIG_ARCH_OMAP1710)
+
 static struct omap_irq_bank omap1610_irq_banks[] = {
        { .base_reg = OMAP_IH1_BASE,            .trigger_map = 0xb3fefe8f },
        { .base_reg = OMAP_IH2_BASE,            .trigger_map = 0xfffff7ff },
@@ -171,8 +173,9 @@ void __init omap_init_irq(void)
                irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
        }
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-       if (cpu_is_omap1610() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+                                 || defined(CONFIG_ARCH_OMAP1710)
+       if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
                irq_banks = omap1610_irq_banks;
                irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
        }
@@ -190,6 +193,11 @@ void __init omap_init_irq(void)
        irq_bank_writel(0x03, 0, IRQ_CONTROL_REG_OFFSET);
        irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET);
 
+       /* Enable interrupts in global mask */
+       if (cpu_is_omap730()) {
+               irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET);
+       }
+
        /* Install the interrupt handlers for each bank */
        for (i = 0; i < irq_bank_count; i++) {
                for (j = i * 32; j < (i + 1) * 32; j++) {
@@ -205,5 +213,9 @@ void __init omap_init_irq(void)
        }
 
        /* Unmask level 2 handler */
-       omap_unmask_irq(INT_IH2_IRQ);
+       if (cpu_is_omap730()) {
+               omap_unmask_irq(INT_730_IH2_IRQ);
+       } else {
+               omap_unmask_irq(INT_IH2_IRQ);
+       }
 }
index e3f378b4a6998aca7ed6846388a2de65e9129ea0..b6d0c7203dab860bec1f5b52aa8ad605829a18ae 100644 (file)
@@ -3,6 +3,7 @@
  *
  * OMAP LEDs dispatcher
  */
+#include <linux/kernel.h>
 #include <linux/init.h>
 
 #include <asm/leds.h>
 #include "leds.h"
 
 static int __init
-omap1510_leds_init(void)
+omap_leds_init(void)
 {
        if (machine_is_omap_innovator())
                leds_event = innovator_leds_event;
 
-       else if (machine_is_omap_perseus2()) {
-               leds_event = perseus2_leds_event;
+       else if (machine_is_omap_h2() || machine_is_omap_perseus2()) {
+               leds_event = h2p2_dbg_leds_event;
        }
 
        leds_event(led_start);
        return 0;
 }
 
-__initcall(omap1510_leds_init);
+__initcall(omap_leds_init);
index ba2eb59d1b87fd5e1d424a2a60209cdfdabce702..7571e2d635e34cfd4d4ac25c4b3e4e157925ed63 100644 (file)
@@ -1,2 +1,2 @@
 extern void innovator_leds_event(led_event_t evt);
-extern void perseus2_leds_event(led_event_t evt);
+extern void h2p2_dbg_leds_event(led_event_t evt);
index 944c294186cbe3a2384c00b5ea41969f96218365..93c7f4aca3bfab0e5f106bef444776f72fd7b143 100644 (file)
@@ -59,8 +59,8 @@ int ocpi_enable(void)
 
        /* Make sure there's clock for OCPI */
 
-#ifdef CONFIG_ARCH_OMAP1610
-        if (cpu_is_omap1610()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+        if (cpu_is_omap1610() || cpu_is_omap1710()) {
                val = omap_readl(OMAP1610_ARM_IDLECT3);
                val |= EN_OCPI_CK;
                val &= ~IDLOCPI_ARM;
diff --git a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c
new file mode 100644 (file)
index 0000000..f3451d2
--- /dev/null
@@ -0,0 +1,541 @@
+/*
+ * arch/arm/mach-omap/usb.c -- platform level USB initialization
+ *
+ * Copyright (C) 2004 Texas Instruments, 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/usb_otg.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+
+/* 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.
+ */
+
+/* TESTED ON:
+ *  - 1611B H2 (with usb1 mini-AB)
+ *  - 1510 Innovator with built-in transceiver (custom cable feeding 5V VBUS)
+ *  - 1710 custom development board using alternate pin group
+ */
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP_OTG
+
+static struct otg_transceiver *xceiv;
+
+/**
+ * otg_get_transceiver - find the (single) OTG transceiver driver
+ *
+ * Returns the transceiver driver, after getting a refcount to it; or
+ * null if there is no such transceiver.  The caller is responsible for
+ * releasing that count.
+ */
+struct otg_transceiver *otg_get_transceiver(void)
+{
+       if (xceiv)
+               get_device(xceiv->dev);
+       return xceiv;
+}
+EXPORT_SYMBOL(otg_get_transceiver);
+
+int otg_set_transceiver(struct otg_transceiver *x)
+{
+       if (xceiv && x)
+               return -EBUSY;
+       xceiv = x;
+       return 0;
+}
+EXPORT_SYMBOL(otg_set_transceiver);
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
+{
+       u32     syscon1 = 0;
+
+       if (nwires == 0) {
+               USB_TRANSCEIVER_CTRL_REG &= ~(1 << 3);
+               return 0;
+       }
+
+       /*
+        * VP and VM are needed for all active usb0 configurations.
+        * USB0_VP and USB0_VM are always set on 1510, there's no muxing
+        * available for them.
+        */
+       if (nwires >= 2 && !cpu_is_omap1510()) {
+               omap_cfg_reg(AA9_USB0_VP);
+               omap_cfg_reg(R9_USB0_VM);
+       }
+
+       /* internal transceiver */
+       if (nwires == 2) {
+               if (cpu_is_omap1510()) {
+                       /* This works for OHCI on 1510-Innovator, nothing to mux */
+                       return 0;
+               }
+
+#if 0
+               /* NOTE:  host OR device mode for now, no OTG */
+               USB_TRANSCEIVER_CTRL_REG &= ~(3 << 4);
+               if (is_device) {
+                       omap_cfg_reg(W4_USB_PUEN);
+                       omap_cfg_reg(R18_1510_USB_GPIO0);
+                       // omap_cfg_reg(USB0_VBUS);
+                       // omap_cfg_reg(USB0_PUEN);
+                       // USB_TRANSCEIVER_CTRL_REG.CONF_USB0_PORT_R = 7
+                       // when USB0_PUEN is needed
+               } else /* host mode needs D+ and D- pulldowns */
+                       USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
+               return 3 << 16;
+#else
+               /* FIXME: 1610 needs to return the right value here */
+               printk(KERN_ERR "usb0 internal transceiver, nyet\n");
+               return 0;
+#endif
+       }
+
+       /* alternate pin config, external transceiver */
+       omap_cfg_reg(V6_USB0_TXD);
+       omap_cfg_reg(W9_USB0_TXEN);
+       omap_cfg_reg(W5_USB0_SE0);
+
+#ifdef CONFIG_ARCH_OMAP_USB_SPEED
+       /* FIXME: there's good chance that pin V9 is used for MMC2 port cmddir */
+       omap_cfg_reg(V9_USB0_SPEED);
+       // omap_cfg_reg(V9_USB0_SUSP);
+#endif
+
+       if (nwires != 3)
+               omap_cfg_reg(Y5_USB0_RCV);
+
+       switch (nwires) {
+       case 3:
+               syscon1 = 2;
+               break;
+       case 4:
+               syscon1 = 1;
+               break;
+       case 6:
+               syscon1 = 3;
+               /* REVISIT: Is CONF_USB2_UNI_R only needed when nwires = 6? */
+               USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+               break;
+       default:
+               printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+                       0, nwires);
+       }
+       return syscon1 << 16;
+}
+
+static u32 __init omap_usb1_init(unsigned nwires)
+{
+       u32     syscon1 = 0;
+
+       if (nwires != 6)
+               USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
+       if (nwires == 0)
+               return 0;
+
+       /* external transceiver */
+       omap_cfg_reg(USB1_TXD);
+       omap_cfg_reg(USB1_TXEN);
+       if (cpu_is_omap1510()) {
+               omap_cfg_reg(USB1_SEO);
+               omap_cfg_reg(USB1_SPEED);
+               // SUSP
+       } else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
+               omap_cfg_reg(W13_1610_USB1_SE0);
+               omap_cfg_reg(R13_1610_USB1_SPEED);
+               // SUSP
+       } else {
+               pr_debug("usb unrecognized\n");
+       }
+       if (nwires != 3)
+               omap_cfg_reg(USB1_RCV);
+
+       switch (nwires) {
+       case 3:
+               syscon1 = 2;
+               break;
+       case 4:
+               syscon1 = 1;
+               break;
+       case 6:
+               syscon1 = 3;
+               omap_cfg_reg(USB1_VP);
+               omap_cfg_reg(USB1_VM);
+               USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
+               break;
+       default:
+               printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+                       1, nwires);
+       }
+       return syscon1 << 20;
+}
+
+static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
+{
+       u32     syscon1 = 0;
+
+       if (alt_pingroup)
+               return 0;
+       if (nwires != 6)
+               USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
+       if (nwires == 0)
+               return 0;
+
+       /* external transceiver */
+       if (cpu_is_omap1510()) {
+               omap_cfg_reg(USB2_TXD);
+               omap_cfg_reg(USB2_TXEN);
+               omap_cfg_reg(USB2_SEO);
+               if (nwires != 3)
+                       omap_cfg_reg(USB2_RCV);
+       } else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
+               omap_cfg_reg(V6_USB2_TXD);
+               omap_cfg_reg(W9_USB2_TXEN);
+               omap_cfg_reg(W5_USB2_SE0);
+               if (nwires != 3)
+                       omap_cfg_reg(Y5_USB2_RCV);
+       } else {
+               pr_debug("usb unrecognized\n");
+       }
+       // omap_cfg_reg(USB2_SUSP);
+       // FIXME omap_cfg_reg(USB2_SPEED);
+
+       switch (nwires) {
+       case 3:
+               syscon1 = 2;
+               break;
+       case 4:
+               syscon1 = 1;
+               break;
+       case 6:
+               syscon1 = 3;
+               if (cpu_is_omap1510()) {
+                       omap_cfg_reg(USB2_VP);
+                       omap_cfg_reg(USB2_VM);
+               } else {
+                       omap_cfg_reg(AA9_USB2_VP);
+                       omap_cfg_reg(R9_USB2_VM);
+               }
+               USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
+               break;
+       default:
+               printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+                       2, nwires);
+       }
+       return syscon1 << 24;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if    defined(CONFIG_USB_GADGET_OMAP) || \
+       defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) || \
+       (defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG))
+static void usb_release(struct device *dev)
+{
+       /* normally not freed */
+}
+#endif
+
+#ifdef CONFIG_USB_GADGET_OMAP
+
+static struct resource udc_resources[] = {
+       /* order is significant! */
+       {               /* registers */
+               .start          = IO_ADDRESS(UDC_BASE),
+               .end            = IO_ADDRESS(UDC_BASE + 0xff),
+               .flags          = IORESOURCE_MEM,
+       }, {            /* general IRQ */
+               .start          = IH2_BASE + 20,
+               .flags          = IORESOURCE_IRQ,
+       }, {            /* PIO IRQ */
+               .start          = IH2_BASE + 30,
+               .flags          = IORESOURCE_IRQ,
+       }, {            /* SOF IRQ */
+               .start          = IH2_BASE + 29,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static u64 udc_dmamask = ~(u32)0;
+
+static struct platform_device udc_device = {
+       .name           = "omap_udc",
+       .id             = -1,
+       .dev = {
+               .release                = usb_release,
+               .dma_mask               = &udc_dmamask,
+               .coherent_dma_mask      = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(udc_resources),
+       .resource       = udc_resources,
+};
+
+#endif
+
+#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32)0;
+
+static struct resource ohci_resources[] = {
+       {
+               .start  = IO_ADDRESS(OMAP_OHCI_BASE),
+               .end    = IO_ADDRESS(OMAP_OHCI_BASE + 4096),
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = INT_USB_HHC_1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device ohci_device = {
+       .name                   = "ohci",
+       .id                     = -1,
+       .dev = {
+               .release                = usb_release,
+               .dma_mask               = &ohci_dmamask,
+               .coherent_dma_mask      = 0x0fffffff,
+       },
+       .num_resources  = ARRAY_SIZE(ohci_resources),
+       .resource               = ohci_resources,
+};
+
+#endif
+
+#if    defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG)
+
+static struct resource otg_resources[] = {
+       /* order is significant! */
+       {
+               .start          = IO_ADDRESS(OTG_BASE),
+               .end            = IO_ADDRESS(OTG_BASE + 0xff),
+               .flags          = IORESOURCE_MEM,
+       }, {
+               .start          = IH2_BASE + 8,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device otg_device = {
+       .name           = "omap_otg",
+       .id             = -1,
+       .dev = {
+               .release                = usb_release,
+       },
+       .num_resources  = ARRAY_SIZE(otg_resources),
+       .resource       = otg_resources,
+};
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+// FIXME correct answer depends on hmc_mode,
+// as does any nonzero value for config->otg port number
+#define        is_usb0_device(config)  0
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP_OTG
+
+void __init
+omap_otg_init(struct omap_usb_config *config)
+{
+       u32             syscon = OTG_SYSCON_1_REG & 0xffff;
+       int             status;
+       int             alt_pingroup = 0;
+
+       /* NOTE:  no bus or clock setup (yet?) */
+
+       syscon = OTG_SYSCON_1_REG & 0xffff;
+       if (!(syscon & OTG_RESET_DONE))
+               pr_debug("USB resets not complete?\n");
+
+       // OTG_IRQ_EN_REG = 0;
+
+       /* pin muxing and transceiver pinouts */
+       if (config->pins[0] > 2)        /* alt pingroup 2 */
+               alt_pingroup = 1;
+       syscon |= omap_usb0_init(config->pins[0], is_usb0_device(config));
+       syscon |= omap_usb1_init(config->pins[1]);
+       syscon |= omap_usb2_init(config->pins[2], alt_pingroup);
+       pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon);
+       OTG_SYSCON_1_REG = syscon;
+
+       syscon = config->hmc_mode;
+       syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */;
+       if (config->otg || config->register_host)
+               syscon |= UHOST_EN;
+#ifdef CONFIG_USB_OTG
+       if (config->otg)
+               syscon |= OTG_EN;
+#endif
+       pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon);
+       OTG_SYSCON_2_REG = syscon;
+
+       printk("USB: hmc %d", config->hmc_mode);
+       if (alt_pingroup)
+               printk(", usb2 alt %d wires", config->pins[2]);
+       else if (config->pins[0])
+               printk(", usb0 %d wires%s", config->pins[2],
+                       is_usb0_device(config) ? " (dev)" : "");
+       if (config->pins[1])
+               printk(", usb1 %d wires", config->pins[1]);
+       if (!alt_pingroup && config->pins[2])
+               printk(", usb2 %d wires", config->pins[2]);
+       if (config->otg)
+               printk(", Mini-AB on usb%d", config->otg - 1);
+       printk("\n");
+
+       /* don't clock unused USB controllers  */
+       syscon = OTG_SYSCON_1_REG;
+       syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
+
+#ifdef CONFIG_USB_GADGET_OMAP
+       if (config->otg || config->register_dev) {
+               syscon &= ~DEV_IDLE_EN;
+               udc_device.dev.platform_data = config;
+               status = platform_device_register(&udc_device);
+               if (status)
+                       pr_debug("can't register UDC device, %d\n", status);
+       }
+#endif
+
+#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+       if (config->otg || config->register_host) {
+               syscon &= ~HST_IDLE_EN;
+               ohci_device.dev.platform_data = config;
+               status = platform_device_register(&ohci_device);
+               if (status)
+                       pr_debug("can't register OHCI device, %d\n", status);
+       }
+#endif
+
+#ifdef CONFIG_USB_OTG
+       if (config->otg) {
+               syscon &= ~OTG_IDLE_EN;
+               if (cpu_is_omap730())
+                       otg_resources[1].start = INT_730_USB_OTG;
+               status = platform_device_register(&otg_device);
+               // ...
+       }
+#endif
+       pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon);
+       OTG_SYSCON_1_REG = syscon;
+
+       status = 0;
+}
+
+#else
+static inline void omap_otg_init(struct omap_usb_config *config) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP1510
+
+static void __init omap_1510_usb_init(struct omap_usb_config *config)
+{
+       int status;
+       unsigned int val;
+
+       omap_usb0_init(config->pins[0], is_usb0_device(config));
+       omap_usb1_init(config->pins[1]);
+       omap_usb2_init(config->pins[2], 0);
+
+       val = omap_readl(MOD_CONF_CTRL_0) & ~(0x3f << 1);
+       val |= (config->hmc_mode << 1);
+       omap_writel(val, MOD_CONF_CTRL_0);
+
+       // FIXME this has a UDC controller too
+
+#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+       if (config->otg || config->register_host) {
+               ohci_device.dev.platform_data = config;
+               status = platform_device_register(&ohci_device);
+               if (status)
+                       pr_debug("can't register OHCI device, %d\n", status);
+       }
+       // FIXME completely untested ...
+#endif
+
+}
+
+#else
+static inline void omap_1510_usb_init(struct omap_usb_config *config) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static struct omap_usb_config platform_data;
+
+static int __init
+omap_usb_init(void)
+{
+       const struct omap_usb_config *config;
+
+       config = omap_get_config(OMAP_TAG_USB, struct omap_usb_config);
+       if (config == NULL) {
+               printk(KERN_ERR "USB: No board-specific platform config found\n");
+               return -ENODEV;
+       }
+       platform_data = *config;
+
+       if (cpu_is_omap730()
+                       || cpu_is_omap1610()
+                       || cpu_is_omap1710()
+                       || cpu_is_omap5912())
+               omap_otg_init(&platform_data);
+       else if (cpu_is_omap1510())
+               omap_1510_usb_init(&platform_data);
+       else {
+               printk(KERN_ERR "USB: No init for your chip yet\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+subsys_initcall(omap_usb_init);