[ARM] 2890/1: OMAP 1/4: Update omap1 specific files, take 2

Patch from Tony Lindgren

This patch syncs the mainline kernel with linux-omap tree.
The highlights of the patch are:
- Convert more drivers to register resources in board-*.c to take
  advantage of the driver model by David Brownell and Ladislav Michl
- Use set_irq_type() for GPIO interrupts instead of
  omap_set_gpio_edge_ctrl() by David Brownell
- Add minimal support for handling optional add-on boards, such as
  OSK Mistral board with LCD and keypad, by David Brownell
- Minimal support for loading functions to SRAM by Tony Lindgren
- Wake up from serial port by muxing RX lines temporarily into GPIO
  interrupts by Tony Lindgren
- 32KHz sched_clock by Tony Lindgren and Juha Yrjola

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 214e5d1..e702e0c 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -24,7 +24,11 @@
 
 #include <asm/arch/board.h>
 #include <asm/arch/mux.h>
+#include <asm/arch/gpio.h>
 #include <asm/arch/fpga.h>
+#ifdef CONFIG_PM
+#include <asm/arch/pm.h>
+#endif
 
 static struct clk * uart1_ck = NULL;
 static struct clk * uart2_ck = NULL;
@@ -193,6 +197,86 @@
 	}
 }
 
+#ifdef CONFIG_OMAP_SERIAL_WAKE
+
+static irqreturn_t omap_serial_wake_interrupt(int irq, void *dev_id,
+					      struct pt_regs *regs)
+{
+	/* Need to do something with serial port right after wake-up? */
+	return IRQ_HANDLED;
+}
+
+/*
+ * Reroutes serial RX lines to GPIO lines for the duration of
+ * sleep to allow waking up the device from serial port even
+ * in deep sleep.
+ */
+void omap_serial_wake_trigger(int enable)
+{
+	if (!cpu_is_omap16xx())
+		return;
+
+	if (uart1_ck != NULL) {
+		if (enable)
+			omap_cfg_reg(V14_16XX_GPIO37);
+		else
+			omap_cfg_reg(V14_16XX_UART1_RX);
+	}
+	if (uart2_ck != NULL) {
+		if (enable)
+			omap_cfg_reg(R9_16XX_GPIO18);
+		else
+			omap_cfg_reg(R9_16XX_UART2_RX);
+	}
+	if (uart3_ck != NULL) {
+		if (enable)
+			omap_cfg_reg(L14_16XX_GPIO49);
+		else
+			omap_cfg_reg(L14_16XX_UART3_RX);
+	}
+}
+
+static void __init omap_serial_set_port_wakeup(int gpio_nr)
+{
+	int ret;
+
+	ret = omap_request_gpio(gpio_nr);
+	if (ret < 0) {
+		printk(KERN_ERR "Could not request UART wake GPIO: %i\n",
+		       gpio_nr);
+		return;
+	}
+	omap_set_gpio_direction(gpio_nr, 1);
+	set_irq_type(OMAP_GPIO_IRQ(gpio_nr), IRQT_RISING);
+	ret = request_irq(OMAP_GPIO_IRQ(gpio_nr), &omap_serial_wake_interrupt,
+			  0, "serial wakeup", NULL);
+	if (ret) {
+		omap_free_gpio(gpio_nr);
+		printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n",
+		       gpio_nr);
+		return;
+	}
+	enable_irq_wake(OMAP_GPIO_IRQ(gpio_nr));
+}
+
+static int __init omap_serial_wakeup_init(void)
+{
+	if (!cpu_is_omap16xx())
+		return 0;
+
+	if (uart1_ck != NULL)
+		omap_serial_set_port_wakeup(37);
+	if (uart2_ck != NULL)
+		omap_serial_set_port_wakeup(18);
+	if (uart3_ck != NULL)
+		omap_serial_set_port_wakeup(49);
+
+	return 0;
+}
+late_initcall(omap_serial_wakeup_init);
+
+#endif	/* CONFIG_OMAP_SERIAL_WAKE */
+
 static int __init omap_init(void)
 {
 	return platform_device_register(&serial_device);