aboutsummaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/configs/at91rm9200dk_defconfig2
-rw-r--r--arch/arm/configs/at91rm9200ek_defconfig2
-rw-r--r--arch/arm/kernel/armksyms.c13
-rw-r--r--arch/arm/kernel/setup.c3
-rw-r--r--arch/arm/mach-at91rm9200/Makefile9
-rw-r--r--arch/arm/mach-at91rm9200/board-csb337.c3
-rw-r--r--arch/arm/mach-at91rm9200/board-csb637.c3
-rw-r--r--arch/arm/mach-at91rm9200/board-dk.c10
-rw-r--r--arch/arm/mach-at91rm9200/board-ek.c10
-rw-r--r--arch/arm/mach-at91rm9200/devices.c154
-rw-r--r--arch/arm/mach-at91rm9200/leds.c100
-rw-r--r--arch/arm/mach-ep93xx/core.c10
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c39
-rw-r--r--arch/arm/mach-imx/dma.c511
-rw-r--r--arch/arm/mach-imx/mx1ads.c18
-rw-r--r--arch/arm/mach-ixp23xx/espresso.c9
-rw-r--r--arch/arm/mach-ixp23xx/pci.c18
-rw-r--r--arch/arm/mach-omap1/Kconfig20
-rw-r--r--arch/arm/mach-omap1/Makefile11
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c116
-rw-r--r--arch/arm/mach-omap1/board-generic.c2
-rw-r--r--arch/arm/mach-omap1/board-h2.c200
-rw-r--r--arch/arm/mach-omap1/board-h3.c277
-rw-r--r--arch/arm/mach-omap1/board-innovator.c56
-rw-r--r--arch/arm/mach-omap1/board-netstar.c160
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c268
-rw-r--r--arch/arm/mach-omap1/board-osk.c95
-rw-r--r--arch/arm/mach-omap1/board-palmte.c12
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c123
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c8
-rw-r--r--arch/arm/mach-omap1/clock.c9
-rw-r--r--arch/arm/mach-omap1/clock.h91
-rw-r--r--arch/arm/mach-omap1/devices.c40
-rw-r--r--arch/arm/mach-omap1/io.c4
-rw-r--r--arch/arm/mach-omap1/irq.c18
-rw-r--r--arch/arm/mach-omap1/mux.c30
-rw-r--r--arch/arm/mach-omap1/pm.c770
-rw-r--r--arch/arm/mach-omap1/serial.c6
-rw-r--r--arch/arm/mach-omap1/sleep.S (renamed from arch/arm/plat-omap/sleep.S)111
-rw-r--r--arch/arm/mach-omap1/time.c197
-rw-r--r--arch/arm/mach-omap2/Kconfig3
-rw-r--r--arch/arm/mach-omap2/Makefile6
-rw-r--r--arch/arm/mach-omap2/board-apollon.c285
-rw-r--r--arch/arm/mach-omap2/board-h4.c174
-rw-r--r--arch/arm/mach-omap2/clock.c79
-rw-r--r--arch/arm/mach-omap2/clock.h37
-rw-r--r--arch/arm/mach-omap2/devices.c42
-rw-r--r--arch/arm/mach-omap2/io.c21
-rw-r--r--arch/arm/mach-omap2/memory.c102
-rw-r--r--arch/arm/mach-omap2/memory.h34
-rw-r--r--arch/arm/mach-omap2/mux.c45
-rw-r--r--arch/arm/mach-omap2/pm.c149
-rw-r--r--arch/arm/mach-omap2/prcm-regs.h (renamed from arch/arm/mach-omap2/prcm.h)188
-rw-r--r--arch/arm/mach-omap2/prcm.c40
-rw-r--r--arch/arm/mach-omap2/sleep.S144
-rw-r--r--arch/arm/mach-omap2/sram-fn.S4
-rw-r--r--arch/arm/mach-pxa/poodle.c4
-rw-r--r--arch/arm/mach-s3c2410/Kconfig7
-rw-r--r--arch/arm/mach-s3c2410/Makefile2
-rw-r--r--arch/arm/mach-s3c2410/clock.c2
-rw-r--r--arch/arm/mach-s3c2410/common-smdk.c134
-rw-r--r--arch/arm/mach-s3c2410/common-smdk.h15
-rw-r--r--arch/arm/mach-s3c2410/mach-anubis.c4
-rw-r--r--arch/arm/mach-s3c2410/mach-rx3715.c35
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c13
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2440.c17
-rw-r--r--arch/arm/mach-sa1100/collie.c72
-rw-r--r--arch/arm/mm/consistent.c17
-rw-r--r--arch/arm/mm/mm-armv.c11
-rw-r--r--arch/arm/mm/proc-xsc3.S2
-rw-r--r--arch/arm/plat-omap/Kconfig4
-rw-r--r--arch/arm/plat-omap/Makefile6
-rw-r--r--arch/arm/plat-omap/clock.c67
-rw-r--r--arch/arm/plat-omap/devices.c143
-rw-r--r--arch/arm/plat-omap/dma.c6
-rw-r--r--arch/arm/plat-omap/dmtimer.c26
-rw-r--r--arch/arm/plat-omap/fb.c80
-rw-r--r--arch/arm/plat-omap/gpio.c86
-rw-r--r--arch/arm/plat-omap/mcbsp.c345
-rw-r--r--arch/arm/plat-omap/ocpi.c3
-rw-r--r--arch/arm/plat-omap/pm.c1
-rw-r--r--arch/arm/plat-omap/sram.c143
-rw-r--r--arch/arm/plat-omap/timer32k.c325
83 files changed, 5566 insertions, 895 deletions
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
index 1fe73d19888..9e1c1cceb73 100644
--- a/arch/arm/configs/at91rm9200dk_defconfig
+++ b/arch/arm/configs/at91rm9200dk_defconfig
@@ -379,7 +379,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
#
# NAND Flash Device Drivers
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
index b7d934cdb1b..6e0805a971d 100644
--- a/arch/arm/configs/at91rm9200ek_defconfig
+++ b/arch/arm/configs/at91rm9200ek_defconfig
@@ -370,7 +370,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
CONFIG_MTD_AT91_DATAFLASH=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
#
# NAND Flash Device Drivers
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 1574941ebfe..ee083b3f052 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -100,23 +100,12 @@ EXPORT_SYMBOL(__raw_writesl);
#endif
/* string / mem functions */
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(__memzero);
@@ -190,8 +179,6 @@ EXPORT_SYMBOL(_find_next_bit_be);
/* syscalls */
EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_read);
EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_open);
EXPORT_SYMBOL(sys_exit);
EXPORT_SYMBOL(sys_wait4);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7cd280bfd6..43752840395 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -252,6 +252,9 @@ static void __init dump_cpu_info(int cpu)
dump_cache("cache", cpu, CACHE_ISIZE(info));
}
}
+
+ if (arch_is_coherent())
+ printk("Cache coherency enabled\n");
}
int cpu_architecture(void)
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile
index 75e6ee318de..ef88c4128ed 100644
--- a/arch/arm/mach-at91rm9200/Makefile
+++ b/arch/arm/mach-at91rm9200/Makefile
@@ -16,11 +16,12 @@ obj-$(CONFIG_MACH_CSB637) += board-csb637.o
#obj-$(CONFIG_MACH_KB9200) += board-kb9202.o
# LEDs support
-#led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
-#led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
-#led-$(CONFIG_MACH_CSB337) += leds.o
-#led-$(CONFIG_MACH_CSB637) += leds.o
+led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
+led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
+led-$(CONFIG_MACH_CSB337) += leds.o
+led-$(CONFIG_MACH_CSB637) += leds.o
#led-$(CONFIG_MACH_KB9200) += leds.o
+#led-$(CONFIG_MACH_KAFA) += leds.o
obj-$(CONFIG_LEDS) += $(led-y)
# VGA support
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index 54022e58d50..f45104ceea8 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -67,6 +67,9 @@ static void __init csb337_map_io(void)
/* Initialize clocks: 3.6864 MHz crystal */
at91_clock_init(3686400);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = CSB337_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index 8195f9d919e..f2c2d6e79bc 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -67,6 +67,9 @@ static void __init csb637_map_io(void)
/* Initialize clocks: 3.6864 MHz crystal */
at91_clock_init(3686400);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = CSB637_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 8a783368366..2d7200ed66e 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -70,6 +70,9 @@ static void __init dk_map_io(void)
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = DK_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
@@ -118,9 +121,14 @@ static void __init dk_board_init(void)
at91_add_device_udc(&dk_udc_data);
/* Compact Flash */
at91_add_device_cf(&dk_cf_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ /* DataFlash card */
+ at91_set_gpio_output(AT91_PIN_PB7, 0);
+#else
/* MMC */
- at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+ at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
at91_add_device_mmc(&dk_mmc_data);
+#endif
/* VGA */
// dk_add_device_video();
}
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index fd0752eba89..80d90f5135a 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -70,6 +70,9 @@ static void __init ek_map_io(void)
/* Initialize clocks: 18.432 MHz crystal */
at91_clock_init(18432000);
+ /* Setup the LEDs */
+ at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
+
#ifdef CONFIG_SERIAL_AT91
at91_console_port = EK_SERIAL_CONSOLE;
memcpy(at91_serial_map, serial, sizeof(serial));
@@ -111,9 +114,14 @@ static void __init ek_board_init(void)
at91_add_device_usbh(&ek_usbh_data);
/* USB Device */
at91_add_device_udc(&ek_udc_data);
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+ /* DataFlash card */
+ at91_set_gpio_output(AT91_PIN_PB22, 0);
+#else
/* MMC */
- at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+ at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
at91_add_device_mmc(&ek_mmc_data);
+#endif
/* VGA */
// ek_add_device_video();
}
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c
index 57eedd5beaf..1781b8f342c 100644
--- a/arch/arm/mach-at91rm9200/devices.c
+++ b/arch/arm/mach-at91rm9200/devices.c
@@ -28,10 +28,10 @@
static u64 ohci_dmamask = 0xffffffffUL;
static struct at91_usbh_data usbh_data;
-static struct resource at91rm9200_usbh_resource[] = {
+static struct resource at91_usbh_resource[] = {
[0] = {
.start = AT91_UHP_BASE,
- .end = AT91_UHP_BASE + SZ_1M -1,
+ .end = AT91_UHP_BASE + SZ_1M - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -49,8 +49,8 @@ static struct platform_device at91rm9200_usbh_device = {
.coherent_dma_mask = 0xffffffff,
.platform_data = &usbh_data,
},
- .resource = at91rm9200_usbh_resource,
- .num_resources = ARRAY_SIZE(at91rm9200_usbh_resource),
+ .resource = at91_usbh_resource,
+ .num_resources = ARRAY_SIZE(at91_usbh_resource),
};
void __init at91_add_device_usbh(struct at91_usbh_data *data)
@@ -121,6 +121,19 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
static u64 eth_dmamask = 0xffffffffUL;
static struct at91_eth_data eth_data;
+static struct resource at91_eth_resources[] = {
+ [0] = {
+ .start = AT91_BASE_EMAC,
+ .end = AT91_BASE_EMAC + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91_ID_EMAC,
+ .end = AT91_ID_EMAC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static struct platform_device at91rm9200_eth_device = {
.name = "at91_ether",
.id = -1,
@@ -129,7 +142,8 @@ static struct platform_device at91rm9200_eth_device = {
.coherent_dma_mask = 0xffffffff,
.platform_data = &eth_data,
},
- .num_resources = 0,
+ .resource = at91_eth_resources,
+ .num_resources = ARRAY_SIZE(at91_eth_resources),
};
void __init at91_add_device_eth(struct at91_eth_data *data)
@@ -224,15 +238,20 @@ static u64 mmc_dmamask = 0xffffffffUL;
static struct at91_mmc_data mmc_data;
static struct resource at91_mmc_resources[] = {
- {
+ [0] = {
.start = AT91_BASE_MCI,
.end = AT91_BASE_MCI + SZ_16K - 1,
.flags = IORESOURCE_MEM,
- }
+ },
+ [1] = {
+ .start = AT91_ID_MCI,
+ .end = AT91_ID_MCI,
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct platform_device at91rm9200_mmc_device = {
- .name = "at91rm9200_mci",
+ .name = "at91_mci",
.id = -1,
.dev = {
.dma_mask = &mmc_dmamask,
@@ -290,4 +309,123 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
#endif
+/* --------------------------------------------------------------------
+ * NAND / SmartMedia
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
+static struct at91_nand_data nand_data;
+
+static struct resource at91_nand_resources[] = {
+ {
+ .start = AT91_SMARTMEDIA_BASE,
+ .end = AT91_SMARTMEDIA_BASE + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91_nand_device = {
+ .name = "at91_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .resource = at91_nand_resources,
+ .num_resources = ARRAY_SIZE(at91_nand_resources),
+};
+
+void __init at91_add_device_nand(struct at91_nand_data *data)
+{
+ if (!data)
+ return;
+
+ /* enable pin */
+ if (data->enable_pin)
+ at91_set_gpio_output(data->enable_pin, 1);
+
+ /* ready/busy pin */
+ if (data->rdy_pin)
+ at91_set_gpio_input(data->rdy_pin, 1);
+
+ /* card detect pin */
+ if (data->det_pin)
+ at91_set_gpio_input(data->det_pin, 1);
+
+ at91_set_A_periph(AT91_PIN_PC1, 0); /* SMOE */
+ at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */
+
+ nand_data = *data;
+ platform_device_register(&at91_nand_device);
+}
+#else
+void __init at91_add_device_nand(struct at91_nand_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * TWI (i2c)
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
+static struct platform_device at91rm9200_twi_device = {
+ .name = "at91_i2c",
+ .id = -1,
+ .num_resources = 0,
+};
+
+void __init at91_add_device_i2c(void)
+{
+ /* pins used for TWI interface */
+ at91_set_A_periph(AT91_PIN_PA25, 0); /* TWD */
+ at91_set_multi_drive(AT91_PIN_PA25, 1);
+
+ at91_set_A_periph(AT91_PIN_PA26, 0); /* TWCK */
+ at91_set_multi_drive(AT91_PIN_PA26, 1);
+
+ platform_device_register(&at91rm9200_twi_device);
+}
+#else
+void __init at91_add_device_i2c(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * RTC
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE)
+static struct platform_device at91rm9200_rtc_device = {
+ .name = "at91_rtc",
+ .id = -1,
+ .num_resources = 0,
+};
+
+void __init at91_add_device_rtc(void)
+{
+ platform_device_register(&at91rm9200_rtc_device);
+}
+#else
+void __init at91_add_device_rtc(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * LEDs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_LEDS)
+u8 at91_leds_cpu;
+u8 at91_leds_timer;
+
+void __init at91_init_leds(u8 cpu_led, u8 timer_led)
+{
+ at91_leds_cpu = cpu_led;
+ at91_leds_timer = timer_led;
+}
+
+#else
+void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
+#endif
+
+
/* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91rm9200/leds.c
new file mode 100644
index 00000000000..28150e8905b
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/leds.c
@@ -0,0 +1,100 @@
+/*
+ * LED driver for Atmel AT91-based boards.
+ *
+ * Copyright (C) SAN People (Pty) Ltd
+ *
+ * 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.
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+#include <asm/leds.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+
+static inline void at91_led_on(unsigned int led)
+{
+ at91_set_gpio_value(led, 0);
+}
+
+static inline void at91_led_off(unsigned int led)
+{
+ at91_set_gpio_value(led, 1);
+}
+
+static inline void at91_led_toggle(unsigned int led)
+{
+ unsigned long is_off = at91_get_gpio_value(led);
+ if (is_off)
+ at91_led_on(led);
+ else
+ at91_led_off(led);
+}
+
+
+/*
+ * Handle LED events.
+ */
+static void at91_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ switch(evt) {
+ case led_start: /* System startup */
+ at91_led_on(at91_leds_cpu);
+ break;
+
+ case led_stop: /* System stop / suspend */
+ at91_led_off(at91_leds_cpu);
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer: /* Every 50 timer ticks */
+ at91_led_toggle(at91_leds_timer);
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start: /* Entering idle state */
+ at91_led_off(at91_leds_cpu);
+ break;
+
+ case led_idle_end: /* Exit idle state */
+ at91_led_on(at91_leds_cpu);
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ local_irq_restore(flags);
+}
+
+
+static int __init leds_init(void)
+{
+ if (!at91_leds_timer || !at91_leds_cpu)
+ return -ENODEV;
+
+ /* Enable PIO to access the LEDs */
+ at91_set_gpio_output(at91_leds_timer, 1);
+ at91_set_gpio_output(at91_leds_cpu, 1);
+
+ leds_event = at91_leds_event;
+
+ leds_event(led_start);
+ return 0;
+}
+
+__initcall(leds_init);
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 2d892e4daa0..dcd41762538 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -424,6 +424,14 @@ static struct amba_device uart3_device = {
.periphid = 0x00041010,
};
+
+static struct platform_device ep93xx_rtc_device = {
+ .name = "ep93xx-rtc",
+ .id = -1,
+ .num_resources = 0,
+};
+
+
void __init ep93xx_init_devices(void)
{
unsigned int v;
@@ -439,4 +447,6 @@ void __init ep93xx_init_devices(void)
amba_device_register(&uart1_device, &iomem_resource);
amba_device_register(&uart2_device, &iomem_resource);
amba_device_register(&uart3_device, &iomem_resource);
+
+ platform_device_register(&ep93xx_rtc_device);
}
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 777e75daa8a..9be01b0c3f4 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -17,6 +17,8 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/m48t86.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -39,6 +41,16 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
.pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
.length = TS72XX_OPTIONS2_SIZE,
.type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_RTC_INDEX_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
+ .length = TS72XX_RTC_INDEX_SIZE,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = TS72XX_RTC_DATA_VIRT_BASE,
+ .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
+ .length = TS72XX_RTC_DATA_SIZE,
+ .type = MT_DEVICE,
}
};
@@ -99,11 +111,38 @@ static void __init ts72xx_map_io(void)
}
}
+static unsigned char ts72xx_rtc_readb(unsigned long addr)
+{
+ __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+ return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static void ts72xx_rtc_writeb(unsigned char value, unsigned long addr)
+{
+ __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
+ __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
+}
+
+static struct m48t86_ops ts72xx_rtc_ops = {
+ .readb = ts72xx_rtc_readb,
+ .writeb = ts72xx_rtc_writeb,
+};
+
+static struct platform_device ts72xx_rtc_device = {
+ .name = "rtc-m48t86",
+ .id = -1,
+ .dev = {
+ .platform_data = &ts72xx_rtc_ops,
+ },
+ .num_resources = 0,
+};
+
static void __init ts72xx_init_machine(void)
{
ep93xx_init_devices();
if (board_is_ts7200())
physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL);
+ platform_device_register(&ts72xx_rtc_device);
}
MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC")
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 71a59e19616..4ca51dcf13a 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -7,11 +7,18 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * 03/03/2004 Sascha Hauer <sascha@saschahauer.de>
+ * 2004-03-03 Sascha Hauer <sascha@saschahauer.de>
* initial version heavily inspired by
* linux/arch/arm/mach-pxa/dma.c
+ *
+ * 2005-04-17 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ * Changed to support scatter gather DMA
+ * by taking Russell's code from RiscPC
+ *
*/
+#undef DEBUG
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -22,69 +29,368 @@
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/dma.h>
+#include <asm/arch/imx-dma.h>
+
+struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
+
+/*
+ * imx_dma_sg_next - prepare next chunk for scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @lastcount: number of bytes transferred during last transfer
+ *
+ * Functions prepares DMA controller for next sg data chunk transfer.
+ * The @lastcount argument informs function about number of bytes transferred
+ * during last block. Zero value can be used for @lastcount to setup DMA
+ * for the first chunk.
+ */
+static inline int imx_dma_sg_next(imx_dmach_t dma_ch, unsigned int lastcount)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned int nextcount;
+ unsigned int nextaddr;
+
+ if (!imxdma->name) {
+ printk(KERN_CRIT "%s: called for not allocated channel %d\n",
+ __FUNCTION__, dma_ch);
+ return 0;
+ }
+
+ imxdma->resbytes -= lastcount;
+
+ if (!imxdma->sg) {
+ pr_debug("imxdma%d: no sg data\n", dma_ch);
+ return 0;
+ }
+
+ imxdma->sgbc += lastcount;
+ if ((imxdma->sgbc >= imxdma->sg->length) || !imxdma->resbytes) {
+ if ((imxdma->sgcount <= 1) || !imxdma->resbytes) {
+ pr_debug("imxdma%d: sg transfer limit reached\n",
+ dma_ch);
+ imxdma->sgcount=0;
+ imxdma->sg = NULL;
+ return 0;
+ } else {
+ imxdma->sgcount--;
+ imxdma->sg++;
+ imxdma->sgbc = 0;
+ }
+ }
+ nextcount = imxdma->sg->length - imxdma->sgbc;
+ nextaddr = imxdma->sg->dma_address + imxdma->sgbc;
-static struct dma_channel {
- char *name;
- void (*irq_handler) (int, void *, struct pt_regs *);
- void (*err_handler) (int, void *, struct pt_regs *);
- void *data;
-} dma_channels[11];
+ if(imxdma->resbytes < nextcount)
+ nextcount = imxdma->resbytes;
-/* set err_handler to NULL to have the standard info-only error handler */
+ if ((imxdma->dma_mode & DMA_MODE_MASK) == DMA_MODE_READ)
+ DAR(dma_ch) = nextaddr;
+ else
+ SAR(dma_ch) = nextaddr;
+
+ CNTR(dma_ch) = nextcount;
+ pr_debug("imxdma%d: next sg chunk dst 0x%08x, src 0x%08x, size 0x%08x\n",
+ dma_ch, DAR(dma_ch), SAR(dma_ch), CNTR(dma_ch));
+
+ return nextcount;
+}
+
+/*
+ * imx_dma_setup_sg_base - scatter-gather DMA emulation
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ *
+ * Functions sets up i.MX DMA state for emulated scatter-gather transfer
+ * and sets up channel registers to be ready for the first chunk
+ */
+static int
+imx_dma_setup_sg_base(imx_dmach_t dma_ch,
+ struct scatterlist *sg, unsigned int sgcount)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+ imxdma->sg = sg;
+ imxdma->sgcount = sgcount;
+ imxdma->sgbc = 0;
+ return imx_dma_sg_next(dma_ch, 0);
+}
+
+/**
+ * imx_dma_setup_single - setup i.MX DMA channel for linear memory to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @dma_address: the DMA/physical memory address of the linear data block
+ * to transfer
+ * @dma_length: length of the data block in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ * or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel source and destination addresses for transfer
+ * specified by provided parameters. The scatter-gather emulation is disabled,
+ * because linear data block
+ * form the physical address range is transfered.
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ * Zero indicates success.
+ */
int
-imx_request_dma(char *name, imx_dma_prio prio,
- void (*irq_handler) (int, void *, struct pt_regs *),
- void (*err_handler) (int, void *, struct pt_regs *), void *data)
+imx_dma_setup_single(imx_dmach_t dma_ch, dma_addr_t dma_address,
+ unsigned int dma_length, unsigned int dev_addr,
+ dmamode_t dmamode)
{
- unsigned long flags;
- int i, found = 0;
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
- /* basic sanity checks */
- if (!name || !irq_handler)
+ imxdma->sg = NULL;
+ imxdma->sgcount = 0;
+ imxdma->dma_mode = dmamode;
+ imxdma->resbytes = dma_length;
+
+ if (!dma_address) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_single null address\n",
+ dma_ch);
return -EINVAL;
+ }
- local_irq_save(flags);
+ if (!dma_length) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_single zero length\n",
+ dma_ch);
+ return -EINVAL;
+ }
- /* try grabbing a DMA channel with the requested priority */
- for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
- if (!dma_channels[i].name) {
- found = 1;
- break;
- }
+ if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+ pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for read\n",
+ dma_ch, (unsigned int)dma_address, dma_length,
+ dev_addr);
+ SAR(dma_ch) = dev_addr;
+ DAR(dma_ch) = (unsigned int)dma_address;
+ } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+ pr_debug("imxdma%d: mx_dma_setup_single2dev dma_addressg=0x%08x dma_length=%d dev_addr=0x%08x for write\n",
+ dma_ch, (unsigned int)dma_address, dma_length,
+ dev_addr);
+ SAR(dma_ch) = (unsigned int)dma_address;
+ DAR(dma_ch) = dev_addr;
+ } else {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_single bad dmamode\n",
+ dma_ch);
+ return -EINVAL;
}
- if (!found) {
- /* requested prio group is full, try hier priorities */
- for (i = prio - 1; i >= 0; i--) {
- if (!dma_channels[i].name) {
- found = 1;
- break;
- }
- }
+ CNTR(dma_ch) = dma_length;
+
+ return 0;
+}
+
+/**
+ * imx_dma_setup_sg - setup i.MX DMA channel SG list to/from device transfer
+ * @dma_ch: i.MX DMA channel number
+ * @sg: pointer to the scatter-gather list/vector
+ * @sgcount: scatter-gather list hungs count
+ * @dma_length: total length of the transfer request in bytes
+ * @dev_addr: physical device port address
+ * @dmamode: DMA transfer mode, %DMA_MODE_READ from the device to the memory
+ * or %DMA_MODE_WRITE from memory to the device
+ *
+ * The function setups DMA channel state and registers to be ready for transfer
+ * specified by provided parameters. The scatter-gather emulation is set up
+ * according to the parameters.
+ *
+ * The full preparation of the transfer requires setup of more register
+ * by the caller before imx_dma_enable() can be called.
+ *
+ * %BLR(dma_ch) holds transfer burst length in bytes, 0 means 64 bytes
+ *
+ * %RSSR(dma_ch) has to be set to the DMA request line source %DMA_REQ_xxx
+ *
+ * %CCR(dma_ch) has to specify transfer parameters, the next settings is typical
+ * for linear or simple scatter-gather transfers if %DMA_MODE_READ is specified
+ *
+ * %CCR_DMOD_LINEAR | %CCR_DSIZ_32 | %CCR_SMOD_FIFO | %CCR_SSIZ_x
+ *
+ * The typical setup for %DMA_MODE_WRITE is specified by next options combination
+ *
+ * %CCR_SMOD_LINEAR | %CCR_SSIZ_32 | %CCR_DMOD_FIFO | %CCR_DSIZ_x
+ *
+ * Be carefull there and do not mistakenly mix source and target device
+ * port sizes constants, they are really different:
+ * %CCR_SSIZ_8, %CCR_SSIZ_16, %CCR_SSIZ_32,
+ * %CCR_DSIZ_8, %CCR_DSIZ_16, %CCR_DSIZ_32
+ *
+ * Return value: if incorrect parameters are provided -%EINVAL.
+ * Zero indicates success.
+ */
+int
+imx_dma_setup_sg(imx_dmach_t dma_ch,
+ struct scatterlist *sg, unsigned int sgcount, unsigned int dma_length,
+ unsigned int dev_addr, dmamode_t dmamode)
+{
+ int res;
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+
+ imxdma->sg = NULL;
+ imxdma->sgcount = 0;
+ imxdma->dma_mode = dmamode;
+ imxdma->resbytes = dma_length;
+
+ if (!sg || !sgcount) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_sg epty sg list\n",
+ dma_ch);
+ return -EINVAL;
+ }
+
+ if (!sg->length) {
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_sg zero length\n",
+ dma_ch);
+ return -EINVAL;
}
- if (found) {
- DIMR &= ~(1 << i);
- dma_channels[i].name = name;
- dma_channels[i].irq_handler = irq_handler;
- dma_channels[i].err_handler = err_handler;
- dma_channels[i].data = data;
+ if ((dmamode & DMA_MODE_MASK) == DMA_MODE_READ) {
+ pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for read\n",
+ dma_ch, sg, sgcount, dma_length, dev_addr);
+ SAR(dma_ch) = dev_addr;
+ } else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
+ pr_debug("imxdma%d: mx_dma_setup_sg2dev sg=%p sgcount=%d total length=%d dev_addr=0x%08x for write\n",
+ dma_ch, sg, sgcount, dma_length, dev_addr);
+ DAR(dma_ch) = dev_addr;
} else {
- printk(KERN_WARNING "No more available DMA channels for %s\n",
- name);
- i = -ENODEV;
+ printk(KERN_ERR "imxdma%d: imx_dma_setup_sg bad dmamode\n",
+ dma_ch);
+ return -EINVAL;
+ }
+
+ res = imx_dma_setup_sg_base(dma_ch, sg, sgcount);
+ if (res <= 0) {
+ printk(KERN_ERR "imxdma%d: no sg chunk ready\n", dma_ch);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * imx_dma_setup_handlers - setup i.MX DMA channel end and error notification handlers
+ * @dma_ch: i.MX DMA channel number
+ * @irq_handler: the pointer to the function called if the transfer
+ * ends successfully
+ * @err_handler: the pointer to the function called if the premature
+ * end caused by error occurs
+ * @data: user specified value to be passed to the handlers
+ */
+int
+imx_dma_setup_handlers(imx_dmach_t dma_ch,
+ void (*irq_handler) (int, void *, struct pt_regs *),
+ void (*err_handler) (int, void *, struct pt_regs *),
+ void *data)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned long flags;
+
+ if (!imxdma->name) {
+ printk(KERN_CRIT "%s: called for not allocated channel %d\n",
+ __FUNCTION__, dma_ch);
+ return -ENODEV;
+ }
+
+ local_irq_save(flags);
+ DISR = (1 << dma_ch);
+ imxdma->irq_handler = irq_handler;
+ imxdma->err_handler = err_handler;
+ imxdma->data = data;
+ local_irq_restore(flags);
+ return 0;
+}
+
+/**
+ * imx_dma_enable - function to start i.MX DMA channel operation
+ * @dma_ch: i.MX DMA channel number
+ *
+ * The channel has to be allocated by driver through imx_dma_request()
+ * or imx_dma_request_by_prio() function.
+ * The transfer parameters has to be set to the channel registers through
+ * call of the imx_dma_setup_single() or imx_dma_setup_sg() function
+ * and registers %BLR(dma_ch), %RSSR(dma_ch) and %CCR(dma_ch) has to
+ * be set prior this function call by the channel user.
+ */
+void imx_dma_enable(imx_dmach_t dma_ch)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned long flags;
+
+ pr_debug("imxdma%d: imx_dma_enable\n", dma_ch);
+
+ if (!imxdma->name) {
+ printk(KERN_CRIT "%s: called for not allocated channel %d\n",
+ __FUNCTION__, dma_ch);
+ return;
+ }
+
+ local_irq_save(flags);
+ DISR = (1 << dma_ch);
+ DIMR &= ~(1 << dma_ch);
+ CCR(dma_ch) |= CCR_CEN;
+ local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_disable - stop, finish i.MX DMA channel operatin
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_disable(imx_dmach_t dma_ch)
+{
+ unsigned long flags;
+
+ pr_debug("imxdma%d: imx_dma_disable\n", dma_ch);
+
+ local_irq_save(flags);
+ DIMR |= (1 << dma_ch);
+ CCR(dma_ch) &= ~CCR_CEN;
+ DISR = (1 << dma_ch);
+ local_irq_restore(flags);
+}
+
+/**
+ * imx_dma_request - request/allocate specified channel number
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ */
+int imx_dma_request(imx_dmach_t dma_ch, const char *name)
+{
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
+ unsigned long flags;
+
+ /* basic sanity checks */
+ if (!name)
+ return -EINVAL;
+
+ if (dma_ch >= IMX_DMA_CHANNELS) {
+ printk(KERN_CRIT "%s: called for non-existed channel %d\n",
+ __FUNCTION__, dma_ch);
+ return -EINVAL;
}
+ local_irq_save(flags);
+ if (imxdma->name) {
+ local_irq_restore(flags);
+ return -ENODEV;
+ }
+
+ imxdma->name = name;
+ imxdma->irq_handler = NULL;
+ imxdma->err_handler = NULL;
+ imxdma->data = NULL;
+ imxdma->sg = NULL;
local_irq_restore(flags);
- return i;
+ return 0;
}
-void
-imx_free_dma(int dma_ch)
+/**
+ * imx_dma_free - release previously acquired channel
+ * @dma_ch: i.MX DMA channel number
+ */
+void imx_dma_free(imx_dmach_t dma_ch)
{
unsigned long flags;
+ struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
- if (!dma_channels[dma_ch].name) {
+ if (!imxdma->name) {
printk(KERN_CRIT
"%s: trying to free channel %d which is already freed\n",
__FUNCTION__, dma_ch);
@@ -92,27 +398,84 @@ imx_free_dma(int dma_ch)
}
local_irq_save(flags);
- DIMR &= ~(1 << dma_ch);
- dma_channels[dma_ch].name = NULL;
+ /* Disable interrupts */
+ DIMR |= (1 << dma_ch);
+ CCR(dma_ch) &= ~CCR_CEN;
+ imxdma->name = NULL;
local_irq_restore(flags);
}
-static irqreturn_t
-dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
+/**
+ * imx_dma_request_by_prio - find and request some of free channels best suiting requested priority
+ * @dma_ch: i.MX DMA channel number
+ * @name: the driver/caller own non-%NULL identification
+ * @prio: one of the hardware distinguished priority level:
+ * %DMA_PRIO_HIGH, %DMA_PRIO_MEDIUM, %DMA_PRIO_LOW
+ *
+ * This function tries to find free channel in the specified priority group
+ * if the priority cannot be achieved it tries to look for free channel
+ * in the higher and then even lower priority groups.
+ *
+ * Return value: If there is no free channel to allocate, -%ENODEV is returned.
+ * Zero value indicates successful channel allocation.
+ */
+int
+imx_dma_request_by_prio(imx_dmach_t * pdma_ch, const char *name,
+ imx_dma_prio prio)
+{
+ int i;
+ int best;
+
+ switch (prio) {
+ case (DMA_PRIO_HIGH):
+ best = 8;
+ break;
+ case (DMA_PRIO_MEDIUM):
+ best = 4;
+ break;
+ case (DMA_PRIO_LOW):
+ default:
+ best = 0;
+ break;
+ }
+
+ for (i = best; i < IMX_DMA_CHANNELS; i++) {
+ if (!imx_dma_request(i, name)) {
+ *pdma_ch = i;
+ return 0;
+ }
+ }
+
+ for (i = best - 1; i >= 0; i--) {
+ if (!imx_dma_request(i, name)) {
+ *pdma_ch = i;
+ return 0;
+ }
+ }
+
+ printk(KERN_ERR "%s: no free DMA channel found\n", __FUNCTION__);
+
+ return -ENODEV;
+}
+
+static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
- struct dma_channel *channel;
+ struct imx_dma_channel *channel;
unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
DISR = disr;
- for (i = 0; i < 11; i++) {
- channel = &dma_channels[i];
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+ channel = &imx_dma_channels[i];
- if ( (err_mask & 1<<i) && channel->name && channel->err_handler) {
+ if ((err_mask & 1 << i) && channel->name
+ && channel->err_handler) {
channel->err_handler(i, channel->data, regs);
continue;
}
+ imx_dma_channels[i].sg = NULL;
+
if (DBTOSR & (1 << i)) {
printk(KERN_WARNING
"Burst timeout on channel %d (%s)\n",
@@ -141,17 +504,27 @@ dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static irqreturn_t
-dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
+ pr_debug("imxdma: dma_irq_handler called, disr=0x%08x\n",
+ disr);
+
DISR = disr;
- for (i = 0; i < 11; i++) {
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
if (disr & (1 << i)) {
- struct dma_channel *channel = &dma_channels[i];
- if (channel->name && channel->irq_handler) {
- channel->irq_handler(i, channel->data, regs);
+ struct imx_dma_channel *channel = &imx_dma_channels[i];
+ if (channel->name) {
+ if (imx_dma_sg_next(i, CNTR(i))) {
+ CCR(i) &= ~CCR_CEN;
+ mb();
+ CCR(i) |= CCR_CEN;
+ } else {
+ if (channel->irq_handler)
+ channel->irq_handler(i,
+ channel->data, regs);
+ }
} else {
/*
* IRQ for an unregistered DMA channel:
@@ -165,10 +538,10 @@ dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static int __init
-imx_dma_init(void)
+static int __init imx_dma_init(void)
{
int ret;
+ int i;
/* reset DMA module */
DCR = DCR_DRST;
@@ -189,15 +562,27 @@ imx_dma_init(void)
DCR = DCR_DEN;
/* clear all interrupts */
- DISR = 0x3ff;
+ DISR = (1 << IMX_DMA_CHANNELS) - 1;
/* enable interrupts */
- DIMR = 0;
+ DIMR = (1 << IMX_DMA_CHANNELS) - 1;
+
+ for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+ imx_dma_channels[i].sg = NULL;
+ imx_dma_channels[i].dma_num = i;
+ }
return ret;
}
arch_initcall(imx_dma_init);
-EXPORT_SYMBOL(imx_request_dma);
-EXPORT_SYMBOL(imx_free_dma);
+EXPORT_SYMBOL(imx_dma_setup_single);
+EXPORT_SYMBOL(imx_dma_setup_sg);
+EXPORT_SYMBOL(imx_dma_setup_handlers);
+EXPORT_SYMBOL(imx_dma_enable);
+EXPORT_SYMBOL(imx_dma_disable);
+EXPORT_SYMBOL(imx_dma_request);
+EXPORT_SYMBOL(imx_dma_free);
+EXPORT_SYMBOL(imx_dma_request_by_prio);
+EXPORT_SYMBOL(imx_dma_channels);
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index 8ab1b040288..e34d0df90ae 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -25,6 +25,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/arch/mmc.h>
#include <linux/interrupt.h>
#include "generic.h"
@@ -51,12 +52,29 @@ static struct platform_device *devices[] __initdata = {
&cs89x0_device,
};
+#ifdef CONFIG_MMC_IMX
+static int mx1ads_mmc_card_present(void)
+{
+ /* MMC/SD Card Detect is PB 20 on MX1ADS V1.0.7 */
+ return (SSR(1) & (1 << 20) ? 0 : 1);
+}
+
+static struct imxmmc_platform_data mx1ads_mmc_info = {
+ .card_present = mx1ads_mmc_card_present,
+};
+#endif
+
static void __init
mx1ads_init(void)
{
#ifdef CONFIG_LEDS
imx_gpio_mode(GPIO_PORTA | GPIO_OUT | 2);
#endif
+#ifdef CONFIG_MMC_IMX
+ /* SD/MMC card detect */
+ imx_gpio_mode(GPIO_PORTB | GPIO_GIUS | GPIO_IN | 20);
+ imx_set_mmc_info(&mx1ads_mmc_info);
+#endif
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
index 2327c979041..bf688c12863 100644
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -44,6 +44,15 @@
#include <asm/mach/irq.h>
#include <asm/mach/pci.h>
+static int __init espresso_pci_init(void)
+{
+ if (machine_is_espresso())
+ ixp23xx_pci_slave_init();
+
+ return 0;
+};
+subsys_initcall(espresso_pci_init);
+
static void __init espresso_init(void)
{
physmap_configure(0x90000000, 0x02000000, 2, NULL);
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c
index 5330ad78c1b..ac72f94c5b4 100644
--- a/arch/arm/mach-ixp23xx/pci.c
+++ b/arch/arm/mach-ixp23xx/pci.c
@@ -201,7 +201,7 @@ int clear_master_aborts(void)
return 0;
}
-void __init ixp23xx_pci_preinit(void)
+static void __init ixp23xx_pci_common_init(void)
{
#ifdef __ARMEB__
*IXP23XX_PCI_CONTROL |= 0x20000; /* set I/O swapping */
@@ -219,7 +219,18 @@ void __init ixp23xx_pci_preinit(void)
*IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
} else {
*IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
+
+ /*
+ * Enable coherency on A2 silicon.
+ */
+ if (arch_is_coherent())
+ *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF;
}
+}
+
+void __init ixp23xx_pci_preinit(void)
+{
+ ixp23xx_pci_common_init();
hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS,
"PCI config cycle to non-existent device");
@@ -273,3 +284,8 @@ int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
return 1;
}
+
+void ixp23xx_pci_slave_init(void)
+{
+ ixp23xx_pci_common_init();
+}
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index 86a0f0d1434..f8d716ccc1d 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -69,12 +69,6 @@ config MACH_VOICEBLUE
Support for Voiceblue GSM/VoIP gateway. Say Y here if you have
such a board.
-config MACH_NETSTAR
- bool "NetStar"
- depends on ARCH_OMAP1 && ARCH_OMAP15XX
- help
- Support for NetStar PBX. Say Y here if you have such a board.
-
config MACH_OMAP_PALMTE
bool "Palm Tungsten E"
depends on ARCH_OMAP1 && ARCH_OMAP15XX
@@ -85,6 +79,20 @@ config MACH_OMAP_PALMTE
informations.
Say Y here if you have such a PDA, say NO otherwise.
+config MACH_NOKIA770
+ bool "Nokia 770"
+ depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ help
+ Support for the Nokia 770 Internet Tablet. Say Y here if you
+ have such a device.
+
+config MACH_AMS_DELTA
+ bool "Amstrad E3 (Delta)"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Amstrad E3 (codename Delta) videophone. Say Y here
+ if you have such a device.
+
config MACH_OMAP_GENERIC
bool "Generic OMAP board"
depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index b0b00156faa..9ea719550ad 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -3,7 +3,13 @@
#
# Common support
-obj-y := io.o id.o clock.o irq.o time.o mux.o serial.o devices.o
+obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o
+
+obj-$(CONFIG_OMAP_MPU_TIMER) += time.o
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
led-y := leds.o
# Specific board support
@@ -14,8 +20,9 @@ obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
-obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o
obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
+obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o
+obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o
ifeq ($(CONFIG_ARCH_OMAP15XX),y)
# Innovator-1510 FPGA
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
new file mode 100644
index 00000000000..6178f046f12
--- /dev/null
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/mach-omap1/board-ams-delta.c
+ *
+ * Modified from board-generic.c
+ *
+ * Board specific inits for the Amstrad E3 (codename Delta) videophone
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board-ams-delta.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+
+static u8 ams_delta_latch1_reg;
+static u16 ams_delta_latch2_reg;
+
+void ams_delta_latch1_write(u8 mask, u8 value)
+{
+ ams_delta_latch1_reg &= ~mask;
+ ams_delta_latch1_reg |= value;
+ *(volatile __u8 *) AMS_DELTA_LATCH1_VIRT = ams_delta_latch1_reg;
+}
+
+void ams_delta_latch2_write(u16 mask, u16 value)
+{
+ ams_delta_latch2_reg &= ~mask;
+ ams_delta_latch2_reg |= value;
+ *(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg;
+}
+
+static void __init ams_delta_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
+}
+
+static struct map_desc ams_delta_io_desc[] __initdata = {
+ // AMS_DELTA_LATCH1
+ {
+ .virtual = AMS_DELTA_LATCH1_VIRT,
+ .pfn = __phys_to_pfn(AMS_DELTA_LATCH1_PHYS),
+ .length = 0x01000000,
+ .type = MT_DEVICE
+ },
+ // AMS_DELTA_LATCH2
+ {
+ .virtual = AMS_DELTA_LATCH2_VIRT,
+ .pfn = __phys_to_pfn(AMS_DELTA_LATCH2_PHYS),
+ .length = 0x01000000,
+ .type = MT_DEVICE
+ },
+ // AMS_DELTA_MODEM
+ {
+ .virtual = AMS_DELTA_MODEM_VIRT,
+ .pfn = __phys_to_pfn(AMS_DELTA_MODEM_PHYS),
+ .length = 0x01000000,
+ .type = MT_DEVICE
+ }
+};
+
+static struct omap_uart_config ams_delta_uart_config __initdata = {
+ .enabled_uarts = 1,
+};
+
+static struct omap_board_config_kernel ams_delta_config[] = {
+ { OMAP_TAG_UART, &ams_delta_uart_config },
+};
+
+static void __init ams_delta_init(void)
+{
+ iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
+
+ omap_board_config = ams_delta_config;
+ omap_board_config_size = ARRAY_SIZE(ams_delta_config);
+ omap_serial_init();
+
+ /* Clear latch2 (NAND, LCD, modem enable) */
+ ams_delta_latch2_write(~0, 0);
+}
+
+static void __init ams_delta_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
+ /* Maintainer: Jonathan McDowell <noodles@earth.li> */
+ .phys_io = 0xfff00000,
+ .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
+ .boot_params = 0x10000100,
+ .map_io = ams_delta_map_io,
+ .init_irq = ams_delta_init_irq,
+ .init_machine = ams_delta_init,
+ .timer = &omap_timer,
+MACHINE_END
+
+EXPORT_SYMBOL(ams_delta_latch1_write);
+EXPORT_SYMBOL(ams_delta_latch2_write);
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index a177e78b2b8..33d01adab1e 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -88,7 +88,7 @@ static struct omap_board_config_kernel generic_config[] = {
static void __init omap_generic_init(void)
{
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
generic_config[0].data = &generic1510_usb_config;
}
#endif
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 89f0cc74a51..cd3a06dfc0a 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -24,7 +24,9 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -35,12 +37,55 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
#include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
extern int omap_gpio_init(void);
-static struct mtd_partition h2_partitions[] = {
+static int h2_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_3),
+ KEY(0, 3, KEY_F10),
+ KEY(0, 4, KEY_F5),
+ KEY(0, 5, KEY_9),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_2),
+ KEY(1, 3, KEY_F9),
+ KEY(1, 4, KEY_F7),
+ KEY(1, 5, KEY_0),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_6),
+ KEY(2, 2, KEY_1),
+ KEY(2, 3, KEY_F2),
+ KEY(2, 4, KEY_F6),
+ KEY(2, 5, KEY_HOME),
+ KEY(3, 0, KEY_8),
+ KEY(3, 1, KEY_5),
+ KEY(3, 2, KEY_F12),
+ KEY(3, 3, KEY_F3),
+ KEY(3, 4, KEY_F8),
+ KEY(3, 5, KEY_END),
+ KEY(4, 0, KEY_7),
+ KEY(4, 1, KEY_4),
+ KEY(4, 2, KEY_F11),
+ KEY(4, 3, KEY_F1),
+ KEY(4, 4, KEY_F4),
+ KEY(4, 5, KEY_ESC),
+ KEY(5, 0, KEY_F13),
+ KEY(5, 1, KEY_F14),
+ KEY(5, 2, KEY_F15),
+ KEY(5, 3, KEY_F16),
+ KEY(5, 4, KEY_SLEEP),
+ 0
+};
+
+static struct mtd_partition h2_nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
@@ -71,26 +116,26 @@ static struct mtd_partition h2_partitions[] = {
}
};
-static struct flash_platform_data h2_flash_data = {
+static struct flash_platform_data h2_nor_data = {
.map_name = "cfi_probe",
.width = 2,
- .parts = h2_partitions,
- .nr_parts = ARRAY_SIZE(h2_partitions),
+ .parts = h2_nor_partitions,
+ .nr_parts = ARRAY_SIZE(h2_nor_partitions),
};
-static struct resource h2_flash_resource = {
+static struct resource h2_nor_resource = {
/* This is on CS3, wherever it's mapped */
.flags = IORESOURCE_MEM,
};
-static struct platform_device h2_flash_device = {
+static struct platform_device h2_nor_device = {
.name = "omapflash",
.id = 0,
.dev = {
- .platform_data = &h2_flash_data,
+ .platform_data = &h2_nor_data,
},
.num_resources = 1,
- .resource = &h2_flash_resource,
+ .resource = &h2_nor_resource,
};
static struct resource h2_smc91x_resources[] = {
@@ -113,9 +158,119 @@ static struct platform_device h2_smc91x_device = {
.resource = h2_smc91x_resources,
};
+static struct resource h2_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data h2_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = h2_keymap,
+ .rep = 1,
+};
+
+static struct platform_device h2_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &h2_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(h2_kp_resources),
+ .resource = h2_kp_resources,
+};
+
+#define H2_IRDA_FIRSEL_GPIO_PIN 17
+
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+static int h2_transceiver_mode(struct device *dev, int state)
+{
+ if (state & IR_SIRMODE)
+ omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+ else /* MIR/FIR */
+ omap_set_gpio_dataout(H2_IRDA_FIRSEL_GPIO_PIN, 1);
+
+ return 0;
+}
+#endif
+
+static struct omap_irda_config h2_irda_data = {
+ .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource h2_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct platform_device h2_irda_device = {
+ .name = "omapirda",
+ .id = 0,
+ .dev = {
+ .platform_data = &h2_irda_data,
+ },
+ .num_resources = ARRAY_SIZE(h2_irda_resources),
+ .resource = h2_irda_resources,
+};
+
+static struct platform_device h2_lcd_device = {
+ .name = "lcd_h2",
+ .id = -1,
+};
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+ .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ .spcr1 = RINTM(3) | RRST,
+ .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+ RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
+ .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+ XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
+ .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr1 = FWID(15),
+ .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
+
+ .pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
+ //.pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+ .name = "H2 TSC2101",
+ .mcbsp_regs_alsa = &mcbsp_regs,
+ .codec_configure_dev = NULL, // tsc2101_configure,
+ .codec_set_samplerate = NULL, // tsc2101_set_samplerate,
+ .codec_clock_setup = NULL, // tsc2101_clock_setup,
+ .codec_clock_on = NULL, // tsc2101_clock_on,
+ .codec_clock_off = NULL, // tsc2101_clock_off,
+ .get_default_samplerate = NULL, // tsc2101_get_default_samplerate,
+};
+
+static struct platform_device h2_mcbsp1_device = {
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &alsa_config,
+ },
+};
+
static struct platform_device *h2_devices[] __initdata = {
- &h2_flash_device,
+ &h2_nor_device,
&h2_smc91x_device,
+ &h2_irda_device,
+ &h2_kp_device,
+ &h2_lcd_device,
+ &h2_mcbsp1_device,
};
static void __init h2_init_smc91x(void)
@@ -164,7 +319,6 @@ static struct omap_uart_config h2_uart_config __initdata = {
};
static struct omap_lcd_config h2_lcd_config __initdata = {
- .panel_name = "h2",
.ctrl_name = "internal",
};
@@ -177,16 +331,34 @@ static struct omap_board_config_kernel h2_config[] = {
static void __init h2_init(void)
{
- /* NOTE: revC boards support NAND-boot, which can put NOR on CS2B
- * and NAND (either 16bit or 8bit) on CS3.
+ /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped
+ * to address 0 by a dip switch), NAND on CS2B. The NAND driver will
+ * notice whether a NAND chip is enabled at probe time.
+ *
+ * FIXME revC boards (and H3) support NAND-boot, with a dip switch to
+ * put NOR on CS2B and NAND (which on H2 may be 16bit) on CS3. Try
+ * detecting that in code here, to avoid probing every possible flash
+ * configuration...
*/
- h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys();
- h2_flash_resource.end += SZ_32M - 1;
+ h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
+ h2_nor_resource.end += SZ_32M - 1;
+
+ omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+ omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
/* MMC: card detect and WP */
// omap_cfg_reg(U19_ARMIO1); /* CD */
omap_cfg_reg(BALLOUT_V8_ARMIO3); /* WP */
+ /* Irda */
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+ omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7, FUNC_MUX_CTRL_A);
+ if (!(omap_request_gpio(H2_IRDA_FIRSEL_GPIO_PIN))) {
+ omap_set_gpio_direction(H2_IRDA_FIRSEL_GPIO_PIN, 0);
+ h2_irda_data.transceiver_mode = h2_transceiver_mode;
+ }
+#endif
+
platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
omap_board_config = h2_config;
omap_board_config_size = ARRAY_SIZE(h2_config);
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index d9f38626599..4b8d0ec73cb 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -21,8 +21,11 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
+#include <linux/workqueue.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/setup.h>
#include <asm/page.h>
@@ -33,15 +36,59 @@
#include <asm/mach/map.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
#include <asm/arch/irqs.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/irda.h>
#include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/dma.h>
#include <asm/arch/common.h>
extern int omap_gpio_init(void);
-static struct mtd_partition h3_partitions[] = {
+static int h3_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_3),
+ KEY(0, 3, KEY_F10),
+ KEY(0, 4, KEY_F5),
+ KEY(0, 5, KEY_9),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_2),
+ KEY(1, 3, KEY_F9),
+ KEY(1, 4, KEY_F7),
+ KEY(1, 5, KEY_0),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_6),
+ KEY(2, 2, KEY_1),
+ KEY(2, 3, KEY_F2),
+ KEY(2, 4, KEY_F6),
+ KEY(2, 5, KEY_HOME),
+ KEY(3, 0, KEY_8),
+ KEY(3, 1, KEY_5),
+ KEY(3, 2, KEY_F12),
+ KEY(3, 3, KEY_F3),
+ KEY(3, 4, KEY_F8),
+ KEY(3, 5, KEY_END),
+ KEY(4, 0, KEY_7),
+ KEY(4, 1, KEY_4),
+ KEY(4, 2, KEY_F11),
+ KEY(4, 3, KEY_F1),
+ KEY(4, 4, KEY_F4),
+ KEY(4, 5, KEY_ESC),
+ KEY(5, 0, KEY_F13),
+ KEY(5, 1, KEY_F14),
+ KEY(5, 2, KEY_F15),
+ KEY(5, 3, KEY_F16),
+ KEY(5, 4, KEY_SLEEP),
+ 0
+};
+
+
+static struct mtd_partition nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
@@ -72,26 +119,80 @@ static struct mtd_partition h3_partitions[] = {
}
};
-static struct flash_platform_data h3_flash_data = {
+static struct flash_platform_data nor_data = {
.map_name = "cfi_probe",
.width = 2,
- .parts = h3_partitions,
- .nr_parts = ARRAY_SIZE(h3_partitions),
+ .parts = nor_partitions,
+ .nr_parts = ARRAY_SIZE(nor_partitions),
};
-static struct resource h3_flash_resource = {
+static struct resource nor_resource = {
/* This is on CS3, wherever it's mapped */
.flags = IORESOURCE_MEM,
};
-static struct platform_device flash_device = {
+static struct platform_device nor_device = {
.name = "omapflash",
.id = 0,
.dev = {
- .platform_data = &h3_flash_data,
+ .platform_data = &nor_data,
+ },
+ .num_resources = 1,
+ .resource = &nor_resource,
+};
+
+static struct mtd_partition nand_partitions[] = {
+#if 0
+ /* REVISIT: enable these partitions if you make NAND BOOT work */
+ {
+ .name = "xloader",
+ .offset = 0,
+ .size = 64 * 1024,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "bootloader",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 192 * 1024,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 2 * SZ_1M,
+ },
+#endif
+ {
+ .name = "filesystem",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ },
+};
+
+/* dip switches control NAND chip access: 8 bit, 16 bit, or neither */
+static struct nand_platform_data nand_data = {
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+ .parts = nand_partitions,
+ .nr_parts = ARRAY_SIZE(nand_partitions),
+};
+
+static struct resource nand_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+ .name = "omapnand",
+ .id = 0,
+ .dev = {
+ .platform_data = &nand_data,
},
.num_resources = 1,
- .resource = &h3_flash_resource,
+ .resource = &nand_resource,
};
static struct resource smc91x_resources[] = {
@@ -138,10 +239,136 @@ static struct platform_device intlat_device = {
.resource = intlat_resources,
};
+static struct resource h3_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data h3_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = h3_keymap,
+ .rep = 1,
+};
+
+static struct platform_device h3_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &h3_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(h3_kp_resources),
+ .resource = h3_kp_resources,
+};
+
+
+/* Select between the IrDA and aGPS module
+ */
+static int h3_select_irda(struct device *dev, int state)
+{
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x26))) {
+ printk(KERN_ERR "Error reading from I/O EXPANDER \n");
+ return err;
+ }
+
+ /* 'P6' enable/disable IRDA_TX and IRDA_RX */
+ if (state & IR_SEL) { /* IrDA */
+ if ((err = write_gpio_expa(expa | 0x40, 0x26))) {
+ printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+ return err;
+ }
+ } else {
+ if ((err = write_gpio_expa(expa & ~0x40, 0x26))) {
+ printk(KERN_ERR "Error writing to I/O EXPANDER \n");
+ return err;
+ }
+ }
+ return err;
+}
+
+static void set_trans_mode(void *data)
+{
+ int *mode = data;
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x27)) != 0) {
+ printk(KERN_ERR "Error reading from I/O expander\n");
+ }
+
+ expa &= ~0x03;
+
+ if (*mode & IR_SIRMODE) {
+ expa |= 0x01;
+ } else { /* MIR/FIR */
+ expa |= 0x03;
+ }
+
+ if ((err = write_gpio_expa(expa, 0x27)) != 0) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ }
+}
+
+static int h3_transceiver_mode(struct device *dev, int mode)
+{
+ struct omap_irda_config *irda_config = dev->platform_data;
+
+ cancel_delayed_work(&irda_config->gpio_expa);
+ PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+ schedule_work(&irda_config->gpio_expa);
+
+ return 0;
+}
+
+static struct omap_irda_config h3_irda_data = {
+ .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+ .transceiver_mode = h3_transceiver_mode,
+ .select_irda = h3_select_irda,
+ .rx_channel = OMAP_DMA_UART3_RX,
+ .tx_channel = OMAP_DMA_UART3_TX,
+ .dest_start = UART3_THR,
+ .src_start = UART3_RHR,
+ .tx_trigger = 0,
+ .rx_trigger = 0,
+};
+
+static struct resource h3_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device h3_irda_device = {
+ .name = "omapirda",
+ .id = 0,
+ .dev = {
+ .platform_data = &h3_irda_data,
+ },
+ .num_resources = ARRAY_SIZE(h3_irda_resources),
+ .resource = h3_irda_resources,
+};
+
+static struct platform_device h3_lcd_device = {
+ .name = "lcd_h3",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
- &flash_device,
+ &nor_device,
+ &nand_device,
&smc91x_device,
&intlat_device,
+ &h3_irda_device,
+ &h3_kp_device,
+ &h3_lcd_device,
};
static struct omap_usb_config h3_usb_config __initdata = {
@@ -171,7 +398,6 @@ static struct omap_uart_config h3_uart_config __initdata = {
};
static struct omap_lcd_config h3_lcd_config __initdata = {
- .panel_name = "h3",
.ctrl_name = "internal",
};
@@ -182,11 +408,36 @@ static struct omap_board_config_kernel h3_config[] = {
{ OMAP_TAG_LCD, &h3_lcd_config },
};
+#define H3_NAND_RB_GPIO_PIN 10
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+ return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN);
+}
+
static void __init h3_init(void)
{
- h3_flash_resource.end = h3_flash_resource.start = omap_cs3_phys();
- h3_flash_resource.end += OMAP_CS3_SIZE - 1;
- (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+ /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped
+ * to address 0 by a dip switch), NAND on CS2B. The NAND driver will
+ * notice whether a NAND chip is enabled at probe time.
+ *
+ * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND
+ * (which on H2 may be 16bit) on CS3. Try detecting that in code here,
+ * to avoid probing every possible flash configuration...
+ */
+ nor_resource.end = nor_resource.start = omap_cs3_phys();
+ nor_resource.end += SZ_32M - 1;
+
+ nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS;
+ nand_resource.end += SZ_4K - 1;
+ if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN)))
+ nand_data.dev_ready = nand_dev_ready;
+
+ /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
+ /* GPIO10 pullup/down register, Enable pullup on GPIO10 */
+ omap_cfg_reg(V2_1710_GPIO10);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
omap_board_config = h3_config;
omap_board_config_size = ARRAY_SIZE(h3_config);
omap_serial_init();
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index a04e4332915..e90c137a4cf 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -34,8 +35,22 @@
#include <asm/arch/gpio.h>
#include <asm/arch/tc.h>
#include <asm/arch/usb.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+static int innovator_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(0, 3, KEY_DOWN),
+ KEY(1, 1, KEY_F2),
+ KEY(1, 2, KEY_RIGHT),
+ KEY(2, 0, KEY_F3),
+ KEY(2, 1, KEY_F4),
+ KEY(2, 2, KEY_UP),
+ KEY(3, 2, KEY_ENTER),
+ KEY(3, 3, KEY_LEFT),
+ 0
+};
+
static struct mtd_partition innovator_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
@@ -97,6 +112,31 @@ static struct platform_device innovator_flash_device = {
.resource = &innovator_flash_resource,
};
+static struct resource innovator_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data innovator_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = innovator_keymap,
+};
+
+static struct platform_device innovator_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &innovator_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(innovator_kp_resources),
+ .resource = innovator_kp_resources,
+};
+
+
#ifdef CONFIG_ARCH_OMAP15XX
/* Only FPGA needs to be mapped here. All others are done with ioremap */
@@ -129,9 +169,16 @@ static struct platform_device innovator1510_smc91x_device = {
.resource = innovator1510_smc91x_resources,
};
+static struct platform_device innovator1510_lcd_device = {
+ .name = "lcd_inn1510",
+ .id = -1,
+};
+
static struct platform_device *innovator1510_devices[] __initdata = {
&innovator_flash_device,
&innovator1510_smc91x_device,
+ &innovator_kp_device,
+ &innovator1510_lcd_device,
};
#endif /* CONFIG_ARCH_OMAP15XX */
@@ -158,9 +205,16 @@ static struct platform_device innovator1610_smc91x_device = {
.resource = innovator1610_smc91x_resources,
};
+static struct platform_device innovator1610_lcd_device = {
+ .name = "inn1610_lcd",
+ .id = -1,
+};
+
static struct platform_device *innovator1610_devices[] __initdata = {
&innovator_flash_device,
&innovator1610_smc91x_device,
+ &innovator_kp_device,
+ &innovator1610_lcd_device,
};
#endif /* CONFIG_ARCH_OMAP16XX */
@@ -206,7 +260,6 @@ static struct omap_usb_config innovator1510_usb_config __initdata = {
};
static struct omap_lcd_config innovator1510_lcd_config __initdata = {
- .panel_name = "inn1510",
.ctrl_name = "internal",
};
#endif
@@ -228,7 +281,6 @@ static struct omap_usb_config h2_usb_config __initdata = {
};
static struct omap_lcd_config innovator1610_lcd_config __initdata = {
- .panel_name = "inn1610",
.ctrl_name = "internal",
};
#endif
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
deleted file mode 100644
index 7520e602d7a..00000000000
--- a/arch/arm/mach-omap1/board-netstar.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Modified from board-generic.c
- *
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Code for Netstar OMAP board.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <asm/arch/gpio.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/usb.h>
-#include <asm/arch/common.h>
-
-extern void __init omap_init_time(void);
-extern int omap_gpio_init(void);
-
-static struct resource netstar_smc91x_resources[] = {
- [0] = {
- .start = OMAP_CS1_PHYS + 0x300,
- .end = OMAP_CS1_PHYS + 0x300 + 16,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = OMAP_GPIO_IRQ(8),
- .end = OMAP_GPIO_IRQ(8),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device netstar_smc91x_device = {
- .name = "smc91x",
- .id = 0,
- .num_resources = ARRAY_SIZE(netstar_smc91x_resources),
- .resource = netstar_smc91x_resources,
-};
-
-static struct platform_device *netstar_devices[] __initdata = {
- &netstar_smc91x_device,
-};
-
-static struct omap_uart_config netstar_uart_config __initdata = {
- .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
-};
-
-static struct omap_board_config_kernel netstar_config[] = {
- { OMAP_TAG_UART, &netstar_uart_config },
-};
-
-static void __init netstar_init_irq(void)
-{
- omap1_init_common_hw();
- omap_init_irq();
- omap_gpio_init();
-}
-
-static void __init netstar_init(void)
-{
- /* green LED */
- omap_request_gpio(4);
- omap_set_gpio_direction(4, 0);
- /* smc91x reset */
- omap_request_gpio(7);
- omap_set_gpio_direction(7, 0);
- omap_set_gpio_dataout(7, 1);
- udelay(2); /* wait at least 100ns */
- omap_set_gpio_dataout(7, 0);
- mdelay(50); /* 50ms until PHY ready */
- /* smc91x interrupt pin */
- omap_request_gpio(8);
-
- omap_request_gpio(12);
- omap_request_gpio(13);
- omap_request_gpio(14);
- omap_request_gpio(15);
- set_irq_type(OMAP_GPIO_IRQ(12), IRQT_FALLING);
- set_irq_type(OMAP_GPIO_IRQ(13), IRQT_FALLING);
- set_irq_type(OMAP_GPIO_IRQ(14), IRQT_FALLING);
- set_irq_type(OMAP_GPIO_IRQ(15), IRQT_FALLING);
-
- platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices));
-
- /* Switch on green LED */
- omap_set_gpio_dataout(4, 0);
- /* Switch off red LED */
- omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */
- omap_writeb(0x80, OMAP_LPG1_LCR);
-
- omap_board_config = netstar_config;
- omap_board_config_size = ARRAY_SIZE(netstar_config);
- omap_serial_init();
-}
-
-static void __init netstar_map_io(void)
-{
- omap1_map_common_io();
-}
-
-#define MACHINE_PANICED 1
-#define MACHINE_REBOOTING 2
-#define MACHINE_REBOOT 4
-static unsigned long machine_state;
-
-static int panic_event(struct notifier_block *this, unsigned long event,
- void *ptr)
-{
- if (test_and_set_bit(MACHINE_PANICED, &machine_state))
- return NOTIFY_DONE;
-
- /* Switch off green LED */
- omap_set_gpio_dataout(4, 1);
- /* Flash red LED */
- omap_writeb(0x78, OMAP_LPG1_LCR);
- omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block panic_block = {
- .notifier_call = panic_event,
-};
-
-static int __init netstar_late_init(void)
-{
- /* TODO: Setup front panel switch here */
-
- /* Setup panic notifier */
- atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
-
- return 0;
-}
-
-postcore_initcall(netstar_late_init);
-
-MACHINE_START(NETSTAR, "NetStar OMAP5910")
- /* Maintainer: Ladislav Michl <michl@2n.cz> */
- .phys_io = 0xfff00000,
- .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
- .boot_params = 0x10000100,
- .map_io = netstar_map_io,
- .init_irq = netstar_init_irq,
- .init_machine = netstar_init,
- .timer = &omap_timer,
-MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
new file mode 100644
index 00000000000..02b980d77b1
--- /dev/null
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -0,0 +1,268 @@
+/*
+ * linux/arch/arm/mach-omap1/board-nokia770.c
+ *
+ * Modified from board-generic.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/common.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/aic23.h>
+#include <asm/arch/gpio.h>
+
+static void __init omap_nokia770_init_irq(void)
+{
+ /* On Nokia 770, the SleepX signal is masked with an
+ * MPUIO line by default. It has to be unmasked for it
+ * to become functional */
+
+ /* SleepX mask direction */
+ omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008);
+ /* Unmask SleepX signal */
+ omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004);
+
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static int nokia770_keymap[] = {
+ KEY(0, 1, GROUP_0 | KEY_UP),
+ KEY(0, 2, GROUP_1 | KEY_F5),
+ KEY(1, 0, GROUP_0 | KEY_LEFT),
+ KEY(1, 1, GROUP_0 | KEY_ENTER),
+ KEY(1, 2, GROUP_0 | KEY_RIGHT),
+ KEY(2, 0, GROUP_1 | KEY_ESC),
+ KEY(2, 1, GROUP_0 | KEY_DOWN),
+ KEY(2, 2, GROUP_1 | KEY_F4),
+ KEY(3, 0, GROUP_2 | KEY_F7),
+ KEY(3, 1, GROUP_2 | KEY_F8),
+ KEY(3, 2, GROUP_2 | KEY_F6),
+ 0
+};
+
+static struct resource nokia770_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data nokia770_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = nokia770_keymap
+};
+
+static struct platform_device nokia770_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &nokia770_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(nokia770_kp_resources),
+ .resource = nokia770_kp_resources,
+};
+
+static struct platform_device *nokia770_devices[] __initdata = {
+ &nokia770_kp_device,
+};
+
+static struct ads7846_platform_data nokia770_ads7846_platform_data __initdata = {
+ .x_max = 0x0fff,
+ .y_max = 0x0fff,
+ .x_plate_ohms = 180,
+ .pressure_max = 255,
+ .debounce_max = 10,
+ .debounce_tol = 3,
+};
+
+static struct spi_board_info nokia770_spi_board_info[] __initdata = {
+ [0] = {
+ .modalias = "lcd_lph8923",
+ .bus_num = 2,
+ .chip_select = 3,
+ .max_speed_hz = 12000000,
+ },
+ [1] = {
+ .modalias = "ads7846",
+ .bus_num = 2,
+ .chip_select = 0,
+ .max_speed_hz = 2500000,
+ .irq = OMAP_GPIO_IRQ(15),
+ .platform_data = &nokia770_ads7846_platform_data,
+ },
+};
+
+
+/* assume no Mini-AB port */
+
+static struct omap_usb_config nokia770_usb_config __initdata = {
+ .otg = 1,
+ .register_host = 1,
+ .register_dev = 1,
+ .hmc_mode = 16,
+ .pins[0] = 6,
+};
+
+static struct omap_mmc_config nokia770_mmc_config __initdata = {
+ .mmc[0] = {
+ .enabled = 0,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1,
+ .switch_pin = -1,
+ },
+ .mmc[1] = {
+ .enabled = 0,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1,
+ .switch_pin = -1,
+ },
+};
+
+static struct omap_board_config_kernel nokia770_config[] = {
+ { OMAP_TAG_USB, NULL },
+ { OMAP_TAG_MMC, &nokia770_mmc_config },
+};
+
+/*
+ * audio power control
+ */
+#define HEADPHONE_GPIO 14
+#define AMPLIFIER_CTRL_GPIO 58
+
+static struct clk *dspxor_ck;
+static DECLARE_MUTEX(audio_pwr_sem);
+/*
+ * audio_pwr_state
+ * +--+-------------------------+---------------------------------------+
+ * |-1|down |power-up request -> 0 |
+ * +--+-------------------------+---------------------------------------+
+ * | 0|up |power-down(1) request -> 1 |
+ * | | |power-down(2) request -> (ignore) |
+ * +--+-------------------------+---------------------------------------+
+ * | 1|up, |power-up request -> 0 |
+ * | |received down(1) request |power-down(2) request -> -1 |
+ * +--+-------------------------+---------------------------------------+
+ */
+static int audio_pwr_state = -1;
+
+/*
+ * audio_pwr_up / down should be called under audio_pwr_sem
+ */
+static void nokia770_audio_pwr_up(void)
+{
+ clk_enable(dspxor_ck);
+
+ /* Turn on codec */
+ tlv320aic23_power_up();
+
+ if (omap_get_gpio_datain(HEADPHONE_GPIO))
+ /* HP not connected, turn on amplifier */
+ omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 1);
+ else
+ /* HP connected, do not turn on amplifier */
+ printk("HP connected\n");
+}
+
+static void codec_delayed_power_down(void *arg)
+{
+ down(&audio_pwr_sem);
+ if (audio_pwr_state == -1)
+ tlv320aic23_power_down();
+ clk_disable(dspxor_ck);
+ up(&audio_pwr_sem);
+}
+
+static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL);
+
+static void nokia770_audio_pwr_down(void)
+{
+ /* Turn off amplifier */
+ omap_set_gpio_dataout(AMPLIFIER_CTRL_GPIO, 0);
+
+ /* Turn off codec: schedule delayed work */
+ schedule_delayed_work(&codec_power_down_work, HZ / 20); /* 50ms */
+}
+
+void nokia770_audio_pwr_up_request(int stage)
+{
+ down(&audio_pwr_sem);
+ if (audio_pwr_state == -1)
+ nokia770_audio_pwr_up();
+ /* force audio_pwr_state = 0, even if it was 1. */
+ audio_pwr_state = 0;
+ up(&audio_pwr_sem);
+}
+
+void nokia770_audio_pwr_down_request(int stage)
+{
+ down(&audio_pwr_sem);
+ switch (stage) {
+ case 1:
+ if (audio_pwr_state == 0)
+ audio_pwr_state = 1;
+ break;
+ case 2:
+ if (audio_pwr_state == 1) {
+ nokia770_audio_pwr_down();
+ audio_pwr_state = -1;
+ }
+ break;
+ }
+ up(&audio_pwr_sem);
+}
+
+static void __init omap_nokia770_init(void)
+{
+ nokia770_config[0].data = &nokia770_usb_config;
+
+ platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
+ spi_register_board_info(nokia770_spi_board_info,
+ ARRAY_SIZE(nokia770_spi_board_info));
+ omap_board_config = nokia770_config;
+ omap_board_config_size = ARRAY_SIZE(nokia770_config);
+ omap_serial_init();
+ omap_dsp_audio_pwr_up_request = nokia770_audio_pwr_up_request;
+ omap_dsp_audio_pwr_down_request = nokia770_audio_pwr_down_request;
+ dspxor_ck = clk_get(0, "dspxor_ck");
+}
+
+static void __init omap_nokia770_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(NOKIA770, "Nokia 770")
+ .phys_io = 0xfff00000,
+ .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
+ .boot_params = 0x10000100,
+ .map_io = omap_nokia770_map_io,
+ .init_irq = omap_nokia770_init_irq,
+ .init_machine = omap_nokia770_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 543fa136106..1160093e8ef 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -33,6 +33,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -44,7 +45,24 @@
#include <asm/arch/usb.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/omap-alsa.h>
+
+static int osk_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(0, 3, KEY_UP),
+ KEY(1, 1, KEY_LEFTCTRL),
+ KEY(1, 2, KEY_LEFT),
+ KEY(2, 0, KEY_SPACE),
+ KEY(2, 1, KEY_ESC),
+ KEY(2, 2, KEY_DOWN),
+ KEY(3, 2, KEY_ENTER),
+ KEY(3, 3, KEY_RIGHT),
+ 0
+};
+
static struct mtd_partition osk_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
@@ -133,9 +151,69 @@ static struct platform_device osk5912_cf_device = {
.resource = osk5912_cf_resources,
};
+#define DEFAULT_BITPERSAMPLE 16
+
+static struct omap_mcbsp_reg_cfg mcbsp_regs = {
+ .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
+ .spcr1 = RINTM(3) | RRST,
+ .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
+ RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
+ .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
+ .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
+ XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
+ .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
+ .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+ .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+ /*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */
+ .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
+};
+
+static struct omap_alsa_codec_config alsa_config = {
+ .name = "OSK AIC23",
+ .mcbsp_regs_alsa = &mcbsp_regs,
+ .codec_configure_dev = NULL, // aic23_configure,
+ .codec_set_samplerate = NULL, // aic23_set_samplerate,
+ .codec_clock_setup = NULL, // aic23_clock_setup,
+ .codec_clock_on = NULL, // aic23_clock_on,
+ .codec_clock_off = NULL, // aic23_clock_off,
+ .get_default_samplerate = NULL, // aic23_get_default_samplerate,
+};
+
static struct platform_device osk5912_mcbsp1_device = {
- .name = "omap_mcbsp",
- .id = 1,
+ .name = "omap_alsa_mcbsp",
+ .id = 1,
+ .dev = {
+ .platform_data = &alsa_config,
+ },
+};
+
+static struct resource osk5912_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data osk_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = osk_keymap,
+};
+
+static struct platform_device osk5912_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &osk_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(osk5912_kp_resources),
+ .resource = osk5912_kp_resources,
+};
+
+static struct platform_device osk5912_lcd_device = {
+ .name = "lcd_osk",
+ .id = -1,
};
static struct platform_device *osk5912_devices[] __initdata = {
@@ -143,6 +221,8 @@ static struct platform_device *osk5912_devices[] __initdata = {
&osk5912_smc91x_device,
&osk5912_cf_device,
&osk5912_mcbsp1_device,
+ &osk5912_kp_device,
+ &osk5912_lcd_device,
};
static void __init osk_init_smc91x(void)
@@ -197,7 +277,6 @@ static struct omap_uart_config osk_uart_config __initdata = {
};
static struct omap_lcd_config osk_lcd_config __initdata = {
- .panel_name = "osk",
.ctrl_name = "internal",
};
@@ -255,8 +334,18 @@ static void __init osk_mistral_init(void)
static void __init osk_mistral_init(void) { }
#endif
+#define EMIFS_CS3_VAL (0x88013141)
+
static void __init osk_init(void)
{
+ /* Workaround for wrong CS3 (NOR flash) timing
+ * There are some U-Boot versions out there which configure
+ * wrong CS3 memory timings. This mainly leads to CRC
+ * or similiar errors if you use NOR flash (e.g. with JFFS2)
+ */
+ if (EMIFS_CCS(3) != EMIFS_CS3_VAL)
+ EMIFS_CCS(3) = EMIFS_CS3_VAL;
+
osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys();
osk_flash_resource.end += SZ_32M - 1;
platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index e488f723677..4bc8a62909b 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -38,6 +38,15 @@ static void __init omap_generic_init_irq(void)
omap_init_irq();
}
+static struct platform_device palmte_lcd_device = {
+ .name = "lcd_palmte",
+ .id = -1,
+};
+
+static struct platform_device *devices[] __initdata = {
+ &palmte_lcd_device,
+};
+
static struct omap_usb_config palmte_usb_config __initdata = {
.register_dev = 1,
.hmc_mode = 0,
@@ -55,7 +64,6 @@ static struct omap_mmc_config palmte_mmc_config __initdata = {
};
static struct omap_lcd_config palmte_lcd_config __initdata = {
- .panel_name = "palmte",
.ctrl_name = "internal",
};
@@ -69,6 +77,8 @@ static void __init omap_generic_init(void)
{
omap_board_config = palmte_config;
omap_board_config_size = ARRAY_SIZE(palmte_config);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
}
static void __init omap_generic_map_io(void)
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 3913a3cc0ce..64b45d8ae35 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -16,7 +16,9 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -28,9 +30,44 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
+#include <asm/arch/keypad.h>
#include <asm/arch/common.h>
#include <asm/arch/board.h>
+static int p2_keymap[] = {
+ KEY(0,0,KEY_UP),
+ KEY(0,1,KEY_RIGHT),
+ KEY(0,2,KEY_LEFT),
+ KEY(0,3,KEY_DOWN),
+ KEY(0,4,KEY_CENTER),
+ KEY(0,5,KEY_0_5),
+ KEY(1,0,KEY_SOFT2),
+ KEY(1,1,KEY_SEND),
+ KEY(1,2,KEY_END),
+ KEY(1,3,KEY_VOLUMEDOWN),
+ KEY(1,4,KEY_VOLUMEUP),
+ KEY(1,5,KEY_RECORD),
+ KEY(2,0,KEY_SOFT1),
+ KEY(2,1,KEY_3),
+ KEY(2,2,KEY_6),
+ KEY(2,3,KEY_9),
+ KEY(2,4,KEY_SHARP),
+ KEY(2,5,KEY_2_5),
+ KEY(3,0,KEY_BACK),
+ KEY(3,1,KEY_2),
+ KEY(3,2,KEY_5),
+ KEY(3,3,KEY_8),
+ KEY(3,4,KEY_0),
+ KEY(3,5,KEY_HEADSETHOOK),
+ KEY(4,0,KEY_HOME),
+ KEY(4,1,KEY_1),
+ KEY(4,2,KEY_4),
+ KEY(4,3,KEY_7),
+ KEY(4,4,KEY_STAR),
+ KEY(4,5,KEY_POWER),
+ 0
+};
+
static struct resource smc91x_resources[] = {
[0] = {
.start = H2P2_DBG_FPGA_ETHR_START, /* Physical */
@@ -44,7 +81,7 @@ static struct resource smc91x_resources[] = {
},
};
-static struct mtd_partition p2_partitions[] = {
+static struct mtd_partition nor_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
.name = "bootloader",
@@ -75,27 +112,47 @@ static struct mtd_partition p2_partitions[] = {
},
};
-static struct flash_platform_data p2_flash_data = {
+static struct flash_platform_data nor_data = {
.map_name = "cfi_probe",
.width = 2,
- .parts = p2_partitions,
- .nr_parts = ARRAY_SIZE(p2_partitions),
+ .parts = nor_partitions,
+ .nr_parts = ARRAY_SIZE(nor_partitions),
};
-static struct resource p2_flash_resource = {
+static struct resource nor_resource = {
.start = OMAP_CS0_PHYS,
.end = OMAP_CS0_PHYS + SZ_32M - 1,
.flags = IORESOURCE_MEM,
};
-static struct platform_device p2_flash_device = {
+static struct platform_device nor_device = {
.name = "omapflash",
.id = 0,
.dev = {
- .platform_data = &p2_flash_data,
+ .platform_data = &nor_data,
+ },
+ .num_resources = 1,
+ .resource = &nor_resource,
+};
+
+static struct nand_platform_data nand_data = {
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+};
+
+static struct resource nand_resource = {
+ .start = OMAP_CS3_PHYS,
+ .end = OMAP_CS3_PHYS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+ .name = "omapnand",
+ .id = 0,
+ .dev = {
+ .platform_data = &nand_data,
},
.num_resources = 1,
- .resource = &p2_flash_resource,
+ .resource = &nand_resource,
};
static struct platform_device smc91x_device = {
@@ -105,17 +162,55 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources,
};
+static struct resource kp_resources[] = {
+ [0] = {
+ .start = INT_730_MPUIO_KEYPAD,
+ .end = INT_730_MPUIO_KEYPAD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct omap_kp_platform_data kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap = p2_keymap,
+};
+
+static struct platform_device kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &kp_data,
+ },
+ .num_resources = ARRAY_SIZE(kp_resources),
+ .resource = kp_resources,
+};
+
+static struct platform_device lcd_device = {
+ .name = "lcd_p2",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
- &p2_flash_device,
+ &nor_device,
+ &nand_device,
&smc91x_device,
+ &kp_device,
+ &lcd_device,
};
+#define P2_NAND_RB_GPIO_PIN 62
+
+static int nand_dev_ready(struct nand_platform_data *data)
+{
+ return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
+}
+
static struct omap_uart_config perseus2_uart_config __initdata = {
.enabled_uarts = ((1 << 0) | (1 << 1)),
};
static struct omap_lcd_config perseus2_lcd_config __initdata = {
- .panel_name = "p2",
.ctrl_name = "internal",
};
@@ -126,7 +221,13 @@ static struct omap_board_config_kernel perseus2_config[] = {
static void __init omap_perseus2_init(void)
{
- (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+ if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN)))
+ nand_data.dev_ready = nand_dev_ready;
+
+ omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+ omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
omap_board_config = perseus2_config;
omap_board_config_size = ARRAY_SIZE(perseus2_config);
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 52e4a9d6964..447a586eb33 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -155,9 +155,9 @@ static struct omap_uart_config voiceblue_uart_config __initdata = {
};
static struct omap_board_config_kernel voiceblue_config[] = {
- { OMAP_TAG_USB, &voiceblue_usb_config },
- { OMAP_TAG_MMC, &voiceblue_mmc_config },
- { OMAP_TAG_UART, &voiceblue_uart_config },
+ { OMAP_TAG_USB, &voiceblue_usb_config },
+ { OMAP_TAG_MMC, &voiceblue_mmc_config },
+ { OMAP_TAG_UART, &voiceblue_uart_config },
};
static void __init voiceblue_init_irq(void)
@@ -235,7 +235,7 @@ static struct notifier_block panic_block = {
static int __init voiceblue_setup(void)
{
/* Setup panic notifier */
- atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+ notifier_chain_register(&panic_notifier_list, &panic_block);
return 0;
}
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 75110ba1042..619db18144e 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -345,7 +345,7 @@ static unsigned calc_ext_dsor(unsigned long rate)
*/
for (dsor = 2; dsor < 96; ++dsor) {
if ((dsor & 1) && dsor > 8)
- continue;
+ continue;
if (rate >= 96000000 / dsor)
break;
}
@@ -687,6 +687,11 @@ int __init omap1_clk_init(void)
clk_register(*clkp);
continue;
}
+
+ if (((*clkp)->flags &CLOCK_IN_OMAP310) && cpu_is_omap310()) {
+ clk_register(*clkp);
+ continue;
+ }
}
info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
@@ -784,7 +789,7 @@ int __init omap1_clk_init(void)
clk_enable(&armxor_ck.clk);
clk_enable(&armtim_ck.clk); /* This should be done by timer code */
- if (cpu_is_omap1510())
+ if (cpu_is_omap15xx())
clk_enable(&arm_gpio_ck);
return 0;
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index 4f18d1b9444..b7c68819c4e 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -151,7 +151,7 @@ static struct clk ck_ref = {
.name = "ck_ref",
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -160,7 +160,7 @@ static struct clk ck_dpll1 = {
.name = "ck_dpll1",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_PROPAGATES | ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | RATE_PROPAGATES | ALWAYS_ENABLED,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -183,7 +183,8 @@ static struct clk arm_ck = {
.name = "arm_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | RATE_CKCTL | RATE_PROPAGATES |
+ ALWAYS_ENABLED,
.rate_offset = CKCTL_ARMDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
.enable = &omap1_clk_enable_generic,
@@ -195,7 +196,8 @@ static struct arm_idlect1_clk armper_ck = {
.name = "armper_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_CKCTL | CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | RATE_CKCTL |
+ CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_PERCK,
.rate_offset = CKCTL_PERDIV_OFFSET,
@@ -209,7 +211,7 @@ static struct arm_idlect1_clk armper_ck = {
static struct clk arm_gpio_ck = {
.name = "arm_gpio_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_GPIOCK,
.recalc = &followparent_recalc,
@@ -222,7 +224,7 @@ static struct arm_idlect1_clk armxor_ck = {
.name = "armxor_ck",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_XORPCK,
.recalc = &followparent_recalc,
@@ -237,7 +239,7 @@ static struct arm_idlect1_clk armtim_ck = {
.name = "armtim_ck",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_TIMCK,
.recalc = &followparent_recalc,
@@ -252,7 +254,7 @@ static struct arm_idlect1_clk armwdt_ck = {
.name = "armwdt_ck",
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_WDTCK,
.recalc = &omap1_watchdog_recalc,
@@ -344,9 +346,9 @@ static struct arm_idlect1_clk tc_ck = {
.name = "tc_ck",
.parent = &ck_dpll1,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IN_OMAP730 | RATE_CKCTL |
- RATE_PROPAGATES | ALWAYS_ENABLED |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP730 | CLOCK_IN_OMAP310 |
+ RATE_CKCTL | RATE_PROPAGATES |
+ ALWAYS_ENABLED | CLOCK_IDLE_CONTROL,
.rate_offset = CKCTL_TCDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
.enable = &omap1_clk_enable_generic,
@@ -358,7 +360,8 @@ static struct arm_idlect1_clk tc_ck = {
static struct clk arminth_ck1510 = {
.name = "arminth_ck",
.parent = &tc_ck.clk,
- .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ALWAYS_ENABLED,
.recalc = &followparent_recalc,
/* Note: On 1510 the frequency follows TC_CK
*
@@ -372,7 +375,8 @@ static struct clk tipb_ck = {
/* No-idle controlled by "tc_ck" */
.name = "tibp_ck",
.parent = &tc_ck.clk,
- .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ALWAYS_ENABLED,
.recalc = &followparent_recalc,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
@@ -417,7 +421,7 @@ static struct clk dma_ck = {
.name = "dma_ck",
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | ALWAYS_ENABLED,
.recalc = &followparent_recalc,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
@@ -437,7 +441,7 @@ static struct arm_idlect1_clk api_ck = {
.name = "api_ck",
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- CLOCK_IDLE_CONTROL,
+ CLOCK_IN_OMAP310 | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_APICK,
.recalc = &followparent_recalc,
@@ -451,7 +455,8 @@ static struct arm_idlect1_clk lb_ck = {
.clk = {
.name = "lb_ck",
.parent = &tc_ck.clk,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IDLE_CONTROL,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_LBCK,
.recalc = &followparent_recalc,
@@ -495,8 +500,8 @@ static struct arm_idlect1_clk lcd_ck_1510 = {
.clk = {
.name = "lcd_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510 | RATE_CKCTL |
- CLOCK_IDLE_CONTROL,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ RATE_CKCTL | CLOCK_IDLE_CONTROL,
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_LCDCK,
.rate_offset = CKCTL_LCDDIV_OFFSET,
@@ -512,8 +517,9 @@ static struct clk uart1_1510 = {
/* Direct from ULPD, no real parent */
.parent = &armper_ck.clk,
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
- ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ENABLE_REG_32BIT | ALWAYS_ENABLED |
+ CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 29, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
@@ -544,8 +550,8 @@ static struct clk uart2_ck = {
.parent = &armper_ck.clk,
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- ENABLE_REG_32BIT | ALWAYS_ENABLED |
- CLOCK_NO_IDLE_PARENT,
+ CLOCK_IN_OMAP310 | ENABLE_REG_32BIT |
+ ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
@@ -559,8 +565,9 @@ static struct clk uart3_1510 = {
/* Direct from ULPD, no real parent */
.parent = &armper_ck.clk,
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | ENABLE_REG_32BIT |
- ALWAYS_ENABLED | CLOCK_NO_IDLE_PARENT,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
+ ENABLE_REG_32BIT | ALWAYS_ENABLED |
+ CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 31, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
@@ -590,7 +597,7 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
/* Direct from ULPD, no parent */
.rate = 6000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_FIXED | ENABLE_REG_32BIT,
+ CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = (void __iomem *)ULPD_CLOCK_CTRL,
.enable_bit = USB_MCLK_EN_BIT,
.enable = &omap1_clk_enable_generic,
@@ -601,7 +608,7 @@ static struct clk usb_hhc_ck1510 = {
.name = "usb_hhc_ck",
/* Direct from ULPD, no parent */
.rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
- .flags = CLOCK_IN_OMAP1510 |
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 |
RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = USB_HOST_HHC_UHOST_EN,
@@ -637,7 +644,9 @@ static struct clk mclk_1510 = {
.name = "mclk",
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
+ .enable_reg = (void __iomem *)SOFT_REQ_REG,
+ .enable_bit = 6,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -659,7 +668,7 @@ static struct clk bclk_1510 = {
.name = "bclk",
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
.rate = 12000000,
- .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | RATE_FIXED,
.enable = &omap1_clk_enable_generic,
.disable = &omap1_clk_disable_generic,
};
@@ -678,12 +687,14 @@ static struct clk bclk_16xx = {
};
static struct clk mmc1_ck = {
- .name = "mmc1_ck",
+ .name = "mmc_ck",
+ .id = 1,
/* Functional clock is direct from ULPD, interface clock is ARMPER */
.parent = &armper_ck.clk,
.rate = 48000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ CLOCK_IN_OMAP310 | RATE_FIXED | ENABLE_REG_32BIT |
+ CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 23,
.enable = &omap1_clk_enable_generic,
@@ -691,7 +702,8 @@ static struct clk mmc1_ck = {
};
static struct clk mmc2_ck = {
- .name = "mmc2_ck",
+ .name = "mmc_ck",
+ .id = 2,
/* Functional clock is direct from ULPD, interface clock is ARMPER */
.parent = &armper_ck.clk,
.rate = 48000000,
@@ -706,7 +718,7 @@ static struct clk mmc2_ck = {
static struct clk virtual_ck_mpu = {
.name = "mpu",
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
- VIRTUAL_CLOCK | ALWAYS_ENABLED,
+ CLOCK_IN_OMAP310 | VIRTUAL_CLOCK | ALWAYS_ENABLED,
.parent = &arm_ck, /* Is smarter alias for */
.recalc = &followparent_recalc,
.set_rate = &omap1_select_table_rate,
@@ -715,6 +727,20 @@ static struct clk virtual_ck_mpu = {
.disable = &omap1_clk_disable_generic,
};
+/* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK
+remains active during MPU idle whenever this is enabled */
+static struct clk i2c_fck = {
+ .name = "i2c_fck",
+ .id = 1,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT |
+ ALWAYS_ENABLED,
+ .parent = &armxor_ck.clk,
+ .recalc = &followparent_recalc,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
+};
+
static struct clk * onchip_clks[] = {
/* non-ULPD clocks */
&ck_ref,
@@ -763,6 +789,7 @@ static struct clk * onchip_clks[] = {
&mmc2_ck,
/* Virtual clocks */
&virtual_ck_mpu,
+ &i2c_fck,
};
#endif
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index ecbc47514ad..876c38da14f 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -99,6 +99,45 @@ static void omap_init_rtc(void)
static inline void omap_init_rtc(void) {}
#endif
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP1_STI_BASE IO_ADDRESS(0xfffea000)
+#define OMAP1_STI_CHANNEL_BASE (OMAP1_STI_BASE + 0x400)
+
+static struct resource sti_resources[] = {
+ {
+ .start = OMAP1_STI_BASE,
+ .end = OMAP1_STI_BASE + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP1_STI_CHANNEL_BASE,
+ .end = OMAP1_STI_CHANNEL_BASE + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_1610_STI,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device sti_device = {
+ .name = "sti",
+ .id = -1,
+ .dev = {
+ .release = omap_nop_release,
+ },
+ .num_resources = ARRAY_SIZE(sti_resources),
+ .resource = sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+ platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
/*-------------------------------------------------------------------------*/
@@ -129,6 +168,7 @@ static int __init omap1_init_devices(void)
*/
omap_init_irda();
omap_init_rtc();
+ omap_init_sti();
return 0;
}
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 82d556be79c..be3a2a4ee2b 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -18,6 +18,7 @@
#include <asm/io.h>
#include <asm/arch/mux.h>
#include <asm/arch/tc.h>
+#include <asm/arch/omapfb.h>
extern int omap1_clk_init(void);
extern void omap_check_revision(void);
@@ -110,7 +111,7 @@ void __init omap1_map_common_io(void)
}
#endif
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
}
#endif
@@ -121,6 +122,7 @@ void __init omap1_map_common_io(void)
#endif
omap_sram_init();
+ omapfb_reserve_mem();
}
/*
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index ed65a7d2e94..a0431c00fa8 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -60,7 +60,7 @@ struct omap_irq_bank {
unsigned long wake_enable;
};
-static unsigned int irq_bank_count = 0;
+static unsigned int irq_bank_count;
static struct omap_irq_bank *irq_banks;
static inline unsigned int irq_bank_readl(int bank, int offset)
@@ -142,28 +142,28 @@ static void omap_irq_set_cfg(int irq, int fiq, int priority, int trigger)
#ifdef CONFIG_ARCH_OMAP730
static struct omap_irq_bank omap730_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 },
{ .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 },
};
#endif
#ifdef CONFIG_ARCH_OMAP15XX
static struct omap_irq_bank omap1510_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3febfff },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xffbfffed },
};
static struct omap_irq_bank omap310_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3faefc3 },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0x65b3c061 },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3faefc3 },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0x65b3c061 },
};
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
static struct omap_irq_bank omap1610_irq_banks[] = {
- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f },
- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd },
+ { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3fefe8f },
+ { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb7c1fd },
{ .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0xffffb7ff },
{ .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff },
};
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index d4b8d624e74..10fe0b3efca 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -35,16 +35,20 @@
#ifdef CONFIG_ARCH_OMAP730
struct pin_config __initdata_or_module omap730_pins[] = {
-MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 0, 20, 1, NA, 0, 0)
-MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 0, 24, 1, NA, 0, 0)
-MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 0, 28, 1, NA, 0, 0)
-MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 0, 1, NA, 0, 0)
-MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 0, 4, 1, NA, 0, 0)
-MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 0, 8, 1, NA, 0, 0)
-MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 0, 12, 1, NA, 0, 0)
-MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 0, 16, 1, NA, 0, 0)
-MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 0, 20, 1, NA, 0, 0)
-MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 0, 24, 1, NA, 0, 0)
+MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 20, 1, 0)
+MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 24, 1, 0)
+MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 28, 1, 0)
+MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 1, 0)
+MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 4, 1, 0)
+MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 8, 1, 0)
+MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 12, 1, 0)
+MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 16, 1, 0)
+MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 20, 1, 0)
+MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 24, 1, 0)
+
+MUX_CFG_730("AA17_730_USB_DM", 2, 21, 0, 20, 0, 0)
+MUX_CFG_730("W16_730_USB_PU_EN", 2, 25, 0, 24, 0, 0)
+MUX_CFG_730("W17_730_USB_VBUSI", 2, 29, 0, 28, 0, 0)
};
#endif
@@ -73,8 +77,8 @@ MUX_CFG("UART3_BCLK", A, 0, 0, 2, 6, 0, NA, 0, 0)
MUX_CFG("Y15_1610_UART3_RTS", A, 0, 1, 2, 6, 0, NA, 0, 0)
/* PWT & PWL, conflicts with UART3 */
-MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0)
-MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0)
+MUX_CFG("PWT", 6, 0, 2, 0, 30, 0, NA, 0, 0)
+MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0)
/* USB internal master generic */
MUX_CFG("R18_USB_VBUS", 7, 9, 2, 1, 11, 0, NA, 0, 1)
@@ -151,7 +155,7 @@ MUX_CFG("MCBSP3_CLKX", 9, 3, 1, 1, 29, 0, NA, 0, 1)
/* Misc ballouts */
MUX_CFG("BALLOUT_V8_ARMIO3", B, 18, 0, 2, 25, 1, NA, 0, 1)
-MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0)
+MUX_CFG("N20_HDQ", 6, 18, 1, 1, 4, 0, 1, 4, 0)
/* OMAP-1610 MMC2 */
MUX_CFG("W8_1610_MMC2_DAT0", B, 21, 6, 2, 23, 1, 2, 1, 1)
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
new file mode 100644
index 00000000000..ddf6b07dc9c
--- /dev/null
+++ b/arch/arm/mach-omap1/pm.c
@@ -0,0 +1,770 @@
+/*
+ * linux/arch/arm/mach-omap1/pm.c
+ *
+ * OMAP Power Management Routines
+ *
+ * Original code for the SA11x0:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * Modified for the PXA250 by Nicolas Pitre:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Modified for the OMAP1510 by David Singleton:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tps65010.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/dsp_common.h>
+#include <asm/arch/dmtimer.h>
+
+static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
+static unsigned short dsp_sleep_save[DSP_SLEEP_SAVE_SIZE];
+static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
+static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE];
+static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
+static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+
+static unsigned short enable_dyn_sleep = 1;
+
+static ssize_t omap_pm_sleep_while_idle_show(struct subsystem * subsys, char *buf)
+{
+ return sprintf(buf, "%hu\n", enable_dyn_sleep);
+}
+
+static ssize_t omap_pm_sleep_while_idle_store(struct subsystem * subsys,
+ const char * buf,
+ size_t n)
+{
+ unsigned short value;
+ if (sscanf(buf, "%hu", &value) != 1 ||
+ (value != 0 && value != 1)) {
+ printk(KERN_ERR "idle_sleep_store: Invalid value\n");
+ return -EINVAL;
+ }
+ enable_dyn_sleep = value;
+ return n;
+}
+
+static struct subsys_attribute sleep_while_idle_attr = {
+ .attr = {
+ .name = __stringify(sleep_while_idle),
+ .mode = 0644,
+ },
+ .show = omap_pm_sleep_while_idle_show,
+ .store = omap_pm_sleep_while_idle_store,
+};
+
+extern struct subsystem power_subsys;
+static void (*omap_sram_idle)(void) = NULL;
+static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
+
+/*
+ * Let's power down on idle, but only if we are really
+ * idle, because once we start down the path of
+ * going idle we continue to do idle even if we get
+ * a clock tick interrupt . .
+ */
+void omap_pm_idle(void)
+{
+ extern __u32 arm_idlect1_mask;
+ __u32 use_idlect1 = arm_idlect1_mask;
+#ifndef CONFIG_OMAP_MPU_TIMER
+ int do_sleep;
+#endif
+
+ local_irq_disable();
+ local_fiq_disable();
+ if (need_resched()) {
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+
+ /*
+ * Since an interrupt may set up a timer, we don't want to
+ * reprogram the hardware timer with interrupts enabled.
+ * Re-enable interrupts only after returning from idle.
+ */
+ timer_dyn_reprogram();
+
+#ifdef CONFIG_OMAP_MPU_TIMER
+#warning Enable 32kHz OS timer in order to allow sleep states in idle
+ use_idlect1 = use_idlect1 & ~(1 << 9);
+#else
+
+ do_sleep = 0;
+ while (enable_dyn_sleep) {
+
+#ifdef CONFIG_CBUS_TAHVO_USB
+ extern int vbus_active;
+ /* Clock requirements? */
+ if (vbus_active)
+ break;
+#endif
+ do_sleep = 1;
+ break;
+ }
+
+#ifdef CONFIG_OMAP_DM_TIMER
+ use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1);
+#endif
+
+ if (omap_dma_running()) {
+ use_idlect1 &= ~(1 << 6);
+ if (omap_lcd_dma_ext_running())
+ use_idlect1 &= ~(1 << 12);
+ }
+
+ /* We should be able to remove the do_sleep variable and multiple
+ * tests above as soon as drivers, timer and DMA code have been fixed.
+ * Even the sleep block count should become obsolete. */
+ if ((use_idlect1 != ~0) || !do_sleep) {
+
+ __u32 saved_idlect1 = omap_readl(ARM_IDLECT1);
+ if (cpu_is_omap15xx())
+ use_idlect1 &= OMAP1510_BIG_SLEEP_REQUEST;
+ else
+ use_idlect1 &= OMAP1610_IDLECT1_SLEEP_VAL;
+ omap_writel(use_idlect1, ARM_IDLECT1);
+ __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
+ omap_writel(saved_idlect1, ARM_IDLECT1);
+
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+ omap_sram_suspend(omap_readl(ARM_IDLECT1),
+ omap_readl(ARM_IDLECT2));
+#endif
+
+ local_fiq_enable();
+ local_irq_enable();
+}
+
+/*
+ * Configuration of the wakeup event is board specific. For the
+ * moment we put it into this helper function. Later it may move
+ * to board specific files.
+ */
+static void omap_pm_wakeup_setup(void)
+{
+ u32 level1_wake = 0;
+ u32 level2_wake = OMAP_IRQ_BIT(INT_UART2);
+
+ /*
+ * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade,
+ * and the L2 wakeup interrupts: keypad and UART2. Note that the
+ * drivers must still separately call omap_set_gpio_wakeup() to
+ * wake up to a GPIO interrupt.
+ */
+ if (cpu_is_omap730())
+ level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_730_IH2_IRQ);
+ else if (cpu_is_omap15xx())
+ level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_1510_IH2_IRQ);
+ else if (cpu_is_omap16xx())
+ level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_1610_IH2_IRQ);
+
+ omap_writel(~level1_wake, OMAP_IH1_MIR);
+
+ if (cpu_is_omap730()) {
+ omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+ omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) |
+ OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)),
+ OMAP_IH2_1_MIR);
+ } else if (cpu_is_omap15xx()) {
+ level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+ omap_writel(~level2_wake, OMAP_IH2_MIR);
+ } else if (cpu_is_omap16xx()) {
+ level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD);
+ omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+
+ /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */
+ omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ),
+ OMAP_IH2_1_MIR);
+ omap_writel(~0x0, OMAP_IH2_2_MIR);
+ omap_writel(~0x0, OMAP_IH2_3_MIR);
+ }
+
+ /* New IRQ agreement, recalculate in cascade order */
+ omap_writel(1, OMAP_IH2_CONTROL);
+ omap_writel(1, OMAP_IH1_CONTROL);
+}
+
+#define EN_DSPCK 13 /* ARM_CKCTL */
+#define EN_APICK 6 /* ARM_IDLECT2 */
+#define DSP_EN 1 /* ARM_RSTCT1 */
+
+void omap_pm_suspend(void)
+{
+ unsigned long arg0 = 0, arg1 = 0;
+
+ printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev);
+
+ omap_serial_wake_trigger(1);
+
+ if (machine_is_omap_osk()) {
+ /* Stop LED1 (D9) blink */
+ tps65010_set_led(LED1, OFF);
+ }
+
+ omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG);
+
+ /*
+ * Step 1: turn off interrupts (FIXME: NOTE: already disabled)
+ */
+
+ local_irq_disable();
+ local_fiq_disable();
+
+ /*
+ * Step 2: save registers
+ *
+ * The omap is a strange/beautiful device. The caches, memory
+ * and register state are preserved across power saves.
+ * We have to save and restore very little register state to
+ * idle the omap.
+ *
+ * Save interrupt, MPUI, ARM and UPLD control registers.
+ */
+
+ if (cpu_is_omap730()) {
+ MPUI730_SAVE(OMAP_IH1_MIR);
+ MPUI730_SAVE(OMAP_IH2_0_MIR);
+ MPUI730_SAVE(OMAP_IH2_1_MIR);
+ MPUI730_SAVE(MPUI_CTRL);
+ MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI730_SAVE(EMIFS_CONFIG);
+ MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+
+ } else if (cpu_is_omap15xx()) {
+ MPUI1510_SAVE(OMAP_IH1_MIR);
+ MPUI1510_SAVE(OMAP_IH2_MIR);
+ MPUI1510_SAVE(MPUI_CTRL);
+ MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1510_SAVE(EMIFS_CONFIG);
+ MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+ } else if (cpu_is_omap16xx()) {
+ MPUI1610_SAVE(OMAP_IH1_MIR);
+ MPUI1610_SAVE(OMAP_IH2_0_MIR);
+ MPUI1610_SAVE(OMAP_IH2_1_MIR);
+ MPUI1610_SAVE(OMAP_IH2_2_MIR);
+ MPUI1610_SAVE(OMAP_IH2_3_MIR);
+ MPUI1610_SAVE(MPUI_CTRL);
+ MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1610_SAVE(EMIFS_CONFIG);
+ MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+ }
+
+ ARM_SAVE(ARM_CKCTL);
+ ARM_SAVE(ARM_IDLECT1);
+ ARM_SAVE(ARM_IDLECT2);
+ if (!(cpu_is_omap15xx()))
+ ARM_SAVE(ARM_IDLECT3);
+ ARM_SAVE(ARM_EWUPCT);
+ ARM_SAVE(ARM_RSTCT1);
+ ARM_SAVE(ARM_RSTCT2);
+ ARM_SAVE(ARM_SYSST);
+ ULPD_SAVE(ULPD_CLOCK_CTRL);
+ ULPD_SAVE(ULPD_STATUS_REQ);
+
+ /* (Step 3 removed - we now allow deep sleep by default) */
+
+ /*
+ * Step 4: OMAP DSP Shutdown
+ */
+
+ /* stop DSP */
+ omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1);
+
+ /* shut down dsp_ck */
+ omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL);
+
+ /* temporarily enabling api_ck to access DSP registers */
+ omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+ /* save DSP registers */
+ DSP_SAVE(DSP_IDLECT2);
+
+ /* Stop all DSP domain clocks */
+ __raw_writew(0, DSP_IDLECT2);
+
+ /*
+ * Step 5: Wakeup Event Setup
+ */
+
+ omap_pm_wakeup_setup();
+
+ /*
+ * Step 6: ARM and Traffic controller shutdown
+ */
+
+ /* disable ARM watchdog */
+ omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
+ omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
+
+ /*
+ * Step 6b: ARM and Traffic controller shutdown
+ *
+ * Step 6 continues here. Prepare jump to power management
+ * assembly code in internal SRAM.
+ *
+ * Since the omap_cpu_suspend routine has been copied to
+ * SRAM, we'll do an indirect procedure call to it and pass the
+ * contents of arm_idlect1 and arm_idlect2 so it can restore
+ * them when it wakes up and it will return.
+ */
+
+ arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
+ arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
+
+ /*
+ * Step 6c: ARM and Traffic controller shutdown
+ *
+ * Jump to assembly code. The processor will stay there
+ * until wake up.
+ */
+ omap_sram_suspend(arg0, arg1);
+
+ /*
+ * If we are here, processor is woken up!
+ */
+
+ /*
+ * Restore DSP clocks
+ */
+
+ /* again temporarily enabling api_ck to access DSP registers */
+ omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
+
+ /* Restore DSP domain clocks */
+ DSP_RESTORE(DSP_IDLECT2);
+
+ /*
+ * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
+ */
+
+ if (!(cpu_is_omap15xx()))
+ ARM_RESTORE(ARM_IDLECT3);
+ ARM_RESTORE(ARM_CKCTL);
+ ARM_RESTORE(ARM_EWUPCT);
+ ARM_RESTORE(ARM_RSTCT1);
+ ARM_RESTORE(ARM_RSTCT2);
+ ARM_RESTORE(ARM_SYSST);
+ ULPD_RESTORE(ULPD_CLOCK_CTRL);
+ ULPD_RESTORE(ULPD_STATUS_REQ);
+
+ if (cpu_is_omap730()) {
+ MPUI730_RESTORE(EMIFS_CONFIG);
+ MPUI730_RESTORE(EMIFF_SDRAM_CONFIG);
+ MPUI730_RESTORE(OMAP_IH1_MIR);
+ MPUI730_RESTORE(OMAP_IH2_0_MIR);
+ MPUI730_RESTORE(OMAP_IH2_1_MIR);
+ } else if (cpu_is_omap15xx()) {
+ MPUI1510_RESTORE(MPUI_CTRL);
+ MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
+ MPUI1510_RESTORE(EMIFS_CONFIG);
+ MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
+ MPUI1510_RESTORE(OMAP_IH1_MIR);
+ MPUI1510_RESTORE(OMAP_IH2_MIR);
+ } else if (cpu_is_omap16xx()) {
+ MPUI1610_RESTORE(MPUI_CTRL);
+ MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
+ MPUI1610_RESTORE(EMIFS_CONFIG);
+ MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
+
+ MPUI1610_RESTORE(OMAP_IH1_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_0_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_1_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_2_MIR);
+ MPUI1610_RESTORE(OMAP_IH2_3_MIR);
+ }
+
+ omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
+
+ /*
+ * Reenable interrupts
+ */
+
+ local_irq_enable();
+ local_fiq_enable();
+
+ omap_serial_wake_trigger(0);
+
+ printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
+
+ if (machine_is_omap_osk()) {
+ /* Let LED1 (D9) blink again */
+ tps65010_set_led(LED1, BLINK);
+ }
+}
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+static int g_read_completed;
+
+/*
+ * Read system PM registers for debugging
+ */
+static int omap_pm_read_proc(
+ char *page_buffer,
+ char **my_first_byte,
+ off_t virtual_start,
+ int length,
+ int *eof,
+ void *data)
+{
+ int my_buffer_offset = 0;
+ char * const my_base = page_buffer;
+
+ ARM_SAVE(ARM_CKCTL);
+ ARM_SAVE(ARM_IDLECT1);
+ ARM_SAVE(ARM_IDLECT2);
+ if (!(cpu_is_omap15xx()))
+ ARM_SAVE(ARM_IDLECT3);
+ ARM_SAVE(ARM_EWUPCT);
+ ARM_SAVE(ARM_RSTCT1);
+ ARM_SAVE(ARM_RSTCT2);
+ ARM_SAVE(ARM_SYSST);
+
+ ULPD_SAVE(ULPD_IT_STATUS);
+ ULPD_SAVE(ULPD_CLOCK_CTRL);
+ ULPD_SAVE(ULPD_SOFT_REQ);
+ ULPD_SAVE(ULPD_STATUS_REQ);
+ ULPD_SAVE(ULPD_DPLL_CTRL);
+ ULPD_SAVE(ULPD_POWER_CTRL);
+
+ if (cpu_is_omap730()) {
+ MPUI730_SAVE(MPUI_CTRL);
+ MPUI730_SAVE(MPUI_DSP_STATUS);
+ MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI730_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI730_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI730_SAVE(EMIFS_CONFIG);
+ } else if (cpu_is_omap15xx()) {
+ MPUI1510_SAVE(MPUI_CTRL);
+ MPUI1510_SAVE(MPUI_DSP_STATUS);
+ MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI1510_SAVE(EMIFS_CONFIG);
+ } else if (cpu_is_omap16xx()) {
+ MPUI1610_SAVE(MPUI_CTRL);
+ MPUI1610_SAVE(MPUI_DSP_STATUS);
+ MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI1610_SAVE(EMIFS_CONFIG);
+ }
+
+ if (virtual_start == 0) {
+ g_read_completed = 0;
+
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "ARM_CKCTL_REG: 0x%-8x \n"
+ "ARM_IDLECT1_REG: 0x%-8x \n"
+ "ARM_IDLECT2_REG: 0x%-8x \n"
+ "ARM_IDLECT3_REG: 0x%-8x \n"
+ "ARM_EWUPCT_REG: 0x%-8x \n"
+ "ARM_RSTCT1_REG: 0x%-8x \n"
+ "ARM_RSTCT2_REG: 0x%-8x \n"
+ "ARM_SYSST_REG: 0x%-8x \n"
+ "ULPD_IT_STATUS_REG: 0x%-4x \n"
+ "ULPD_CLOCK_CTRL_REG: 0x%-4x \n"
+ "ULPD_SOFT_REQ_REG: 0x%-4x \n"
+ "ULPD_DPLL_CTRL_REG: 0x%-4x \n"
+ "ULPD_STATUS_REQ_REG: 0x%-4x \n"
+ "ULPD_POWER_CTRL_REG: 0x%-4x \n",
+ ARM_SHOW(ARM_CKCTL),
+ ARM_SHOW(ARM_IDLECT1),
+ ARM_SHOW(ARM_IDLECT2),
+ ARM_SHOW(ARM_IDLECT3),
+ ARM_SHOW(ARM_EWUPCT),
+ ARM_SHOW(ARM_RSTCT1),
+ ARM_SHOW(ARM_RSTCT2),
+ ARM_SHOW(ARM_SYSST),
+ ULPD_SHOW(ULPD_IT_STATUS),
+ ULPD_SHOW(ULPD_CLOCK_CTRL),
+ ULPD_SHOW(ULPD_SOFT_REQ),
+ ULPD_SHOW(ULPD_DPLL_CTRL),
+ ULPD_SHOW(ULPD_STATUS_REQ),
+ ULPD_SHOW(ULPD_POWER_CTRL));
+
+ if (cpu_is_omap730()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI730_CTRL_REG 0x%-8x \n"
+ "MPUI730_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI730_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI730_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI730_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI730_SHOW(MPUI_CTRL),
+ MPUI730_SHOW(MPUI_DSP_STATUS),
+ MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI730_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI730_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI730_SHOW(EMIFS_CONFIG));
+ } else if (cpu_is_omap15xx()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI1510_CTRL_REG 0x%-8x \n"
+ "MPUI1510_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI1510_SHOW(MPUI_CTRL),
+ MPUI1510_SHOW(MPUI_DSP_STATUS),
+ MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI1510_SHOW(EMIFS_CONFIG));
+ } else if (cpu_is_omap16xx()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI1610_CTRL_REG 0x%-8x \n"
+ "MPUI1610_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI1610_SHOW(MPUI_CTRL),
+ MPUI1610_SHOW(MPUI_DSP_STATUS),
+ MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI1610_SHOW(EMIFS_CONFIG));
+ }
+
+ g_read_completed++;
+ } else if (g_read_completed >= 1) {
+ *eof = 1;
+ return 0;
+ }
+ g_read_completed++;
+
+ *my_first_byte = page_buffer;
+ return my_buffer_offset;
+}
+
+static void omap_pm_init_proc(void)
+{
+ struct proc_dir_entry *entry;
+
+ entry = create_proc_read_entry("driver/omap_pm",
+ S_IWUSR | S_IRUGO, NULL,
+ omap_pm_read_proc, NULL);
+}
+
+#endif /* DEBUG && CONFIG_PROC_FS */
+
+static void (*saved_idle)(void) = NULL;
+
+/*
+ * omap_pm_prepare - Do preliminary suspend work.
+ * @state: suspend state we're entering.
+ *
+ */
+static int omap_pm_prepare(suspend_state_t state)
+{
+ int error = 0;
+
+ /* We cannot sleep in idle until we have resumed */
+ saved_idle = pm_idle;
+ pm_idle = NULL;
+
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return error;
+}
+
+
+/*
+ * omap_pm_enter - Actually enter a sleep state.
+ * @state: State we're entering.
+ *
+ */
+
+static int omap_pm_enter(suspend_state_t state)
+{
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ omap_pm_suspend();
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/**
+ * omap_pm_finish - Finish up suspend sequence.
+ * @state: State we're coming out of.
+ *
+ * This is called after we wake back up (or if entering the sleep state
+ * failed).
+ */
+
+static int omap_pm_finish(suspend_state_t state)
+{
+ pm_idle = saved_idle;
+ return 0;
+}
+
+
+static irqreturn_t omap_wakeup_interrupt(int irq, void * dev,
+ struct pt_regs * regs)
+{
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap_wakeup_irq = {
+ .name = "peripheral wakeup",
+ .flags = SA_INTERRUPT,
+ .handler = omap_wakeup_interrupt
+};
+
+
+
+static struct pm_ops omap_pm_ops ={
+ .pm_disk_mode = 0,
+ .prepare = omap_pm_prepare,
+ .enter = omap_pm_enter,
+ .finish = omap_pm_finish,
+};
+
+static int __init omap_pm_init(void)
+{
+ printk("Power Management for TI OMAP.\n");
+
+ /*
+ * We copy the assembler sleep/wakeup routines to SRAM.
+ * These routines need to be in SRAM as that's the only
+ * memory the MPU can see when it wakes up.
+ */
+ if (cpu_is_omap730()) {
+ omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend,
+ omap730_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap730_cpu_suspend,
+ omap730_cpu_suspend_sz);
+ } else if (cpu_is_omap15xx()) {
+ omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend,
+ omap1510_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
+ omap1510_cpu_suspend_sz);
+ } else if (cpu_is_omap16xx()) {
+ omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend,
+ omap1610_idle_loop_suspend_sz);
+ omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
+ omap1610_cpu_suspend_sz);
+ }
+
+ if (omap_sram_idle == NULL || omap_sram_suspend == NULL) {
+ printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
+ return -ENODEV;
+ }
+
+ pm_idle = omap_pm_idle;
+
+ if (cpu_is_omap730())
+ setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq);
+ else if (cpu_is_omap16xx())
+ setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+
+ /* Program new power ramp-up time
+ * (0 for most boards since we don't lower voltage when in deep sleep)
+ */
+ omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3);
+
+ /* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */
+ omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL);
+
+ /* Configure IDLECT3 */
+ if (cpu_is_omap730())
+ omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3);
+ else if (cpu_is_omap16xx())
+ omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
+
+ pm_set_ops(&omap_pm_ops);
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+ omap_pm_init_proc();
+#endif
+
+ subsys_create_file(&power_subsys, &sleep_while_idle_attr);
+
+ if (cpu_is_omap16xx()) {
+ /* configure LOW_PWR pin */
+ omap_cfg_reg(T20_1610_LOW_PWR);
+ }
+
+ return 0;
+}
+__initcall(omap_pm_init);
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index e924e0c6a4c..9b4cd698bec 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -30,9 +30,9 @@
#include <asm/arch/pm.h>
#endif
-static struct clk * uart1_ck = NULL;
-static struct clk * uart2_ck = NULL;
-static struct clk * uart3_ck = NULL;
+static struct clk * uart1_ck;
+static struct clk * uart2_ck;
+static struct clk * uart3_ck;
static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
int offset)
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/mach-omap1/sleep.S
index 4cd7d292f85..e58295e2d3b 100644
--- a/arch/arm/plat-omap/sleep.S
+++ b/arch/arm/mach-omap1/sleep.S
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/plat-omap/sleep.S
+ * linux/arch/arm/mach-omap1/sleep.S
*
* Low-level OMAP730/1510/1610 sleep/wakeUp support
*
@@ -383,60 +383,133 @@ ENTRY(omap1610_cpu_suspend)
mcr p15, 0, r0, c7, c10, 4
nop
- @ load base address of Traffic Controller
+ @ Load base address of Traffic Controller
mov r6, #TCMIF_ASM_BASE & 0xff000000
orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
- @ prepare to put SDRAM into self-refresh manually
+ @ Prepare to put SDRAM into self-refresh manually
ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
- @ prepare to put EMIFS to Sleep
+ @ Prepare to put EMIFS to Sleep
ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
- @ load base address of ARM_IDLECT1 and ARM_IDLECT2
+ @ Load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
- @ turn off clock domains
- @ do not disable PERCK (0x04)
+ @ Turn off clock domains
+ @ Do not disable PERCK (0x04)
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
- @ request ARM idle
+ @ Request ARM idle
mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
- @ disable instruction cache
- mrc p15, 0, r9, c1, c0, 0
- bic r2, r9, #0x1000
- mcr p15, 0, r2, c1, c0, 0
- nop
-
/*
* Let's wait for the next wake up event to wake us up. r0 can't be
* used here because r0 holds ARM_IDLECT1
*/
mov r2, #0
mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
+
+ @ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
+ @ according to this formula:
+ @ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
+ @ Max DPLL_MULT = 18
+ @ DPLL_DIV = 1
+ @ ARMDIV = 1
+ @ => 74 nop-instructions
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @10
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @20
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @30
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @40
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @50
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @60
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop @70
+ nop
+ nop
+ nop
+ nop @74
/*
* omap1610_cpu_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
* stack.
*/
- @ re-enable Icache
- mcr p15, 0, r9, c1, c0, 0
-
- @ reset the ARM_IDLECT1 and ARM_IDLECT2.
+ @ Restore the ARM_IDLECT1 and ARM_IDLECT2.
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
@@ -444,7 +517,7 @@ ENTRY(omap1610_cpu_suspend)
str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
- @ restore regs and return
+ @ Restore regs and return
ldmfd sp!, {r0 - r12, pc}
ENTRY(omap1610_cpu_suspend_sz)
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index cdbf4d7620c..a85fe6066bc 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -51,8 +51,6 @@
struct sys_timer omap_timer;
-#ifdef CONFIG_OMAP_MPU_TIMER
-
/*
* ---------------------------------------------------------------------------
* MPU timer
@@ -222,195 +220,6 @@ unsigned long long sched_clock(void)
return cycles_2_ns(ticks64);
}
-#endif /* CONFIG_OMAP_MPU_TIMER */
-
-#ifdef CONFIG_OMAP_32K_TIMER
-
-#ifdef CONFIG_ARCH_OMAP15XX
-#error OMAP 32KHz timer does not currently work on 15XX!
-#endif
-
-/*
- * ---------------------------------------------------------------------------
- * 32KHz OS timer
- *
- * This currently works only on 16xx, as 1510 does not have the continuous
- * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
- * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
- * on 1510 would be possible, but the timer would not be as accurate as
- * with the 32KHz synchronized timer.
- * ---------------------------------------------------------------------------
- */
-#define OMAP_32K_TIMER_BASE 0xfffb9000
-#define OMAP_32K_TIMER_CR 0x08
-#define OMAP_32K_TIMER_TVR 0x00
-#define OMAP_32K_TIMER_TCR 0x04
-
-#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
-
-/*
- * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
- * so with HZ = 100, TVR = 327.68.
- */
-#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
-#define TIMER_32K_SYNCHRONIZED 0xfffbc410
-
-#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
- (((nr_jiffies) * (clock_rate)) / HZ)
-
-static inline void omap_32k_timer_write(int val, int reg)
-{
- omap_writew(val, reg + OMAP_32K_TIMER_BASE);
-}
-
-static inline unsigned long omap_32k_timer_read(int reg)
-{
- return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff;
-}
-
-/*
- * The 32KHz synchronized timer is an additional timer on 16xx.
- * It is always running.
- */
-static inline unsigned long omap_32k_sync_timer_read(void)
-{
- return omap_readl(TIMER_32K_SYNCHRONIZED);
-}
-
-static inline void omap_32k_timer_start(unsigned long load_val)
-{
- omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR);
- omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR);
-}
-
-static inline void omap_32k_timer_stop(void)
-{
- omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR);
-}
-
-/*
- * Rounds down to nearest usec. Note that this will overflow for larger values.
- */
-static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
-{
- return (ticks_32k * 5*5*5*5*5*5) >> 9;
-}
-
-/*
- * Rounds down to nearest nsec.
- */
-static inline unsigned long long
-omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
-{
- return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
-}
-
-static unsigned long omap_32k_last_tick = 0;
-
-/*
- * Returns elapsed usecs since last 32k timer interrupt
- */
-static unsigned long omap_32k_timer_gettimeoffset(void)
-{
- unsigned long now = omap_32k_sync_timer_read();
- return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
-}
-
-/*
- * Returns current time from boot in nsecs. It's OK for this to wrap
- * around for now, as it's just a relative time stamp.
- */
-unsigned long long sched_clock(void)
-{
- return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
-}
-
-/*
- * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
- * function is also called from other interrupts to remove latency
- * issues with dynamic tick. In the dynamic tick case, we need to lock
- * with irqsave.
- */
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
-{
- unsigned long flags;
- unsigned long now;
-
- write_seqlock_irqsave(&xtime_lock, flags);
- now = omap_32k_sync_timer_read();
-
- while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
- omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
- timer_tick(regs);
- }
-
- /* Restart timer so we don't drift off due to modulo or dynamic tick.
- * By default we program the next timer to be continuous to avoid
- * latencies during high system load. During dynamic tick operation the
- * continuous timer can be overridden from pm_idle to be longer.
- */
- omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
- write_sequnlock_irqrestore(&xtime_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_NO_IDLE_HZ
-/*
- * Programs the next timer interrupt needed. Called when dynamic tick is
- * enabled, and to reprogram the ticks to skip from pm_idle. Note that
- * we can keep the timer continuous, and don't need to set it to run in
- * one-shot mode. This is because the timer will get reprogrammed again
- * after next interrupt.
- */
-void omap_32k_timer_reprogram(unsigned long next_tick)
-{
- omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
-}
-
-static struct irqaction omap_32k_timer_irq;
-extern struct timer_update_handler timer_update;
-
-static int omap_32k_timer_enable_dyn_tick(void)
-{
- /* No need to reprogram timer, just use the next interrupt */
- return 0;
-}
-
-static int omap_32k_timer_disable_dyn_tick(void)
-{
- omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
- return 0;
-}
-
-static struct dyn_tick_timer omap_dyn_tick_timer = {
- .enable = omap_32k_timer_enable_dyn_tick,
- .disable = omap_32k_timer_disable_dyn_tick,
- .reprogram = omap_32k_timer_reprogram,
- .handler = omap_32k_timer_interrupt,
-};
-#endif /* CONFIG_NO_IDLE_HZ */
-
-static struct irqaction omap_32k_timer_irq = {
- .name = "32KHz timer",
- .flags = SA_INTERRUPT | SA_TIMER,
- .handler = omap_32k_timer_interrupt,
-};
-
-static __init void omap_init_32k_timer(void)
-{
-
-#ifdef CONFIG_NO_IDLE_HZ
- omap_timer.dyn_tick = &omap_dyn_tick_timer;
-#endif
-
- setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
- omap_timer.offset = omap_32k_timer_gettimeoffset;
- omap_32k_last_tick = omap_32k_sync_timer_read();
- omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
-}
-#endif /* CONFIG_OMAP_32K_TIMER */
/*
* ---------------------------------------------------------------------------
@@ -419,13 +228,7 @@ static __init void omap_init_32k_timer(void)
*/
static void __init omap_timer_init(void)
{
-#if defined(CONFIG_OMAP_MPU_TIMER)
omap_init_mpu_timer();
-#elif defined(CONFIG_OMAP_32K_TIMER)
- omap_init_32k_timer();
-#else
-#error No system timer selected in Kconfig!
-#endif
}
struct sys_timer omap_timer = {
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 578880943cf..537dd2e6d38 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -20,3 +20,6 @@ config MACH_OMAP_H4
bool "OMAP 2420 H4 board"
depends on ARCH_OMAP2 && ARCH_OMAP24XX
+config MACH_OMAP_APOLLON
+ bool "OMAP 2420 Apollon board"
+ depends on ARCH_OMAP2 && ARCH_OMAP24XX
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 42041166435..111eaa64258 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,11 +3,15 @@
#
# Common support
-obj-y := irq.o id.o io.o sram-fn.o clock.o mux.o devices.o serial.o
+obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o serial.o
obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
# Specific board support
obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
+obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
new file mode 100644
index 00000000000..6c6ba172cdf
--- /dev/null
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -0,0 +1,285 @@
+/*
+ * linux/arch/arm/mach-omap/omap2/board-apollon.c
+ *
+ * Copyright (C) 2005,2006 Samsung Electronics
+ * Author: Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * Modified from mach-omap/omap2/board-h4.c
+ *
+ * Code for apollon OMAP2 board. Should work on many OMAP2 systems where
+ * the bootloader passes the board-specific data to the kernel.
+ * Do not put any board specific code to this file; create a new machine
+ * type if you need custom low-level initializations.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/onenand.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
+#include <asm/arch/common.h>
+#include "prcm-regs.h"
+
+/* LED & Switch macros */
+#define LED0_GPIO13 13
+#define LED1_GPIO14 14
+#define LED2_GPIO15 15
+#define SW_ENTER_GPIO16 16
+#define SW_UP_GPIO17 17
+#define SW_DOWN_GPIO58 58
+
+static struct mtd_partition apollon_partitions[] = {
+ {
+ .name = "X-Loader + U-Boot",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ },
+ {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_16M,
+ },
+ {
+ .name = "filesystem00",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_32M,
+ },
+ {
+ .name = "filesystem01",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct flash_platform_data apollon_flash_data = {
+ .parts = apollon_partitions,
+ .nr_parts = ARRAY_SIZE(apollon_partitions),
+};
+
+static struct resource apollon_flash_resource = {
+ .start = APOLLON_CS0_BASE,
+ .end = APOLLON_CS0_BASE + SZ_128K,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device apollon_onenand_device = {
+ .name = "onenand",
+ .id = -1,
+ .dev = {
+ .platform_data = &apollon_flash_data,
+ },
+ .num_resources = ARRAY_SIZE(&apollon_flash_resource),
+ .resource = &apollon_flash_resource,
+};
+
+static struct resource apollon_smc91x_resources[] = {
+ [0] = {
+ .start = APOLLON_ETHR_START, /* Physical */
+ .end = APOLLON_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+ .end = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device apollon_smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(apollon_smc91x_resources),
+ .resource = apollon_smc91x_resources,
+};
+
+static struct platform_device apollon_lcd_device = {
+ .name = "apollon_lcd",
+ .id = -1,
+};
+
+static struct platform_device *apollon_devices[] __initdata = {
+ &apollon_onenand_device,
+ &apollon_smc91x_device,
+ &apollon_lcd_device,
+};
+
+static inline void __init apollon_init_smc91x(void)
+{
+ /* Make sure CS1 timings are correct */
+ GPMC_CONFIG1_1 = 0x00011203;
+ GPMC_CONFIG2_1 = 0x001f1f01;
+ GPMC_CONFIG3_1 = 0x00080803;
+ GPMC_CONFIG4_1 = 0x1c091c09;
+ GPMC_CONFIG5_1 = 0x041f1f1f;
+ GPMC_CONFIG6_1 = 0x000004c4;
+ GPMC_CONFIG7_1 = 0x00000f40 | (APOLLON_CS1_BASE >> 24);
+ udelay(100);
+
+ omap_cfg_reg(W4__24XX_GPIO74);
+ if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) {
+ printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
+ APOLLON_ETHR_GPIO_IRQ);
+ return;
+ }
+ omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
+}
+
+static void __init omap_apollon_init_irq(void)
+{
+ omap2_init_common_hw();
+ omap_init_irq();
+ omap_gpio_init();
+ apollon_init_smc91x();
+}
+
+static struct omap_uart_config apollon_uart_config __initdata = {
+ .enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2),
+};
+
+static struct omap_mmc_config apollon_mmc_config __initdata = {
+ .mmc [0] = {
+ .enabled = 0,
+ .wire4 = 0,
+ .wp_pin = -1,
+ .power_pin = -1,
+ .switch_pin = -1,
+ },
+};
+
+static struct omap_lcd_config apollon_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel apollon_config[] = {
+ { OMAP_TAG_UART, &apollon_uart_config },
+ { OMAP_TAG_MMC, &apollon_mmc_config },
+ { OMAP_TAG_LCD, &apollon_lcd_config },
+};
+
+static void __init apollon_led_init(void)
+{
+ /* LED0 - AA10 */
+ omap_cfg_reg(AA10_242X_GPIO13);
+ omap_request_gpio(LED0_GPIO13);
+ omap_set_gpio_direction(LED0_GPIO13, 0);
+ omap_set_gpio_dataout(LED0_GPIO13, 0);
+ /* LED1 - AA6 */
+ omap_cfg_reg(AA6_242X_GPIO14);
+ omap_request_gpio(LED1_GPIO14);
+ omap_set_gpio_direction(LED1_GPIO14, 0);
+ omap_set_gpio_dataout(LED1_GPIO14, 0);
+ /* LED2 - AA4 */
+ omap_cfg_reg(AA4_242X_GPIO15);
+ omap_request_gpio(LED2_GPIO15);
+ omap_set_gpio_direction(LED2_GPIO15, 0);
+ omap_set_gpio_dataout(LED2_GPIO15, 0);
+}
+
+static irqreturn_t apollon_sw_interrupt(int irq, void *ignored, struct pt_regs *regs)
+{
+ static unsigned int led0, led1, led2;
+
+ if (irq == OMAP_GPIO_IRQ(SW_ENTER_GPIO16))
+ omap_set_gpio_dataout(LED0_GPIO13, led0 ^= 1);
+ else if (irq == OMAP_GPIO_IRQ(SW_UP_GPIO17))
+ omap_set_gpio_dataout(LED1_GPIO14, led1 ^= 1);
+ else if (irq == OMAP_GPIO_IRQ(SW_DOWN_GPIO58))
+ omap_set_gpio_dataout(LED2_GPIO15, led2 ^= 1);
+
+ return IRQ_HANDLED;
+}
+
+static void __init apollon_sw_init(void)
+{
+ /* Enter SW - Y11 */
+ omap_cfg_reg(Y11_242X_GPIO16);
+ omap_request_gpio(SW_ENTER_GPIO16);
+ omap_set_gpio_direction(SW_ENTER_GPIO16, 1);
+ /* Up SW - AA12 */
+ omap_cfg_reg(AA12_242X_GPIO17);
+ omap_request_gpio(SW_UP_GPIO17);
+ omap_set_gpio_direction(SW_UP_GPIO17, 1);
+ /* Down SW - AA8 */
+ omap_cfg_reg(AA8_242X_GPIO58);
+ omap_request_gpio(SW_DOWN_GPIO58);
+ omap_set_gpio_direction(SW_DOWN_GPIO58, 1);
+
+ set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING);
+ if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt,
+ SA_SHIRQ, "enter sw",
+ &apollon_sw_interrupt))
+ return;
+ set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING);
+ if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt,
+ SA_SHIRQ, "up sw",
+ &apollon_sw_interrupt))
+ return;
+ set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING);
+ if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt,
+ SA_SHIRQ, "down sw",
+ &apollon_sw_interrupt))
+ return;
+}
+
+static void __init omap_apollon_init(void)
+{
+ apollon_led_init();
+ apollon_sw_init();
+
+ /* REVISIT: where's the correct place */
+ omap_cfg_reg(W19_24XX_SYS_NIRQ);
+
+ /*
+ * Make sure the serial ports are muxed on at this point.
+ * You have to mux them off in device drivers later on
+ * if not needed.
+ */
+ platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
+ omap_board_config = apollon_config;
+ omap_board_config_size = ARRAY_SIZE(apollon_config);
+ omap_serial_init();
+}
+
+static void __init omap_apollon_map_io(void)
+{
+ omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
+ /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+ .phys_io = 0x48000000,
+ .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
+ .boot_params = 0x80000100,
+ .map_io = omap_apollon_map_io,
+ .init_irq = omap_apollon_init_irq,
+ .init_machine = omap_apollon_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index a300d634d8a..4933fce766c 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -17,6 +17,8 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -25,15 +27,57 @@
#include <asm/mach/flash.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/gpioexpander.h>
#include <asm/arch/mux.h>
#include <asm/arch/usb.h>
+#include <asm/arch/irda.h>
#include <asm/arch/board.h>
#include <asm/arch/common.h>
-#include <asm/arch/prcm.h>
+#include <asm/arch/keypad.h>
+#include <asm/arch/menelaus.h>
+#include <asm/arch/dma.h>
+#include "prcm-regs.h"
#include <asm/io.h>
#include <asm/delay.h>
+static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
+static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
+
+static int h4_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_A),
+ KEY(0, 3, KEY_B),
+ KEY(0, 4, KEY_C),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_E),
+ KEY(1, 3, KEY_F),
+ KEY(1, 4, KEY_G),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_I),
+ KEY(2, 2, KEY_J),
+ KEY(2, 3, KEY_K),
+ KEY(2, 4, KEY_3),
+ KEY(3, 0, KEY_M),
+ KEY(3, 1, KEY_N),
+ KEY(3, 2, KEY_O),
+ KEY(3, 3, KEY_P),
+ KEY(3, 4, KEY_Q),
+ KEY(4, 0, KEY_R),
+ KEY(4, 1, KEY_4),
+ KEY(4, 2, KEY_T),
+ KEY(4, 3, KEY_U),
+ KEY(4, 4, KEY_ENTER),
+ KEY(5, 0, KEY_V),
+ KEY(5, 1, KEY_W),
+ KEY(5, 2, KEY_L),
+ KEY(5, 3, KEY_S),
+ KEY(5, 4, KEY_ENTER),
+ 0
+};
+
static struct mtd_partition h4_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
{
@@ -108,9 +152,123 @@ static struct platform_device h4_smc91x_device = {
.resource = h4_smc91x_resources,
};
+/* Select between the IrDA and aGPS module
+ */
+static int h4_select_irda(struct device *dev, int state)
+{
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x21))) {
+ printk(KERN_ERR "Error reading from I/O expander\n");
+ return err;
+ }
+
+ /* 'P6' enable/disable IRDA_TX and IRDA_RX */
+ if (state & IR_SEL) { /* IrDa */
+ if ((err = write_gpio_expa(expa | 0x01, 0x21))) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ return err;
+ }
+ } else {
+ if ((err = write_gpio_expa(expa & ~0x01, 0x21))) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ return err;
+ }
+ }
+ return err;
+}
+
+static void set_trans_mode(void *data)
+{
+ int *mode = data;
+ unsigned char expa;
+ int err = 0;
+
+ if ((err = read_gpio_expa(&expa, 0x20)) != 0) {
+ printk(KERN_ERR "Error reading from I/O expander\n");
+ }
+
+ expa &= ~0x01;
+
+ if (!(*mode & IR_SIRMODE)) { /* MIR/FIR */
+ expa |= 0x01;
+ }
+
+ if ((err = write_gpio_expa(expa, 0x20)) != 0) {
+ printk(KERN_ERR "Error writing to I/O expander\n");
+ }
+}
+
+static int h4_transceiver_mode(struct device *dev, int mode)
+{
+ struct omap_irda_config *irda_config = dev->platform_data;
+
+ cancel_delayed_work(&irda_config->gpio_expa);
+ PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode);
+ schedule_work(&irda_config->gpio_expa);
+
+ return 0;
+}
+
+static struct omap_irda_config h4_irda_data = {
+ .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
+ .transceiver_mode = h4_transceiver_mode,
+ .select_irda = h4_select_irda,
+ .rx_channel = OMAP24XX_DMA_UART3_RX,
+ .tx_channel = OMAP24XX_DMA_UART3_TX,
+ .dest_start = OMAP_UART3_BASE,
+ .src_start = OMAP_UART3_BASE,
+ .tx_trigger = OMAP24XX_DMA_UART3_TX,
+ .rx_trigger = OMAP24XX_DMA_UART3_RX,
+};
+
+static struct resource h4_irda_resources[] = {
+ [0] = {
+ .start = INT_24XX_UART3_IRQ,
+ .end = INT_24XX_UART3_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device h4_irda_device = {
+ .name = "omapirda",
+ .id = -1,
+ .dev = {
+ .platform_data = &h4_irda_data,
+ },
+ .num_resources = 1,
+ .resource = h4_irda_resources,
+};
+
+static struct omap_kp_platform_data h4_kp_data = {
+ .rows = 6,
+ .cols = 7,
+ .keymap = h4_keymap,
+ .rep = 1,
+ .row_gpios = row_gpios,
+ .col_gpios = col_gpios,
+};
+
+static struct platform_device h4_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &h4_kp_data,
+ },
+};
+
+static struct platform_device h4_lcd_device = {
+ .name = "lcd_h4",
+ .id = -1,
+};
+
static struct platform_device *h4_devices[] __initdata = {
&h4_smc91x_device,
&h4_flash_device,
+ &h4_irda_device,
+ &h4_kp_device,
+ &h4_lcd_device,
};
static inline void __init h4_init_smc91x(void)
@@ -157,7 +315,6 @@ static struct omap_mmc_config h4_mmc_config __initdata = {
};
static struct omap_lcd_config h4_lcd_config __initdata = {
- .panel_name = "h4",
.ctrl_name = "internal",
};
@@ -174,6 +331,19 @@ static void __init omap_h4_init(void)
* You have to mux them off in device drivers later on
* if not needed.
*/
+#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE)
+ omap_cfg_reg(K15_24XX_UART3_TX);
+ omap_cfg_reg(K14_24XX_UART3_RX);
+#endif
+
+#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+ if (omap_has_menelaus()) {
+ row_gpios[5] = 0;
+ col_gpios[2] = 15;
+ col_gpios[6] = 18;
+ }
+#endif
+
platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
omap_board_config = h4_config;
omap_board_config_size = ARRAY_SIZE(h4_config);
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 180f675c906..72eb4bf571a 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -28,14 +28,14 @@
#include <asm/arch/clock.h>
#include <asm/arch/sram.h>
-#include <asm/arch/prcm.h>
+#include "prcm-regs.h"
+#include "memory.h"
#include "clock.h"
//#define DOWN_VARIABLE_DPLL 1 /* Experimental */
static struct prcm_config *curr_prcm_set;
-static struct memory_timings mem_timings;
static u32 curr_perf_level = PRCM_FULL_SPEED;
/*-------------------------------------------------------------------------
@@ -54,11 +54,13 @@ static void omap2_sys_clk_recalc(struct clk * clk)
static u32 omap2_get_dpll_rate(struct clk * tclk)
{
- int dpll_clk, dpll_mult, dpll_div, amult;
+ long long dpll_clk;
+ int dpll_mult, dpll_div, amult;
dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */
dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */
- dpll_clk = (tclk->parent->rate * dpll_mult) / (dpll_div + 1);
+ dpll_clk = (long long)tclk->parent->rate * dpll_mult;
+ do_div(dpll_clk, dpll_div + 1);
amult = CM_CLKSEL2_PLL & 0x3;
dpll_clk *= amult;
@@ -385,75 +387,23 @@ static u32 omap2_dll_force_needed(void)
return 0;
}
-static void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
-{
- unsigned long dll_cnt;
- u32 fast_dll = 0;
-
- mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
-
- /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
- * In the case of 2422, its ok to use CS1 instead of CS0.
- */
-
-#if 0 /* FIXME: Enable after 24xx cpu detection works */
- ctype = get_cpu_type();
- if (cpu_is_omap2422())
- mem_timings.base_cs = 1;
- else
-#endif
- mem_timings.base_cs = 0;
-
- if (mem_timings.m_type != M_DDR)
- return;
-
- /* With DDR we need to determine the low frequency DLL value */
- if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
- mem_timings.dll_mode = M_UNLOCK;
- else
- mem_timings.dll_mode = M_LOCK;
-
- if (mem_timings.base_cs == 0) {
- fast_dll = SDRC_DLLA_CTRL;
- dll_cnt = SDRC_DLLA_STATUS & 0xff00;
- } else {
- fast_dll = SDRC_DLLB_CTRL;
- dll_cnt = SDRC_DLLB_STATUS & 0xff00;
- }
- if (force_lock_to_unlock_mode) {
- fast_dll &= ~0xff00;
- fast_dll |= dll_cnt; /* Current lock mode */
- }
- mem_timings.fast_dll_ctrl = fast_dll;
-
- /* No disruptions, DDR will be offline & C-ABI not followed */
- omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
- mem_timings.fast_dll_ctrl,
- mem_timings.base_cs,
- force_lock_to_unlock_mode);
- mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */
-
- /* Turn status into unlock ctrl */
- mem_timings.slow_dll_ctrl |=
- ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
-
- /* 90 degree phase for anything below 133Mhz */
- mem_timings.slow_dll_ctrl |= (1 << 1);
-}
-
static u32 omap2_reprogram_sdrc(u32 level, u32 force)
{
+ u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
u32 prev = curr_perf_level, flags;
if ((curr_perf_level == level) && !force)
return prev;
+ m_type = omap2_memory_get_type();
+ slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
+ fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
+
if (level == PRCM_HALF_SPEED) {
local_irq_save(flags);
PRCM_VOLTSETUP = 0xffff;
omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
- mem_timings.slow_dll_ctrl,
- mem_timings.m_type);
+ slow_dll_ctrl, m_type);
curr_perf_level = PRCM_HALF_SPEED;
local_irq_restore(flags);
}
@@ -461,8 +411,7 @@ static u32 omap2_reprogram_sdrc(u32 level, u32 force)
local_irq_save(flags);
PRCM_VOLTSETUP = 0xffff;
omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
- mem_timings.fast_dll_ctrl,
- mem_timings.m_type);
+ fast_dll_ctrl, m_type);
curr_perf_level = PRCM_FULL_SPEED;
local_irq_restore(flags);
}
@@ -650,7 +599,7 @@ static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
case 13: /* dss2 */
mask = 0x1; break;
case 25: /* usb */
- mask = 0xf; break;
+ mask = 0x7; break;
}
}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 6cab20b1d3c..6c78d471fab 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -33,20 +33,6 @@ static u32 omap2_clksel_get_divisor(struct clk *clk);
#define RATE_IN_242X (1 << 0)
#define RATE_IN_243X (1 << 1)
-/* Memory timings */
-#define M_DDR 1
-#define M_LOCK_CTRL (1 << 2)
-#define M_UNLOCK 0
-#define M_LOCK 1
-
-struct memory_timings {
- u32 m_type; /* ddr = 1, sdr = 0 */
- u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */
- u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */
- u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */
- u32 base_cs; /* base chip select to use for calculations */
-};
-
/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
* xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
* CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
@@ -731,6 +717,16 @@ static struct clk sys_clkout2 = {
.recalc = &omap2_clksel_recalc,
};
+static struct clk emul_ck = {
+ .name = "emul_ck",
+ .parent = &func_54m_ck,
+ .flags = CLOCK_IN_OMAP242X,
+ .enable_reg = (void __iomem *)&PRCM_CLKEMUL_CTRL,
+ .enable_bit = 0,
+ .recalc = &omap2_propagate_rate,
+
+};
+
/*
* MPU clock domain
* Clocks:
@@ -1702,7 +1698,8 @@ static struct clk hdq_fck = {
};
static struct clk i2c2_ick = {
- .name = "i2c2_ick",
+ .name = "i2c_ick",
+ .id = 2,
.parent = &l4_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1711,7 +1708,8 @@ static struct clk i2c2_ick = {
};
static struct clk i2c2_fck = {
- .name = "i2c2_fck",
+ .name = "i2c_fck",
+ .id = 2,
.parent = &func_12m_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1729,7 +1727,8 @@ static struct clk i2chs2_fck = {
};
static struct clk i2c1_ick = {
- .name = "i2c1_ick",
+ .name = "i2c_ick",
+ .id = 1,
.parent = &l4_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_ICLKEN1_CORE,
@@ -1738,7 +1737,8 @@ static struct clk i2c1_ick = {
};
static struct clk i2c1_fck = {
- .name = "i2c1_fck",
+ .name = "i2c_fck",
+ .id = 1,
.parent = &func_12m_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_FCLKEN1_CORE,
@@ -1971,6 +1971,7 @@ static struct clk *onchip_clks[] = {
&wdt1_osc_ck,
&sys_clkout,
&sys_clkout2,
+ &emul_ck,
/* mpu domain clocks */
&mpu_ck,
/* dsp domain clocks */
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 7181edb8935..def9e5370ed 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -74,6 +74,47 @@ static void omap_init_i2c(void) {}
#endif
+#if defined(CONFIG_OMAP_STI)
+
+#define OMAP2_STI_BASE IO_ADDRESS(0x48068000)
+#define OMAP2_STI_CHANNEL_BASE 0x54000000
+#define OMAP2_STI_IRQ 4
+
+static struct resource sti_resources[] = {
+ {
+ .start = OMAP2_STI_BASE,
+ .end = OMAP2_STI_BASE + 0x7ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP2_STI_CHANNEL_BASE,
+ .end = OMAP2_STI_CHANNEL_BASE + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = OMAP2_STI_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device sti_device = {
+ .name = "sti",
+ .id = -1,
+ .dev = {
+ .release = omap_nop_release,
+ },
+ .num_resources = ARRAY_SIZE(sti_resources),
+ .resource = sti_resources,
+};
+
+static inline void omap_init_sti(void)
+{
+ platform_device_register(&sti_device);
+}
+#else
+static inline void omap_init_sti(void) {}
+#endif
+
/*-------------------------------------------------------------------------*/
static int __init omap2_init_devices(void)
@@ -82,6 +123,7 @@ static int __init omap2_init_devices(void)
* in alphabetical order so they're easier to sort through.
*/
omap_init_i2c();
+ omap_init_sti();
return 0;
}
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 8ea67bf196a..7d5711611f2 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -16,9 +16,13 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/mach/map.h>
+#include <asm/tlb.h>
#include <asm/io.h>
+
+#include <asm/mach/map.h>
+
#include <asm/arch/mux.h>
+#include <asm/arch/omapfb.h>
extern void omap_sram_init(void);
extern int omap2_clk_init(void);
@@ -43,11 +47,24 @@ static struct map_desc omap2_io_desc[] __initdata = {
}
};
-void __init omap_map_common_io(void)
+void __init omap2_map_common_io(void)
{
iotable_init(omap2_io_desc, ARRAY_SIZE(omap2_io_desc));
+
+ /* Normally devicemaps_init() would flush caches and tlb after
+ * mdesc->map_io(), but we must also do it here because of the CPU
+ * revision check below.
+ */
+ local_flush_tlb_all();
+ flush_cache_all();
+
omap2_check_revision();
omap_sram_init();
+ omapfb_reserve_mem();
+}
+
+void __init omap2_init_common_hw(void)
+{
omap2_mux_init();
omap2_clk_init();
}
diff --git a/arch/arm/mach-omap2/memory.c b/arch/arm/mach-omap2/memory.c
new file mode 100644
index 00000000000..1d925d69fc3
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.c
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.c
+ *
+ * Memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+
+#include "prcm-regs.h"
+#include "memory.h"
+
+static struct memory_timings mem_timings;
+
+u32 omap2_memory_get_slow_dll_ctrl(void)
+{
+ return mem_timings.slow_dll_ctrl;
+}
+
+u32 omap2_memory_get_fast_dll_ctrl(void)
+{
+ return mem_timings.fast_dll_ctrl;
+}
+
+u32 omap2_memory_get_type(void)
+{
+ return mem_timings.m_type;
+}
+
+void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+{
+ unsigned long dll_cnt;
+ u32 fast_dll = 0;
+
+ mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+
+ /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
+ * In the case of 2422, its ok to use CS1 instead of CS0.
+ */
+ if (cpu_is_omap2422())
+ mem_timings.base_cs = 1;
+ else
+ mem_timings.base_cs = 0;
+
+ if (mem_timings.m_type != M_DDR)
+ return;
+
+ /* With DDR we need to determine the low frequency DLL value */
+ if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
+ mem_timings.dll_mode = M_UNLOCK;
+ else
+ mem_timings.dll_mode = M_LOCK;
+
+ if (mem_timings.base_cs == 0) {
+ fast_dll = SDRC_DLLA_CTRL;
+ dll_cnt = SDRC_DLLA_STATUS & 0xff00;
+ } else {
+ fast_dll = SDRC_DLLB_CTRL;
+ dll_cnt = SDRC_DLLB_STATUS & 0xff00;
+ }
+ if (force_lock_to_unlock_mode) {
+ fast_dll &= ~0xff00;
+ fast_dll |= dll_cnt; /* Current lock mode */
+ }
+ /* set fast timings with DLL filter disabled */
+ mem_timings.fast_dll_ctrl = (fast_dll | (3 << 8));
+
+ /* No disruptions, DDR will be offline & C-ABI not followed */
+ omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
+ mem_timings.fast_dll_ctrl,
+ mem_timings.base_cs,
+ force_lock_to_unlock_mode);
+ mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */
+
+ /* Turn status into unlock ctrl */
+ mem_timings.slow_dll_ctrl |=
+ ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
+
+ /* 90 degree phase for anything below 133Mhz + disable DLL filter */
+ mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8));
+}
diff --git a/arch/arm/mach-omap2/memory.h b/arch/arm/mach-omap2/memory.h
new file mode 100644
index 00000000000..d212eea83a0
--- /dev/null
+++ b/arch/arm/mach-omap2/memory.h
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/arm/mach-omap2/memory.h
+ *
+ * Interface for memory timing related functions for OMAP24XX
+ *
+ * Copyright (C) 2005 Texas Instruments Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Memory timings */
+#define M_DDR 1
+#define M_LOCK_CTRL (1 << 2)
+#define M_UNLOCK 0
+#define M_LOCK 1
+
+struct memory_timings {
+ u32 m_type; /* ddr = 1, sdr = 0 */
+ u32 dll_mode; /* use lock mode = 1, unlock mode = 0 */
+ u32 slow_dll_ctrl; /* unlock mode, dll value for slow speed */
+ u32 fast_dll_ctrl; /* unlock mode, dll value for fast speed */
+ u32 base_cs; /* base chip select to use for calculations */
+};
+
+extern void omap2_init_memory_params(u32 force_lock_to_unlock_mode);
+extern u32 omap2_memory_get_slow_dll_ctrl(void);
+extern u32 omap2_memory_get_fast_dll_ctrl(void);
+extern u32 omap2_memory_get_type(void);
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index ea4654815dd..1197dc38c20 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -50,9 +50,54 @@ MUX_CFG_24XX("H19_24XX_I2C2_SDA", 0x114, 0, 0, 0, 1)
/* Menelaus interrupt */
MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1)
+/* 24xx clocks */
+MUX_CFG_24XX("W14_24XX_SYS_CLKOUT", 0x137, 0, 1, 1, 1)
+
+/* 24xx McBSP */
+MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX", 0x124, 1, 1, 0, 1)
+MUX_CFG_24XX("R14_24XX_MCBSP2_FSX", 0x125, 1, 1, 0, 1)
+MUX_CFG_24XX("W15_24XX_MCBSP2_DR", 0x126, 1, 1, 0, 1)
+MUX_CFG_24XX("V15_24XX_MCBSP2_DX", 0x127, 1, 1, 0, 1)
+
/* 24xx GPIO */
+MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1)
+MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1)
+MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1)
+MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1)
+MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1)
+MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1)
+MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1)
MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1)
+MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1)
MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1)
+MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1)
+
+/* TSC IRQ */
+MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1)
+
+/* UART3 */
+MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1)
+MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1)
+
+/* Keypad GPIO*/
+MUX_CFG_24XX("T19_24XX_KBR0", 0x106, 3, 1, 1, 1)
+MUX_CFG_24XX("R19_24XX_KBR1", 0x107, 3, 1, 1, 1)
+MUX_CFG_24XX("V18_24XX_KBR2", 0x139, 3, 1, 1, 1)
+MUX_CFG_24XX("M21_24XX_KBR3", 0xc9, 3, 1, 1, 1)
+MUX_CFG_24XX("E5__24XX_KBR4", 0x138, 3, 1, 1, 1)
+MUX_CFG_24XX("M18_24XX_KBR5", 0x10e, 3, 1, 1, 1)
+MUX_CFG_24XX("R20_24XX_KBC0", 0x108, 3, 0, 0, 1)
+MUX_CFG_24XX("M14_24XX_KBC1", 0x109, 3, 0, 0, 1)
+MUX_CFG_24XX("H19_24XX_KBC2", 0x114, 3, 0, 0, 1)
+MUX_CFG_24XX("V17_24XX_KBC3", 0x135, 3, 0, 0, 1)
+MUX_CFG_24XX("P21_24XX_KBC4", 0xca, 3, 0, 0, 1)
+MUX_CFG_24XX("L14_24XX_KBC5", 0x10f, 3, 0, 0, 1)
+MUX_CFG_24XX("N19_24XX_KBC6", 0x110, 3, 0, 0, 1)
+
+/* 24xx Menelaus Keypad GPIO */
+MUX_CFG_24XX("B3__24XX_KBR5", 0x30, 3, 1, 1, 1)
+MUX_CFG_24XX("AA4_24XX_KBC2", 0xe7, 3, 0, 0, 1)
+MUX_CFG_24XX("B13_24XX_KBC6", 0x110, 3, 0, 0, 1)
};
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
new file mode 100644
index 00000000000..562168fa2b1
--- /dev/null
+++ b/arch/arm/mach-omap2/pm.c
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/arm/mach-omap2/pm.c
+ *
+ * OMAP2 Power Management Routines
+ *
+ * Copyright (C) 2006 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2005 Texas Instruments, Inc.
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * Based on pm.c for omap1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/pm.h>
+
+static struct clk *vclk;
+static void (*omap2_sram_idle)(void);
+static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
+static void (*saved_idle)(void);
+
+void omap2_pm_idle(void)
+{
+ local_irq_disable();
+ local_fiq_disable();
+ if (need_resched()) {
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+
+ /*
+ * Since an interrupt may set up a timer, we don't want to
+ * reprogram the hardware timer with interrupts enabled.
+ * Re-enable interrupts only after returning from idle.
+ */
+ timer_dyn_reprogram();
+
+ omap2_sram_idle();
+ local_fiq_enable();
+ local_irq_enable();
+}
+
+static int omap2_pm_prepare(suspend_state_t state)
+{
+ int error = 0;
+
+ /* We cannot sleep in idle until we have resumed */
+ saved_idle = pm_idle;
+ pm_idle = NULL;
+
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return error;
+}
+
+static int omap2_pm_enter(suspend_state_t state)
+{
+ switch (state)
+ {
+ case PM_SUSPEND_STANDBY:
+ case PM_SUSPEND_MEM:
+ /* FIXME: Add suspend */
+ break;
+
+ case PM_SUSPEND_DISK:
+ return -ENOTSUPP;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int omap2_pm_finish(suspend_state_t state)
+{
+ pm_idle = saved_idle;
+ return 0;
+}
+
+static struct pm_ops omap_pm_ops = {
+ .pm_disk_mode = 0,
+ .prepare = omap2_pm_prepare,
+ .enter = omap2_pm_enter,
+ .finish = omap2_pm_finish,
+};
+
+int __init omap2_pm_init(void)
+{
+ printk("Power Management for TI OMAP.\n");
+
+ vclk = clk_get(NULL, "virt_prcm_set");
+ if (IS_ERR(vclk)) {
+ printk(KERN_ERR "Could not get PM vclk\n");
+ return -ENODEV;
+ }
+
+ /*
+ * We copy the assembler sleep/wakeup routines to SRAM.
+ * These routines need to be in SRAM as that's the only
+ * memory the MPU can see when it wakes up.
+ */
+ omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+ omap24xx_idle_loop_suspend_sz);
+
+ omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+ omap24xx_cpu_suspend_sz);
+
+ pm_set_ops(&omap_pm_ops);
+ pm_idle = omap2_pm_idle;
+
+ return 0;
+}
+
+__initcall(omap2_pm_init);
diff --git a/arch/arm/mach-omap2/prcm.h b/arch/arm/mach-omap2/prcm-regs.h
index 2eb89b936c8..22ac7be4f78 100644
--- a/arch/arm/mach-omap2/prcm.h
+++ b/arch/arm/mach-omap2/prcm-regs.h
@@ -1,5 +1,7 @@
/*
- * prcm.h - Access definations for use in OMAP24XX clock and power management
+ * linux/arch/arm/mach-omap2/prcm-reg.h
+ *
+ * OMAP24XX Power Reset and Clock Management (PRCM) registers
*
* Copyright (C) 2005 Texas Instruments, Inc.
*
@@ -18,8 +20,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_ARM_ARCH_DPM_PRCM_H
-#define __ASM_ARM_ARCH_DPM_PRCM_H
+#ifndef __ARCH_ARM_MACH_OMAP2_PRCM_H
+#define __ARCH_ARM_MACH_OMAP2_PRCM_H
/* SET_PERFORMANCE_LEVEL PARAMETERS */
#define PRCM_HALF_SPEED 1
@@ -159,54 +161,63 @@
#define CM_FCLKEN_MDM PRCM_REG32(0xC00)
#define CM_ICLKEN_MDM PRCM_REG32(0xC10)
#define CM_IDLEST_MDM PRCM_REG32(0xC20)
+#define CM_AUTOIDLE_MDM PRCM_REG32(0xC30)
#define CM_CLKSEL_MDM PRCM_REG32(0xC40)
-
-/* FIXME: Move to header for 2430 */
-#define DISP_BASE (OMAP24XX_L4_IO_BASE+0x50000)
+#define CM_CLKSTCTRL_MDM PRCM_REG32(0xC48)
+#define RM_RSTCTRL_MDM PRCM_REG32(0xC50)
+#define RM_RSTST_MDM PRCM_REG32(0xC58)
+#define PM_WKEN_MDM PRCM_REG32(0xCA0)
+#define PM_WKST_MDM PRCM_REG32(0xCB0)
+#define PM_WKDEP_MDM PRCM_REG32(0xCC8)
+#define PM_PWSTCTRL_MDM PRCM_REG32(0xCE0)
+#define PM_PWSTST_MDM PRCM_REG32(0xCE4)
+
+#define OMAP24XX_L4_IO_BASE 0x48000000
+
+#define DISP_BASE (OMAP24XX_L4_IO_BASE + 0x50000)
#define DISP_REG32(offset) __REG32(DISP_BASE + (offset))
-#define GPMC_BASE (OMAP24XX_GPMC_BASE)
-#define GPMC_REG32(offset) __REG32(GPMC_BASE + (offset))
+#define OMAP24XX_GPMC_BASE (L3_24XX_BASE + 0xa000)
+#define GPMC_REG32(offset) __REG32(OMAP24XX_GPMC_BASE + (offset))
-#define GPT1_BASE (OMAP24XX_GPT1)
+/* FIXME: Move these to timer code */
+#define GPT1_BASE (0x48028000)
#define GPT1_REG32(offset) __REG32(GPT1_BASE + (offset))
/* Misc sysconfig */
#define DISPC_SYSCONFIG DISP_REG32(0x410)
-#define SPI_BASE (OMAP24XX_L4_IO_BASE+0x98000)
+#define SPI_BASE (OMAP24XX_L4_IO_BASE + 0x98000)
#define MCSPI1_SYSCONFIG __REG32(SPI_BASE + 0x10)
-#define MCSPI2_SYSCONFIG __REG32(SPI_BASE+0x2000 + 0x10)
-
-//#define DSP_MMU_SYSCONFIG 0x5A000010
-#define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE+0x2C10)
-//#define IVA_MMU_SYSCONFIG 0x5D000010
-//#define DSP_DMA_SYSCONFIG 0x00FCC02C
-#define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE+0x282C)
-#define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE+0x602C)
+#define MCSPI2_SYSCONFIG __REG32(SPI_BASE + 0x2000 + 0x10)
+#define MCSPI3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0xb8010)
+
+#define CAMERA_MMU_SYSCONFIG __REG32(DISP_BASE + 0x2C10)
+#define CAMERA_DMA_SYSCONFIG __REG32(DISP_BASE + 0x282C)
+#define SYSTEM_DMA_SYSCONFIG __REG32(DISP_BASE + 0x602C)
#define GPMC_SYSCONFIG GPMC_REG32(0x010)
-#define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x94010)
-#define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6A054)
-#define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6C054)
-#define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE+0x6E054)
-//#define IVA_SYSCONFIG 0x5C060010
-#define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE+0x10)
-#define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE+0x10)
-#define SSI_SYSCONFIG __REG32(DISP_BASE+0x8010)
-//#define VLYNQ_SYSCONFIG 0x67FFFE10
+#define MAILBOXES_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x94010)
+#define UART1_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6A054)
+#define UART2_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6C054)
+#define UART3_SYSCONFIG __REG32(OMAP24XX_L4_IO_BASE + 0x6E054)
+#define SDRC_SYSCONFIG __REG32(OMAP24XX_SDRC_BASE + 0x10)
+#define OMAP24XX_SMS_BASE (L3_24XX_BASE + 0x8000)
+#define SMS_SYSCONFIG __REG32(OMAP24XX_SMS_BASE + 0x10)
+#define SSI_SYSCONFIG __REG32(DISP_BASE + 0x8010)
/* rkw - good cannidates for PM_ to start what nm was trying */
-#define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE+0x2A000)
-#define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE+0x78000)
-#define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE+0x7A000)
-#define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE+0x7C000)
-#define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE+0x7E000)
-#define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE+0x80000)
-#define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE+0x82000)
-#define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE+0x84000)
-#define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE+0x86000)
-#define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE+0x88000)
-#define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE+0x8A000)
-
+#define OMAP24XX_GPT2 (OMAP24XX_L4_IO_BASE + 0x2A000)
+#define OMAP24XX_GPT3 (OMAP24XX_L4_IO_BASE + 0x78000)
+#define OMAP24XX_GPT4 (OMAP24XX_L4_IO_BASE + 0x7A000)
+#define OMAP24XX_GPT5 (OMAP24XX_L4_IO_BASE + 0x7C000)
+#define OMAP24XX_GPT6 (OMAP24XX_L4_IO_BASE + 0x7E000)
+#define OMAP24XX_GPT7 (OMAP24XX_L4_IO_BASE + 0x80000)
+#define OMAP24XX_GPT8 (OMAP24XX_L4_IO_BASE + 0x82000)
+#define OMAP24XX_GPT9 (OMAP24XX_L4_IO_BASE + 0x84000)
+#define OMAP24XX_GPT10 (OMAP24XX_L4_IO_BASE + 0x86000)
+#define OMAP24XX_GPT11 (OMAP24XX_L4_IO_BASE + 0x88000)
+#define OMAP24XX_GPT12 (OMAP24XX_L4_IO_BASE + 0x8A000)
+
+/* FIXME: Move these to timer code */
#define GPTIMER1_SYSCONFIG GPT1_REG32(0x010)
#define GPTIMER2_SYSCONFIG __REG32(OMAP24XX_GPT2 + 0x10)
#define GPTIMER3_SYSCONFIG __REG32(OMAP24XX_GPT3 + 0x10)
@@ -220,12 +231,18 @@
#define GPTIMER11_SYSCONFIG __REG32(OMAP24XX_GPT11 + 0x10)
#define GPTIMER12_SYSCONFIG __REG32(OMAP24XX_GPT12 + 0x10)
-#define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE+(0x2000*((X)-1)))
+/* FIXME: Move these to gpio code */
+#define OMAP24XX_GPIO_BASE 0x48018000
+#define GPIOX_BASE(X) (OMAP24XX_GPIO_BASE + (0x2000 * ((X) - 1)))
+
+#define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1) + 0x10))
+#define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2) + 0x10))
+#define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3) + 0x10))
+#define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4) + 0x10))
-#define GPIO1_SYSCONFIG __REG32((GPIOX_BASE(1)+0x10))
-#define GPIO2_SYSCONFIG __REG32((GPIOX_BASE(2)+0x10))
-#define GPIO3_SYSCONFIG __REG32((GPIOX_BASE(3)+0x10))
-#define GPIO4_SYSCONFIG __REG32((GPIOX_BASE(4)+0x10))
+#if defined(CONFIG_ARCH_OMAP243X)
+#define GPIO5_SYSCONFIG __REG32((OMAP24XX_GPIO5_BASE + 0x10))
+#endif
/* GP TIMER 1 */
#define GPTIMER1_TISTAT GPT1_REG32(0x014)
@@ -243,15 +260,15 @@
#define GPTIMER1_TCAR2 GPT1_REG32(0x044)
/* rkw -- base fix up please... */
-#define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE+0x78018)
+#define GPTIMER3_TISR __REG32(OMAP24XX_L4_IO_BASE + 0x78018)
/* SDRC */
-#define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE+0x060)
-#define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE+0x064)
-#define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE+0x068)
-#define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE+0x06C)
-#define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE+0x070)
-#define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE+0x084)
+#define SDRC_DLLA_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x060)
+#define SDRC_DLLA_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x064)
+#define SDRC_DLLB_CTRL __REG32(OMAP24XX_SDRC_BASE + 0x068)
+#define SDRC_DLLB_STATUS __REG32(OMAP24XX_SDRC_BASE + 0x06C)
+#define SDRC_POWER __REG32(OMAP24XX_SDRC_BASE + 0x070)
+#define SDRC_MR_0 __REG32(OMAP24XX_SDRC_BASE + 0x084)
/* GPIO 1 */
#define GPIO1_BASE GPIOX_BASE(1)
@@ -278,6 +295,8 @@
#define GPIO2_DATAIN GPIO2_REG32(0x038)
#define GPIO2_OE GPIO2_REG32(0x034)
#define GPIO2_DATAOUT GPIO2_REG32(0x03C)
+#define GPIO2_DEBOUNCENABLE GPIO2_REG32(0x050)
+#define GPIO2_DEBOUNCINGTIME GPIO2_REG32(0x054)
/* GPIO 3 */
#define GPIO3_BASE GPIOX_BASE(3)
@@ -294,6 +313,8 @@
#define GPIO3_DATAOUT GPIO3_REG32(0x03C)
#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
+#define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050)
+#define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054)
/* GPIO 4 */
#define GPIO4_BASE GPIOX_BASE(4)
@@ -311,10 +332,26 @@
#define GPIO4_DEBOUNCENABLE GPIO4_REG32(0x050)
#define GPIO4_DEBOUNCINGTIME GPIO4_REG32(0x054)
+#if defined(CONFIG_ARCH_OMAP243X)
+/* GPIO 5 */
+#define GPIO5_REG32(offset) __REG32((OMAP24XX_GPIO5_BASE + (offset)))
+#define GPIO5_IRQENABLE1 GPIO5_REG32(0x01C)
+#define GPIO5_IRQSTATUS1 GPIO5_REG32(0x018)
+#define GPIO5_IRQENABLE2 GPIO5_REG32(0x02C)
+#define GPIO5_IRQSTATUS2 GPIO5_REG32(0x028)
+#define GPIO5_WAKEUPENABLE GPIO5_REG32(0x020)
+#define GPIO5_RISINGDETECT GPIO5_REG32(0x048)
+#define GPIO5_FALLINGDETECT GPIO5_REG32(0x04C)
+#define GPIO5_DATAIN GPIO5_REG32(0x038)
+#define GPIO5_OE GPIO5_REG32(0x034)
+#define GPIO5_DATAOUT GPIO5_REG32(0x03C)
+#define GPIO5_DEBOUNCENABLE GPIO5_REG32(0x050)
+#define GPIO5_DEBOUNCINGTIME GPIO5_REG32(0x054)
+#endif
/* IO CONFIG */
-#define CONTROL_BASE (OMAP24XX_CTRL_BASE)
-#define CONTROL_REG32(offset) __REG32(CONTROL_BASE + (offset))
+#define OMAP24XX_CTRL_BASE (L4_24XX_BASE)
+#define CONTROL_REG32(offset) __REG32(OMAP24XX_CTRL_BASE + (offset))
#define CONTROL_PADCONF_SPI1_NCS2 CONTROL_REG32(0x104)
#define CONTROL_PADCONF_SYS_XTALOUT CONTROL_REG32(0x134)
@@ -322,15 +359,18 @@
#define CONTROL_PADCONF_MCBSP1_DX CONTROL_REG32(0x10C)
#define CONTROL_PADCONF_GPMC_NCS4 CONTROL_REG32(0x090)
#define CONTROL_PADCONF_DSS_D5 CONTROL_REG32(0x0B8)
-#define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC)
+#define CONTROL_PADCONF_DSS_D9 CONTROL_REG32(0x0BC) /* 2420 */
#define CONTROL_PADCONF_DSS_D13 CONTROL_REG32(0x0C0)
#define CONTROL_PADCONF_DSS_VSYNC CONTROL_REG32(0x0CC)
+#define CONTROL_PADCONF_SYS_NIRQW0 CONTROL_REG32(0x0BC) /* 2430 */
+#define CONTROL_PADCONF_SSI1_FLAG_TX CONTROL_REG32(0x108) /* 2430 */
/* CONTROL */
#define CONTROL_DEVCONF CONTROL_REG32(0x274)
+#define CONTROL_DEVCONF1 CONTROL_REG32(0x2E8)
/* INTERRUPT CONTROLLER */
-#define INTC_BASE (OMAP24XX_L4_IO_BASE+0xfe000)
+#define INTC_BASE ((L4_24XX_BASE) + 0xfe000)
#define INTC_REG32(offset) __REG32(INTC_BASE + (offset))
#define INTC1_U_BASE INTC_REG32(0x000)
@@ -348,10 +388,12 @@
#define INTC_ISR_CLEAR2 INTC_REG32(0x0D4)
#define INTC_SIR_IRQ INTC_REG32(0x040)
#define INTC_CONTROL INTC_REG32(0x048)
-#define INTC_ILR11 INTC_REG32(0x12C)
+#define INTC_ILR11 INTC_REG32(0x12C) /* PRCM on MPU PIC */
+#define INTC_ILR30 INTC_REG32(0x178)
+#define INTC_ILR31 INTC_REG32(0x17C)
#define INTC_ILR32 INTC_REG32(0x180)
-#define INTC_ILR37 INTC_REG32(0x194)
-#define INTC_SYSCONFIG INTC_REG32(0x010)
+#define INTC_ILR37 INTC_REG32(0x194) /* GPIO4 on MPU PIC */
+#define INTC_SYSCONFIG INTC_REG32(0x010) /* GPT1 on MPU PIC */
/* RAM FIREWALL */
#define RAMFW_BASE (0x68005000)
@@ -373,6 +415,24 @@
#define GPMC_CONFIG6_0 GPMC_REG32(0x074)
#define GPMC_CONFIG7_0 GPMC_REG32(0x078)
+/* GPMC CS1 */
+#define GPMC_CONFIG1_1 GPMC_REG32(0x090)
+#define GPMC_CONFIG2_1 GPMC_REG32(0x094)
+#define GPMC_CONFIG3_1 GPMC_REG32(0x098)
+#define GPMC_CONFIG4_1 GPMC_REG32(0x09C)
+#define GPMC_CONFIG5_1 GPMC_REG32(0x0a0)
+#define GPMC_CONFIG6_1 GPMC_REG32(0x0a4)
+#define GPMC_CONFIG7_1 GPMC_REG32(0x0a8)
+
+/* GPMC CS3 */
+#define GPMC_CONFIG1_3 GPMC_REG32(0x0F0)
+#define GPMC_CONFIG2_3 GPMC_REG32(0x0F4)
+#define GPMC_CONFIG3_3 GPMC_REG32(0x0F8)
+#define GPMC_CONFIG4_3 GPMC_REG32(0x0FC)
+#define GPMC_CONFIG5_3 GPMC_REG32(0x100)
+#define GPMC_CONFIG6_3 GPMC_REG32(0x104)
+#define GPMC_CONFIG7_3 GPMC_REG32(0x108)
+
/* DSS */
#define DSS_CONTROL DISP_REG32(0x040)
#define DISPC_CONTROL DISP_REG32(0x440)
@@ -405,11 +465,15 @@
#define DISPC_DATA_CYCLE2 DISP_REG32(0x5D8)
#define DISPC_DATA_CYCLE3 DISP_REG32(0x5DC)
-/* Wake up define for board */
-#define GPIO97 (1 << 1)
-#define GPIO88 (1 << 24)
+/* HSUSB Suspend */
+#define HSUSB_CTRL __REG8(0x480AC001)
+#define USBOTG_POWER __REG32(0x480AC000)
+
+/* HS MMC */
+#define MMCHS1_SYSCONFIG __REG32(0x4809C010)
+#define MMCHS2_SYSCONFIG __REG32(0x480b4010)
-#endif /* __ASSEMBLER__ */
+#endif /* __ASSEMBLER__ */
#endif
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
new file mode 100644
index 00000000000..8893479dc7e
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm.c
@@ -0,0 +1,40 @@
+/*
+ * linux/arch/arm/mach-omap2/prcm.c
+ *
+ * OMAP 24xx Power Reset and Clock Management (PRCM) functions
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * Written by Tony Lindgren <tony.lindgren@nokia.com>
+ *
+ * Some pieces of code Copyright (C) 2005 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include "prcm-regs.h"
+
+u32 omap_prcm_get_reset_sources(void)
+{
+ return RM_RSTST_WKUP & 0x7f;
+}
+EXPORT_SYMBOL(omap_prcm_get_reset_sources);
+
+/* Resets clock rates and reboots the system. Only called from system.h */
+void omap_prcm_arch_reset(char mode)
+{
+ u32 rate;
+ struct clk *vclk, *sclk;
+
+ vclk = clk_get(NULL, "virt_prcm_set");
+ sclk = clk_get(NULL, "sys_ck");
+ rate = clk_get_rate(sclk);
+ clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */
+ RM_RSTCTRL_WKUP |= 2;
+}
diff --git a/arch/arm/mach-omap2/sleep.S b/arch/arm/mach-omap2/sleep.S
new file mode 100644
index 00000000000..00299cbeb91
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep.S
@@ -0,0 +1,144 @@
+/*
+ * linux/arch/arm/mach-omap2/sleep.S
+ *
+ * (C) Copyright 2004
+ * Texas Instruments, <www.ti.com>
+ * Richard Woodruff <r-woodruff2@ti.com>
+ *
+ * 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
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/pm.h>
+
+#define A_32KSYNC_CR_V IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
+#define A_PRCM_VOLTCTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
+#define A_PRCM_CLKCFG_CTRL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
+#define A_CM_CLKEN_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
+#define A_CM_IDLEST_CKGEN_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
+#define A_CM_CLKSEL1_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
+#define A_CM_CLKSEL2_PLL_V IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
+
+#define A_SDRC_DLLA_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
+#define A_SDRC_POWER_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
+#define A_SDRC_RFR_CTRL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
+#define A_SDRC0_V (0xC0000000)
+#define A_SDRC_MANUAL_V IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA8)
+
+ .text
+
+/*
+ * Forces OMAP into idle state
+ *
+ * omap24xx_idle_loop_suspend() - This bit of code just executes the WFI
+ * for normal idles.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ * wakes up it continues execution at the point it went to sleep.
+ */
+ENTRY(omap24xx_idle_loop_suspend)
+ stmfd sp!, {r0, lr} @ save registers on stack
+ mov r0, #0 @ clear for mcr setup
+ mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt
+ ldmfd sp!, {r0, pc} @ restore regs and return
+
+ENTRY(omap24xx_idle_loop_suspend_sz)
+ .word . - omap24xx_idle_loop_suspend
+
+/*
+ * omap242x_cpu_suspend() - Forces OMAP into deep sleep state by completing
+ * SDRC shutdown then ARM shutdown. Upon wake MPU is back on so just restore
+ * SDRC.
+ *
+ * Input:
+ * R0 : DLL ctrl value pre-Sleep
+ * R1 : Processor+Revision
+ * 2420: 0x21 = 242xES1, 0x26 = 242xES2.2
+ * 2430: 0x31 = 2430ES1, 0x32 = 2430ES2
+ *
+ * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
+ * when we get called, but the DLL probably isn't. We will wait a bit more in
+ * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
+ * if in unlocked mode.
+ *
+ * For less than 242x-ES2.2 upon wake from a sleep mode where the external
+ * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
+ * clock can pass into the PRCM can cause problems at DSP and IVA.
+ * To work around this the code will switch to the 32kHz source prior to sleep.
+ * Post sleep we will shift back to using the DPLL. Apparently,
+ * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
+ * 3x12MHz + 3x32kHz clocks for a full switch.
+ *
+ * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
+ * at wake
+ */
+ENTRY(omap24xx_cpu_suspend)
+ stmfd sp!, {r0 - r12, lr} @ save registers on stack
+ mov r3, #0x0 @ clear for mrc call
+ mcr p15, 0, r3, c7, c10, 4 @ memory barrier, hope SDR/DDR finished
+ nop
+ nop
+ ldr r3, A_SDRC_POWER @ addr of sdrc power
+ ldr r4, [r3] @ value of sdrc power
+ orr r4, r4, #0x40 @ enable self refresh on idle req
+ mov r5, #0x2000 @ set delay (DPLL relock + DLL relock)
+ str r4, [r3] @ make it so
+ mov r2, #0
+ nop
+ mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
+ nop
+loop:
+ subs r5, r5, #0x1 @ awake, wait just a bit
+ bne loop
+
+ /* The DPLL has on before we take the DDR out of self refresh */
+ bic r4, r4, #0x40 @ now clear self refresh bit.
+ str r4, [r3] @ put vlaue back.
+ ldr r4, A_SDRC0 @ make a clock happen
+ ldr r4, [r4]
+ nop @ start auto refresh only after clk ok
+ movs r0, r0 @ see if DDR or SDR
+ ldrne r1, A_SDRC_DLLA_CTRL_S @ get addr of DLL ctrl
+ strne r0, [r1] @ rewrite DLLA to force DLL reload
+ addne r1, r1, #0x8 @ move to DLLB
+ strne r0, [r1] @ rewrite DLLB to force DLL reload
+
+ mov r5, #0x1000
+loop2:
+ subs r5, r5, #0x1
+ bne loop2
+ /* resume*/
+ ldmfd sp!, {r0 - r12, pc} @ restore regs and return
+
+A_SDRC_POWER:
+ .word A_SDRC_POWER_V
+A_SDRC0:
+ .word A_SDRC0_V
+A_CM_CLKSEL2_PLL_S:
+ .word A_CM_CLKSEL2_PLL_V
+A_CM_CLKEN_PLL:
+ .word A_CM_CLKEN_PLL_V
+A_SDRC_DLLA_CTRL_S:
+ .word A_SDRC_DLLA_CTRL_V
+A_SDRC_MANUAL_S:
+ .word A_SDRC_MANUAL_V
+
+ENTRY(omap24xx_cpu_suspend_sz)
+ .word . - omap24xx_cpu_suspend
+
diff --git a/arch/arm/mach-omap2/sram-fn.S b/arch/arm/mach-omap2/sram-fn.S
index 2a869e20334..d261e4ff4d9 100644
--- a/arch/arm/mach-omap2/sram-fn.S
+++ b/arch/arm/mach-omap2/sram-fn.S
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/mach-omap1/sram.S
+ * linux/arch/arm/mach-omap2/sram.S
*
* Omap2 specific functions that need to be run in internal SRAM
*
@@ -28,7 +28,7 @@
#include <asm/arch/io.h>
#include <asm/hardware.h>
-#include <asm/arch/prcm.h>
+#include "prcm-regs.h"
#define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP24XX_32KSYNCT_BASE + 0x010)
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index b45560a8f6c..a042473deed 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -307,6 +307,10 @@ static void __init fixup_poodle(struct machine_desc *desc,
struct tag *tags, char **cmdline, struct meminfo *mi)
{
sharpsl_save_param();
+ mi->nr_banks=1;
+ mi->bank[0].start = 0xa0000000;
+ mi->bank[0].node = 0;
+ mi->bank[0].size = (32*1024*1024);
}
MACHINE_START(POODLE, "SHARP Poodle")
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index ed07c4149d8..ce7d8100069 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -50,9 +50,15 @@ config MACH_N30
<http://zoo.weinigel.se/n30>.
+config MACH_SMDK
+ bool
+ help
+ Common machine code for SMDK2410 and SMDK2440
+
config ARCH_SMDK2410
bool "SMDK2410/A9M2410"
select CPU_S3C2410
+ select MACH_SMDK
help
Say Y here if you are using the SMDK2410 or the derived module A9M2410
<http://www.fsforth.de>
@@ -60,6 +66,7 @@ config ARCH_SMDK2410
config ARCH_S3C2440
bool "SMDK2440"
select CPU_S3C2440
+ select MACH_SMDK
help
Say Y here if you are using the SMDK2440.
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 1b3b476e563..3e5712db6b5 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -48,3 +48,5 @@ obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
obj-$(CONFIG_MACH_OTOM) += mach-otom.o
obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
+
+obj-$(CONFIG_MACH_SMDK) += common-smdk.o \ No newline at end of file
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index fec02c92f95..b7f85e6d6b7 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -249,7 +249,7 @@ static int s3c24xx_upll_enable(struct clk *clk, int enable)
/* if we started the UPLL, then allow to settle */
- if (enable && !(orig & S3C2410_CLKSLOW_UCLK_OFF))
+ if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
udelay(200);
return 0;
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c
new file mode 100644
index 00000000000..36b8291b5e0
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.c
@@ -0,0 +1,134 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/arch/nand.h>
+
+#include "devs.h"
+#include "pm.h"
+
+/* NAND parititon from 2.4.18-swl5 */
+
+static struct mtd_partition smdk_default_nand_part[] = {
+ [0] = {
+ .name = "Boot Agent",
+ .size = SZ_16K,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "S3C2410 flash parition 1",
+ .offset = 0,
+ .size = SZ_2M,
+ },
+ [2] = {
+ .name = "S3C2410 flash partition 2",
+ .offset = SZ_4M,
+ .size = SZ_4M,
+ },
+ [3] = {
+ .name = "S3C2410 flash partition 3",
+ .offset = SZ_8M,
+ .size = SZ_2M,
+ },
+ [4] = {
+ .name = "S3C2410 flash partition 4",
+ .offset = SZ_1M * 10,
+ .size = SZ_4M,
+ },
+ [5] = {
+ .name = "S3C2410 flash partition 5",
+ .offset = SZ_1M * 14,
+ .size = SZ_1M * 10,
+ },
+ [6] = {
+ .name = "S3C2410 flash partition 6",
+ .offset = SZ_1M * 24,
+ .size = SZ_1M * 24,
+ },
+ [7] = {
+ .name = "S3C2410 flash partition 7",
+ .offset = SZ_1M * 48,
+ .size = SZ_16M,
+ }
+};
+
+static struct s3c2410_nand_set smdk_nand_sets[] = {
+ [0] = {
+ .name = "NAND",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(smdk_default_nand_part),
+ .partitions = smdk_default_nand_part,
+ },
+};
+
+/* choose a set of timings which should suit most 512Mbit
+ * chips and beyond.
+*/
+
+static struct s3c2410_platform_nand smdk_nand_info = {
+ .tacls = 20,
+ .twrph0 = 60,
+ .twrph1 = 20,
+ .nr_sets = ARRAY_SIZE(smdk_nand_sets),
+ .sets = smdk_nand_sets,
+};
+
+/* devices we initialise */
+
+static struct platform_device __initdata *smdk_devs[] = {
+ &s3c_device_nand,
+};
+
+void __init smdk_machine_init(void)
+{
+ /* Configure the LEDs (even if we have no LED support)*/
+
+ s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
+
+ s3c2410_gpio_setpin(S3C2410_GPF4, 1);
+ s3c2410_gpio_setpin(S3C2410_GPF5, 1);
+ s3c2410_gpio_setpin(S3C2410_GPF6, 1);
+ s3c2410_gpio_setpin(S3C2410_GPF7, 1);
+
+ s3c_device_nand.dev.platform_data = &smdk_nand_info;
+
+ platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
+
+ s3c2410_pm_init();
+}
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/arch/arm/mach-s3c2410/common-smdk.h
new file mode 100644
index 00000000000..0e3a3be330a
--- /dev/null
+++ b/arch/arm/mach-s3c2410/common-smdk.h
@@ -0,0 +1,15 @@
+/* linux/arch/arm/mach-s3c2410/common-smdk.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Common code for SMDK2410 and SMDK2440 boards
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern void smdk_machine_init(void);
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 3e327b8e46b..cc97fbf6629 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -232,8 +232,8 @@ static void anubis_nand_select(struct s3c2410_nand_set *set, int slot)
static struct s3c2410_platform_nand anubis_nand_info = {
.tacls = 25,
- .twrph0 = 80,
- .twrph1 = 80,
+ .twrph0 = 55,
+ .twrph1 = 40,
.nr_sets = ARRAY_SIZE(anubis_nand_sets),
.sets = anubis_nand_sets,
.select_chip = anubis_nand_select,
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index 0260ed5ab94..306afc1d7cd 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -32,6 +32,11 @@
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
@@ -46,6 +51,7 @@
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-lcd.h>
+#include <asm/arch/nand.h>
#include <asm/arch/fb.h>
#include "clock.h"
@@ -170,12 +176,39 @@ static struct s3c2410fb_mach_info rx3715_lcdcfg __initdata = {
},
};
+static struct mtd_partition rx3715_nand_part[] = {
+ [0] = {
+ .name = "Whole Flash",
+ .offset = 0,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = MTD_WRITEABLE,
+ }
+};
+
+static struct s3c2410_nand_set rx3715_nand_sets[] = {
+ [0] = {
+ .name = "Internal",
+ .nr_chips = 1,
+ .nr_partitions = ARRAY_SIZE(rx3715_nand_part),
+ .partitions = rx3715_nand_part,
+ },
+};
+
+static struct s3c2410_platform_nand rx3715_nand_info = {
+ .tacls = 25,
+ .twrph0 = 50,
+ .twrph1 = 15,
+ .nr_sets = ARRAY_SIZE(rx3715_nand_sets),
+ .sets = rx3715_nand_sets,
+};
+
static struct platform_device *rx3715_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
+ &s3c_device_nand,
};
static struct s3c24xx_board rx3715_board __initdata = {
@@ -185,6 +218,8 @@ static struct s3c24xx_board rx3715_board __initdata = {
static void __init rx3715_map_io(void)
{
+ s3c_device_nand.dev.platform_data = &rx3715_nand_info;
+
s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
s3c24xx_init_clocks(16934000);
s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 1e76e1fdfce..2db932d72c5 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -28,7 +28,8 @@
* Ben Dooks <ben@simtec.co.uk>
*
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
- * 20-Sep-2005 BJD Added static to non-exported items
+ * 20-Sep-2005 BJD Added static to non-exported items
+ * 01-Apr-2006 BJD Moved init code to common smdk
*
***********************************************************************/
@@ -54,6 +55,8 @@
#include "devs.h"
#include "cpu.h"
+#include "common-smdk.h"
+
static struct map_desc smdk2410_iodesc[] __initdata = {
/* nothing here yet */
};
@@ -107,11 +110,6 @@ static void __init smdk2410_map_io(void)
s3c24xx_set_board(&smdk2410_board);
}
-static void __init smdk2410_init_irq(void)
-{
- s3c24xx_init_irq();
-}
-
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
/* Maintainer: Jonas Dietsche */
@@ -119,7 +117,8 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = smdk2410_map_io,
- .init_irq = smdk2410_init_irq,
+ .init_irq = s3c24xx_init_irq,
+ .init_machine = smdk_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index f4315721c3b..5fffd1d5104 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -53,7 +53,8 @@
#include "clock.h"
#include "devs.h"
#include "cpu.h"
-#include "pm.h"
+
+#include "common-smdk.h"
static struct map_desc smdk2440_iodesc[] __initdata = {
/* ISA IO Space map (memory space selected by A24) */
@@ -197,21 +198,9 @@ static void __init smdk2440_map_io(void)
static void __init smdk2440_machine_init(void)
{
- /* Configure the LEDs (even if we have no LED support)*/
-
- s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
- s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
- s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
- s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
-
- s3c2410_gpio_setpin(S3C2410_GPF4, 0);
- s3c2410_gpio_setpin(S3C2410_GPF5, 0);
- s3c2410_gpio_setpin(S3C2410_GPF6, 0);
- s3c2410_gpio_setpin(S3C2410_GPF7, 0);
-
s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);
- s3c2410_pm_init();
+ smdk_machine_init();
}
MACHINE_START(S3C2440, "SMDK2440")
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 10245408247..676b5c5b75b 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -11,7 +11,8 @@
* published by the Free Software Foundation.
*
* ChangeLog:
- * 03-06-2004 John Lenz <jelenz@wisc.edu>
+ * 2006 Pavel Machek <pavel@suse.cz>
+ * 03-06-2004 John Lenz <lenz@cs.wisc.edu>
* 06-04-2002 Chris Larson <kergoth@digitalnemesis.net>
* 04-16-2001 Lineo Japan,Inc. ...
*/
@@ -87,12 +88,75 @@ static struct mcp_plat_data collie_mcp_data = {
.sclk_rate = 11981000,
};
+#ifdef CONFIG_SHARP_LOCOMO
+/*
+ * low-level UART features.
+ */
+static struct locomo_dev *uart_dev = NULL;
+
+static void collie_uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ if (!uart_dev) return;
+
+ if (mctrl & TIOCM_RTS)
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 0);
+ else
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_RTS, 1);
+
+ if (mctrl & TIOCM_DTR)
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 0);
+ else
+ locomo_gpio_write(uart_dev, LOCOMO_GPIO_DTR, 1);
+}
+
+static u_int collie_uart_get_mctrl(struct uart_port *port)
+{
+ int ret = TIOCM_CD;
+ unsigned int r;
+ if (!uart_dev) return ret;
+
+ r = locomo_gpio_read_output(uart_dev, LOCOMO_GPIO_CTS & LOCOMO_GPIO_DSR);
+ if (r & LOCOMO_GPIO_CTS)
+ ret |= TIOCM_CTS;
+ if (r & LOCOMO_GPIO_DSR)
+ ret |= TIOCM_DSR;
+
+ return ret;
+}
static struct sa1100_port_fns collie_port_fns __initdata = {
.set_mctrl = collie_uart_set_mctrl,
.get_mctrl = collie_uart_get_mctrl,
};
+static int collie_uart_probe(struct locomo_dev *dev)
+{
+ uart_dev = dev;
+ return 0;
+}
+
+static int collie_uart_remove(struct locomo_dev *dev)
+{
+ uart_dev = NULL;
+ return 0;
+}
+
+static struct locomo_driver collie_uart_driver = {
+ .drv = {
+ .name = "collie_uart",
+ },
+ .devid = LOCOMO_DEVID_UART,
+ .probe = collie_uart_probe,
+ .remove = collie_uart_remove,
+};
+
+static int __init collie_uart_init(void) {
+ return locomo_driver_register(&collie_uart_driver);
+}
+device_initcall(collie_uart_init);
+
+#endif
+
static struct resource locomo_resources[] = {
[0] = {
@@ -218,6 +282,12 @@ static void __init collie_map_io(void)
{
sa1100_map_io();
iotable_init(collie_io_desc, ARRAY_SIZE(collie_io_desc));
+
+#ifdef CONFIG_SHARP_LOCOMO
+ sa1100_register_uart_fns(&collie_port_fns);
+#endif
+ sa1100_register_uart(0, 3);
+ sa1100_register_uart(1, 1);
}
MACHINE_START(COLLIE, "Sharp-Collie")
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 8a1bfcd5008..50e6b6bfb2e 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <asm/memory.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/sizes.h>
@@ -272,6 +273,17 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
{
+ if (arch_is_coherent()) {
+ void *virt;
+
+ virt = kmalloc(size, gfp);
+ if (!virt)
+ return NULL;
+ *handle = virt_to_dma(dev, virt);
+
+ return virt;
+ }
+
return __dma_alloc(dev, size, handle, gfp,
pgprot_noncached(pgprot_kernel));
}
@@ -350,6 +362,11 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
WARN_ON(irqs_disabled());
+ if (arch_is_coherent()) {
+ kfree(cpu_addr);
+ return;
+ }
+
size = PAGE_ALIGN(size);
spin_lock_irqsave(&consistent_lock, flags);
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 5e5d05bcad5..f14b2d0f369 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -389,6 +389,17 @@ void __init build_mem_type_table(void)
kern_pgprot = user_pgprot = cp->pte;
/*
+ * Enable CPU-specific coherency if supported.
+ * (Only available on XSC3 at the moment.)
+ */
+ if (arch_is_coherent()) {
+ if (cpu_is_xsc3()) {
+ mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+ mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT;
+ }
+ }
+
+ /*
* ARMv6 and above have extended page tables.
*/
if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index b9dfce57c27..80873b36c3f 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -371,7 +371,7 @@ ENTRY(cpu_xsc3_switch_mm)
ENTRY(cpu_xsc3_set_pte)
str r1, [r0], #-2048 @ linux version
- bic r2, r1, #0xff0
+ bic r2, r1, #0xdf0 @ Keep C, B, coherency bits
orr r2, r2, #PTE_TYPE_EXT @ extended page
eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 0887bb2a255..ec49495e651 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -70,13 +70,13 @@ config OMAP_MPU_TIMER
config OMAP_32K_TIMER
bool "Use 32KHz timer"
- depends on ARCH_OMAP16XX
+ depends on ARCH_OMAP16XX || ARCH_OMAP24XX
help
Select this option if you want to enable the OMAP 32KHz timer.
This timer saves power compared to the OMAP_MPU_TIMER, and has
support for no tick during idle. The 32KHz timer provides less
intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
- currently only available for OMAP-16xx.
+ currently only available for OMAP16XX and 24XX.
endchoice
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 9ccf1943fc9..2896b454641 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,16 +3,16 @@
#
# Common support
-obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o
+obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o
obj-m :=
obj-n :=
obj- :=
+obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
+
# OCPI interconnect support for 1710, 1610 and 5912
obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
-# Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 3c2bfc0efda..06485c193ee 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -21,6 +21,7 @@
#include <linux/string.h>
#include <linux/clk.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/semaphore.h>
@@ -37,17 +38,37 @@ static struct clk_functions *arch_clock;
* Standard clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
struct clk * clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
+ int idno;
+
+ if (dev == NULL || dev->bus != &platform_bus_type)
+ idno = -1;
+ else
+ idno = to_platform_device(dev)->id;
mutex_lock(&clocks_mutex);
+
+ list_for_each_entry(p, &clocks, node) {
+ if (p->id == idno &&
+ strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
+
mutex_unlock(&clocks_mutex);
return clk;
@@ -59,6 +80,9 @@ int clk_enable(struct clk *clk)
unsigned long flags;
int ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_enable)
ret = arch_clock->clk_enable(clk);
@@ -72,6 +96,9 @@ void clk_disable(struct clk *clk)
{
unsigned long flags;
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_disable)
arch_clock->clk_disable(clk);
@@ -84,6 +111,9 @@ int clk_get_usecount(struct clk *clk)
unsigned long flags;
int ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return 0;
+
spin_lock_irqsave(&clockfw_lock, flags);
ret = clk->usecount;
spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -97,6 +127,9 @@ unsigned long clk_get_rate(struct clk *clk)
unsigned long flags;
unsigned long ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return 0;
+
spin_lock_irqsave(&clockfw_lock, flags);
ret = clk->rate;
spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -121,6 +154,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
unsigned long flags;
long ret = 0;
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_round_rate)
ret = arch_clock->clk_round_rate(clk, rate);
@@ -133,7 +169,10 @@ EXPORT_SYMBOL(clk_round_rate);
int clk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long flags;
- int ret = 0;
+ int ret = -EINVAL;
+
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_set_rate)
@@ -147,7 +186,10 @@ EXPORT_SYMBOL(clk_set_rate);
int clk_set_parent(struct clk *clk, struct clk *parent)
{
unsigned long flags;
- int ret = 0;
+ int ret = -EINVAL;
+
+ if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
+ return ret;
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_set_parent)
@@ -163,6 +205,9 @@ struct clk *clk_get_parent(struct clk *clk)
unsigned long flags;
struct clk * ret = NULL;
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_get_parent)
ret = arch_clock->clk_get_parent(clk);
@@ -199,6 +244,9 @@ __setup("mpurate=", omap_clk_setup);
/* Used for clocks that always have same value as the parent clock */
void followparent_recalc(struct clk *clk)
{
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
clk->rate = clk->parent->rate;
}
@@ -207,6 +255,9 @@ void propagate_rate(struct clk * tclk)
{
struct clk *clkp;
+ if (tclk == NULL || IS_ERR(tclk))
+ return;
+
list_for_each_entry(clkp, &clocks, node) {
if (likely(clkp->parent != tclk))
continue;
@@ -217,6 +268,9 @@ void propagate_rate(struct clk * tclk)
int clk_register(struct clk *clk)
{
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
if (clk->init)
@@ -229,6 +283,9 @@ EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
mutex_lock(&clocks_mutex);
list_del(&clk->node);
mutex_unlock(&clocks_mutex);
@@ -239,6 +296,9 @@ void clk_deny_idle(struct clk *clk)
{
unsigned long flags;
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_deny_idle)
arch_clock->clk_deny_idle(clk);
@@ -250,6 +310,9 @@ void clk_allow_idle(struct clk *clk)
{
unsigned long flags;
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_allow_idle)
arch_clock->clk_allow_idle(clk);
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 9dcce904b60..079b67deac0 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -24,6 +24,7 @@
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/menelaus.h>
void omap_nop_release(struct device *dev)
@@ -98,6 +99,62 @@ static inline void omap_init_i2c(void) {}
#endif
/*-------------------------------------------------------------------------*/
+#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+
+static void omap_init_kp(void)
+{
+ if (machine_is_omap_h2() || machine_is_omap_h3()) {
+ omap_cfg_reg(F18_1610_KBC0);
+ omap_cfg_reg(D20_1610_KBC1);
+ omap_cfg_reg(D19_1610_KBC2);
+ omap_cfg_reg(E18_1610_KBC3);
+ omap_cfg_reg(C21_1610_KBC4);
+
+ omap_cfg_reg(G18_1610_KBR0);
+ omap_cfg_reg(F19_1610_KBR1);
+ omap_cfg_reg(H14_1610_KBR2);
+ omap_cfg_reg(E20_1610_KBR3);
+ omap_cfg_reg(E19_1610_KBR4);
+ omap_cfg_reg(N19_1610_KBR5);
+ } else if (machine_is_omap_perseus2()) {
+ omap_cfg_reg(E2_730_KBR0);
+ omap_cfg_reg(J7_730_KBR1);
+ omap_cfg_reg(E1_730_KBR2);
+ omap_cfg_reg(F3_730_KBR3);
+ omap_cfg_reg(D2_730_KBR4);
+
+ omap_cfg_reg(C2_730_KBC0);
+ omap_cfg_reg(D3_730_KBC1);
+ omap_cfg_reg(E4_730_KBC2);
+ omap_cfg_reg(F4_730_KBC3);
+ omap_cfg_reg(E3_730_KBC4);
+ } else if (machine_is_omap_h4()) {
+ omap_cfg_reg(T19_24XX_KBR0);
+ omap_cfg_reg(R19_24XX_KBR1);
+ omap_cfg_reg(V18_24XX_KBR2);
+ omap_cfg_reg(M21_24XX_KBR3);
+ omap_cfg_reg(E5__24XX_KBR4);
+ if (omap_has_menelaus()) {
+ omap_cfg_reg(B3__24XX_KBR5);
+ omap_cfg_reg(AA4_24XX_KBC2);
+ omap_cfg_reg(B13_24XX_KBC6);
+ } else {
+ omap_cfg_reg(M18_24XX_KBR5);
+ omap_cfg_reg(H19_24XX_KBC2);
+ omap_cfg_reg(N19_24XX_KBC6);
+ }
+ omap_cfg_reg(R20_24XX_KBC0);
+ omap_cfg_reg(M14_24XX_KBC1);
+ omap_cfg_reg(V17_24XX_KBC3);
+ omap_cfg_reg(P21_24XX_KBC4);
+ omap_cfg_reg(L14_24XX_KBC5);
+ }
+}
+#else
+static inline void omap_init_kp(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
@@ -240,6 +297,55 @@ static void __init omap_init_mmc(void)
static inline void omap_init_mmc(void) {}
#endif
+/*-------------------------------------------------------------------------*/
+
+/* Numbering for the SPI-capable controllers when used for SPI:
+ * spi = 1
+ * uwire = 2
+ * mmc1..2 = 3..4
+ * mcbsp1..3 = 5..7
+ */
+
+#if defined(CONFIG_SPI_OMAP_UWIRE) || defined(CONFIG_SPI_OMAP_UWIRE_MODULE)
+
+#define OMAP_UWIRE_BASE 0xfffb3000
+
+static struct resource uwire_resources[] = {
+ {
+ .start = OMAP_UWIRE_BASE,
+ .end = OMAP_UWIRE_BASE + 0x20,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device omap_uwire_device = {
+ .name = "omap_uwire",
+ .id = -1,
+ .dev = {
+ .release = omap_nop_release,
+ },
+ .num_resources = ARRAY_SIZE(uwire_resources),
+ .resource = uwire_resources,
+};
+
+static void omap_init_uwire(void)
+{
+ /* FIXME define and use a boot tag; not all boards will be hooking
+ * up devices to the microwire controller, and multi-board configs
+ * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway...
+ */
+
+ /* board-specific code must configure chipselects (only a few
+ * are normally used) and SCLK/SDI/SDO (each has two choices).
+ */
+ (void) platform_device_register(&omap_uwire_device);
+}
+#else
+static inline void omap_init_uwire(void) {}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
#ifdef CONFIG_ARCH_OMAP24XX
@@ -310,40 +416,6 @@ static void omap_init_rng(void)
static inline void omap_init_rng(void) {}
#endif
-#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
-
-static struct omap_lcd_config omap_fb_conf;
-
-static u64 omap_fb_dma_mask = ~(u32)0;
-
-static struct platform_device omap_fb_device = {
- .name = "omapfb",
- .id = -1,
- .dev = {
- .release = omap_nop_release,
- .dma_mask = &omap_fb_dma_mask,
- .coherent_dma_mask = ~(u32)0,
- .platform_data = &omap_fb_conf,
- },
- .num_resources = 0,
-};
-
-static inline void omap_init_fb(void)
-{
- const struct omap_lcd_config *conf;
-
- conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
- if (conf != NULL)
- omap_fb_conf = *conf;
- platform_device_register(&omap_fb_device);
-}
-
-#else
-
-static inline void omap_init_fb(void) {}
-
-#endif
-
/*
* This gets called after board-specific INIT_MACHINE, and initializes most
* on-chip peripherals accessible on this board (except for few like USB):
@@ -369,9 +441,10 @@ static int __init omap_init_devices(void)
/* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
- omap_init_fb();
omap_init_i2c();
+ omap_init_kp();
omap_init_mmc();
+ omap_init_uwire();
omap_init_wdt();
omap_init_rng();
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index a4e5ac77f6d..5dac4230360 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1258,6 +1258,11 @@ void omap_stop_lcd_dma(void)
omap_writew(w, OMAP1610_DMA_LCD_CTRL);
}
+int omap_lcd_dma_ext_running(void)
+{
+ return lcd_dma.ext_ctrl && lcd_dma.active;
+}
+
/*----------------------------------------------------------------------------*/
static int __init omap_init_dma(void)
@@ -1389,6 +1394,7 @@ EXPORT_SYMBOL(omap_free_lcd_dma);
EXPORT_SYMBOL(omap_enable_lcd_dma);
EXPORT_SYMBOL(omap_setup_lcd_dma);
EXPORT_SYMBOL(omap_stop_lcd_dma);
+EXPORT_SYMBOL(omap_lcd_dma_ext_running);
EXPORT_SYMBOL(omap_set_lcd_dma_b1);
EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 38d7ebf8792..eba3cb52ad8 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -97,6 +97,32 @@ int omap_dm_timers_active(void)
}
+/**
+ * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
+ * @inputmask: current value of idlect mask
+ */
+__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
+{
+ int n;
+
+ /* If ARMXOR cannot be idled this function call is unnecessary */
+ if (!(inputmask & (1 << 1)))
+ return inputmask;
+
+ /* If any active timer is using ARMXOR return modified mask */
+ for (n = 0; dm_timers[n].base; ++n)
+ if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)&
+ OMAP_TIMER_CTRL_ST) {
+ if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0)
+ inputmask &= ~(1 << 1);
+ else
+ inputmask &= ~(1 << 2);
+ }
+
+ return inputmask;
+}
+
+
void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
int n = (timer - dm_timers) << 1;
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
new file mode 100644
index 00000000000..305e9b990b7
--- /dev/null
+++ b/arch/arm/plat-omap/fb.c
@@ -0,0 +1,80 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/sram.h>
+#include <asm/arch/omapfb.h>
+
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+
+static struct omapfb_platform_data omapfb_config;
+
+static u64 omap_fb_dma_mask = ~(u32)0;
+
+static struct platform_device omap_fb_device = {
+ .name = "omapfb",
+ .id = -1,
+ .dev = {
+ .dma_mask = &omap_fb_dma_mask,
+ .coherent_dma_mask = ~(u32)0,
+ .platform_data = &omapfb_config,
+ },
+ .num_resources = 0,
+};
+
+/* called from map_io */
+void omapfb_reserve_mem(void)
+{
+ const struct omap_fbmem_config *fbmem_conf;
+
+ omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start;
+ omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size;
+
+ fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+
+ if (fbmem_conf != NULL) {
+ /* indicate that the bootloader already initialized the
+ * fb device, so we'll skip that part in the fb driver
+ */
+ omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start;
+ omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size;
+ if (fbmem_conf->fb_sdram_size) {
+ pr_info("Reserving %u bytes SDRAM for frame buffer\n",
+ fbmem_conf->fb_sdram_size);
+ reserve_bootmem(fbmem_conf->fb_sdram_start,
+ fbmem_conf->fb_sdram_size);
+ }
+ }
+}
+
+static inline int omap_init_fb(void)
+{
+ const struct omap_lcd_config *conf;
+
+ conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+ if (conf == NULL)
+ return 0;
+
+ omapfb_config.lcd = *conf;
+
+ return platform_device_register(&omap_fb_device);
+}
+
+arch_initcall(omap_init_fb);
+
+#else
+
+void omapfb_reserve_mem(void) {}
+
+#endif
+
+
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index b4d5b9e4bfc..d3c8ea7eecf 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -174,7 +174,7 @@ static int gpio_bank_count;
static inline struct gpio_bank *get_gpio_bank(int gpio)
{
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
if (OMAP_GPIO_IS_MPUIO(gpio))
return &gpio_bank[0];
return &gpio_bank[1];
@@ -223,7 +223,7 @@ static inline int gpio_valid(int gpio)
return 0;
}
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510() && gpio < 16)
+ if (cpu_is_omap15xx() && gpio < 16)
return 0;
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
@@ -402,13 +402,13 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr
u32 gpio_bit = 1 << gpio;
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
- trigger & IRQT_LOW);
+ trigger & __IRQT_LOWLVL);
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
- trigger & IRQT_HIGH);
+ trigger & __IRQT_HIGHLVL);
MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
- trigger & IRQT_RISING);
+ trigger & __IRQT_RISEDGE);
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
- trigger & IRQT_FALLING);
+ trigger & __IRQT_FALEDGE);
/* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
* triggering requested. */
}
@@ -422,9 +422,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
case METHOD_MPUIO:
reg += OMAP_MPUIO_GPIO_INT_EDGE;
l = __raw_readl(reg);
- if (trigger == IRQT_RISING)
+ if (trigger & __IRQT_RISEDGE)
l |= 1 << gpio;
- else if (trigger == IRQT_FALLING)
+ else if (trigger & __IRQT_FALEDGE)
l &= ~(1 << gpio);
else
goto bad;
@@ -432,9 +432,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
case METHOD_GPIO_1510:
reg += OMAP1510_GPIO_INT_CONTROL;
l = __raw_readl(reg);
- if (trigger == IRQT_RISING)
+ if (trigger & __IRQT_RISEDGE)
l |= 1 << gpio;
- else if (trigger == IRQT_FALLING)
+ else if (trigger & __IRQT_FALEDGE)
l &= ~(1 << gpio);
else
goto bad;
@@ -446,20 +446,21 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
reg += OMAP1610_GPIO_EDGE_CTRL1;
gpio &= 0x07;
/* We allow only edge triggering, i.e. two lowest bits */
- if (trigger & ~IRQT_BOTHEDGE)
+ if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL))
BUG();
- /* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
- trigger &= 0x03;
l = __raw_readl(reg);
l &= ~(3 << (gpio << 1));
- l |= trigger << (gpio << 1);
+ if (trigger & __IRQT_RISEDGE)
+ l |= 2 << (gpio << 1);
+ if (trigger & __IRQT_FALEDGE)
+ l |= 1 << (gpio << 1);
break;
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_CONTROL;
l = __raw_readl(reg);
- if (trigger == IRQT_RISING)
+ if (trigger & __IRQT_RISEDGE)
l |= 1 << gpio;
- else if (trigger == IRQT_FALLING)
+ else if (trigger & __IRQT_FALEDGE)
l &= ~(1 << gpio);
else
goto bad;
@@ -491,7 +492,9 @@ static int gpio_irq_type(unsigned irq, unsigned type)
if (check_gpio(gpio) < 0)
return -EINVAL;
- if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
+ if (type & IRQT_PROBE)
+ return -EINVAL;
+ if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL)))
return -EINVAL;
bank = get_gpio_bank(gpio);
@@ -755,13 +758,32 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
if (bank->method == METHOD_GPIO_24XX)
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
#endif
-
while(1) {
- isr = __raw_readl(isr_reg);
- _enable_gpio_irqbank(bank, isr, 0);
- _clear_gpio_irqbank(bank, isr);
- _enable_gpio_irqbank(bank, isr, 1);
- desc->chip->unmask(irq);
+ u32 isr_saved, level_mask = 0;
+
+ isr_saved = isr = __raw_readl(isr_reg);
+
+ if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
+ isr &= 0x0000ffff;
+
+ if (cpu_is_omap24xx())
+ level_mask =
+ __raw_readl(bank->base +
+ OMAP24XX_GPIO_LEVELDETECT0) |
+ __raw_readl(bank->base +
+ OMAP24XX_GPIO_LEVELDETECT1);
+
+ /* clear edge sensitive interrupts before handler(s) are
+ called so that we don't miss any interrupt occurred while
+ executing them */
+ _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
+ _clear_gpio_irqbank(bank, isr_saved & ~level_mask);
+ _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
+
+ /* if there is only edge sensitive GPIO pin interrupts
+ configured, we could unmask GPIO bank interrupt immediately */
+ if (!level_mask)
+ desc->chip->unmask(irq);
if (!isr)
break;
@@ -774,6 +796,20 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
d = irq_desc + gpio_irq;
desc_handle_irq(gpio_irq, d, regs);
}
+
+ if (cpu_is_omap24xx()) {
+ /* clear level sensitive interrupts after handler(s) */
+ _enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
+ _clear_gpio_irqbank(bank, isr_saved & level_mask);
+ _enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
+ }
+
+ /* if bank has any level sensitive GPIO pin interrupt
+ configured, we must unmask the bank interrupt only after
+ handler(s) are executed in order to avoid spurious bank
+ interrupt */
+ if (level_mask)
+ desc->chip->unmask(irq);
}
}
@@ -848,7 +884,7 @@ static int __init _omap_gpio_init(void)
initialized = 1;
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
gpio_ick = clk_get(NULL, "arm_gpio_ck");
if (IS_ERR(gpio_ick))
printk("Could not get arm_gpio_ck\n");
@@ -869,7 +905,7 @@ static int __init _omap_gpio_init(void)
}
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
gpio_bank_count = 2;
gpio_bank = gpio_bank_1510;
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 1cd2cace7e1..196aac3ac32 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -34,7 +34,7 @@
#ifdef CONFIG_MCBSP_DEBUG
#define DBG(x...) printk(x)
#else
-#define DBG(x...) do { } while (0)
+#define DBG(x...) do { } while (0)
#endif
struct omap_mcbsp {
@@ -44,6 +44,7 @@ struct omap_mcbsp {
omap_mcbsp_word_length rx_word_length;
omap_mcbsp_word_length tx_word_length;
+ omap_mcbsp_io_type_t io_type; /* IRQ or poll */
/* IRQ based TX/RX */
int rx_irq;
int tx_irq;
@@ -64,10 +65,19 @@ struct omap_mcbsp {
};
static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
+#ifdef CONFIG_ARCH_OMAP1
static struct clk *mcbsp_dsp_ck = 0;
static struct clk *mcbsp_api_ck = 0;
static struct clk *mcbsp_dspxor_ck = 0;
-
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+static struct clk *mcbsp1_ick = 0;
+static struct clk *mcbsp1_fck = 0;
+static struct clk *mcbsp2_ick = 0;
+static struct clk *mcbsp2_fck = 0;
+static struct clk *sys_ck = 0;
+static struct clk *sys_clkout = 0;
+#endif
static void omap_mcbsp_dump_reg(u8 id)
{
@@ -88,7 +98,6 @@ static void omap_mcbsp_dump_reg(u8 id)
DBG("***********************\n");
}
-
static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
@@ -109,7 +118,6 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_re
return IRQ_HANDLED;
}
-
static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
{
struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
@@ -176,7 +184,7 @@ static int omap_mcbsp_check(unsigned int id)
return 0;
}
- if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+ if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) {
if (id > OMAP_MAX_MCBSP_COUNT) {
printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
return -1;
@@ -187,9 +195,10 @@ static int omap_mcbsp_check(unsigned int id)
return -1;
}
+#ifdef CONFIG_ARCH_OMAP1
static void omap_mcbsp_dsp_request(void)
{
- if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+ if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
clk_enable(mcbsp_dsp_ck);
clk_enable(mcbsp_api_ck);
@@ -207,12 +216,49 @@ static void omap_mcbsp_dsp_request(void)
static void omap_mcbsp_dsp_free(void)
{
- if (cpu_is_omap1510() || cpu_is_omap16xx()) {
+ if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
clk_disable(mcbsp_dspxor_ck);
clk_disable(mcbsp_dsp_ck);
clk_disable(mcbsp_api_ck);
}
}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+static void omap2_mcbsp2_mux_setup(void)
+{
+ omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
+ omap_cfg_reg(R14_24XX_MCBSP2_FSX);
+ omap_cfg_reg(W15_24XX_MCBSP2_DR);
+ omap_cfg_reg(V15_24XX_MCBSP2_DX);
+ omap_cfg_reg(V14_24XX_GPIO117);
+ omap_cfg_reg(W14_24XX_SYS_CLKOUT);
+}
+#endif
+
+/*
+ * We can choose between IRQ based or polled IO.
+ * This needs to be called before omap_mcbsp_request().
+ */
+int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
+{
+ if (omap_mcbsp_check(id) < 0)
+ return -EINVAL;
+
+ spin_lock(&mcbsp[id].lock);
+
+ if (!mcbsp[id].free) {
+ printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
+ spin_unlock(&mcbsp[id].lock);
+ return -EINVAL;
+ }
+
+ mcbsp[id].io_type = io_type;
+
+ spin_unlock(&mcbsp[id].lock);
+
+ return 0;
+}
int omap_mcbsp_request(unsigned int id)
{
@@ -221,12 +267,26 @@ int omap_mcbsp_request(unsigned int id)
if (omap_mcbsp_check(id) < 0)
return -EINVAL;
+#ifdef CONFIG_ARCH_OMAP1
/*
* On 1510, 1610 and 1710, McBSP1 and McBSP3
* are DSP public peripherals.
*/
if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
omap_mcbsp_dsp_request();
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+ if (cpu_is_omap24xx()) {
+ if (id == OMAP_MCBSP1) {
+ clk_enable(mcbsp1_ick);
+ clk_enable(mcbsp1_fck);
+ } else {
+ clk_enable(mcbsp2_ick);
+ clk_enable(mcbsp2_fck);
+ }
+ }
+#endif
spin_lock(&mcbsp[id].lock);
if (!mcbsp[id].free) {
@@ -238,30 +298,33 @@ int omap_mcbsp_request(unsigned int id)
mcbsp[id].free = 0;
spin_unlock(&mcbsp[id].lock);
- /* We need to get IRQs here */
- err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
- "McBSP",
- (void *) (&mcbsp[id]));
- if (err != 0) {
- printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
- mcbsp[id].tx_irq, mcbsp[id].id);
- return err;
- }
+ if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+ /* We need to get IRQs here */
+ err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
+ "McBSP",
+ (void *) (&mcbsp[id]));
+ if (err != 0) {
+ printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
+ mcbsp[id].tx_irq, mcbsp[id].id);
+ return err;
+ }
- init_completion(&(mcbsp[id].tx_irq_completion));
+ init_completion(&(mcbsp[id].tx_irq_completion));
- err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
- "McBSP",
- (void *) (&mcbsp[id]));
- if (err != 0) {
- printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
- mcbsp[id].rx_irq, mcbsp[id].id);
- free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
- return err;
+ err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
+ "McBSP",
+ (void *) (&mcbsp[id]));
+ if (err != 0) {
+ printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
+ mcbsp[id].rx_irq, mcbsp[id].id);
+ free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+ return err;
+ }
+
+ init_completion(&(mcbsp[id].rx_irq_completion));
}
- init_completion(&(mcbsp[id].rx_irq_completion));
return 0;
}
@@ -271,8 +334,24 @@ void omap_mcbsp_free(unsigned int id)
if (omap_mcbsp_check(id) < 0)
return;
- if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
- omap_mcbsp_dsp_free();
+#ifdef CONFIG_ARCH_OMAP1
+ if (cpu_class_is_omap1()) {
+ if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
+ omap_mcbsp_dsp_free();
+ }
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+ if (cpu_is_omap24xx()) {
+ if (id == OMAP_MCBSP1) {
+ clk_disable(mcbsp1_ick);
+ clk_disable(mcbsp1_fck);
+ } else {
+ clk_disable(mcbsp2_ick);
+ clk_disable(mcbsp2_fck);
+ }
+ }
+#endif
spin_lock(&mcbsp[id].lock);
if (mcbsp[id].free) {
@@ -284,9 +363,11 @@ void omap_mcbsp_free(unsigned int id)
mcbsp[id].free = 1;
spin_unlock(&mcbsp[id].lock);
- /* Free IRQs */
- free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
- free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+ if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
+ /* Free IRQs */
+ free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
+ free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
+ }
}
/*
@@ -461,6 +542,115 @@ u32 omap_mcbsp_recv_word(unsigned int id)
}
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
+{
+ u32 io_base = mcbsp[id].io_base;
+ omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+ omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+ if (tx_word_length != rx_word_length)
+ return -EINVAL;
+
+ /* First we wait for the transmitter to be ready */
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ while (!(spcr2 & XRDY)) {
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ if (attempts++ > 1000) {
+ /* We must reset the transmitter */
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+ udelay(10);
+ printk("McBSP transmitter not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* Now we can push the data */
+ if (tx_word_length > OMAP_MCBSP_WORD_16)
+ OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
+ OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
+
+ /* We wait for the receiver to be ready */
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ while (!(spcr1 & RRDY)) {
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ if (attempts++ > 1000) {
+ /* We must reset the receiver */
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+ udelay(10);
+ printk("McBSP receiver not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* Receiver is ready, let's read the dummy data */
+ if (rx_word_length > OMAP_MCBSP_WORD_16)
+ word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+ word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+ return 0;
+}
+
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word)
+{
+ u32 io_base = mcbsp[id].io_base, clock_word = 0;
+ omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
+ omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+ if (tx_word_length != rx_word_length)
+ return -EINVAL;
+
+ /* First we wait for the transmitter to be ready */
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ while (!(spcr2 & XRDY)) {
+ spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
+ if (attempts++ > 1000) {
+ /* We must reset the transmitter */
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
+ udelay(10);
+ printk("McBSP transmitter not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* We first need to enable the bus clock */
+ if (tx_word_length > OMAP_MCBSP_WORD_16)
+ OMAP_MCBSP_WRITE(io_base, DXR2, clock_word >> 16);
+ OMAP_MCBSP_WRITE(io_base, DXR1, clock_word & 0xffff);
+
+ /* We wait for the receiver to be ready */
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ while (!(spcr1 & RRDY)) {
+ spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
+ if (attempts++ > 1000) {
+ /* We must reset the receiver */
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
+ udelay(10);
+ OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
+ udelay(10);
+ printk("McBSP receiver not ready\n");
+ return -EAGAIN;
+ }
+ }
+
+ /* Receiver is ready, there is something for us */
+ if (rx_word_length > OMAP_MCBSP_WORD_16)
+ word_msb = OMAP_MCBSP_READ(io_base, DRR2);
+ word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
+
+ word[0] = (word_lsb | (word_msb << 16));
+
+ return 0;
+}
+
+
/*
* Simple DMA based buffer rx/tx routines.
* Nothing fancy, just a single buffer tx/rx through DMA.
@@ -471,6 +661,9 @@ u32 omap_mcbsp_recv_word(unsigned int id)
int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
{
int dma_tx_ch;
+ int src_port = 0;
+ int dest_port = 0;
+ int sync_dev = 0;
if (omap_mcbsp_check(id) < 0)
return -EINVAL;
@@ -487,20 +680,27 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
init_completion(&(mcbsp[id].tx_dma_completion));
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_TIPB;
+ dest_port = OMAP_DMA_PORT_EMIFF;
+ }
+ if (cpu_is_omap24xx())
+ sync_dev = mcbsp[id].dma_tx_sync;
+
omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
OMAP_DMA_DATA_TYPE_S16,
length >> 1, 1,
OMAP_DMA_SYNC_ELEMENT,
- 0, 0);
+ sync_dev, 0);
omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
- OMAP_DMA_PORT_TIPB,
+ src_port,
OMAP_DMA_AMODE_CONSTANT,
mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
0, 0);
omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
- OMAP_DMA_PORT_EMIFF,
+ dest_port,
OMAP_DMA_AMODE_POST_INC,
buffer,
0, 0);
@@ -514,6 +714,9 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
{
int dma_rx_ch;
+ int src_port = 0;
+ int dest_port = 0;
+ int sync_dev = 0;
if (omap_mcbsp_check(id) < 0)
return -EINVAL;
@@ -530,20 +733,27 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
init_completion(&(mcbsp[id].rx_dma_completion));
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_TIPB;
+ dest_port = OMAP_DMA_PORT_EMIFF;
+ }
+ if (cpu_is_omap24xx())
+ sync_dev = mcbsp[id].dma_rx_sync;
+
omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
OMAP_DMA_DATA_TYPE_S16,
length >> 1, 1,
OMAP_DMA_SYNC_ELEMENT,
- 0, 0);
+ sync_dev, 0);
omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
- OMAP_DMA_PORT_TIPB,
+ src_port,
OMAP_DMA_AMODE_CONSTANT,
mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
0, 0);
omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
- OMAP_DMA_PORT_EMIFF,
+ dest_port,
OMAP_DMA_AMODE_POST_INC,
buffer,
0, 0);
@@ -688,6 +898,23 @@ static const struct omap_mcbsp_info mcbsp_1610[] = {
};
#endif
+#if defined(CONFIG_ARCH_OMAP24XX)
+static const struct omap_mcbsp_info mcbsp_24xx[] = {
+ [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
+ .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
+ .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
+ .rx_irq = INT_24XX_MCBSP1_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP1_IRQ_TX,
+ },
+ [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
+ .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
+ .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
+ .rx_irq = INT_24XX_MCBSP2_IRQ_RX,
+ .tx_irq = INT_24XX_MCBSP2_IRQ_TX,
+ },
+};
+#endif
+
static int __init omap_mcbsp_init(void)
{
int mcbsp_count = 0, i;
@@ -695,6 +922,7 @@ static int __init omap_mcbsp_init(void)
printk("Initializing OMAP McBSP system\n");
+#ifdef CONFIG_ARCH_OMAP1
mcbsp_dsp_ck = clk_get(0, "dsp_ck");
if (IS_ERR(mcbsp_dsp_ck)) {
printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
@@ -710,6 +938,29 @@ static int __init omap_mcbsp_init(void)
printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");
return PTR_ERR(mcbsp_dspxor_ck);
}
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+ mcbsp1_ick = clk_get(0, "mcbsp1_ick");
+ if (IS_ERR(mcbsp1_ick)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n");
+ return PTR_ERR(mcbsp1_ick);
+ }
+ mcbsp1_fck = clk_get(0, "mcbsp1_fck");
+ if (IS_ERR(mcbsp1_fck)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n");
+ return PTR_ERR(mcbsp1_fck);
+ }
+ mcbsp2_ick = clk_get(0, "mcbsp2_ick");
+ if (IS_ERR(mcbsp2_ick)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n");
+ return PTR_ERR(mcbsp2_ick);
+ }
+ mcbsp2_fck = clk_get(0, "mcbsp2_fck");
+ if (IS_ERR(mcbsp2_fck)) {
+ printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n");
+ return PTR_ERR(mcbsp2_fck);
+ }
+#endif
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730()) {
@@ -718,7 +969,7 @@ static int __init omap_mcbsp_init(void)
}
#endif
#ifdef CONFIG_ARCH_OMAP15XX
- if (cpu_is_omap1510()) {
+ if (cpu_is_omap15xx()) {
mcbsp_info = mcbsp_1510;
mcbsp_count = ARRAY_SIZE(mcbsp_1510);
}
@@ -729,6 +980,19 @@ static int __init omap_mcbsp_init(void)
mcbsp_count = ARRAY_SIZE(mcbsp_1610);
}
#endif
+#if defined(CONFIG_ARCH_OMAP24XX)
+ if (cpu_is_omap24xx()) {
+ mcbsp_info = mcbsp_24xx;
+ mcbsp_count = ARRAY_SIZE(mcbsp_24xx);
+
+ /* REVISIT: where's the right place? */
+ omap2_mcbsp2_mux_setup();
+ sys_ck = clk_get(0, "sys_ck");
+ sys_clkout = clk_get(0, "sys_clkout");
+ clk_set_parent(sys_clkout, sys_ck);
+ clk_enable(sys_clkout);
+ }
+#endif
for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
if (i >= mcbsp_count) {
mcbsp[i].io_base = 0;
@@ -741,6 +1005,7 @@ static int __init omap_mcbsp_init(void)
mcbsp[i].dma_rx_lch = -1;
mcbsp[i].io_base = mcbsp_info[i].virt_base;
+ mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */
mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
@@ -751,11 +1016,11 @@ static int __init omap_mcbsp_init(void)
return 0;
}
-
arch_initcall(omap_mcbsp_init);
EXPORT_SYMBOL(omap_mcbsp_config);
EXPORT_SYMBOL(omap_mcbsp_request);
+EXPORT_SYMBOL(omap_mcbsp_set_io_type);
EXPORT_SYMBOL(omap_mcbsp_free);
EXPORT_SYMBOL(omap_mcbsp_start);
EXPORT_SYMBOL(omap_mcbsp_stop);
@@ -763,4 +1028,6 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_word);
EXPORT_SYMBOL(omap_mcbsp_recv_word);
EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
+EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c
index 5cc6775c789..37792d43738 100644
--- a/arch/arm/plat-omap/ocpi.c
+++ b/arch/arm/plat-omap/ocpi.c
@@ -62,9 +62,6 @@ int ocpi_enable(void)
if (!cpu_is_omap16xx())
return -ENODEV;
- /* Make sure there's clock for OCPI */
- clk_enable(ocpi_ck);
-
/* Enable access for OHCI in OCPI */
val = omap_readl(OCPI_PROT);
val &= ~0xff;
diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c
index 093efd786f2..1a24e2c1071 100644
--- a/arch/arm/plat-omap/pm.c
+++ b/arch/arm/plat-omap/pm.c
@@ -38,6 +38,7 @@
#include <linux/pm.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
+#include <linux/pm.h>
#include <linux/interrupt.h>
#include <asm/io.h>
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index ee82763b02b..b7bf09b1b41 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -16,24 +16,94 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <asm/mach/map.h>
#include <asm/tlb.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
+#include <asm/mach/map.h>
+
#include <asm/arch/sram.h>
+#include <asm/arch/board.h>
#define OMAP1_SRAM_PA 0x20000000
#define OMAP1_SRAM_VA 0xd0000000
#define OMAP2_SRAM_PA 0x40200000
+#define OMAP2_SRAM_PUB_PA 0x4020f800
#define OMAP2_SRAM_VA 0xd0000000
+#define OMAP2_SRAM_PUB_VA 0xd0000800
+#if defined(CONFIG_ARCH_OMAP24XX)
+#define SRAM_BOOTLOADER_SZ 0x00
+#else
#define SRAM_BOOTLOADER_SZ 0x80
+#endif
+
+#define VA_REQINFOPERM0 IO_ADDRESS(0x68005048)
+#define VA_READPERM0 IO_ADDRESS(0x68005050)
+#define VA_WRITEPERM0 IO_ADDRESS(0x68005058)
+#define VA_CONTROL_STAT IO_ADDRESS(0x480002F8)
+#define GP_DEVICE 0x300
+#define TYPE_MASK 0x700
+
+#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
static unsigned long omap_sram_base;
static unsigned long omap_sram_size;
static unsigned long omap_sram_ceil;
+unsigned long omap_fb_sram_start;
+unsigned long omap_fb_sram_size;
+
+/* Depending on the target RAMFS firewall setup, the public usable amount of
+ * SRAM varies. The default accessable size for all device types is 2k. A GP
+ * device allows ARM11 but not other initators for full size. This
+ * functionality seems ok until some nice security API happens.
+ */
+static int is_sram_locked(void)
+{
+ int type = 0;
+
+ if (cpu_is_omap242x())
+ type = __raw_readl(VA_CONTROL_STAT) & TYPE_MASK;
+
+ if (type == GP_DEVICE) {
+ /* RAMFW: R/W access to all initators for all qualifier sets */
+ if (cpu_is_omap242x()) {
+ __raw_writel(0xFF, VA_REQINFOPERM0); /* all q-vects */
+ __raw_writel(0xCFDE, VA_READPERM0); /* all i-read */
+ __raw_writel(0xCFDE, VA_WRITEPERM0); /* all i-write */
+ }
+ return 0;
+ } else
+ return 1; /* assume locked with no PPA or security driver */
+}
+
+void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail,
+ unsigned long *start, unsigned long *size)
+{
+ const struct omap_fbmem_config *fbmem_conf;
+
+ fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config);
+ if (fbmem_conf != NULL) {
+ *start = fbmem_conf->fb_sram_start;
+ *size = fbmem_conf->fb_sram_size;
+ } else {
+ *size = 0;
+ *start = 0;
+ }
+
+ if (*size && (
+ *start < start_avail ||
+ *start + *size > start_avail + size_avail)) {
+ printk(KERN_ERR "invalid FB SRAM configuration\n");
+ *start = start_avail;
+ *size = size_avail;
+ }
+
+ if (*size)
+ pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size);
+}
+
/*
* The amount of SRAM depends on the core type.
* Note that we cannot try to test for SRAM here because writes
@@ -42,26 +112,45 @@ static unsigned long omap_sram_ceil;
*/
void __init omap_detect_sram(void)
{
- if (!cpu_is_omap24xx())
+ unsigned long sram_start;
+
+ if (cpu_is_omap24xx()) {
+ if (is_sram_locked()) {
+ omap_sram_base = OMAP2_SRAM_PUB_VA;
+ sram_start = OMAP2_SRAM_PUB_PA;
+ omap_sram_size = 0x800; /* 2K */
+ } else {
+ omap_sram_base = OMAP2_SRAM_VA;
+ sram_start = OMAP2_SRAM_PA;
+ if (cpu_is_omap242x())
+ omap_sram_size = 0xa0000; /* 640K */
+ else if (cpu_is_omap243x())
+ omap_sram_size = 0x10000; /* 64K */
+ }
+ } else {
omap_sram_base = OMAP1_SRAM_VA;
- else
- omap_sram_base = OMAP2_SRAM_VA;
-
- if (cpu_is_omap730())
- omap_sram_size = 0x32000; /* 200K */
- else if (cpu_is_omap15xx())
- omap_sram_size = 0x30000; /* 192K */
- else if (cpu_is_omap1610() || cpu_is_omap1621() || cpu_is_omap1710())
- omap_sram_size = 0x4000; /* 16K */
- else if (cpu_is_omap1611())
- omap_sram_size = 0x3e800; /* 250K */
- else if (cpu_is_omap2420())
- omap_sram_size = 0xa0014; /* 640K */
- else {
- printk(KERN_ERR "Could not detect SRAM size\n");
- omap_sram_size = 0x4000;
+ sram_start = OMAP1_SRAM_PA;
+
+ if (cpu_is_omap730())
+ omap_sram_size = 0x32000; /* 200K */
+ else if (cpu_is_omap15xx())
+ omap_sram_size = 0x30000; /* 192K */
+ else if (cpu_is_omap1610() || cpu_is_omap1621() ||
+ cpu_is_omap1710())
+ omap_sram_size = 0x4000; /* 16K */
+ else if (cpu_is_omap1611())
+ omap_sram_size = 0x3e800; /* 250K */
+ else {
+ printk(KERN_ERR "Could not detect SRAM size\n");
+ omap_sram_size = 0x4000;
+ }
}
-
+ get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ,
+ omap_sram_size - SRAM_BOOTLOADER_SZ,
+ &omap_fb_sram_start, &omap_fb_sram_size);
+ if (omap_fb_sram_size)
+ omap_sram_size -= sram_start + omap_sram_size -
+ omap_fb_sram_start;
omap_sram_ceil = omap_sram_base + omap_sram_size;
}
@@ -80,12 +169,20 @@ static struct map_desc omap_sram_io_desc[] __initdata = {
*/
void __init omap_map_sram(void)
{
+ unsigned long base;
+
if (omap_sram_size == 0)
return;
if (cpu_is_omap24xx()) {
omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA;
- omap_sram_io_desc[0].pfn = __phys_to_pfn(OMAP2_SRAM_PA);
+
+ if (is_sram_locked())
+ base = OMAP2_SRAM_PUB_PA;
+ else
+ base = OMAP2_SRAM_PA;
+ base = ROUND_DOWN(base, PAGE_SIZE);
+ omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
}
omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE;
@@ -93,7 +190,8 @@ void __init omap_map_sram(void)
iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
- omap_sram_io_desc[0].pfn, omap_sram_io_desc[0].virtual,
+ __pfn_to_phys(omap_sram_io_desc[0].pfn),
+ omap_sram_io_desc[0].virtual,
omap_sram_io_desc[0].length);
/*
@@ -118,8 +216,9 @@ void * omap_sram_push(void * start, unsigned long size)
printk(KERN_ERR "Not enough space in SRAM\n");
return NULL;
}
+
omap_sram_ceil -= size;
- omap_sram_ceil &= ~0x3;
+ omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
memcpy((void *)omap_sram_ceil, start, size);
return (void *)omap_sram_ceil;
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
new file mode 100644
index 00000000000..b2a943bf11e
--- /dev/null
+++ b/arch/arm/plat-omap/timer32k.c
@@ -0,0 +1,325 @@
+/*
+ * linux/arch/arm/plat-omap/timer32k.c
+ *
+ * OMAP 32K Timer
+ *
+ * Copyright (C) 2004 - 2005 Nokia Corporation
+ * Partial timer rewrite and additional dynamic tick timer support by
+ * Tony Lindgen <tony@atomide.com> and
+ * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ * MPU timer code based on the older MPU timer code for OMAP
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+struct sys_timer omap_timer;
+
+/*
+ * ---------------------------------------------------------------------------
+ * 32KHz OS timer
+ *
+ * This currently works only on 16xx, as 1510 does not have the continuous
+ * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
+ * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
+ * on 1510 would be possible, but the timer would not be as accurate as
+ * with the 32KHz synchronized timer.
+ * ---------------------------------------------------------------------------
+ */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+#define TIMER_32K_SYNCHRONIZED 0xfffbc410
+#elif defined(CONFIG_ARCH_OMAP24XX)
+#define TIMER_32K_SYNCHRONIZED 0x48004010
+#else
+#error OMAP 32KHz timer does not currently work on 15XX!
+#endif
+
+/* 16xx specific defines */
+#define OMAP1_32K_TIMER_BASE 0xfffb9000
+#define OMAP1_32K_TIMER_CR 0x08
+#define OMAP1_32K_TIMER_TVR 0x00
+#define OMAP1_32K_TIMER_TCR 0x04
+
+/* 24xx specific defines */
+#define OMAP2_GP_TIMER_BASE 0x48028000
+#define CM_CLKSEL_WKUP 0x48008440
+#define GP_TIMER_TIDR 0x00
+#define GP_TIMER_TISR 0x18
+#define GP_TIMER_TIER 0x1c
+#define GP_TIMER_TCLR 0x24
+#define GP_TIMER_TCRR 0x28
+#define GP_TIMER_TLDR 0x2c
+#define GP_TIMER_TTGR 0x30
+#define GP_TIMER_TSICR 0x40
+
+#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
+
+/*
+ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+ * so with HZ = 128, TVR = 255.
+ */
+#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
+
+#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
+ (((nr_jiffies) * (clock_rate)) / HZ)
+
+static inline void omap_32k_timer_write(int val, int reg)
+{
+ if (cpu_class_is_omap1())
+ omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
+
+ if (cpu_is_omap24xx())
+ omap_writel(val, OMAP2_GP_TIMER_BASE + reg);
+}
+
+static inline unsigned long omap_32k_timer_read(int reg)
+{
+ if (cpu_class_is_omap1())
+ return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
+
+ if (cpu_is_omap24xx())
+ return omap_readl(OMAP2_GP_TIMER_BASE + reg);
+}
+
+/*
+ * The 32KHz synchronized timer is an additional timer on 16xx.
+ * It is always running.
+ */
+static inline unsigned long omap_32k_sync_timer_read(void)
+{
+ return omap_readl(TIMER_32K_SYNCHRONIZED);
+}
+
+static inline void omap_32k_timer_start(unsigned long load_val)
+{
+ if (cpu_class_is_omap1()) {
+ omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
+ omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
+ }
+
+ if (cpu_is_omap24xx()) {
+ omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR);
+ omap_32k_timer_write((1 << 1), GP_TIMER_TIER);
+ omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR);
+ }
+}
+
+static inline void omap_32k_timer_stop(void)
+{
+ if (cpu_class_is_omap1())
+ omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
+
+ if (cpu_is_omap24xx())
+ omap_32k_timer_write(0x0, GP_TIMER_TCLR);
+}
+
+/*
+ * Rounds down to nearest usec. Note that this will overflow for larger values.
+ */
+static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
+{
+ return (ticks_32k * 5*5*5*5*5*5) >> 9;
+}
+
+/*
+ * Rounds down to nearest nsec.
+ */
+static inline unsigned long long
+omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
+{
+ return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9;
+}
+
+static unsigned long omap_32k_last_tick = 0;
+
+/*
+ * Returns elapsed usecs since last 32k timer interrupt
+ */
+static unsigned long omap_32k_timer_gettimeoffset(void)
+{
+ unsigned long now = omap_32k_sync_timer_read();
+ return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
+}
+
+/*
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
+ */
+unsigned long long sched_clock(void)
+{
+ return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read());
+}
+
+/*
+ * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
+ * function is also called from other interrupts to remove latency
+ * issues with dynamic tick. In the dynamic tick case, we need to lock
+ * with irqsave.
+ */
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ unsigned long flags;
+ unsigned long now;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+
+ if (cpu_is_omap24xx()) {
+ u32 status = omap_32k_timer_read(GP_TIMER_TISR);
+ omap_32k_timer_write(status, GP_TIMER_TISR);
+ }
+
+ now = omap_32k_sync_timer_read();
+
+ while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+ omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
+ timer_tick(regs);
+ }
+
+ /* Restart timer so we don't drift off due to modulo or dynamic tick.
+ * By default we program the next timer to be continuous to avoid
+ * latencies during high system load. During dynamic tick operation the
+ * continuous timer can be overridden from pm_idle to be longer.
+ */
+ omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NO_IDLE_HZ
+/*
+ * Programs the next timer interrupt needed. Called when dynamic tick is
+ * enabled, and to reprogram the ticks to skip from pm_idle. Note that
+ * we can keep the timer continuous, and don't need to set it to run in
+ * one-shot mode. This is because the timer will get reprogrammed again
+ * after next interrupt.
+ */
+void omap_32k_timer_reprogram(unsigned long next_tick)
+{
+ omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
+}
+
+static struct irqaction omap_32k_timer_irq;
+extern struct timer_update_handler timer_update;
+
+static int omap_32k_timer_enable_dyn_tick(void)
+{
+ /* No need to reprogram timer, just use the next interrupt */
+ return 0;
+}
+
+static int omap_32k_timer_disable_dyn_tick(void)
+{
+ omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+ return 0;
+}
+
+static struct dyn_tick_timer omap_dyn_tick_timer = {
+ .enable = omap_32k_timer_enable_dyn_tick,
+ .disable = omap_32k_timer_disable_dyn_tick,
+ .reprogram = omap_32k_timer_reprogram,
+ .handler = omap_32k_timer_interrupt,
+};
+#endif /* CONFIG_NO_IDLE_HZ */
+
+static struct irqaction omap_32k_timer_irq = {
+ .name = "32KHz timer",
+ .flags = SA_INTERRUPT | SA_TIMER,
+ .handler = omap_32k_timer_interrupt,
+};
+
+static struct clk * gpt1_ick;
+static struct clk * gpt1_fck;
+
+static __init void omap_init_32k_timer(void)
+{
+#ifdef CONFIG_NO_IDLE_HZ
+ omap_timer.dyn_tick = &omap_dyn_tick_timer;
+#endif
+
+ if (cpu_class_is_omap1())
+ setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+ if (cpu_is_omap24xx())
+ setup_irq(37, &omap_32k_timer_irq);
+ omap_timer.offset = omap_32k_timer_gettimeoffset;
+ omap_32k_last_tick = omap_32k_sync_timer_read();
+
+ /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */
+ if (cpu_is_omap24xx()) {
+ omap_32k_timer_write(0, GP_TIMER_TCLR);
+ omap_writel(0, CM_CLKSEL_WKUP); /* 32KHz clock source */
+
+ gpt1_ick = clk_get(NULL, "gpt1_ick");
+ if (IS_ERR(gpt1_ick))
+ printk(KERN_ERR "Could not get gpt1_ick\n");
+ else
+ clk_enable(gpt1_ick);
+
+ gpt1_fck = clk_get(NULL, "gpt1_fck");
+ if (IS_ERR(gpt1_fck))
+ printk(KERN_ERR "Could not get gpt1_fck\n");
+ else
+ clk_enable(gpt1_fck);
+
+ mdelay(100); /* Wait for clocks to stabilize */
+
+ omap_32k_timer_write(0x7, GP_TIMER_TISR);
+ }
+
+ omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+static void __init omap_timer_init(void)
+{
+ omap_init_32k_timer();
+}
+
+struct sys_timer omap_timer = {
+ .init = omap_timer_init,
+ .offset = NULL, /* Initialized later */
+};