aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorTony Lindgren <tony@com.rmk.(none)>2004-08-14 19:27:39 +0100
committerRussell King <rmk@flint.arm.linux.org.uk>2004-08-14 19:27:39 +0100
commit958163e228de2f11c26bd3b9da4c2ebb427fb561 (patch)
tree92d6370eebe0fe5e3688456d922da55413b7089a /arch
parenta7116ca5d502b6a1733336f239089885178234ea (diff)
downloadhistory-958163e228de2f11c26bd3b9da4c2ebb427fb561.tar.gz
[ARM PATCH] 2007/1: OMAP update 3/6: Arch files
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
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-omap/Makefile10
-rw-r--r--arch/arm/mach-omap/board-generic.c56
-rw-r--r--arch/arm/mach-omap/board-innovator.c58
-rw-r--r--arch/arm/mach-omap/board-osk.c4
-rw-r--r--arch/arm/mach-omap/board-perseus2.c15
-rw-r--r--arch/arm/mach-omap/clocks.c11
-rw-r--r--arch/arm/mach-omap/common.c53
-rw-r--r--arch/arm/mach-omap/common.h1
-rw-r--r--arch/arm/mach-omap/dma.c156
-rw-r--r--arch/arm/mach-omap/fpga.c30
-rw-r--r--arch/arm/mach-omap/gpio.c28
-rw-r--r--arch/arm/mach-omap/irq.c20
-rw-r--r--arch/arm/mach-omap/leds.c9
-rw-r--r--arch/arm/mach-omap/leds.h2
-rw-r--r--arch/arm/mach-omap/ocpi.c4
-rw-r--r--arch/arm/mach-omap/usb.c541
16 files changed, 842 insertions, 156 deletions
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index 5fcb1e5c76270d..b483092dd2832e 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -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
diff --git a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c
index 447046b24a082d..03da924c778677 100644
--- a/arch/arm/mach-omap/board-generic.c
+++ b/arch/arm/mach-omap/board-generic.c
@@ -25,9 +25,13 @@
#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
-
diff --git a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c
index 6ef4d8dcf90398..8fd97e7af54972 100644
--- a/arch/arm/mach-omap/board-innovator.c
+++ b/arch/arm/mach-omap/board-innovator.c
@@ -29,9 +29,12 @@
#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
diff --git a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c
index 16ecd6be5a6099..85d9a0ac33e32d 100644
--- a/arch/arm/mach-omap/board-osk.c
+++ b/arch/arm/mach-omap/board-osk.c
@@ -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
diff --git a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c
index 8015d10fc75e30..95833f3b942325 100644
--- a/arch/arm/mach-omap/board-perseus2.c
+++ b/arch/arm/mach-omap/board-perseus2.c
@@ -23,9 +23,12 @@
#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
diff --git a/arch/arm/mach-omap/clocks.c b/arch/arm/mach-omap/clocks.c
index bda7c6f381ee3c..b507856597321c 100644
--- a/arch/arm/mach-omap/clocks.c
+++ b/arch/arm/mach-omap/clocks.c
@@ -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 */
diff --git a/arch/arm/mach-omap/common.c b/arch/arm/mach-omap/common.c
index 43aaa1c6c5458b..17d82a7f3a3f8d 100644
--- a/arch/arm/mach-omap/common.c
+++ b/arch/arm/mach-omap/common.c
@@ -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;
diff --git a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h
index 96dcb3c5397360..1cc559dd2f8172 100644
--- a/arch/arm/mach-omap/common.h
+++ b/arch/arm/mach-omap/common.h
@@ -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 */
diff --git a/arch/arm/mach-omap/dma.c b/arch/arm/mach-omap/dma.c
index 385b4d1cc055c9..cfb23d894a958a 100644
--- a/arch/arm/mach-omap/dma.c
+++ b/arch/arm/mach-omap/dma.c
@@ -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);
diff --git a/arch/arm/mach-omap/fpga.c b/arch/arm/mach-omap/fpga.c
index d9246b1dcc1e61..f0ce5c12a2ad96 100644
--- a/arch/arm/mach-omap/fpga.c
+++ b/arch/arm/mach-omap/fpga.c
@@ -31,19 +31,9 @@
#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);
diff --git a/arch/arm/mach-omap/gpio.c b/arch/arm/mach-omap/gpio.c
index 2f052a959af178..206bee968329f2 100644
--- a/arch/arm/mach-omap/gpio.c
+++ b/arch/arm/mach-omap/gpio.c
@@ -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;
diff --git a/arch/arm/mach-omap/irq.c b/arch/arm/mach-omap/irq.c
index 18da117f6c1c1c..3eec2986b40bae 100644
--- a/arch/arm/mach-omap/irq.c
+++ b/arch/arm/mach-omap/irq.c
@@ -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);
+ }
}
diff --git a/arch/arm/mach-omap/leds.c b/arch/arm/mach-omap/leds.c
index e3f378b4a6998a..b6d0c7203dab86 100644
--- a/arch/arm/mach-omap/leds.c
+++ b/arch/arm/mach-omap/leds.c
@@ -3,6 +3,7 @@
*
* OMAP LEDs dispatcher
*/
+#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/leds.h>
@@ -11,17 +12,17 @@
#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);
diff --git a/arch/arm/mach-omap/leds.h b/arch/arm/mach-omap/leds.h
index ba2eb59d1b87fd..7571e2d635e34c 100644
--- a/arch/arm/mach-omap/leds.h
+++ b/arch/arm/mach-omap/leds.h
@@ -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);
diff --git a/arch/arm/mach-omap/ocpi.c b/arch/arm/mach-omap/ocpi.c
index 944c294186cbe3..93c7f4aca3bfab 100644
--- a/arch/arm/mach-omap/ocpi.c
+++ b/arch/arm/mach-omap/ocpi.c
@@ -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
index 00000000000000..f3451d269159d8
--- /dev/null
+++ b/arch/arm/mach-omap/usb.c
@@ -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);