aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap1
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap1')
-rw-r--r--arch/arm/mach-omap1/Kconfig245
-rw-r--r--arch/arm/mach-omap1/Makefile67
-rw-r--r--arch/arm/mach-omap1/Makefile.boot3
-rw-r--r--arch/arm/mach-omap1/ams-delta-fiq-handler.S278
-rw-r--r--arch/arm/mach-omap1/ams-delta-fiq.c157
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c398
-rw-r--r--arch/arm/mach-omap1/board-fsample.c398
-rw-r--r--arch/arm/mach-omap1/board-generic.c103
-rw-r--r--arch/arm/mach-omap1/board-h2-mmc.c80
-rw-r--r--arch/arm/mach-omap1/board-h2.c470
-rw-r--r--arch/arm/mach-omap1/board-h2.h38
-rw-r--r--arch/arm/mach-omap1/board-h3-mmc.c69
-rw-r--r--arch/arm/mach-omap1/board-h3.c458
-rw-r--r--arch/arm/mach-omap1/board-h3.h35
-rw-r--r--arch/arm/mach-omap1/board-htcherald.c620
-rw-r--r--arch/arm/mach-omap1/board-innovator.c468
-rw-r--r--arch/arm/mach-omap1/board-nokia770.c273
-rw-r--r--arch/arm/mach-omap1/board-osk.c592
-rw-r--r--arch/arm/mach-omap1/board-palmte.c284
-rw-r--r--arch/arm/mach-omap1/board-palmtt.c330
-rw-r--r--arch/arm/mach-omap1/board-palmz71.c350
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c359
-rw-r--r--arch/arm/mach-omap1/board-sx1-mmc.c66
-rw-r--r--arch/arm/mach-omap1/board-sx1.c430
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c310
-rw-r--r--arch/arm/mach-omap1/clock.c609
-rw-r--r--arch/arm/mach-omap1/clock.h113
-rw-r--r--arch/arm/mach-omap1/clock_data.c927
-rw-r--r--arch/arm/mach-omap1/devices.c333
-rw-r--r--arch/arm/mach-omap1/dma.c391
-rw-r--r--arch/arm/mach-omap1/flash.c34
-rw-r--r--arch/arm/mach-omap1/fpga.c188
-rw-r--r--arch/arm/mach-omap1/gpio15xx.c99
-rw-r--r--arch/arm/mach-omap1/gpio16xx.c200
-rw-r--r--arch/arm/mach-omap1/gpio7xx.c262
-rw-r--r--arch/arm/mach-omap1/i2c.c35
-rw-r--r--arch/arm/mach-omap1/id.c204
-rw-r--r--arch/arm/mach-omap1/include/mach/ams-delta-fiq.h79
-rw-r--r--arch/arm/mach-omap1/include/mach/camera.h13
-rw-r--r--arch/arm/mach-omap1/include/mach/clkdev.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/debug-macro.S107
-rw-r--r--arch/arm/mach-omap1/include/mach/entry-macro.S46
-rw-r--r--arch/arm/mach-omap1/include/mach/gpio.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/hardware.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/io.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/irqs.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/lcd_dma.h78
-rw-r--r--arch/arm/mach-omap1/include/mach/lcdc.h57
-rw-r--r--arch/arm/mach-omap1/include/mach/memory.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/mtd-xip.h61
-rw-r--r--arch/arm/mach-omap1/include/mach/smp.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/system.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/timex.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/uncompress.h5
-rw-r--r--arch/arm/mach-omap1/include/mach/vmalloc.h20
-rw-r--r--arch/arm/mach-omap1/io.c183
-rw-r--r--arch/arm/mach-omap1/irq.c247
-rw-r--r--arch/arm/mach-omap1/lcd_dma.c451
-rw-r--r--arch/arm/mach-omap1/leds-h2p2-debug.c167
-rw-r--r--arch/arm/mach-omap1/leds-innovator.c99
-rw-r--r--arch/arm/mach-omap1/leds-osk.c115
-rw-r--r--arch/arm/mach-omap1/leds.c69
-rw-r--r--arch/arm/mach-omap1/leds.h3
-rw-r--r--arch/arm/mach-omap1/mailbox.c198
-rw-r--r--arch/arm/mach-omap1/mcbsp.c410
-rw-r--r--arch/arm/mach-omap1/mux.c471
-rw-r--r--arch/arm/mach-omap1/opp.h28
-rw-r--r--arch/arm/mach-omap1/opp_data.c59
-rw-r--r--arch/arm/mach-omap1/pm.c730
-rw-r--r--arch/arm/mach-omap1/pm.h281
-rw-r--r--arch/arm/mach-omap1/pm_bus.c79
-rw-r--r--arch/arm/mach-omap1/reset.c25
-rw-r--r--arch/arm/mach-omap1/serial.c266
-rw-r--r--arch/arm/mach-omap1/sleep.S366
-rw-r--r--arch/arm/mach-omap1/sram.S58
-rw-r--r--arch/arm/mach-omap1/time.c312
-rw-r--r--arch/arm/mach-omap1/timer32k.c193
-rw-r--r--arch/arm/mach-omap1/usb.c530
78 files changed, 16127 insertions, 0 deletions
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
new file mode 100644
index 00000000..e0a02816
--- /dev/null
+++ b/arch/arm/mach-omap1/Kconfig
@@ -0,0 +1,245 @@
+if ARCH_OMAP1
+
+menu "TI OMAP1 specific features"
+
+comment "OMAP Core Type"
+ depends on ARCH_OMAP1
+
+config ARCH_OMAP730
+ depends on ARCH_OMAP1
+ bool "OMAP730 Based System"
+ select CPU_ARM926T
+ select OMAP_MPU_TIMER
+ select ARCH_OMAP_OTG
+
+config ARCH_OMAP850
+ depends on ARCH_OMAP1
+ bool "OMAP850 Based System"
+ select CPU_ARM926T
+ select ARCH_OMAP_OTG
+
+config ARCH_OMAP15XX
+ depends on ARCH_OMAP1
+ default y
+ bool "OMAP15xx Based System"
+ select CPU_ARM925T
+ select OMAP_MPU_TIMER
+
+config ARCH_OMAP16XX
+ depends on ARCH_OMAP1
+ bool "OMAP16xx Based System"
+ select CPU_ARM926T
+ select ARCH_OMAP_OTG
+
+comment "OMAP Board Type"
+ depends on ARCH_OMAP1
+
+config MACH_OMAP_INNOVATOR
+ bool "TI Innovator"
+ depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
+ select OMAP_MCBSP
+ help
+ TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
+ have such a board.
+
+config MACH_OMAP_H2
+ bool "TI H2 Support"
+ depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ select OMAP_MCBSP
+ help
+ TI OMAP 1610/1611B H2 board support. Say Y here if you have such
+ a board.
+
+config MACH_OMAP_H3
+ bool "TI H3 Support"
+ depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ help
+ TI OMAP 1710 H3 board support. Say Y here if you have such
+ a board.
+
+config MACH_OMAP_HTCWIZARD
+ bool "HTC Wizard"
+ depends on ARCH_OMAP850
+ help
+ HTC Wizard smartphone support (AKA QTEK 9100, ...)
+
+config MACH_HERALD
+ bool "HTC Herald"
+ depends on ARCH_OMAP850
+ help
+ HTC Herald smartphone support (AKA T-Mobile Wing, ...)
+
+config MACH_OMAP_OSK
+ bool "TI OSK Support"
+ depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ select OMAP_MCBSP
+ help
+ TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
+ if you have such a board.
+
+config OMAP_OSK_MISTRAL
+ bool "Mistral QVGA board Support"
+ depends on MACH_OMAP_OSK
+ help
+ The OSK supports an optional add-on board with a Quarter-VGA
+ touchscreen, PDA-ish buttons, a resume button, bicolor LED,
+ and camera connector. Say Y here if you have this board.
+
+config MACH_OMAP_PERSEUS2
+ bool "TI Perseus2"
+ depends on ARCH_OMAP1 && ARCH_OMAP730
+ help
+ Support for TI OMAP 730 Perseus2 board. Say Y here if you have such
+ a board.
+
+config MACH_OMAP_FSAMPLE
+ bool "TI F-Sample"
+ depends on ARCH_OMAP1 && ARCH_OMAP730
+ help
+ Support for TI OMAP 850 F-Sample board. Say Y here if you have such
+ a board.
+
+config MACH_VOICEBLUE
+ bool "Voiceblue"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for Voiceblue GSM/VoIP gateway. Say Y here if you have
+ such a board.
+
+config MACH_OMAP_PALMTE
+ bool "Palm Tungsten E"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Palm Tungsten E PDA. To boot the kernel, you'll
+ need a PalmOS compatible bootloader; check out
+ http://palmtelinux.sourceforge.net/ for more information.
+ Say Y here if you have this PDA model, say N otherwise.
+
+config MACH_OMAP_PALMZ71
+ bool "Palm Zire71"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Palm Zire71 PDA. To boot the kernel,
+ you'll need a PalmOS compatible bootloader; check out
+ http://hackndev.com/palm/z71 for more information.
+ Say Y here if you have such a PDA, say N otherwise.
+
+config MACH_OMAP_PALMTT
+ bool "Palm Tungsten|T"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Palm Tungsten|T PDA. To boot the kernel, you'll
+ need a PalmOS compatible bootloader (Garux); check out
+ http://garux.sourceforge.net/ for more information.
+ Say Y here if you have this PDA model, say N otherwise.
+
+config MACH_SX1
+ bool "Siemens SX1"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Support for the Siemens SX1 phone. To boot the kernel,
+ you'll need a SX1 compatible bootloader; check out
+ http://forum.oslik.ru and
+ http://www.handhelds.org/moin/moin.cgi/SiemensSX1
+ for more information.
+ Say Y here if you have such a phone, 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
+ select FIQ
+ 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)
+ help
+ Support for generic OMAP-1510, 1610 or 1710 board with
+ no FPGA. Can be used as template for porting Linux to
+ custom OMAP boards. Say Y here if you have a custom
+ board.
+
+comment "OMAP CPU Speed"
+ depends on ARCH_OMAP1
+
+config OMAP_CLOCKS_SET_BY_BOOTLOADER
+ bool "OMAP clocks set by bootloader"
+ depends on ARCH_OMAP1
+ help
+ Enable this option to prevent the kernel from overriding the clock
+ frequencies programmed by bootloader for MPU, DSP, MMUs, TC,
+ internal LCD controller and MPU peripherals.
+
+config OMAP_ARM_216MHZ
+ bool "OMAP ARM 216 MHz CPU (1710 only)"
+ depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ help
+ Enable 216 MHz clock for OMAP1710 CPU. If unsure, say N.
+
+config OMAP_ARM_195MHZ
+ bool "OMAP ARM 195 MHz CPU"
+ depends on ARCH_OMAP1 && (ARCH_OMAP730 || ARCH_OMAP850)
+ help
+ Enable 195MHz clock for OMAP CPU. If unsure, say N.
+
+config OMAP_ARM_192MHZ
+ bool "OMAP ARM 192 MHz CPU"
+ depends on ARCH_OMAP1 && ARCH_OMAP16XX
+ help
+ Enable 192MHz clock for OMAP CPU. If unsure, say N.
+
+config OMAP_ARM_182MHZ
+ bool "OMAP ARM 182 MHz CPU"
+ depends on ARCH_OMAP1 && (ARCH_OMAP730 || ARCH_OMAP850)
+ help
+ Enable 182MHz clock for OMAP CPU. If unsure, say N.
+
+config OMAP_ARM_168MHZ
+ bool "OMAP ARM 168 MHz CPU"
+ depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850)
+ help
+ Enable 168MHz clock for OMAP CPU. If unsure, say N.
+
+config OMAP_ARM_150MHZ
+ bool "OMAP ARM 150 MHz CPU"
+ depends on ARCH_OMAP1 && ARCH_OMAP15XX
+ help
+ Enable 150MHz clock for OMAP CPU. If unsure, say N.
+
+config OMAP_ARM_120MHZ
+ bool "OMAP ARM 120 MHz CPU"
+ depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850)
+ help
+ Enable 120MHz clock for OMAP CPU. If unsure, say N.
+
+config OMAP_ARM_96MHZ
+ bool "OMAP ARM 96 MHz CPU"
+ depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850)
+ help
+ Enable 96MHz clock for OMAP CPU. If unsure, say N.
+
+config OMAP_ARM_60MHZ
+ bool "OMAP ARM 60 MHz CPU"
+ depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850)
+ default y
+ help
+ Enable 60MHz clock for OMAP CPU. If unsure, say Y.
+
+config OMAP_ARM_30MHZ
+ bool "OMAP ARM 30 MHz CPU"
+ depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_OMAP850)
+ help
+ Enable 30MHz clock for OMAP CPU. If unsure, say N.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
new file mode 100644
index 00000000..5b114d15
--- /dev/null
+++ b/arch/arm/mach-omap1/Makefile
@@ -0,0 +1,67 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support
+obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
+obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o
+
+obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
+
+obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
+# DSP
+obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
+mailbox_mach-objs := mailbox.o
+
+i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
+obj-y += $(i2c-omap-m) $(i2c-omap-y)
+
+led-y := leds.o
+
+usb-fs-$(CONFIG_USB) := usb.o
+obj-y += $(usb-fs-m) $(usb-fs-y)
+
+# Specific board support
+obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o board-h2-mmc.o
+obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
+obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
+obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
+obj-$(CONFIG_MACH_OMAP_FSAMPLE) += board-fsample.o
+obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
+obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o board-h3-mmc.o
+obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
+obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
+obj-$(CONFIG_MACH_OMAP_PALMZ71) += board-palmz71.o
+obj-$(CONFIG_MACH_OMAP_PALMTT) += board-palmtt.o
+obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o
+obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o ams-delta-fiq.o \
+ ams-delta-fiq-handler.o
+obj-$(CONFIG_MACH_SX1) += board-sx1.o board-sx1-mmc.o
+obj-$(CONFIG_MACH_HERALD) += board-htcherald.o
+
+ifeq ($(CONFIG_ARCH_OMAP15XX),y)
+# Innovator-1510 FPGA
+obj-$(CONFIG_MACH_OMAP_INNOVATOR) += fpga.o
+endif
+
+# GPIO
+obj-$(CONFIG_ARCH_OMAP730) += gpio7xx.o
+obj-$(CONFIG_ARCH_OMAP850) += gpio7xx.o
+obj-$(CONFIG_ARCH_OMAP15XX) += gpio15xx.o
+obj-$(CONFIG_ARCH_OMAP16XX) += gpio16xx.o
+
+# LEDs support
+led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o
+led-$(CONFIG_MACH_OMAP_H3) += leds-h2p2-debug.o
+led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o
+led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o
+led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o
+obj-$(CONFIG_LEDS) += $(led-y)
+
+ifneq ($(CONFIG_FB_OMAP),)
+obj-y += lcd_dma.o
+endif
diff --git a/arch/arm/mach-omap1/Makefile.boot b/arch/arm/mach-omap1/Makefile.boot
new file mode 100644
index 00000000..292d56c5
--- /dev/null
+++ b/arch/arm/mach-omap1/Makefile.boot
@@ -0,0 +1,3 @@
+ zreladdr-y := 0x10008000
+params_phys-y := 0x10000100
+initrd_phys-y := 0x10800000
diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
new file mode 100644
index 00000000..c1c5fb6a
--- /dev/null
+++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
@@ -0,0 +1,278 @@
+/*
+ * linux/arch/arm/mach-omap1/ams-delta-fiq-handler.S
+ *
+ * Based on linux/arch/arm/lib/floppydma.S
+ * Renamed and modified to work with 2.6 kernel by Matt Callow
+ * Copyright (C) 1995, 1996 Russell King
+ * Copyright (C) 2004 Pete Trapps
+ * Copyright (C) 2006 Matt Callow
+ * Copyright (C) 2010 Janusz Krzysztofik
+ *
+ * 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/linkage.h>
+
+#include <plat/io.h>
+#include <plat/board-ams-delta.h>
+
+#include <mach/ams-delta-fiq.h>
+
+/*
+ * GPIO related definitions, copied from arch/arm/plat-omap/gpio.c.
+ * Unfortunately, those were not placed in a separate header file.
+ */
+#define OMAP1510_GPIO_BASE 0xFFFCE000
+#define OMAP1510_GPIO_DATA_INPUT 0x00
+#define OMAP1510_GPIO_DATA_OUTPUT 0x04
+#define OMAP1510_GPIO_DIR_CONTROL 0x08
+#define OMAP1510_GPIO_INT_CONTROL 0x0c
+#define OMAP1510_GPIO_INT_MASK 0x10
+#define OMAP1510_GPIO_INT_STATUS 0x14
+#define OMAP1510_GPIO_PIN_CONTROL 0x18
+
+/* GPIO register bitmasks */
+#define KEYBRD_DATA_MASK (0x1 << AMS_DELTA_GPIO_PIN_KEYBRD_DATA)
+#define KEYBRD_CLK_MASK (0x1 << AMS_DELTA_GPIO_PIN_KEYBRD_CLK)
+#define MODEM_IRQ_MASK (0x1 << AMS_DELTA_GPIO_PIN_MODEM_IRQ)
+#define HOOK_SWITCH_MASK (0x1 << AMS_DELTA_GPIO_PIN_HOOK_SWITCH)
+#define OTHERS_MASK (MODEM_IRQ_MASK | HOOK_SWITCH_MASK)
+
+/* IRQ handler register bitmasks */
+#define DEFERRED_FIQ_MASK (0x1 << (INT_DEFERRED_FIQ % IH2_BASE))
+#define GPIO_BANK1_MASK (0x1 << INT_GPIO_BANK1)
+
+/* Driver buffer byte offsets */
+#define BUF_MASK (FIQ_MASK * 4)
+#define BUF_STATE (FIQ_STATE * 4)
+#define BUF_KEYS_CNT (FIQ_KEYS_CNT * 4)
+#define BUF_TAIL_OFFSET (FIQ_TAIL_OFFSET * 4)
+#define BUF_HEAD_OFFSET (FIQ_HEAD_OFFSET * 4)
+#define BUF_BUF_LEN (FIQ_BUF_LEN * 4)
+#define BUF_KEY (FIQ_KEY * 4)
+#define BUF_MISSED_KEYS (FIQ_MISSED_KEYS * 4)
+#define BUF_BUFFER_START (FIQ_BUFFER_START * 4)
+#define BUF_GPIO_INT_MASK (FIQ_GPIO_INT_MASK * 4)
+#define BUF_KEYS_HICNT (FIQ_KEYS_HICNT * 4)
+#define BUF_IRQ_PEND (FIQ_IRQ_PEND * 4)
+#define BUF_SIR_CODE_L1 (FIQ_SIR_CODE_L1 * 4)
+#define BUF_SIR_CODE_L2 (IRQ_SIR_CODE_L2 * 4)
+#define BUF_CNT_INT_00 (FIQ_CNT_INT_00 * 4)
+#define BUF_CNT_INT_KEY (FIQ_CNT_INT_KEY * 4)
+#define BUF_CNT_INT_MDM (FIQ_CNT_INT_MDM * 4)
+#define BUF_CNT_INT_03 (FIQ_CNT_INT_03 * 4)
+#define BUF_CNT_INT_HSW (FIQ_CNT_INT_HSW * 4)
+#define BUF_CNT_INT_05 (FIQ_CNT_INT_05 * 4)
+#define BUF_CNT_INT_06 (FIQ_CNT_INT_06 * 4)
+#define BUF_CNT_INT_07 (FIQ_CNT_INT_07 * 4)
+#define BUF_CNT_INT_08 (FIQ_CNT_INT_08 * 4)
+#define BUF_CNT_INT_09 (FIQ_CNT_INT_09 * 4)
+#define BUF_CNT_INT_10 (FIQ_CNT_INT_10 * 4)
+#define BUF_CNT_INT_11 (FIQ_CNT_INT_11 * 4)
+#define BUF_CNT_INT_12 (FIQ_CNT_INT_12 * 4)
+#define BUF_CNT_INT_13 (FIQ_CNT_INT_13 * 4)
+#define BUF_CNT_INT_14 (FIQ_CNT_INT_14 * 4)
+#define BUF_CNT_INT_15 (FIQ_CNT_INT_15 * 4)
+#define BUF_CIRC_BUFF (FIQ_CIRC_BUFF * 4)
+
+
+/*
+ * Register usage
+ * r8 - temporary
+ * r9 - the driver buffer
+ * r10 - temporary
+ * r11 - interrupts mask
+ * r12 - base pointers
+ * r13 - interrupts status
+ */
+
+ .text
+
+ .global qwerty_fiqin_end
+
+ENTRY(qwerty_fiqin_start)
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ FIQ intrrupt handler
+ ldr r12, omap_ih1_base @ set pointer to level1 handler
+
+ ldr r11, [r12, #IRQ_MIR_REG_OFFSET] @ fetch interrupts mask
+
+ ldr r13, [r12, #IRQ_ITR_REG_OFFSET] @ fetch interrupts status
+ bics r13, r13, r11 @ clear masked - any left?
+ beq exit @ none - spurious FIQ? exit
+
+ ldr r10, [r12, #IRQ_SIR_FIQ_REG_OFFSET] @ get requested interrupt number
+
+ mov r8, #2 @ reset FIQ agreement
+ str r8, [r12, #IRQ_CONTROL_REG_OFFSET]
+
+ cmp r10, #INT_GPIO_BANK1 @ is it GPIO bank interrupt?
+ beq gpio @ yes - process it
+
+ mov r8, #1
+ orr r8, r11, r8, lsl r10 @ mask spurious interrupt
+ str r8, [r12, #IRQ_MIR_REG_OFFSET]
+exit:
+ subs pc, lr, #4 @ return from FIQ
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@
+gpio: @ GPIO bank interrupt handler
+ ldr r12, omap1510_gpio_base @ set base pointer to GPIO bank
+
+ ldr r11, [r12, #OMAP1510_GPIO_INT_MASK] @ fetch GPIO interrupts mask
+restart:
+ ldr r13, [r12, #OMAP1510_GPIO_INT_STATUS] @ fetch status bits
+ bics r13, r13, r11 @ clear masked - any left?
+ beq exit @ no - spurious interrupt? exit
+
+ orr r11, r11, r13 @ mask all requested interrupts
+ str r11, [r12, #OMAP1510_GPIO_INT_MASK]
+
+ ands r10, r13, #KEYBRD_CLK_MASK @ extract keyboard status - set?
+ beq hksw @ no - try next source
+
+
+ @@@@@@@@@@@@@@@@@@@@@@
+ @ Keyboard clock FIQ mode interrupt handler
+ @ r10 now contains KEYBRD_CLK_MASK, use it
+ str r10, [r12, #OMAP1510_GPIO_INT_STATUS] @ ack the interrupt
+ bic r11, r11, r10 @ unmask it
+ str r11, [r12, #OMAP1510_GPIO_INT_MASK]
+
+ @ Process keyboard data
+ ldr r8, [r12, #OMAP1510_GPIO_DATA_INPUT] @ fetch GPIO input
+
+ ldr r10, [r9, #BUF_STATE] @ fetch kbd interface state
+ cmp r10, #0 @ are we expecting start bit?
+ bne data @ no - go to data processing
+
+ ands r8, r8, #KEYBRD_DATA_MASK @ check start bit - detected?
+ beq hksw @ no - try next source
+
+ @ r8 contains KEYBRD_DATA_MASK, use it
+ str r8, [r9, #BUF_STATE] @ enter data processing state
+ @ r10 already contains 0, reuse it
+ str r10, [r9, #BUF_KEY] @ clear keycode
+ mov r10, #2 @ reset input bit mask
+ str r10, [r9, #BUF_MASK]
+
+ @ Mask other GPIO line interrupts till key done
+ str r11, [r9, #BUF_GPIO_INT_MASK] @ save mask for later restore
+ mvn r11, #KEYBRD_CLK_MASK @ prepare all except kbd mask
+ str r11, [r12, #OMAP1510_GPIO_INT_MASK] @ store into the mask register
+
+ b restart @ restart
+
+data: ldr r10, [r9, #BUF_MASK] @ fetch current input bit mask
+
+ @ r8 still contains GPIO input bits
+ ands r8, r8, #KEYBRD_DATA_MASK @ is keyboard data line low?
+ ldreq r8, [r9, #BUF_KEY] @ yes - fetch collected so far,
+ orreq r8, r8, r10 @ set 1 at current mask position
+ streq r8, [r9, #BUF_KEY] @ and save back
+
+ mov r10, r10, lsl #1 @ shift mask left
+ bics r10, r10, #0x800 @ have we got all the bits?
+ strne r10, [r9, #BUF_MASK] @ not yet - store the mask
+ bne restart @ and restart
+
+ @ r10 already contains 0, reuse it
+ str r10, [r9, #BUF_STATE] @ reset state to start
+
+ @ Key done - restore interrupt mask
+ ldr r10, [r9, #BUF_GPIO_INT_MASK] @ fetch saved mask
+ and r11, r11, r10 @ unmask all saved as unmasked
+ str r11, [r12, #OMAP1510_GPIO_INT_MASK] @ restore into the mask register
+
+ @ Try appending the keycode to the circular buffer
+ ldr r10, [r9, #BUF_KEYS_CNT] @ get saved keystrokes count
+ ldr r8, [r9, #BUF_BUF_LEN] @ get buffer size
+ cmp r10, r8 @ is buffer full?
+ beq hksw @ yes - key lost, next source
+
+ add r10, r10, #1 @ incremet keystrokes counter
+ str r10, [r9, #BUF_KEYS_CNT]
+
+ ldr r10, [r9, #BUF_TAIL_OFFSET] @ get buffer tail offset
+ @ r8 already contains buffer size
+ cmp r10, r8 @ end of buffer?
+ moveq r10, #0 @ yes - rewind to buffer start
+
+ ldr r12, [r9, #BUF_BUFFER_START] @ get buffer start address
+ add r12, r12, r10, LSL #2 @ calculate buffer tail address
+ ldr r8, [r9, #BUF_KEY] @ get last keycode
+ str r8, [r12] @ append it to the buffer tail
+
+ add r10, r10, #1 @ increment buffer tail offset
+ str r10, [r9, #BUF_TAIL_OFFSET]
+
+ ldr r10, [r9, #BUF_CNT_INT_KEY] @ increment interrupts counter
+ add r10, r10, #1
+ str r10, [r9, #BUF_CNT_INT_KEY]
+ @@@@@@@@@@@@@@@@@@@@@@@@
+
+
+hksw: @Is hook switch interrupt requested?
+ tst r13, #HOOK_SWITCH_MASK @ is hook switch status bit set?
+ beq mdm @ no - try next source
+
+
+ @@@@@@@@@@@@@@@@@@@@@@@@
+ @ Hook switch interrupt FIQ mode simple handler
+
+ @ Don't toggle active edge, the switch always bounces
+
+ @ Increment hook switch interrupt counter
+ ldr r10, [r9, #BUF_CNT_INT_HSW]
+ add r10, r10, #1
+ str r10, [r9, #BUF_CNT_INT_HSW]
+ @@@@@@@@@@@@@@@@@@@@@@@@
+
+
+mdm: @Is it a modem interrupt?
+ tst r13, #MODEM_IRQ_MASK @ is modem status bit set?
+ beq irq @ no - check for next interrupt
+
+
+ @@@@@@@@@@@@@@@@@@@@@@@@
+ @ Modem FIQ mode interrupt handler stub
+
+ @ Increment modem interrupt counter
+ ldr r10, [r9, #BUF_CNT_INT_MDM]
+ add r10, r10, #1
+ str r10, [r9, #BUF_CNT_INT_MDM]
+ @@@@@@@@@@@@@@@@@@@@@@@@
+
+
+irq: @ Place deferred_fiq interrupt request
+ ldr r12, deferred_fiq_ih_base @ set pointer to IRQ handler
+ mov r10, #DEFERRED_FIQ_MASK @ set deferred_fiq bit
+ str r10, [r12, #IRQ_ISR_REG_OFFSET] @ place it in the ISR register
+
+ ldr r12, omap1510_gpio_base @ set pointer back to GPIO bank
+ b restart @ check for next GPIO interrupt
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+
+/*
+ * Virtual addresses for IO
+ */
+omap_ih1_base:
+ .word OMAP1_IO_ADDRESS(OMAP_IH1_BASE)
+deferred_fiq_ih_base:
+ .word OMAP1_IO_ADDRESS(DEFERRED_FIQ_IH_BASE)
+omap1510_gpio_base:
+ .word OMAP1_IO_ADDRESS(OMAP1510_GPIO_BASE)
+qwerty_fiqin_end:
+
+/*
+ * Check the size of the FIQ,
+ * it cannot go beyond 0xffff0200, and is copied to 0xffff001c
+ */
+.if (qwerty_fiqin_end - qwerty_fiqin_start) > (0x200 - 0x1c)
+ .err
+.endif
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
new file mode 100644
index 00000000..152b32c1
--- /dev/null
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -0,0 +1,157 @@
+/*
+ * Amstrad E3 FIQ handling
+ *
+ * Copyright (C) 2009 Janusz Krzysztofik
+ * Copyright (c) 2006 Matt Callow
+ * Copyright (c) 2004 Amstrad Plc
+ * Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Parts of this code are taken from linux/arch/arm/mach-omap/irq.c
+ * in the MontaVista 2.4 kernel (and the Amstrad changes therein)
+ *
+ * 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/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <plat/board-ams-delta.h>
+
+#include <asm/fiq.h>
+#include <mach/ams-delta-fiq.h>
+
+static struct fiq_handler fh = {
+ .name = "ams-delta-fiq"
+};
+
+/*
+ * This buffer is shared between FIQ and IRQ contexts.
+ * The FIQ and IRQ isrs can both read and write it.
+ * It is structured as a header section several 32bit slots,
+ * followed by the circular buffer where the FIQ isr stores
+ * keystrokes received from the qwerty keyboard.
+ * See ams-delta-fiq.h for details of offsets.
+ */
+unsigned int fiq_buffer[1024];
+EXPORT_SYMBOL(fiq_buffer);
+
+static unsigned int irq_counter[16];
+
+static irqreturn_t deferred_fiq(int irq, void *dev_id)
+{
+ struct irq_desc *irq_desc;
+ struct irq_chip *irq_chip = NULL;
+ int gpio, irq_num, fiq_count;
+
+ irq_desc = irq_to_desc(IH_GPIO_BASE);
+ if (irq_desc)
+ irq_chip = irq_desc->irq_data.chip;
+
+ /*
+ * For each handled GPIO interrupt, keep calling its interrupt handler
+ * until the IRQ counter catches the FIQ incremented interrupt counter.
+ */
+ for (gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK;
+ gpio <= AMS_DELTA_GPIO_PIN_HOOK_SWITCH; gpio++) {
+ irq_num = gpio_to_irq(gpio);
+ fiq_count = fiq_buffer[FIQ_CNT_INT_00 + gpio];
+
+ while (irq_counter[gpio] < fiq_count) {
+ if (gpio != AMS_DELTA_GPIO_PIN_KEYBRD_CLK) {
+ struct irq_data *d = irq_get_irq_data(irq_num);
+
+ /*
+ * It looks like handle_edge_irq() that
+ * OMAP GPIO edge interrupts default to,
+ * expects interrupt already unmasked.
+ */
+ if (irq_chip && irq_chip->irq_unmask)
+ irq_chip->irq_unmask(d);
+ }
+ generic_handle_irq(irq_num);
+
+ irq_counter[gpio]++;
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+void __init ams_delta_init_fiq(void)
+{
+ void *fiqhandler_start;
+ unsigned int fiqhandler_length;
+ struct pt_regs FIQ_regs;
+ unsigned long val, offset;
+ int i, retval;
+
+ fiqhandler_start = &qwerty_fiqin_start;
+ fiqhandler_length = &qwerty_fiqin_end - &qwerty_fiqin_start;
+ pr_info("Installing fiq handler from %p, length 0x%x\n",
+ fiqhandler_start, fiqhandler_length);
+
+ retval = claim_fiq(&fh);
+ if (retval) {
+ pr_err("ams_delta_init_fiq(): couldn't claim FIQ, ret=%d\n",
+ retval);
+ return;
+ }
+
+ retval = request_irq(INT_DEFERRED_FIQ, deferred_fiq,
+ IRQ_TYPE_EDGE_RISING, "deferred_fiq", 0);
+ if (retval < 0) {
+ pr_err("Failed to get deferred_fiq IRQ, ret=%d\n", retval);
+ release_fiq(&fh);
+ return;
+ }
+ /*
+ * Since no set_type() method is provided by OMAP irq chip,
+ * switch to edge triggered interrupt type manually.
+ */
+ offset = IRQ_ILR0_REG_OFFSET + INT_DEFERRED_FIQ * 0x4;
+ val = omap_readl(DEFERRED_FIQ_IH_BASE + offset) & ~(1 << 1);
+ omap_writel(val, DEFERRED_FIQ_IH_BASE + offset);
+
+ set_fiq_handler(fiqhandler_start, fiqhandler_length);
+
+ /*
+ * Initialise the buffer which is shared
+ * between FIQ mode and IRQ mode
+ */
+ fiq_buffer[FIQ_GPIO_INT_MASK] = 0;
+ fiq_buffer[FIQ_MASK] = 0;
+ fiq_buffer[FIQ_STATE] = 0;
+ fiq_buffer[FIQ_KEY] = 0;
+ fiq_buffer[FIQ_KEYS_CNT] = 0;
+ fiq_buffer[FIQ_KEYS_HICNT] = 0;
+ fiq_buffer[FIQ_TAIL_OFFSET] = 0;
+ fiq_buffer[FIQ_HEAD_OFFSET] = 0;
+ fiq_buffer[FIQ_BUF_LEN] = 256;
+ fiq_buffer[FIQ_MISSED_KEYS] = 0;
+ fiq_buffer[FIQ_BUFFER_START] =
+ (unsigned int) &fiq_buffer[FIQ_CIRC_BUFF];
+
+ for (i = FIQ_CNT_INT_00; i <= FIQ_CNT_INT_15; i++)
+ fiq_buffer[i] = 0;
+
+ /*
+ * FIQ mode r9 always points to the fiq_buffer, becauses the FIQ isr
+ * will run in an unpredictable context. The fiq_buffer is the FIQ isr's
+ * only means of communication with the IRQ level and other kernel
+ * context code.
+ */
+ FIQ_regs.ARM_r9 = (unsigned int)fiq_buffer;
+ set_fiq_regs(&FIQ_regs);
+
+ pr_info("request_fiq(): fiq_buffer = %p\n", fiq_buffer);
+
+ /*
+ * Redirect GPIO interrupts to FIQ
+ */
+ offset = IRQ_ILR0_REG_OFFSET + INT_GPIO_BANK1 * 0x4;
+ val = omap_readl(OMAP_IH1_BASE + offset) | 1;
+ omap_writel(val, OMAP_IH1_BASE + offset);
+}
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 00000000..f49ce85d
--- /dev/null
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -0,0 +1,398 @@
+/*
+ * 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/input.h>
+#include <linux/interrupt.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <media/soc_camera.h>
+
+#include <asm/serial.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/io.h>
+#include <plat/board-ams-delta.h>
+#include <mach/gpio.h>
+#include <plat/keypad.h>
+#include <plat/mux.h>
+#include <plat/usb.h>
+#include <plat/board.h>
+#include <plat/common.h>
+#include <mach/camera.h>
+
+#include <mach/ams-delta-fiq.h>
+
+static u8 ams_delta_latch1_reg;
+static u16 ams_delta_latch2_reg;
+
+static const unsigned int ams_delta_keymap[] = {
+ KEY(0, 0, KEY_F1), /* Advert */
+
+ KEY(0, 3, KEY_COFFEE), /* Games */
+ KEY(0, 2, KEY_QUESTION), /* Directory */
+ KEY(2, 3, KEY_CONNECT), /* Internet */
+ KEY(1, 2, KEY_SHOP), /* Services */
+ KEY(1, 1, KEY_PHONE), /* VoiceMail */
+
+ KEY(0, 1, KEY_DELETE), /* Delete */
+ KEY(2, 2, KEY_PLAY), /* Play */
+ KEY(1, 0, KEY_PAGEUP), /* Up */
+ KEY(1, 3, KEY_PAGEDOWN), /* Down */
+ KEY(2, 0, KEY_EMAIL), /* ReadEmail */
+ KEY(2, 1, KEY_STOP), /* Stop */
+
+ /* Numeric keypad portion */
+ KEY(0, 7, KEY_KP1),
+ KEY(0, 6, KEY_KP2),
+ KEY(0, 5, KEY_KP3),
+ KEY(1, 7, KEY_KP4),
+ KEY(1, 6, KEY_KP5),
+ KEY(1, 5, KEY_KP6),
+ KEY(2, 7, KEY_KP7),
+ KEY(2, 6, KEY_KP8),
+ KEY(2, 5, KEY_KP9),
+ KEY(3, 6, KEY_KP0),
+ KEY(3, 7, KEY_KPASTERISK),
+ KEY(3, 5, KEY_KPDOT), /* # key */
+ KEY(7, 2, KEY_NUMLOCK), /* Mute */
+ KEY(7, 1, KEY_KPMINUS), /* Recall */
+ KEY(6, 1, KEY_KPPLUS), /* Redial */
+ KEY(7, 6, KEY_KPSLASH), /* Handsfree */
+ KEY(6, 0, KEY_ENTER), /* Video */
+
+ KEY(7, 4, KEY_CAMERA), /* Photo */
+
+ KEY(0, 4, KEY_F2), /* Home */
+ KEY(1, 4, KEY_F3), /* Office */
+ KEY(2, 4, KEY_F4), /* Mobile */
+ KEY(7, 7, KEY_F5), /* SMS */
+ KEY(7, 5, KEY_F6), /* Email */
+
+ /* QWERTY portion of keypad */
+ KEY(3, 4, KEY_Q),
+ KEY(3, 3, KEY_W),
+ KEY(3, 2, KEY_E),
+ KEY(3, 1, KEY_R),
+ KEY(3, 0, KEY_T),
+ KEY(4, 7, KEY_Y),
+ KEY(4, 6, KEY_U),
+ KEY(4, 5, KEY_I),
+ KEY(4, 4, KEY_O),
+ KEY(4, 3, KEY_P),
+
+ KEY(4, 2, KEY_A),
+ KEY(4, 1, KEY_S),
+ KEY(4, 0, KEY_D),
+ KEY(5, 7, KEY_F),
+ KEY(5, 6, KEY_G),
+ KEY(5, 5, KEY_H),
+ KEY(5, 4, KEY_J),
+ KEY(5, 3, KEY_K),
+ KEY(5, 2, KEY_L),
+
+ KEY(5, 1, KEY_Z),
+ KEY(5, 0, KEY_X),
+ KEY(6, 7, KEY_C),
+ KEY(6, 6, KEY_V),
+ KEY(6, 5, KEY_B),
+ KEY(6, 4, KEY_N),
+ KEY(6, 3, KEY_M),
+ KEY(6, 2, KEY_SPACE),
+
+ KEY(7, 0, KEY_LEFTSHIFT), /* Vol up */
+ KEY(7, 3, KEY_LEFTCTRL), /* Vol down */
+};
+
+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();
+}
+
+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_lcd_config ams_delta_lcd_config = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_usb_config ams_delta_usb_config __initdata = {
+ .register_host = 1,
+ .hmc_mode = 16,
+ .pins[0] = 2,
+};
+
+static struct omap_board_config_kernel ams_delta_config[] __initdata = {
+ { OMAP_TAG_LCD, &ams_delta_lcd_config },
+};
+
+static struct resource ams_delta_nand_resources[] = {
+ [0] = {
+ .start = OMAP1_MPUIO_BASE,
+ .end = OMAP1_MPUIO_BASE +
+ OMAP_MPUIO_IO_CNTL + sizeof(u32) - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ams_delta_nand_device = {
+ .name = "ams-delta-nand",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ams_delta_nand_resources),
+ .resource = ams_delta_nand_resources,
+};
+
+static struct resource ams_delta_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct matrix_keymap_data ams_delta_keymap_data = {
+ .keymap = ams_delta_keymap,
+ .keymap_size = ARRAY_SIZE(ams_delta_keymap),
+};
+
+static struct omap_kp_platform_data ams_delta_kp_data __initdata = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &ams_delta_keymap_data,
+ .delay = 9,
+};
+
+static struct platform_device ams_delta_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &ams_delta_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(ams_delta_kp_resources),
+ .resource = ams_delta_kp_resources,
+};
+
+static struct platform_device ams_delta_lcd_device = {
+ .name = "lcd_ams_delta",
+ .id = -1,
+};
+
+static struct platform_device ams_delta_led_device = {
+ .name = "ams-delta-led",
+ .id = -1
+};
+
+static struct i2c_board_info ams_delta_camera_board_info[] = {
+ {
+ I2C_BOARD_INFO("ov6650", 0x60),
+ },
+};
+
+#ifdef CONFIG_LEDS_TRIGGERS
+DEFINE_LED_TRIGGER(ams_delta_camera_led_trigger);
+
+static int ams_delta_camera_power(struct device *dev, int power)
+{
+ /*
+ * turn on camera LED
+ */
+ if (power)
+ led_trigger_event(ams_delta_camera_led_trigger, LED_FULL);
+ else
+ led_trigger_event(ams_delta_camera_led_trigger, LED_OFF);
+ return 0;
+}
+#else
+#define ams_delta_camera_power NULL
+#endif
+
+static struct soc_camera_link ams_delta_iclink = {
+ .bus_id = 0, /* OMAP1 SoC camera bus */
+ .i2c_adapter_id = 1,
+ .board_info = &ams_delta_camera_board_info[0],
+ .module_name = "ov6650",
+ .power = ams_delta_camera_power,
+};
+
+static struct platform_device ams_delta_camera_device = {
+ .name = "soc-camera-pdrv",
+ .id = 0,
+ .dev = {
+ .platform_data = &ams_delta_iclink,
+ },
+};
+
+static struct omap1_cam_platform_data ams_delta_camera_platform_data = {
+ .camexclk_khz = 12000, /* default 12MHz clock, no extra DPLL */
+ .lclk_khz_max = 1334, /* results in 5fps CIF, 10fps QCIF */
+};
+
+static struct platform_device *ams_delta_devices[] __initdata = {
+ &ams_delta_nand_device,
+ &ams_delta_kp_device,
+ &ams_delta_lcd_device,
+ &ams_delta_led_device,
+ &ams_delta_camera_device,
+};
+
+static void __init ams_delta_init(void)
+{
+ /* mux pins for uarts */
+ omap_cfg_reg(UART1_TX);
+ omap_cfg_reg(UART1_RTS);
+
+ /* parallel camera interface */
+ omap_cfg_reg(H19_1610_CAM_EXCLK);
+ omap_cfg_reg(J15_1610_CAM_LCLK);
+ omap_cfg_reg(L18_1610_CAM_VS);
+ omap_cfg_reg(L15_1610_CAM_HS);
+ omap_cfg_reg(L19_1610_CAM_D0);
+ omap_cfg_reg(K14_1610_CAM_D1);
+ omap_cfg_reg(K15_1610_CAM_D2);
+ omap_cfg_reg(K19_1610_CAM_D3);
+ omap_cfg_reg(K18_1610_CAM_D4);
+ omap_cfg_reg(J14_1610_CAM_D5);
+ omap_cfg_reg(J19_1610_CAM_D6);
+ omap_cfg_reg(J18_1610_CAM_D7);
+
+ 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();
+ omap_register_i2c_bus(1, 100, NULL, 0);
+
+ /* Clear latch2 (NAND, LCD, modem enable) */
+ ams_delta_latch2_write(~0, 0);
+
+ omap1_usb_init(&ams_delta_usb_config);
+ omap1_set_camera_info(&ams_delta_camera_platform_data);
+#ifdef CONFIG_LEDS_TRIGGERS
+ led_trigger_register_simple("ams_delta_camera",
+ &ams_delta_camera_led_trigger);
+#endif
+ platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
+
+ ams_delta_init_fiq();
+
+ omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
+}
+
+static struct plat_serial8250_port ams_delta_modem_ports[] = {
+ {
+ .membase = IOMEM(AMS_DELTA_MODEM_VIRT),
+ .mapbase = AMS_DELTA_MODEM_PHYS,
+ .irq = -EINVAL, /* changed later */
+ .flags = UPF_BOOT_AUTOCONF,
+ .irqflags = IRQF_TRIGGER_RISING,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = BASE_BAUD * 16,
+ },
+ { },
+};
+
+static struct platform_device ams_delta_modem_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM1,
+ .dev = {
+ .platform_data = ams_delta_modem_ports,
+ },
+};
+
+static int __init ams_delta_modem_init(void)
+{
+ int err;
+
+ if (!machine_is_ams_delta())
+ return -ENODEV;
+
+ omap_cfg_reg(M14_1510_GPIO2);
+ ams_delta_modem_ports[0].irq =
+ gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
+
+ err = gpio_request(AMS_DELTA_GPIO_PIN_MODEM_IRQ, "modem");
+ if (err) {
+ pr_err("Couldn't request gpio pin for modem\n");
+ return err;
+ }
+ gpio_direction_input(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
+
+ ams_delta_latch2_write(
+ AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC,
+ AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC);
+
+ return platform_device_register(&ams_delta_modem_device);
+}
+arch_initcall(ams_delta_modem_init);
+
+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> */
+ .boot_params = 0x10000100,
+ .map_io = ams_delta_map_io,
+ .reserve = omap_reserve,
+ .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-fsample.c b/arch/arm/mach-omap1/board-fsample.c
new file mode 100644
index 00000000..87f173d9
--- /dev/null
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -0,0 +1,398 @@
+/*
+ * linux/arch/arm/mach-omap1/board-fsample.c
+ *
+ * Modified from board-perseus2.c
+ *
+ * Original OMAP730 support by Jean Pihet <j-pihet@ti.com>
+ * Updated for 2.6 by Kevin Hilman <kjh@hilman.org>
+ *
+ * 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/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/smc91x.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/tc.h>
+#include <mach/gpio.h>
+#include <plat/mux.h>
+#include <plat/flash.h>
+#include <plat/fpga.h>
+#include <plat/keypad.h>
+#include <plat/common.h>
+#include <plat/board.h>
+
+/* fsample is pretty close to p2-sample */
+
+#define fsample_cpld_read(reg) __raw_readb(reg)
+#define fsample_cpld_write(val, reg) __raw_writeb(val, reg)
+
+#define FSAMPLE_CPLD_BASE 0xE8100000
+#define FSAMPLE_CPLD_SIZE SZ_4K
+#define FSAMPLE_CPLD_START 0x05080000
+
+#define FSAMPLE_CPLD_REG_A (FSAMPLE_CPLD_BASE + 0x00)
+#define FSAMPLE_CPLD_SWITCH (FSAMPLE_CPLD_BASE + 0x02)
+#define FSAMPLE_CPLD_UART (FSAMPLE_CPLD_BASE + 0x02)
+#define FSAMPLE_CPLD_REG_B (FSAMPLE_CPLD_BASE + 0x04)
+#define FSAMPLE_CPLD_VERSION (FSAMPLE_CPLD_BASE + 0x06)
+#define FSAMPLE_CPLD_SET_CLR (FSAMPLE_CPLD_BASE + 0x06)
+
+#define FSAMPLE_CPLD_BIT_BT_RESET 0
+#define FSAMPLE_CPLD_BIT_LCD_RESET 1
+#define FSAMPLE_CPLD_BIT_CAM_PWDN 2
+#define FSAMPLE_CPLD_BIT_CHARGER_ENABLE 3
+#define FSAMPLE_CPLD_BIT_SD_MMC_EN 4
+#define FSAMPLE_CPLD_BIT_aGPS_PWREN 5
+#define FSAMPLE_CPLD_BIT_BACKLIGHT 6
+#define FSAMPLE_CPLD_BIT_aGPS_EN_RESET 7
+#define FSAMPLE_CPLD_BIT_aGPS_SLEEPx_N 8
+#define FSAMPLE_CPLD_BIT_OTG_RESET 9
+
+#define fsample_cpld_set(bit) \
+ fsample_cpld_write((((bit) & 15) << 4) | 0x0f, FSAMPLE_CPLD_SET_CLR)
+
+#define fsample_cpld_clear(bit) \
+ fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR)
+
+static const unsigned int fsample_keymap[] = {
+ KEY(0, 0, KEY_UP),
+ KEY(1, 0, KEY_RIGHT),
+ KEY(2, 0, KEY_LEFT),
+ KEY(3, 0, KEY_DOWN),
+ KEY(4, 0, KEY_ENTER),
+ KEY(0, 1, KEY_F10),
+ KEY(1, 1, KEY_SEND),
+ KEY(2, 1, KEY_END),
+ KEY(3, 1, KEY_VOLUMEDOWN),
+ KEY(4, 1, KEY_VOLUMEUP),
+ KEY(5, 1, KEY_RECORD),
+ KEY(0, 2, KEY_F9),
+ KEY(1, 2, KEY_3),
+ KEY(2, 2, KEY_6),
+ KEY(3, 2, KEY_9),
+ KEY(4, 2, KEY_KPDOT),
+ KEY(0, 3, KEY_BACK),
+ KEY(1, 3, KEY_2),
+ KEY(2, 3, KEY_5),
+ KEY(3, 3, KEY_8),
+ KEY(4, 3, KEY_0),
+ KEY(5, 3, KEY_KPSLASH),
+ KEY(0, 4, KEY_HOME),
+ KEY(1, 4, KEY_1),
+ KEY(2, 4, KEY_4),
+ KEY(3, 4, KEY_7),
+ KEY(4, 4, KEY_KPASTERISK),
+ KEY(5, 4, KEY_POWER),
+};
+
+static struct smc91x_platdata smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+ .leda = RPC_LED_100_10,
+ .ledb = RPC_LED_TX_RX,
+};
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */
+ .end = H2P2_DBG_FPGA_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_7XX_MPU_EXT_NIRQ,
+ .end = 0,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ },
+};
+
+static void __init fsample_init_smc91x(void)
+{
+ fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
+ mdelay(50);
+ fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
+ H2P2_DBG_FPGA_LAN_RESET);
+ mdelay(50);
+}
+
+static struct mtd_partition nor_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* rest of flash is a file system */
+ {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ },
+};
+
+static struct physmap_flash_data nor_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = nor_partitions,
+ .nr_parts = ARRAY_SIZE(nor_partitions),
+};
+
+static struct resource nor_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nor_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &nor_data,
+ },
+ .num_resources = 1,
+ .resource = &nor_resource,
+};
+
+static void nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long mask;
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ mask = (ctrl & NAND_CLE) ? 0x02 : 0;
+ if (ctrl & NAND_ALE)
+ mask |= 0x04;
+ writeb(cmd, (unsigned long)this->IO_ADDR_W | mask);
+}
+
+#define FSAMPLE_NAND_RB_GPIO_PIN 62
+
+static int nand_dev_ready(struct mtd_info *mtd)
+{
+ return gpio_get_value(FSAMPLE_NAND_RB_GPIO_PIN);
+}
+
+static const char *part_probes[] = { "cmdlinepart", NULL };
+
+static struct platform_nand_data nand_data = {
+ .chip = {
+ .nr_chips = 1,
+ .chip_offset = 0,
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+ .part_probe_types = part_probes,
+ },
+ .ctrl = {
+ .cmd_ctrl = nand_cmd_ctl,
+ .dev_ready = nand_dev_ready,
+ },
+};
+
+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 = "gen_nand",
+ .id = 0,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .num_resources = 1,
+ .resource = &nand_resource,
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .dev = {
+ .platform_data = &smc91x_info,
+ },
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static struct resource kp_resources[] = {
+ [0] = {
+ .start = INT_7XX_MPUIO_KEYPAD,
+ .end = INT_7XX_MPUIO_KEYPAD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct matrix_keymap_data fsample_keymap_data = {
+ .keymap = fsample_keymap,
+ .keymap_size = ARRAY_SIZE(fsample_keymap),
+};
+
+static struct omap_kp_platform_data kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &fsample_keymap_data,
+ .delay = 4,
+};
+
+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 = {
+ &nor_device,
+ &nand_device,
+ &smc91x_device,
+ &kp_device,
+ &lcd_device,
+};
+
+static struct omap_lcd_config fsample_lcd_config = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel fsample_config[] __initdata = {
+ { OMAP_TAG_LCD, &fsample_lcd_config },
+};
+
+static void __init omap_fsample_init(void)
+{
+ fsample_init_smc91x();
+
+ if (gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0)
+ BUG();
+ gpio_direction_input(FSAMPLE_NAND_RB_GPIO_PIN);
+
+ omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+ omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+
+ /* Mux pins for keypad */
+ omap_cfg_reg(E2_7XX_KBR0);
+ omap_cfg_reg(J7_7XX_KBR1);
+ omap_cfg_reg(E1_7XX_KBR2);
+ omap_cfg_reg(F3_7XX_KBR3);
+ omap_cfg_reg(D2_7XX_KBR4);
+ omap_cfg_reg(C2_7XX_KBC0);
+ omap_cfg_reg(D3_7XX_KBC1);
+ omap_cfg_reg(E4_7XX_KBC2);
+ omap_cfg_reg(F4_7XX_KBC3);
+ omap_cfg_reg(E3_7XX_KBC4);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ omap_board_config = fsample_config;
+ omap_board_config_size = ARRAY_SIZE(fsample_config);
+ omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
+}
+
+static void __init omap_fsample_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+/* Only FPGA needs to be mapped here. All others are done with ioremap */
+static struct map_desc omap_fsample_io_desc[] __initdata = {
+ {
+ .virtual = H2P2_DBG_FPGA_BASE,
+ .pfn = __phys_to_pfn(H2P2_DBG_FPGA_START),
+ .length = H2P2_DBG_FPGA_SIZE,
+ .type = MT_DEVICE
+ },
+ {
+ .virtual = FSAMPLE_CPLD_BASE,
+ .pfn = __phys_to_pfn(FSAMPLE_CPLD_START),
+ .length = FSAMPLE_CPLD_SIZE,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init omap_fsample_map_io(void)
+{
+ omap1_map_common_io();
+ iotable_init(omap_fsample_io_desc,
+ ARRAY_SIZE(omap_fsample_io_desc));
+
+ /* Early, board-dependent init */
+
+ /*
+ * Hold GSM Reset until needed
+ */
+ omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+ /*
+ * UARTs -> done automagically by 8250 driver
+ */
+
+ /*
+ * CSx timings, GPIO Mux ... setup
+ */
+
+ /* Flash: CS0 timings setup */
+ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+ omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+ /*
+ * Ethernet support through the debug board
+ * CS1 timings setup
+ */
+ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+ omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+ /*
+ * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+ * It is used as the Ethernet controller interrupt
+ */
+ omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
+}
+
+MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
+/* Maintainer: Brian Swetland <swetland@google.com> */
+ .boot_params = 0x10000100,
+ .map_io = omap_fsample_map_io,
+ .reserve = omap_reserve,
+ .init_irq = omap_fsample_init_irq,
+ .init_machine = omap_fsample_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
new file mode 100644
index 00000000..23f4ab9e
--- /dev/null
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -0,0 +1,103 @@
+/*
+ * linux/arch/arm/mach-omap1/board-generic.c
+ *
+ * Modified from board-innovator1510.c
+ *
+ * Code for generic OMAP board. Should work on many OMAP systems where
+ * the device drivers take care of all the necessary hardware initialization.
+ * 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 <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/gpio.h>
+#include <plat/mux.h>
+#include <plat/usb.h>
+#include <plat/board.h>
+#include <plat/common.h>
+
+static void __init omap_generic_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+/* assume no Mini-AB port */
+
+#ifdef CONFIG_ARCH_OMAP15XX
+static struct omap_usb_config generic1510_usb_config __initdata = {
+ .register_host = 1,
+ .register_dev = 1,
+ .hmc_mode = 16,
+ .pins[0] = 3,
+};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+static struct omap_usb_config generic1610_usb_config __initdata = {
+#ifdef CONFIG_USB_OTG
+ .otg = 1,
+#endif
+ .register_host = 1,
+ .register_dev = 1,
+ .hmc_mode = 16,
+ .pins[0] = 6,
+};
+#endif
+
+static struct omap_board_config_kernel generic_config[] __initdata = {
+};
+
+static void __init omap_generic_init(void)
+{
+#ifdef CONFIG_ARCH_OMAP15XX
+ if (cpu_is_omap15xx()) {
+ /* mux pins for uarts */
+ omap_cfg_reg(UART1_TX);
+ omap_cfg_reg(UART1_RTS);
+ omap_cfg_reg(UART2_TX);
+ omap_cfg_reg(UART2_RTS);
+ omap_cfg_reg(UART3_TX);
+ omap_cfg_reg(UART3_RX);
+
+ omap1_usb_init(&generic1510_usb_config);
+ }
+#endif
+#if defined(CONFIG_ARCH_OMAP16XX)
+ if (!cpu_is_omap1510()) {
+ omap1_usb_init(&generic1610_usb_config);
+ }
+#endif
+
+ omap_board_config = generic_config;
+ omap_board_config_size = ARRAY_SIZE(generic_config);
+ omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
+}
+
+static void __init omap_generic_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
+ /* Maintainer: Tony Lindgren <tony@atomide.com> */
+ .boot_params = 0x10000100,
+ .map_io = omap_generic_map_io,
+ .reserve = omap_reserve,
+ .init_irq = omap_generic_init_irq,
+ .init_machine = omap_generic_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c
new file mode 100644
index 00000000..f2fc43d8
--- /dev/null
+++ b/arch/arm/mach-omap1/board-h2-mmc.c
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/arm/mach-omap1/board-h2-mmc.c
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Author: Felipe Balbi <felipe.lima@indt.org.br>
+ *
+ * This code is based on linux/arch/arm/mach-omap2/board-n800-mmc.c, which is:
+ * Copyright (C) 2006 Nokia Corporation
+ *
+ * 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/platform_device.h>
+
+#include <linux/i2c/tps65010.h>
+
+#include <plat/mmc.h>
+#include <mach/gpio.h>
+
+#include "board-h2.h"
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+static int mmc_set_power(struct device *dev, int slot, int power_on,
+ int vdd)
+{
+ gpio_set_value(H2_TPS_GPIO_MMC_PWR_EN, power_on);
+ return 0;
+}
+
+static int mmc_late_init(struct device *dev)
+{
+ int ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
+ if (ret < 0)
+ return ret;
+
+ gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);
+
+ return ret;
+}
+
+static void mmc_cleanup(struct device *dev)
+{
+ gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
+}
+
+/*
+ * H2 could use the following functions tested:
+ * - mmc_get_cover_state that uses OMAP_MPUIO(1)
+ * - mmc_get_wp that uses OMAP_MPUIO(3)
+ */
+static struct omap_mmc_platform_data mmc1_data = {
+ .nr_slots = 1,
+ .init = mmc_late_init,
+ .cleanup = mmc_cleanup,
+ .dma_mask = 0xffffffff,
+ .slots[0] = {
+ .set_power = mmc_set_power,
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+ .name = "mmcblk",
+ },
+};
+
+static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
+
+void __init h2_mmc_init(void)
+{
+ mmc_data[0] = &mmc1_data;
+ omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC);
+}
+
+#else
+
+void __init h2_mmc_init(void)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
new file mode 100644
index 00000000..ba3bd09c
--- /dev/null
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -0,0 +1,470 @@
+/*
+ * linux/arch/arm/mach-omap1/board-h2.c
+ *
+ * Board specific inits for OMAP-1610 H2
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ *
+ * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
+ * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com>
+ *
+ * H2 specific changes and cleanup
+ * Copyright (C) 2004 Nokia Corporation by Imre Deak <imre.deak@nokia.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/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/i2c/tps65010.h>
+#include <linux/smc91x.h>
+
+#include <mach/hardware.h>
+#include <asm/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/mux.h>
+#include <plat/dma.h>
+#include <plat/tc.h>
+#include <plat/irda.h>
+#include <plat/usb.h>
+#include <plat/keypad.h>
+#include <plat/common.h>
+#include <plat/flash.h>
+
+#include "board-h2.h"
+
+/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
+#define OMAP1610_ETHR_START 0x04000300
+
+static const unsigned int h2_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(1, 0, KEY_RIGHT),
+ KEY(2, 0, KEY_3),
+ KEY(3, 0, KEY_F10),
+ KEY(4, 0, KEY_F5),
+ KEY(5, 0, KEY_9),
+ KEY(0, 1, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(2, 1, KEY_2),
+ KEY(3, 1, KEY_F9),
+ KEY(4, 1, KEY_F7),
+ KEY(5, 1, KEY_0),
+ KEY(0, 2, KEY_ENTER),
+ KEY(1, 2, KEY_6),
+ KEY(2, 2, KEY_1),
+ KEY(3, 2, KEY_F2),
+ KEY(4, 2, KEY_F6),
+ KEY(5, 2, KEY_HOME),
+ KEY(0, 3, KEY_8),
+ KEY(1, 3, KEY_5),
+ KEY(2, 3, KEY_F12),
+ KEY(3, 3, KEY_F3),
+ KEY(4, 3, KEY_F8),
+ KEY(5, 3, KEY_END),
+ KEY(0, 4, KEY_7),
+ KEY(1, 4, KEY_4),
+ KEY(2, 4, KEY_F11),
+ KEY(3, 4, KEY_F1),
+ KEY(4, 4, KEY_F4),
+ KEY(5, 4, KEY_ESC),
+ KEY(0, 5, KEY_F13),
+ KEY(1, 5, KEY_F14),
+ KEY(2, 5, KEY_F15),
+ KEY(3, 5, KEY_F16),
+ KEY(4, 5, KEY_SLEEP),
+};
+
+static struct mtd_partition h2_nor_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct physmap_flash_data h2_nor_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = h2_nor_partitions,
+ .nr_parts = ARRAY_SIZE(h2_nor_partitions),
+};
+
+static struct resource h2_nor_resource = {
+ /* This is on CS3, wherever it's mapped */
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device h2_nor_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &h2_nor_data,
+ },
+ .num_resources = 1,
+ .resource = &h2_nor_resource,
+};
+
+static struct mtd_partition h2_nand_partitions[] = {
+#if 0
+ /* REVISIT: enable these partitions if you make NAND BOOT
+ * work on your H2 (rev C or newer); published versions of
+ * x-load only support P2 and H3.
+ */
+ {
+ .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,
+ },
+};
+
+static void h2_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long mask;
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ mask = (ctrl & NAND_CLE) ? 0x02 : 0;
+ if (ctrl & NAND_ALE)
+ mask |= 0x04;
+ writeb(cmd, (unsigned long)this->IO_ADDR_W | mask);
+}
+
+#define H2_NAND_RB_GPIO_PIN 62
+
+static int h2_nand_dev_ready(struct mtd_info *mtd)
+{
+ return gpio_get_value(H2_NAND_RB_GPIO_PIN);
+}
+
+static const char *h2_part_probes[] = { "cmdlinepart", NULL };
+
+static struct platform_nand_data h2_nand_platdata = {
+ .chip = {
+ .nr_chips = 1,
+ .chip_offset = 0,
+ .nr_partitions = ARRAY_SIZE(h2_nand_partitions),
+ .partitions = h2_nand_partitions,
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+ .part_probe_types = h2_part_probes,
+ },
+ .ctrl = {
+ .cmd_ctrl = h2_nand_cmd_ctl,
+ .dev_ready = h2_nand_dev_ready,
+
+ },
+};
+
+static struct resource h2_nand_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device h2_nand_device = {
+ .name = "gen_nand",
+ .id = 0,
+ .dev = {
+ .platform_data = &h2_nand_platdata,
+ },
+ .num_resources = 1,
+ .resource = &h2_nand_resource,
+};
+
+static struct smc91x_platdata h2_smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+ .leda = RPC_LED_100_10,
+ .ledb = RPC_LED_TX_RX,
+};
+
+static struct resource h2_smc91x_resources[] = {
+ [0] = {
+ .start = OMAP1610_ETHR_START, /* Physical */
+ .end = OMAP1610_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(0),
+ .end = OMAP_GPIO_IRQ(0),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
+ },
+};
+
+static struct platform_device h2_smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .dev = {
+ .platform_data = &h2_smc91x_info,
+ },
+ .num_resources = ARRAY_SIZE(h2_smc91x_resources),
+ .resource = h2_smc91x_resources,
+};
+
+static struct resource h2_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct matrix_keymap_data h2_keymap_data = {
+ .keymap = h2_keymap,
+ .keymap_size = ARRAY_SIZE(h2_keymap),
+};
+
+static struct omap_kp_platform_data h2_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &h2_keymap_data,
+ .rep = true,
+ .delay = 9,
+ .dbounce = true,
+};
+
+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
+
+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 u64 irda_dmamask = 0xffffffff;
+
+static struct platform_device h2_irda_device = {
+ .name = "omapirda",
+ .id = 0,
+ .dev = {
+ .platform_data = &h2_irda_data,
+ .dma_mask = &irda_dmamask,
+ },
+ .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 platform_device *h2_devices[] __initdata = {
+ &h2_nor_device,
+ &h2_nand_device,
+ &h2_smc91x_device,
+ &h2_irda_device,
+ &h2_kp_device,
+ &h2_lcd_device,
+};
+
+static void __init h2_init_smc91x(void)
+{
+ if (gpio_request(0, "SMC91x irq") < 0) {
+ printk("Error requesting gpio 0 for smc91x irq\n");
+ return;
+ }
+}
+
+static int tps_setup(struct i2c_client *client, void *context)
+{
+ tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V |
+ TPS_LDO1_ENABLE | TPS_VLDO1_3_0V);
+
+ return 0;
+}
+
+static struct tps65010_board tps_board = {
+ .base = H2_TPS_GPIO_BASE,
+ .outmask = 0x0f,
+ .setup = tps_setup,
+};
+
+static struct i2c_board_info __initdata h2_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("tps65010", 0x48),
+ .irq = OMAP_GPIO_IRQ(58),
+ .platform_data = &tps_board,
+ }, {
+ I2C_BOARD_INFO("isp1301_omap", 0x2d),
+ .irq = OMAP_GPIO_IRQ(2),
+ },
+};
+
+static void __init h2_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static struct omap_usb_config h2_usb_config __initdata = {
+ /* usb1 has a Mini-AB port and external isp1301 transceiver */
+ .otg = 2,
+
+#ifdef CONFIG_USB_GADGET_OMAP
+ .hmc_mode = 19, /* 0:host(off) 1:dev|otg 2:disabled */
+ /* .hmc_mode = 21,*/ /* 0:host(off) 1:dev(loopback) 2:host(loopback) */
+#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+ /* needs OTG cable, or NONSTANDARD (B-to-MiniB) */
+ .hmc_mode = 20, /* 1:dev|otg(off) 1:host 2:disabled */
+#endif
+
+ .pins[1] = 3,
+};
+
+static struct omap_lcd_config h2_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel h2_config[] __initdata = {
+ { OMAP_TAG_LCD, &h2_lcd_config },
+};
+
+static void __init h2_init(void)
+{
+ h2_init_smc91x();
+
+ /* 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_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
+ h2_nor_resource.end += SZ_32M - 1;
+
+ h2_nand_resource.end = h2_nand_resource.start = OMAP_CS2B_PHYS;
+ h2_nand_resource.end += SZ_4K - 1;
+ if (gpio_request(H2_NAND_RB_GPIO_PIN, "NAND ready") < 0)
+ BUG();
+ gpio_direction_input(H2_NAND_RB_GPIO_PIN);
+
+ 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 */
+
+ /* Mux pins for keypad */
+ 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);
+
+ platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
+ omap_board_config = h2_config;
+ omap_board_config_size = ARRAY_SIZE(h2_config);
+ omap_serial_init();
+ omap_register_i2c_bus(1, 100, h2_i2c_board_info,
+ ARRAY_SIZE(h2_i2c_board_info));
+ omap1_usb_init(&h2_usb_config);
+ h2_mmc_init();
+}
+
+static void __init h2_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(OMAP_H2, "TI-H2")
+ /* Maintainer: Imre Deak <imre.deak@nokia.com> */
+ .boot_params = 0x10000100,
+ .map_io = h2_map_io,
+ .reserve = omap_reserve,
+ .init_irq = h2_init_irq,
+ .init_machine = h2_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h2.h b/arch/arm/mach-omap1/board-h2.h
new file mode 100644
index 00000000..315e2662
--- /dev/null
+++ b/arch/arm/mach-omap1/board-h2.h
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-omap1/board-h2.h
+ *
+ * Hardware definitions for TI OMAP1610 H2 board.
+ *
+ * Cleanup for Linux-2.6 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.
+ */
+
+#ifndef __ASM_ARCH_OMAP_H2_H
+#define __ASM_ARCH_OMAP_H2_H
+
+#define H2_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
+# define H2_TPS_GPIO_MMC_PWR_EN (H2_TPS_GPIO_BASE + 3)
+
+extern void h2_mmc_init(void);
+
+#endif /* __ASM_ARCH_OMAP_H2_H */
+
diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c
new file mode 100644
index 00000000..2098525e
--- /dev/null
+++ b/arch/arm/mach-omap1/board-h3-mmc.c
@@ -0,0 +1,69 @@
+/*
+ * linux/arch/arm/mach-omap1/board-h3-mmc.c
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Author: Felipe Balbi <felipe.lima@indt.org.br>
+ *
+ * This code is based on linux/arch/arm/mach-omap2/board-n800-mmc.c, which is:
+ * Copyright (C) 2006 Nokia Corporation
+ *
+ * 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/platform_device.h>
+
+#include <linux/i2c/tps65010.h>
+
+#include <plat/mmc.h>
+#include <mach/gpio.h>
+
+#include "board-h3.h"
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+static int mmc_set_power(struct device *dev, int slot, int power_on,
+ int vdd)
+{
+ gpio_set_value(H3_TPS_GPIO_MMC_PWR_EN, power_on);
+ return 0;
+}
+
+/*
+ * H3 could use the following functions tested:
+ * - mmc_get_cover_state that uses OMAP_MPUIO(1)
+ * - mmc_get_wp that maybe uses OMAP_MPUIO(3)
+ */
+static struct omap_mmc_platform_data mmc1_data = {
+ .nr_slots = 1,
+ .dma_mask = 0xffffffff,
+ .slots[0] = {
+ .set_power = mmc_set_power,
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+ .name = "mmcblk",
+ },
+};
+
+static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
+
+void __init h3_mmc_init(void)
+{
+ int ret;
+
+ ret = gpio_request(H3_TPS_GPIO_MMC_PWR_EN, "MMC power");
+ if (ret < 0)
+ return;
+ gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0);
+
+ mmc_data[0] = &mmc1_data;
+ omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC);
+}
+
+#else
+
+void __init h3_mmc_init(void)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
new file mode 100644
index 00000000..ac486776
--- /dev/null
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -0,0 +1,458 @@
+/*
+ * linux/arch/arm/mach-omap1/board-h3.c
+ *
+ * This file contains OMAP1710 H3 specific code.
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ * Greg Lonnon (glonnon@ridgerun.com) or info@ridgerun.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/types.h>
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/workqueue.h>
+#include <linux/i2c.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c/tps65010.h>
+#include <linux/smc91x.h>
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <mach/hardware.h>
+#include <asm/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/irqs.h>
+#include <plat/mux.h>
+#include <plat/tc.h>
+#include <plat/usb.h>
+#include <plat/keypad.h>
+#include <plat/dma.h>
+#include <plat/common.h>
+#include <plat/flash.h>
+
+#include "board-h3.h"
+
+/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
+#define OMAP1710_ETHR_START 0x04000300
+
+#define H3_TS_GPIO 48
+
+static const unsigned int h3_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(1, 0, KEY_RIGHT),
+ KEY(2, 0, KEY_3),
+ KEY(3, 0, KEY_F10),
+ KEY(4, 0, KEY_F5),
+ KEY(5, 0, KEY_9),
+ KEY(0, 1, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(2, 1, KEY_2),
+ KEY(3, 1, KEY_F9),
+ KEY(4, 1, KEY_F7),
+ KEY(5, 1, KEY_0),
+ KEY(0, 2, KEY_ENTER),
+ KEY(1, 2, KEY_6),
+ KEY(2, 2, KEY_1),
+ KEY(3, 2, KEY_F2),
+ KEY(4, 2, KEY_F6),
+ KEY(5, 2, KEY_HOME),
+ KEY(0, 3, KEY_8),
+ KEY(1, 3, KEY_5),
+ KEY(2, 3, KEY_F12),
+ KEY(3, 3, KEY_F3),
+ KEY(4, 3, KEY_F8),
+ KEY(5, 3, KEY_END),
+ KEY(0, 4, KEY_7),
+ KEY(1, 4, KEY_4),
+ KEY(2, 4, KEY_F11),
+ KEY(3, 4, KEY_F1),
+ KEY(4, 4, KEY_F4),
+ KEY(5, 4, KEY_ESC),
+ KEY(0, 5, KEY_F13),
+ KEY(1, 5, KEY_F14),
+ KEY(2, 5, KEY_F15),
+ KEY(3, 5, KEY_F16),
+ KEY(4, 5, KEY_SLEEP),
+};
+
+
+static struct mtd_partition nor_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct physmap_flash_data nor_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = nor_partitions,
+ .nr_parts = ARRAY_SIZE(nor_partitions),
+};
+
+static struct resource nor_resource = {
+ /* This is on CS3, wherever it's mapped */
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nor_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .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,
+ },
+};
+
+static void nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long mask;
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ mask = (ctrl & NAND_CLE) ? 0x02 : 0;
+ if (ctrl & NAND_ALE)
+ mask |= 0x04;
+ writeb(cmd, (unsigned long)this->IO_ADDR_W | mask);
+}
+
+#define H3_NAND_RB_GPIO_PIN 10
+
+static int nand_dev_ready(struct mtd_info *mtd)
+{
+ return gpio_get_value(H3_NAND_RB_GPIO_PIN);
+}
+
+static const char *part_probes[] = { "cmdlinepart", NULL };
+
+static struct platform_nand_data nand_platdata = {
+ .chip = {
+ .nr_chips = 1,
+ .chip_offset = 0,
+ .nr_partitions = ARRAY_SIZE(nand_partitions),
+ .partitions = nand_partitions,
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+ .part_probe_types = part_probes,
+ },
+ .ctrl = {
+ .cmd_ctrl = nand_cmd_ctl,
+ .dev_ready = nand_dev_ready,
+
+ },
+};
+
+static struct resource nand_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nand_device = {
+ .name = "gen_nand",
+ .id = 0,
+ .dev = {
+ .platform_data = &nand_platdata,
+ },
+ .num_resources = 1,
+ .resource = &nand_resource,
+};
+
+static struct smc91x_platdata smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+ .leda = RPC_LED_100_10,
+ .ledb = RPC_LED_TX_RX,
+};
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = OMAP1710_ETHR_START, /* Physical */
+ .end = OMAP1710_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(40),
+ .end = OMAP_GPIO_IRQ(40),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .dev = {
+ .platform_data = &smc91x_info,
+ },
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static void __init h3_init_smc91x(void)
+{
+ omap_cfg_reg(W15_1710_GPIO40);
+ if (gpio_request(40, "SMC91x irq") < 0) {
+ printk("Error requesting gpio 40 for smc91x irq\n");
+ return;
+ }
+}
+
+#define GPTIMER_BASE 0xFFFB1400
+#define GPTIMER_REGS(x) (0xFFFB1400 + (x * 0x800))
+#define GPTIMER_REGS_SIZE 0x46
+
+static struct resource intlat_resources[] = {
+ [0] = {
+ .start = GPTIMER_REGS(0), /* Physical */
+ .end = GPTIMER_REGS(0) + GPTIMER_REGS_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_1610_GPTIMER1,
+ .end = INT_1610_GPTIMER1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device intlat_device = {
+ .name = "omap_intlat",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(intlat_resources),
+ .resource = intlat_resources,
+};
+
+static struct resource h3_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct matrix_keymap_data h3_keymap_data = {
+ .keymap = h3_keymap,
+ .keymap_size = ARRAY_SIZE(h3_keymap),
+};
+
+static struct omap_kp_platform_data h3_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &h3_keymap_data,
+ .rep = true,
+ .delay = 9,
+ .dbounce = true,
+};
+
+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,
+};
+
+static struct platform_device h3_lcd_device = {
+ .name = "lcd_h3",
+ .id = -1,
+};
+
+static struct spi_board_info h3_spi_board_info[] __initdata = {
+ [0] = {
+ .modalias = "tsc2101",
+ .bus_num = 2,
+ .chip_select = 0,
+ .irq = OMAP_GPIO_IRQ(H3_TS_GPIO),
+ .max_speed_hz = 16000000,
+ /* .platform_data = &tsc_platform_data, */
+ },
+};
+
+static struct platform_device *devices[] __initdata = {
+ &nor_device,
+ &nand_device,
+ &smc91x_device,
+ &intlat_device,
+ &h3_kp_device,
+ &h3_lcd_device,
+};
+
+static struct omap_usb_config h3_usb_config __initdata = {
+ /* usb1 has a Mini-AB port and external isp1301 transceiver */
+ .otg = 2,
+
+#ifdef CONFIG_USB_GADGET_OMAP
+ .hmc_mode = 19, /* 0:host(off) 1:dev|otg 2:disabled */
+#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+ /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
+ .hmc_mode = 20, /* 1:dev|otg(off) 1:host 2:disabled */
+#endif
+
+ .pins[1] = 3,
+};
+
+static struct omap_lcd_config h3_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel h3_config[] __initdata = {
+ { OMAP_TAG_LCD, &h3_lcd_config },
+};
+
+static struct i2c_board_info __initdata h3_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("tps65013", 0x48),
+ /* .irq = OMAP_GPIO_IRQ(??), */
+ },
+ {
+ I2C_BOARD_INFO("isp1301_omap", 0x2d),
+ .irq = OMAP_GPIO_IRQ(14),
+ },
+};
+
+static void __init h3_init(void)
+{
+ h3_init_smc91x();
+
+ /* 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 (gpio_request(H3_NAND_RB_GPIO_PIN, "NAND ready") < 0)
+ BUG();
+ gpio_direction_input(H3_NAND_RB_GPIO_PIN);
+
+ /* 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);
+
+ /* Mux pins for keypad */
+ 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);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+ spi_register_board_info(h3_spi_board_info,
+ ARRAY_SIZE(h3_spi_board_info));
+ omap_board_config = h3_config;
+ omap_board_config_size = ARRAY_SIZE(h3_config);
+ omap_serial_init();
+ omap_register_i2c_bus(1, 100, h3_i2c_board_info,
+ ARRAY_SIZE(h3_i2c_board_info));
+ omap1_usb_init(&h3_usb_config);
+ h3_mmc_init();
+}
+
+static void __init h3_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static void __init h3_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
+ /* Maintainer: Texas Instruments, Inc. */
+ .boot_params = 0x10000100,
+ .map_io = h3_map_io,
+ .reserve = omap_reserve,
+ .init_irq = h3_init_irq,
+ .init_machine = h3_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h3.h b/arch/arm/mach-omap1/board-h3.h
new file mode 100644
index 00000000..78de535b
--- /dev/null
+++ b/arch/arm/mach-omap1/board-h3.h
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/mach-omap1/board-h3.h
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS 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.
+ */
+#ifndef __ASM_ARCH_OMAP_H3_H
+#define __ASM_ARCH_OMAP_H3_H
+
+#define H3_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
+# define H3_TPS_GPIO_MMC_PWR_EN (H3_TPS_GPIO_BASE + 4)
+
+extern void h3_mmc_init(void);
+
+#endif /* __ASM_ARCH_OMAP_H3_H */
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
new file mode 100644
index 00000000..ba05a51f
--- /dev/null
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -0,0 +1,620 @@
+/*
+ * HTC Herald board configuration
+ * Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com>
+ * Copyright (C) 2009 Wing Linux
+ *
+ * Based on the board-htcwizard.c file from the linwizard project:
+ * Copyright (C) 2006 Unai Uribarri
+ * Copyright (C) 2008 linwizard.sourceforge.net
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/htcpld.h>
+#include <linux/leds.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <plat/omap7xx.h>
+#include <plat/common.h>
+#include <plat/board.h>
+#include <plat/keypad.h>
+#include <plat/usb.h>
+#include <plat/mmc.h>
+
+#include <mach/irqs.h>
+
+#include <linux/delay.h>
+
+/* LCD register definition */
+#define OMAP_LCDC_CONTROL (0xfffec000 + 0x00)
+#define OMAP_LCDC_STATUS (0xfffec000 + 0x10)
+#define OMAP_DMA_LCD_CCR (0xfffee300 + 0xc2)
+#define OMAP_DMA_LCD_CTRL (0xfffee300 + 0xc4)
+#define OMAP_LCDC_CTRL_LCD_EN (1 << 0)
+#define OMAP_LCDC_STAT_DONE (1 << 0)
+
+/* GPIO definitions for the power button and keyboard slide switch */
+#define HTCHERALD_GPIO_POWER 139
+#define HTCHERALD_GPIO_SLIDE 174
+#define HTCHERALD_GIRQ_BTNS 141
+
+/* GPIO definitions for the touchscreen */
+#define HTCHERALD_GPIO_TS 76
+
+/* HTCPLD definitions */
+
+/*
+ * CPLD Logic
+ *
+ * Chip 3 - 0x03
+ *
+ * Function 7 6 5 4 3 2 1 0
+ * ------------------------------------
+ * DPAD light x x x x x x x 1
+ * SoundDev x x x x 1 x x x
+ * Screen white 1 x x x x x x x
+ * MMC power on x x x x x 1 x x
+ * Happy times (n) 0 x x x x 1 x x
+ *
+ * Chip 4 - 0x04
+ *
+ * Function 7 6 5 4 3 2 1 0
+ * ------------------------------------
+ * Keyboard light x x x x x x x 1
+ * LCD Bright (4) x x x x x 1 1 x
+ * LCD Bright (3) x x x x x 0 1 x
+ * LCD Bright (2) x x x x x 1 0 x
+ * LCD Bright (1) x x x x x 0 0 x
+ * LCD Off x x x x 0 x x x
+ * LCD image (fb) 1 x x x x x x x
+ * LCD image (white) 0 x x x x x x x
+ * Caps lock LED x x 1 x x x x x
+ *
+ * Chip 5 - 0x05
+ *
+ * Function 7 6 5 4 3 2 1 0
+ * ------------------------------------
+ * Red (solid) x x x x x 1 x x
+ * Red (flash) x x x x x x 1 x
+ * Green (GSM flash) x x x x 1 x x x
+ * Green (GSM solid) x x x 1 x x x x
+ * Green (wifi flash) x x 1 x x x x x
+ * Blue (bt flash) x 1 x x x x x x
+ * DPAD Int Enable 1 x x x x x x 0
+ *
+ * (Combinations of the above can be made for different colors.)
+ * The direction pad interrupt enable must be set each time the
+ * interrupt is handled.
+ *
+ * Chip 6 - 0x06
+ *
+ * Function 7 6 5 4 3 2 1 0
+ * ------------------------------------
+ * Vibrator x x x x 1 x x x
+ * Alt LED x x x 1 x x x x
+ * Screen white 1 x x x x x x x
+ * Screen white x x 1 x x x x x
+ * Screen white x 0 x x x x x x
+ * Enable kbd dpad x x x x x x 0 x
+ * Happy Times 0 1 0 x x x 0 x
+ */
+
+/*
+ * HTCPLD GPIO lines start 16 after OMAP_MAX_GPIO_LINES to account
+ * for the 16 MPUIO lines.
+ */
+#define HTCPLD_GPIO_START_OFFSET (OMAP_MAX_GPIO_LINES + 16)
+#define HTCPLD_IRQ(chip, offset) (OMAP_IRQ_END + 8 * (chip) + (offset))
+#define HTCPLD_BASE(chip, offset) \
+ (HTCPLD_GPIO_START_OFFSET + 8 * (chip) + (offset))
+
+#define HTCPLD_GPIO_LED_DPAD HTCPLD_BASE(0, 0)
+#define HTCPLD_GPIO_LED_KBD HTCPLD_BASE(1, 0)
+#define HTCPLD_GPIO_LED_CAPS HTCPLD_BASE(1, 5)
+#define HTCPLD_GPIO_LED_RED_FLASH HTCPLD_BASE(2, 1)
+#define HTCPLD_GPIO_LED_RED_SOLID HTCPLD_BASE(2, 2)
+#define HTCPLD_GPIO_LED_GREEN_FLASH HTCPLD_BASE(2, 3)
+#define HTCPLD_GPIO_LED_GREEN_SOLID HTCPLD_BASE(2, 4)
+#define HTCPLD_GPIO_LED_WIFI HTCPLD_BASE(2, 5)
+#define HTCPLD_GPIO_LED_BT HTCPLD_BASE(2, 6)
+#define HTCPLD_GPIO_LED_VIBRATE HTCPLD_BASE(3, 3)
+#define HTCPLD_GPIO_LED_ALT HTCPLD_BASE(3, 4)
+
+#define HTCPLD_GPIO_RIGHT_KBD HTCPLD_BASE(6, 7)
+#define HTCPLD_GPIO_UP_KBD HTCPLD_BASE(6, 6)
+#define HTCPLD_GPIO_LEFT_KBD HTCPLD_BASE(6, 5)
+#define HTCPLD_GPIO_DOWN_KBD HTCPLD_BASE(6, 4)
+
+#define HTCPLD_GPIO_RIGHT_DPAD HTCPLD_BASE(7, 7)
+#define HTCPLD_GPIO_UP_DPAD HTCPLD_BASE(7, 6)
+#define HTCPLD_GPIO_LEFT_DPAD HTCPLD_BASE(7, 5)
+#define HTCPLD_GPIO_DOWN_DPAD HTCPLD_BASE(7, 4)
+#define HTCPLD_GPIO_ENTER_DPAD HTCPLD_BASE(7, 3)
+
+/*
+ * The htcpld chip requires a gpio write to a specific line
+ * to re-enable interrupts after one has occurred.
+ */
+#define HTCPLD_GPIO_INT_RESET_HI HTCPLD_BASE(2, 7)
+#define HTCPLD_GPIO_INT_RESET_LO HTCPLD_BASE(2, 0)
+
+/* Chip 5 */
+#define HTCPLD_IRQ_RIGHT_KBD HTCPLD_IRQ(0, 7)
+#define HTCPLD_IRQ_UP_KBD HTCPLD_IRQ(0, 6)
+#define HTCPLD_IRQ_LEFT_KBD HTCPLD_IRQ(0, 5)
+#define HTCPLD_IRQ_DOWN_KBD HTCPLD_IRQ(0, 4)
+
+/* Chip 6 */
+#define HTCPLD_IRQ_RIGHT_DPAD HTCPLD_IRQ(1, 7)
+#define HTCPLD_IRQ_UP_DPAD HTCPLD_IRQ(1, 6)
+#define HTCPLD_IRQ_LEFT_DPAD HTCPLD_IRQ(1, 5)
+#define HTCPLD_IRQ_DOWN_DPAD HTCPLD_IRQ(1, 4)
+#define HTCPLD_IRQ_ENTER_DPAD HTCPLD_IRQ(1, 3)
+
+/* Keyboard definition */
+
+static const unsigned int htc_herald_keymap[] = {
+ KEY(0, 0, KEY_RECORD), /* Mail button */
+ KEY(1, 0, KEY_CAMERA), /* Camera */
+ KEY(2, 0, KEY_PHONE), /* Send key */
+ KEY(3, 0, KEY_VOLUMEUP), /* Volume up */
+ KEY(4, 0, KEY_F2), /* Right bar (landscape) */
+ KEY(5, 0, KEY_MAIL), /* Win key (portrait) */
+ KEY(6, 0, KEY_DIRECTORY), /* Right bar (protrait) */
+ KEY(0, 1, KEY_LEFTCTRL), /* Windows key */
+ KEY(1, 1, KEY_COMMA),
+ KEY(2, 1, KEY_M),
+ KEY(3, 1, KEY_K),
+ KEY(4, 1, KEY_SLASH), /* OK key */
+ KEY(5, 1, KEY_I),
+ KEY(6, 1, KEY_U),
+ KEY(0, 2, KEY_LEFTALT),
+ KEY(1, 2, KEY_TAB),
+ KEY(2, 2, KEY_N),
+ KEY(3, 2, KEY_J),
+ KEY(4, 2, KEY_ENTER),
+ KEY(5, 2, KEY_H),
+ KEY(6, 2, KEY_Y),
+ KEY(0, 3, KEY_SPACE),
+ KEY(1, 3, KEY_L),
+ KEY(2, 3, KEY_B),
+ KEY(3, 3, KEY_V),
+ KEY(4, 3, KEY_BACKSPACE),
+ KEY(5, 3, KEY_G),
+ KEY(6, 3, KEY_T),
+ KEY(0, 4, KEY_CAPSLOCK), /* Shift */
+ KEY(1, 4, KEY_C),
+ KEY(2, 4, KEY_F),
+ KEY(3, 4, KEY_R),
+ KEY(4, 4, KEY_O),
+ KEY(5, 4, KEY_E),
+ KEY(6, 4, KEY_D),
+ KEY(0, 5, KEY_X),
+ KEY(1, 5, KEY_Z),
+ KEY(2, 5, KEY_S),
+ KEY(3, 5, KEY_W),
+ KEY(4, 5, KEY_P),
+ KEY(5, 5, KEY_Q),
+ KEY(6, 5, KEY_A),
+ KEY(0, 6, KEY_CONNECT), /* Voice button */
+ KEY(2, 6, KEY_CANCEL), /* End key */
+ KEY(3, 6, KEY_VOLUMEDOWN), /* Volume down */
+ KEY(4, 6, KEY_F1), /* Left bar (landscape) */
+ KEY(5, 6, KEY_WWW), /* OK button (portrait) */
+ KEY(6, 6, KEY_CALENDAR), /* Left bar (portrait) */
+};
+
+static const struct matrix_keymap_data htc_herald_keymap_data = {
+ .keymap = htc_herald_keymap,
+ .keymap_size = ARRAY_SIZE(htc_herald_keymap),
+};
+
+static struct omap_kp_platform_data htcherald_kp_data = {
+ .rows = 7,
+ .cols = 7,
+ .delay = 20,
+ .rep = true,
+ .keymap_data = &htc_herald_keymap_data,
+};
+
+static struct resource kp_resources[] = {
+ [0] = {
+ .start = INT_7XX_MPUIO_KEYPAD,
+ .end = INT_7XX_MPUIO_KEYPAD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &htcherald_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(kp_resources),
+ .resource = kp_resources,
+};
+
+/* GPIO buttons for keyboard slide and power button */
+static struct gpio_keys_button herald_gpio_keys_table[] = {
+ {BTN_0, HTCHERALD_GPIO_POWER, 1, "POWER", EV_KEY, 1, 20},
+ {SW_LID, HTCHERALD_GPIO_SLIDE, 0, "SLIDE", EV_SW, 1, 20},
+
+ {KEY_LEFT, HTCPLD_GPIO_LEFT_KBD, 1, "LEFT", EV_KEY, 1, 20},
+ {KEY_RIGHT, HTCPLD_GPIO_RIGHT_KBD, 1, "RIGHT", EV_KEY, 1, 20},
+ {KEY_UP, HTCPLD_GPIO_UP_KBD, 1, "UP", EV_KEY, 1, 20},
+ {KEY_DOWN, HTCPLD_GPIO_DOWN_KBD, 1, "DOWN", EV_KEY, 1, 20},
+
+ {KEY_LEFT, HTCPLD_GPIO_LEFT_DPAD, 1, "DLEFT", EV_KEY, 1, 20},
+ {KEY_RIGHT, HTCPLD_GPIO_RIGHT_DPAD, 1, "DRIGHT", EV_KEY, 1, 20},
+ {KEY_UP, HTCPLD_GPIO_UP_DPAD, 1, "DUP", EV_KEY, 1, 20},
+ {KEY_DOWN, HTCPLD_GPIO_DOWN_DPAD, 1, "DDOWN", EV_KEY, 1, 20},
+ {KEY_ENTER, HTCPLD_GPIO_ENTER_DPAD, 1, "DENTER", EV_KEY, 1, 20},
+};
+
+static struct gpio_keys_platform_data herald_gpio_keys_data = {
+ .buttons = herald_gpio_keys_table,
+ .nbuttons = ARRAY_SIZE(herald_gpio_keys_table),
+ .rep = true,
+};
+
+static struct platform_device herald_gpiokeys_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &herald_gpio_keys_data,
+ },
+};
+
+/* LEDs for the Herald. These connect to the HTCPLD GPIO device. */
+static struct gpio_led gpio_leds[] = {
+ {"dpad", NULL, HTCPLD_GPIO_LED_DPAD, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"kbd", NULL, HTCPLD_GPIO_LED_KBD, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"vibrate", NULL, HTCPLD_GPIO_LED_VIBRATE, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"green_solid", NULL, HTCPLD_GPIO_LED_GREEN_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"green_flash", NULL, HTCPLD_GPIO_LED_GREEN_FLASH, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"red_solid", "mmc0", HTCPLD_GPIO_LED_RED_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"red_flash", NULL, HTCPLD_GPIO_LED_RED_FLASH, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"wifi", NULL, HTCPLD_GPIO_LED_WIFI, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"bt", NULL, HTCPLD_GPIO_LED_BT, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"caps", NULL, HTCPLD_GPIO_LED_CAPS, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+ {"alt", NULL, HTCPLD_GPIO_LED_ALT, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+};
+
+static struct gpio_led_platform_data gpio_leds_data = {
+ .leds = gpio_leds,
+ .num_leds = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device gpio_leds_device = {
+ .name = "leds-gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &gpio_leds_data,
+ },
+};
+
+/* HTC PLD chips */
+
+static struct resource htcpld_resources[] = {
+ [0] = {
+ .start = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+ .end = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct htcpld_chip_platform_data htcpld_chips[] = {
+ [0] = {
+ .addr = 0x03,
+ .reset = 0x04,
+ .num_gpios = 8,
+ .gpio_out_base = HTCPLD_BASE(0, 0),
+ .gpio_in_base = HTCPLD_BASE(4, 0),
+ },
+ [1] = {
+ .addr = 0x04,
+ .reset = 0x8e,
+ .num_gpios = 8,
+ .gpio_out_base = HTCPLD_BASE(1, 0),
+ .gpio_in_base = HTCPLD_BASE(5, 0),
+ },
+ [2] = {
+ .addr = 0x05,
+ .reset = 0x80,
+ .num_gpios = 8,
+ .gpio_out_base = HTCPLD_BASE(2, 0),
+ .gpio_in_base = HTCPLD_BASE(6, 0),
+ .irq_base = HTCPLD_IRQ(0, 0),
+ .num_irqs = 8,
+ },
+ [3] = {
+ .addr = 0x06,
+ .reset = 0x40,
+ .num_gpios = 8,
+ .gpio_out_base = HTCPLD_BASE(3, 0),
+ .gpio_in_base = HTCPLD_BASE(7, 0),
+ .irq_base = HTCPLD_IRQ(1, 0),
+ .num_irqs = 8,
+ },
+};
+
+static struct htcpld_core_platform_data htcpld_pfdata = {
+ .int_reset_gpio_hi = HTCPLD_GPIO_INT_RESET_HI,
+ .int_reset_gpio_lo = HTCPLD_GPIO_INT_RESET_LO,
+ .i2c_adapter_id = 1,
+
+ .chip = htcpld_chips,
+ .num_chip = ARRAY_SIZE(htcpld_chips),
+};
+
+static struct platform_device htcpld_device = {
+ .name = "i2c-htcpld",
+ .id = -1,
+ .resource = htcpld_resources,
+ .num_resources = ARRAY_SIZE(htcpld_resources),
+ .dev = {
+ .platform_data = &htcpld_pfdata,
+ },
+};
+
+/* USB Device */
+static struct omap_usb_config htcherald_usb_config __initdata = {
+ .otg = 0,
+ .register_host = 0,
+ .register_dev = 1,
+ .hmc_mode = 4,
+ .pins[0] = 2,
+};
+
+/* LCD Device resources */
+static struct omap_lcd_config htcherald_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel htcherald_config[] __initdata = {
+ { OMAP_TAG_LCD, &htcherald_lcd_config },
+};
+
+static struct platform_device lcd_device = {
+ .name = "lcd_htcherald",
+ .id = -1,
+};
+
+/* MMC Card */
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+static struct omap_mmc_platform_data htc_mmc1_data = {
+ .nr_slots = 1,
+ .switch_slot = NULL,
+ .slots[0] = {
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+ .name = "mmcblk",
+ .nomux = 1,
+ .wires = 4,
+ .switch_pin = -1,
+ },
+};
+
+static struct omap_mmc_platform_data *htc_mmc_data[1];
+#endif
+
+
+/* Platform devices for the Herald */
+static struct platform_device *devices[] __initdata = {
+ &kp_device,
+ &lcd_device,
+ &htcpld_device,
+ &gpio_leds_device,
+ &herald_gpiokeys_device,
+};
+
+/*
+ * Touchscreen
+ */
+static const struct ads7846_platform_data htcherald_ts_platform_data = {
+ .model = 7846,
+ .keep_vref_on = 1,
+ .x_plate_ohms = 496,
+ .gpio_pendown = HTCHERALD_GPIO_TS,
+ .pressure_max = 10000,
+ .pressure_min = 5000,
+ .x_min = 528,
+ .x_max = 3760,
+ .y_min = 624,
+ .y_max = 3760,
+};
+
+static struct spi_board_info __initdata htcherald_spi_board_info[] = {
+ {
+ .modalias = "ads7846",
+ .platform_data = &htcherald_ts_platform_data,
+ .irq = OMAP_GPIO_IRQ(HTCHERALD_GPIO_TS),
+ .max_speed_hz = 2500000,
+ .bus_num = 2,
+ .chip_select = 1,
+ }
+};
+
+/*
+ * Init functions from here on
+ */
+
+static void __init htcherald_lcd_init(void)
+{
+ u32 reg;
+ unsigned int tries = 200;
+
+ /* disable controller if active */
+ reg = omap_readl(OMAP_LCDC_CONTROL);
+ if (reg & OMAP_LCDC_CTRL_LCD_EN) {
+ reg &= ~OMAP_LCDC_CTRL_LCD_EN;
+ omap_writel(reg, OMAP_LCDC_CONTROL);
+
+ /* wait for end of frame */
+ while (!(omap_readl(OMAP_LCDC_STATUS) & OMAP_LCDC_STAT_DONE)) {
+ tries--;
+ if (!tries)
+ break;
+ }
+ if (!tries)
+ printk(KERN_WARNING "Timeout waiting for end of frame "
+ "-- LCD may not be available\n");
+
+ /* turn off DMA */
+ reg = omap_readw(OMAP_DMA_LCD_CCR);
+ reg &= ~(1 << 7);
+ omap_writew(reg, OMAP_DMA_LCD_CCR);
+
+ reg = omap_readw(OMAP_DMA_LCD_CTRL);
+ reg &= ~(1 << 8);
+ omap_writew(reg, OMAP_DMA_LCD_CTRL);
+ }
+}
+
+static void __init htcherald_map_io(void)
+{
+ omap1_map_common_io();
+
+ /*
+ * The LCD panel must be disabled and DMA turned off here, as doing
+ * it later causes the LCD never to reinitialize.
+ */
+ htcherald_lcd_init();
+
+ printk(KERN_INFO "htcherald_map_io done.\n");
+}
+
+static void __init htcherald_disable_watchdog(void)
+{
+ /* Disable watchdog if running */
+ if (omap_readl(OMAP_WDT_TIMER_MODE) & 0x8000) {
+ /*
+ * disable a potentially running watchdog timer before
+ * it kills us.
+ */
+ printk(KERN_WARNING "OMAP850 Watchdog seems to be activated, disabling it for now.\n");
+ omap_writel(0xF5, OMAP_WDT_TIMER_MODE);
+ omap_writel(0xA0, OMAP_WDT_TIMER_MODE);
+ }
+}
+
+#define HTCHERALD_GPIO_USB_EN1 33
+#define HTCHERALD_GPIO_USB_EN2 73
+#define HTCHERALD_GPIO_USB_DM 35
+#define HTCHERALD_GPIO_USB_DP 36
+
+static void __init htcherald_usb_enable(void)
+{
+ unsigned int tries = 20;
+ unsigned int value = 0;
+
+ /* Request the GPIOs we need to control here */
+ if (gpio_request(HTCHERALD_GPIO_USB_EN1, "herald_usb") < 0)
+ goto err1;
+
+ if (gpio_request(HTCHERALD_GPIO_USB_EN2, "herald_usb") < 0)
+ goto err2;
+
+ if (gpio_request(HTCHERALD_GPIO_USB_DM, "herald_usb") < 0)
+ goto err3;
+
+ if (gpio_request(HTCHERALD_GPIO_USB_DP, "herald_usb") < 0)
+ goto err4;
+
+ /* force USB_EN GPIO to 0 */
+ do {
+ /* output low */
+ gpio_direction_output(HTCHERALD_GPIO_USB_EN1, 0);
+ } while ((value = gpio_get_value(HTCHERALD_GPIO_USB_EN1)) == 1 &&
+ --tries);
+
+ if (value == 1)
+ printk(KERN_WARNING "Unable to reset USB, trying to continue\n");
+
+ gpio_direction_output(HTCHERALD_GPIO_USB_EN2, 0); /* output low */
+ gpio_direction_input(HTCHERALD_GPIO_USB_DM); /* input */
+ gpio_direction_input(HTCHERALD_GPIO_USB_DP); /* input */
+
+ goto done;
+
+err4:
+ gpio_free(HTCHERALD_GPIO_USB_DM);
+err3:
+ gpio_free(HTCHERALD_GPIO_USB_EN2);
+err2:
+ gpio_free(HTCHERALD_GPIO_USB_EN1);
+err1:
+ printk(KERN_ERR "Unabled to request GPIO for USB\n");
+done:
+ printk(KERN_INFO "USB setup complete.\n");
+}
+
+static void __init htcherald_init(void)
+{
+ printk(KERN_INFO "HTC Herald init.\n");
+
+ /* Do board initialization before we register all the devices */
+ omap_board_config = htcherald_config;
+ omap_board_config_size = ARRAY_SIZE(htcherald_config);
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ htcherald_disable_watchdog();
+
+ htcherald_usb_enable();
+ omap1_usb_init(&htcherald_usb_config);
+
+ spi_register_board_info(htcherald_spi_board_info,
+ ARRAY_SIZE(htcherald_spi_board_info));
+
+ omap_register_i2c_bus(1, 100, NULL, 0);
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+ htc_mmc_data[0] = &htc_mmc1_data;
+ omap1_init_mmc(htc_mmc_data, 1);
+#endif
+}
+
+static void __init htcherald_init_irq(void)
+{
+ printk(KERN_INFO "htcherald_init_irq.\n");
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+MACHINE_START(HERALD, "HTC Herald")
+ /* Maintainer: Cory Maccarrone <darkstar6262@gmail.com> */
+ /* Maintainer: wing-linux.sourceforge.net */
+ .boot_params = 0x10000100,
+ .map_io = htcherald_map_io,
+ .reserve = omap_reserve,
+ .init_irq = htcherald_init_irq,
+ .init_machine = htcherald_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
new file mode 100644
index 00000000..2d9b8cbd
--- /dev/null
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -0,0 +1,468 @@
+/*
+ * linux/arch/arm/mach-omap1/board-innovator.c
+ *
+ * Board specific inits for OMAP-1510 and OMAP-1610 Innovator
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ *
+ * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
+ * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/smc91x.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/mux.h>
+#include <plat/flash.h>
+#include <plat/fpga.h>
+#include <mach/gpio.h>
+#include <plat/tc.h>
+#include <plat/usb.h>
+#include <plat/keypad.h>
+#include <plat/common.h>
+#include <plat/mmc.h>
+
+/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
+#define INNOVATOR1610_ETHR_START 0x04000300
+
+static const unsigned int innovator_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(3, 0, KEY_DOWN),
+ KEY(1, 1, KEY_F2),
+ KEY(2, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_F3),
+ KEY(1, 2, KEY_F4),
+ KEY(2, 2, KEY_UP),
+ KEY(2, 3, KEY_ENTER),
+ KEY(3, 3, KEY_LEFT),
+};
+
+static struct mtd_partition innovator_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* rest of flash1 is a file system */
+ {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_16M - SZ_2M - 2 * SZ_128K,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct physmap_flash_data innovator_flash_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = innovator_partitions,
+ .nr_parts = ARRAY_SIZE(innovator_partitions),
+};
+
+static struct resource innovator_flash_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device innovator_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &innovator_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &innovator_flash_resource,
+};
+
+static struct resource innovator_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct matrix_keymap_data innovator_keymap_data = {
+ .keymap = innovator_keymap,
+ .keymap_size = ARRAY_SIZE(innovator_keymap),
+};
+
+static struct omap_kp_platform_data innovator_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &innovator_keymap_data,
+ .delay = 4,
+};
+
+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,
+};
+
+static struct smc91x_platdata innovator_smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+ .leda = RPC_LED_100_10,
+ .ledb = RPC_LED_TX_RX,
+};
+
+#ifdef CONFIG_ARCH_OMAP15XX
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+
+/* Only FPGA needs to be mapped here. All others are done with ioremap */
+static struct map_desc innovator1510_io_desc[] __initdata = {
+ {
+ .virtual = OMAP1510_FPGA_BASE,
+ .pfn = __phys_to_pfn(OMAP1510_FPGA_START),
+ .length = OMAP1510_FPGA_SIZE,
+ .type = MT_DEVICE
+ }
+};
+
+static struct resource innovator1510_smc91x_resources[] = {
+ [0] = {
+ .start = OMAP1510_FPGA_ETHR_START, /* Physical */
+ .end = OMAP1510_FPGA_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP1510_INT_ETHER,
+ .end = OMAP1510_INT_ETHER,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ },
+};
+
+static struct platform_device innovator1510_smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .dev = {
+ .platform_data = &innovator_smc91x_info,
+ },
+ .num_resources = ARRAY_SIZE(innovator1510_smc91x_resources),
+ .resource = innovator1510_smc91x_resources,
+};
+
+static struct platform_device innovator1510_lcd_device = {
+ .name = "lcd_inn1510",
+ .id = -1,
+};
+
+static struct platform_device innovator1510_spi_device = {
+ .name = "spi_inn1510",
+ .id = -1,
+};
+
+static struct platform_device *innovator1510_devices[] __initdata = {
+ &innovator_flash_device,
+ &innovator1510_smc91x_device,
+ &innovator_kp_device,
+ &innovator1510_lcd_device,
+ &innovator1510_spi_device,
+};
+
+static int innovator_get_pendown_state(void)
+{
+ return !(fpga_read(OMAP1510_FPGA_TOUCHSCREEN) & (1 << 5));
+}
+
+static const struct ads7846_platform_data innovator1510_ts_info = {
+ .model = 7846,
+ .vref_delay_usecs = 100, /* internal, no capacitor */
+ .x_plate_ohms = 419,
+ .y_plate_ohms = 486,
+ .get_pendown_state = innovator_get_pendown_state,
+};
+
+static struct spi_board_info __initdata innovator1510_boardinfo[] = { {
+ /* FPGA (bus "10") CS0 has an ads7846e */
+ .modalias = "ads7846",
+ .platform_data = &innovator1510_ts_info,
+ .irq = OMAP1510_INT_FPGA_TS,
+ .max_speed_hz = 120000 /* max sample rate at 3V */
+ * 26 /* command + data + overhead */,
+ .bus_num = 10,
+ .chip_select = 0,
+} };
+
+#endif /* CONFIG_ARCH_OMAP15XX */
+
+#ifdef CONFIG_ARCH_OMAP16XX
+
+static struct resource innovator1610_smc91x_resources[] = {
+ [0] = {
+ .start = INNOVATOR1610_ETHR_START, /* Physical */
+ .end = INNOVATOR1610_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(0),
+ .end = OMAP_GPIO_IRQ(0),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
+ },
+};
+
+static struct platform_device innovator1610_smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .dev = {
+ .platform_data = &innovator_smc91x_info,
+ },
+ .num_resources = ARRAY_SIZE(innovator1610_smc91x_resources),
+ .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 */
+
+static void __init innovator_init_smc91x(void)
+{
+ if (cpu_is_omap1510()) {
+ fpga_write(fpga_read(OMAP1510_FPGA_RST) & ~1,
+ OMAP1510_FPGA_RST);
+ udelay(750);
+ } else {
+ if (gpio_request(0, "SMC91x irq") < 0) {
+ printk("Error requesting gpio 0 for smc91x irq\n");
+ return;
+ }
+ }
+}
+
+static void __init innovator_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+#ifdef CONFIG_ARCH_OMAP15XX
+static struct omap_usb_config innovator1510_usb_config __initdata = {
+ /* for bundled non-standard host and peripheral cables */
+ .hmc_mode = 4,
+
+ .register_host = 1,
+ .pins[1] = 6,
+ .pins[2] = 6, /* Conflicts with UART2 */
+
+ .register_dev = 1,
+ .pins[0] = 2,
+};
+
+static struct omap_lcd_config innovator1510_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+static struct omap_usb_config h2_usb_config __initdata = {
+ /* usb1 has a Mini-AB port and external isp1301 transceiver */
+ .otg = 2,
+
+#ifdef CONFIG_USB_GADGET_OMAP
+ .hmc_mode = 19, /* 0:host(off) 1:dev|otg 2:disabled */
+ /* .hmc_mode = 21,*/ /* 0:host(off) 1:dev(loopback) 2:host(loopback) */
+#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+ /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
+ .hmc_mode = 20, /* 1:dev|otg(off) 1:host 2:disabled */
+#endif
+
+ .pins[1] = 3,
+};
+
+static struct omap_lcd_config innovator1610_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+#endif
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+static int mmc_set_power(struct device *dev, int slot, int power_on,
+ int vdd)
+{
+ if (power_on)
+ fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
+ OMAP1510_FPGA_POWER);
+ else
+ fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3),
+ OMAP1510_FPGA_POWER);
+
+ return 0;
+}
+
+/*
+ * Innovator could use the following functions tested:
+ * - mmc_get_wp that uses OMAP_MPUIO(3)
+ * - mmc_get_cover_state that uses FPGA F4 UIO43
+ */
+static struct omap_mmc_platform_data mmc1_data = {
+ .nr_slots = 1,
+ .slots[0] = {
+ .set_power = mmc_set_power,
+ .wires = 4,
+ .name = "mmcblk",
+ },
+};
+
+static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
+
+static void __init innovator_mmc_init(void)
+{
+ mmc_data[0] = &mmc1_data;
+ omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC);
+}
+
+#else
+static inline void innovator_mmc_init(void)
+{
+}
+#endif
+
+static struct omap_board_config_kernel innovator_config[] = {
+ { OMAP_TAG_LCD, NULL },
+};
+
+static void __init innovator_init(void)
+{
+ if (cpu_is_omap1510())
+ omap1510_fpga_init_irq();
+ innovator_init_smc91x();
+
+#ifdef CONFIG_ARCH_OMAP15XX
+ if (cpu_is_omap1510()) {
+ unsigned char reg;
+
+ /* mux pins for uarts */
+ omap_cfg_reg(UART1_TX);
+ omap_cfg_reg(UART1_RTS);
+ omap_cfg_reg(UART2_TX);
+ omap_cfg_reg(UART2_RTS);
+ omap_cfg_reg(UART3_TX);
+ omap_cfg_reg(UART3_RX);
+
+ reg = fpga_read(OMAP1510_FPGA_POWER);
+ reg |= OMAP1510_FPGA_PCR_COM1_EN;
+ fpga_write(reg, OMAP1510_FPGA_POWER);
+ udelay(10);
+
+ reg = fpga_read(OMAP1510_FPGA_POWER);
+ reg |= OMAP1510_FPGA_PCR_COM2_EN;
+ fpga_write(reg, OMAP1510_FPGA_POWER);
+ udelay(10);
+
+ platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
+ spi_register_board_info(innovator1510_boardinfo,
+ ARRAY_SIZE(innovator1510_boardinfo));
+ }
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ if (!cpu_is_omap1510()) {
+ platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices));
+ }
+#endif
+
+#ifdef CONFIG_ARCH_OMAP15XX
+ if (cpu_is_omap1510()) {
+ omap1_usb_init(&innovator1510_usb_config);
+ innovator_config[1].data = &innovator1510_lcd_config;
+ }
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ if (cpu_is_omap1610()) {
+ omap1_usb_init(&h2_usb_config);
+ innovator_config[1].data = &innovator1610_lcd_config;
+ }
+#endif
+ omap_board_config = innovator_config;
+ omap_board_config_size = ARRAY_SIZE(innovator_config);
+ omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
+ innovator_mmc_init();
+}
+
+static void __init innovator_map_io(void)
+{
+ omap1_map_common_io();
+
+#ifdef CONFIG_ARCH_OMAP15XX
+ if (cpu_is_omap1510()) {
+ iotable_init(innovator1510_io_desc, ARRAY_SIZE(innovator1510_io_desc));
+ udelay(10); /* Delay needed for FPGA */
+
+ /* Dump the Innovator FPGA rev early - useful info for support. */
+ printk("Innovator FPGA Rev %d.%d Board Rev %d\n",
+ fpga_read(OMAP1510_FPGA_REV_HIGH),
+ fpga_read(OMAP1510_FPGA_REV_LOW),
+ fpga_read(OMAP1510_FPGA_BOARD_REV));
+ }
+#endif
+}
+
+MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
+ /* Maintainer: MontaVista Software, Inc. */
+ .boot_params = 0x10000100,
+ .map_io = innovator_map_io,
+ .reserve = omap_reserve,
+ .init_irq = innovator_init_irq,
+ .init_machine = innovator_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 00000000..cfd08492
--- /dev/null
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -0,0 +1,273 @@
+/*
+ * 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/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+#include <linux/omapfb.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/gpio.h>
+#include <plat/mux.h>
+#include <plat/usb.h>
+#include <plat/board.h>
+#include <plat/keypad.h>
+#include <plat/common.h>
+#include <plat/hwa742.h>
+#include <plat/lcd_mipid.h>
+#include <plat/mmc.h>
+#include <plat/clock.h>
+
+#define ADS7846_PENDOWN_GPIO 15
+
+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 const unsigned int nokia770_keymap[] = {
+ KEY(1, 0, GROUP_0 | KEY_UP),
+ KEY(2, 0, GROUP_1 | KEY_F5),
+ KEY(0, 1, GROUP_0 | KEY_LEFT),
+ KEY(1, 1, GROUP_0 | KEY_ENTER),
+ KEY(2, 1, GROUP_0 | KEY_RIGHT),
+ KEY(0, 2, GROUP_1 | KEY_ESC),
+ KEY(1, 2, GROUP_0 | KEY_DOWN),
+ KEY(2, 2, GROUP_1 | KEY_F4),
+ KEY(0, 3, GROUP_2 | KEY_F7),
+ KEY(1, 3, GROUP_2 | KEY_F8),
+ KEY(2, 3, GROUP_2 | KEY_F6),
+};
+
+static struct resource nokia770_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct matrix_keymap_data nokia770_keymap_data = {
+ .keymap = nokia770_keymap,
+ .keymap_size = ARRAY_SIZE(nokia770_keymap),
+};
+
+static struct omap_kp_platform_data nokia770_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &nokia770_keymap_data,
+ .delay = 4,
+};
+
+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 void mipid_shutdown(struct mipid_platform_data *pdata)
+{
+ if (pdata->nreset_gpio != -1) {
+ printk(KERN_INFO "shutdown LCD\n");
+ gpio_set_value(pdata->nreset_gpio, 0);
+ msleep(120);
+ }
+}
+
+static struct mipid_platform_data nokia770_mipid_platform_data = {
+ .shutdown = mipid_shutdown,
+};
+
+static void __init mipid_dev_init(void)
+{
+ const struct omap_lcd_config *conf;
+
+ conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
+ if (conf != NULL) {
+ nokia770_mipid_platform_data.nreset_gpio = conf->nreset_gpio;
+ nokia770_mipid_platform_data.data_lines = conf->data_lines;
+ }
+}
+
+static void __init ads7846_dev_init(void)
+{
+ if (gpio_request(ADS7846_PENDOWN_GPIO, "ADS7846 pendown") < 0)
+ printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
+}
+
+static int ads7846_get_pendown_state(void)
+{
+ return !gpio_get_value(ADS7846_PENDOWN_GPIO);
+}
+
+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,
+ .debounce_rep = 1,
+ .get_pendown_state = ads7846_get_pendown_state,
+};
+
+static struct spi_board_info nokia770_spi_board_info[] __initdata = {
+ [0] = {
+ .modalias = "lcd_mipid",
+ .bus_num = 2,
+ .chip_select = 3,
+ .max_speed_hz = 12000000,
+ .platform_data = &nokia770_mipid_platform_data,
+ },
+ [1] = {
+ .modalias = "ads7846",
+ .bus_num = 2,
+ .chip_select = 0,
+ .max_speed_hz = 2500000,
+ .irq = OMAP_GPIO_IRQ(15),
+ .platform_data = &nokia770_ads7846_platform_data,
+ },
+};
+
+static struct hwa742_platform_data nokia770_hwa742_platform_data = {
+ .te_connected = 1,
+};
+
+static void __init hwa742_dev_init(void)
+{
+ clk_add_alias("hwa_sys_ck", NULL, "bclk", NULL);
+ omapfb_set_ctrl_platform_data(&nokia770_hwa742_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,
+};
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+#define NOKIA770_GPIO_MMC_POWER 41
+#define NOKIA770_GPIO_MMC_SWITCH 23
+
+static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on,
+ int vdd)
+{
+ gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on);
+ return 0;
+}
+
+static int nokia770_mmc_get_cover_state(struct device *dev, int slot)
+{
+ return gpio_get_value(NOKIA770_GPIO_MMC_SWITCH);
+}
+
+static struct omap_mmc_platform_data nokia770_mmc2_data = {
+ .nr_slots = 1,
+ .dma_mask = 0xffffffff,
+ .max_freq = 12000000,
+ .slots[0] = {
+ .set_power = nokia770_mmc_set_power,
+ .get_cover_state = nokia770_mmc_get_cover_state,
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .name = "mmcblk",
+ },
+};
+
+static struct omap_mmc_platform_data *nokia770_mmc_data[OMAP16XX_NR_MMC];
+
+static void __init nokia770_mmc_init(void)
+{
+ int ret;
+
+ ret = gpio_request(NOKIA770_GPIO_MMC_POWER, "MMC power");
+ if (ret < 0)
+ return;
+ gpio_direction_output(NOKIA770_GPIO_MMC_POWER, 0);
+
+ ret = gpio_request(NOKIA770_GPIO_MMC_SWITCH, "MMC cover");
+ if (ret < 0) {
+ gpio_free(NOKIA770_GPIO_MMC_POWER);
+ return;
+ }
+ gpio_direction_input(NOKIA770_GPIO_MMC_SWITCH);
+
+ /* Only the second MMC controller is used */
+ nokia770_mmc_data[1] = &nokia770_mmc2_data;
+ omap1_init_mmc(nokia770_mmc_data, OMAP16XX_NR_MMC);
+}
+
+#else
+static inline void nokia770_mmc_init(void)
+{
+}
+#endif
+
+static void __init omap_nokia770_init(void)
+{
+ platform_add_devices(nokia770_devices, ARRAY_SIZE(nokia770_devices));
+ spi_register_board_info(nokia770_spi_board_info,
+ ARRAY_SIZE(nokia770_spi_board_info));
+ omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
+ hwa742_dev_init();
+ ads7846_dev_init();
+ mipid_dev_init();
+ omap1_usb_init(&nokia770_usb_config);
+ nokia770_mmc_init();
+}
+
+static void __init omap_nokia770_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(NOKIA770, "Nokia 770")
+ .boot_params = 0x10000100,
+ .map_io = omap_nokia770_map_io,
+ .reserve = omap_reserve,
+ .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
new file mode 100644
index 00000000..e68dfde1
--- /dev/null
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -0,0 +1,592 @@
+/*
+ * linux/arch/arm/mach-omap1/board-osk.c
+ *
+ * Board specific init for OMAP5912 OSK
+ *
+ * Written 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/smc91x.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#include <linux/i2c/tps65010.h>
+
+#include <mach/hardware.h>
+#include <asm/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/flash.h>
+#include <plat/usb.h>
+#include <plat/mux.h>
+#include <plat/tc.h>
+#include <plat/common.h>
+
+/* At OMAP5912 OSK the Ethernet is directly connected to CS1 */
+#define OMAP_OSK_ETHR_START 0x04800300
+
+/* TPS65010 has four GPIOs. nPG and LED2 can be treated like GPIOs with
+ * alternate pin configurations for hardware-controlled blinking.
+ */
+#define OSK_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
+# define OSK_TPS_GPIO_USB_PWR_EN (OSK_TPS_GPIO_BASE + 0)
+# define OSK_TPS_GPIO_LED_D3 (OSK_TPS_GPIO_BASE + 1)
+# define OSK_TPS_GPIO_LAN_RESET (OSK_TPS_GPIO_BASE + 2)
+# define OSK_TPS_GPIO_DSP_PWR_EN (OSK_TPS_GPIO_BASE + 3)
+# define OSK_TPS_GPIO_LED_D9 (OSK_TPS_GPIO_BASE + 4)
+# define OSK_TPS_GPIO_LED_D2 (OSK_TPS_GPIO_BASE + 5)
+
+static struct mtd_partition osk_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ }, {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct physmap_flash_data osk_flash_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = osk_partitions,
+ .nr_parts = ARRAY_SIZE(osk_partitions),
+};
+
+static struct resource osk_flash_resource = {
+ /* this is on CS3, wherever it's mapped */
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device osk5912_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &osk_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &osk_flash_resource,
+};
+
+static struct smc91x_platdata osk5912_smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+ .leda = RPC_LED_100_10,
+ .ledb = RPC_LED_TX_RX,
+};
+
+static struct resource osk5912_smc91x_resources[] = {
+ [0] = {
+ .start = OMAP_OSK_ETHR_START, /* Physical */
+ .end = OMAP_OSK_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(0),
+ .end = OMAP_GPIO_IRQ(0),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ },
+};
+
+static struct platform_device osk5912_smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+ .dev = {
+ .platform_data = &osk5912_smc91x_info,
+ },
+ .num_resources = ARRAY_SIZE(osk5912_smc91x_resources),
+ .resource = osk5912_smc91x_resources,
+};
+
+static struct resource osk5912_cf_resources[] = {
+ [0] = {
+ .start = OMAP_GPIO_IRQ(62),
+ .end = OMAP_GPIO_IRQ(62),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device osk5912_cf_device = {
+ .name = "omap_cf",
+ .id = -1,
+ .dev = {
+ .platform_data = (void *) 2 /* CS2 */,
+ },
+ .num_resources = ARRAY_SIZE(osk5912_cf_resources),
+ .resource = osk5912_cf_resources,
+};
+
+static struct platform_device *osk5912_devices[] __initdata = {
+ &osk5912_flash_device,
+ &osk5912_smc91x_device,
+ &osk5912_cf_device,
+};
+
+static struct gpio_led tps_leds[] = {
+ /* NOTE: D9 and D2 have hardware blink support.
+ * Also, D9 requires non-battery power.
+ */
+ { .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9",
+ .default_trigger = "ide-disk", },
+ { .gpio = OSK_TPS_GPIO_LED_D2, .name = "d2", },
+ { .gpio = OSK_TPS_GPIO_LED_D3, .name = "d3", .active_low = 1,
+ .default_trigger = "heartbeat", },
+};
+
+static struct gpio_led_platform_data tps_leds_data = {
+ .num_leds = 3,
+ .leds = tps_leds,
+};
+
+static struct platform_device osk5912_tps_leds = {
+ .name = "leds-gpio",
+ .id = 0,
+ .dev.platform_data = &tps_leds_data,
+};
+
+static int osk_tps_setup(struct i2c_client *client, void *context)
+{
+ /* Set GPIO 1 HIGH to disable VBUS power supply;
+ * OHCI driver powers it up/down as needed.
+ */
+ gpio_request(OSK_TPS_GPIO_USB_PWR_EN, "n_vbus_en");
+ gpio_direction_output(OSK_TPS_GPIO_USB_PWR_EN, 1);
+
+ /* Set GPIO 2 high so LED D3 is off by default */
+ tps65010_set_gpio_out_value(GPIO2, HIGH);
+
+ /* Set GPIO 3 low to take ethernet out of reset */
+ gpio_request(OSK_TPS_GPIO_LAN_RESET, "smc_reset");
+ gpio_direction_output(OSK_TPS_GPIO_LAN_RESET, 0);
+
+ /* GPIO4 is VDD_DSP */
+ gpio_request(OSK_TPS_GPIO_DSP_PWR_EN, "dsp_power");
+ gpio_direction_output(OSK_TPS_GPIO_DSP_PWR_EN, 1);
+ /* REVISIT if DSP support isn't configured, power it off ... */
+
+ /* Let LED1 (D9) blink; leds-gpio may override it */
+ tps65010_set_led(LED1, BLINK);
+
+ /* Set LED2 off by default */
+ tps65010_set_led(LED2, OFF);
+
+ /* Enable LOW_PWR handshake */
+ tps65010_set_low_pwr(ON);
+
+ /* Switch VLDO2 to 3.0V for AIC23 */
+ tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
+ | TPS_LDO1_ENABLE);
+
+ /* register these three LEDs */
+ osk5912_tps_leds.dev.parent = &client->dev;
+ platform_device_register(&osk5912_tps_leds);
+
+ return 0;
+}
+
+static struct tps65010_board tps_board = {
+ .base = OSK_TPS_GPIO_BASE,
+ .outmask = 0x0f,
+ .setup = osk_tps_setup,
+};
+
+static struct i2c_board_info __initdata osk_i2c_board_info[] = {
+ {
+ I2C_BOARD_INFO("tps65010", 0x48),
+ .irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
+ .platform_data = &tps_board,
+
+ },
+ {
+ I2C_BOARD_INFO("tlv320aic23", 0x1B),
+ },
+ /* TODO when driver support is ready:
+ * - optionally on Mistral, ov9640 camera sensor at 0x30
+ */
+};
+
+static void __init osk_init_smc91x(void)
+{
+ u32 l;
+
+ if ((gpio_request(0, "smc_irq")) < 0) {
+ printk("Error requesting gpio 0 for smc91x irq\n");
+ return;
+ }
+
+ /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */
+ l = omap_readl(EMIFS_CCS(1));
+ l |= 0x3;
+ omap_writel(l, EMIFS_CCS(1));
+}
+
+static void __init osk_init_cf(void)
+{
+ omap_cfg_reg(M7_1610_GPIO62);
+ if ((gpio_request(62, "cf_irq")) < 0) {
+ printk("Error requesting gpio 62 for CF irq\n");
+ return;
+ }
+ /* the CF I/O IRQ is really active-low */
+ irq_set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING);
+}
+
+static void __init osk_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static struct omap_usb_config osk_usb_config __initdata = {
+ /* has usb host connector (A) ... for development it can also
+ * be used, with a NONSTANDARD gender-bending cable/dongle, as
+ * a peripheral.
+ */
+#ifdef CONFIG_USB_GADGET_OMAP
+ .register_dev = 1,
+ .hmc_mode = 0,
+#else
+ .register_host = 1,
+ .hmc_mode = 16,
+ .rwc = 1,
+#endif
+ .pins[0] = 2,
+};
+
+#ifdef CONFIG_OMAP_OSK_MISTRAL
+static struct omap_lcd_config osk_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+#endif
+
+static struct omap_board_config_kernel osk_config[] __initdata = {
+#ifdef CONFIG_OMAP_OSK_MISTRAL
+ { OMAP_TAG_LCD, &osk_lcd_config },
+#endif
+};
+
+#ifdef CONFIG_OMAP_OSK_MISTRAL
+
+#include <linux/input.h>
+#include <linux/i2c/at24.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include <plat/keypad.h>
+
+static struct at24_platform_data at24c04 = {
+ .byte_len = SZ_4K / 8,
+ .page_size = 16,
+};
+
+static struct i2c_board_info __initdata mistral_i2c_board_info[] = {
+ {
+ /* NOTE: powered from LCD supply */
+ I2C_BOARD_INFO("24c04", 0x50),
+ .platform_data = &at24c04,
+ },
+ /* TODO when driver support is ready:
+ * - optionally ov9640 camera sensor at 0x30
+ */
+};
+
+static const unsigned int osk_keymap[] = {
+ /* KEY(col, row, code) */
+ KEY(0, 0, KEY_F1), /* SW4 */
+ KEY(3, 0, KEY_UP), /* (sw2/up) */
+ KEY(1, 1, KEY_LEFTCTRL), /* SW5 */
+ KEY(2, 1, KEY_LEFT), /* (sw2/left) */
+ KEY(0, 2, KEY_SPACE), /* SW3 */
+ KEY(1, 2, KEY_ESC), /* SW6 */
+ KEY(2, 2, KEY_DOWN), /* (sw2/down) */
+ KEY(2, 3, KEY_ENTER), /* (sw2/select) */
+ KEY(3, 3, KEY_RIGHT), /* (sw2/right) */
+};
+
+static const struct matrix_keymap_data osk_keymap_data = {
+ .keymap = osk_keymap,
+ .keymap_size = ARRAY_SIZE(osk_keymap),
+};
+
+static struct omap_kp_platform_data osk_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &osk_keymap_data,
+ .delay = 9,
+};
+
+static struct resource osk5912_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+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 omap_backlight_config mistral_bl_data = {
+ .default_intensity = 0xa0,
+};
+
+static struct platform_device mistral_bl_device = {
+ .name = "omap-bl",
+ .id = -1,
+ .dev = {
+ .platform_data = &mistral_bl_data,
+ },
+};
+
+static struct platform_device osk5912_lcd_device = {
+ .name = "lcd_osk",
+ .id = -1,
+};
+
+static struct platform_device *mistral_devices[] __initdata = {
+ &osk5912_kp_device,
+ &mistral_bl_device,
+ &osk5912_lcd_device,
+};
+
+static int mistral_get_pendown_state(void)
+{
+ return !gpio_get_value(4);
+}
+
+static const struct ads7846_platform_data mistral_ts_info = {
+ .model = 7846,
+ .vref_delay_usecs = 100, /* internal, no capacitor */
+ .x_plate_ohms = 419,
+ .y_plate_ohms = 486,
+ .get_pendown_state = mistral_get_pendown_state,
+};
+
+static struct spi_board_info __initdata mistral_boardinfo[] = { {
+ /* MicroWire (bus 2) CS0 has an ads7846e */
+ .modalias = "ads7846",
+ .platform_data = &mistral_ts_info,
+ .irq = OMAP_GPIO_IRQ(4),
+ .max_speed_hz = 120000 /* max sample rate at 3V */
+ * 26 /* command + data + overhead */,
+ .bus_num = 2,
+ .chip_select = 0,
+} };
+
+#ifdef CONFIG_PM
+static irqreturn_t
+osk_mistral_wake_interrupt(int irq, void *ignored)
+{
+ return IRQ_HANDLED;
+}
+#endif
+
+static void __init osk_mistral_init(void)
+{
+ /* NOTE: we could actually tell if there's a Mistral board
+ * attached, e.g. by trying to read something from the ads7846.
+ * But this arch_init() code is too early for that, since we
+ * can't talk to the ads or even the i2c eeprom.
+ */
+
+ /* parallel camera interface */
+ omap_cfg_reg(J15_1610_CAM_LCLK);
+ omap_cfg_reg(J18_1610_CAM_D7);
+ omap_cfg_reg(J19_1610_CAM_D6);
+ omap_cfg_reg(J14_1610_CAM_D5);
+ omap_cfg_reg(K18_1610_CAM_D4);
+ omap_cfg_reg(K19_1610_CAM_D3);
+ omap_cfg_reg(K15_1610_CAM_D2);
+ omap_cfg_reg(K14_1610_CAM_D1);
+ omap_cfg_reg(L19_1610_CAM_D0);
+ omap_cfg_reg(L18_1610_CAM_VS);
+ omap_cfg_reg(L15_1610_CAM_HS);
+ omap_cfg_reg(M19_1610_CAM_RSTZ);
+ omap_cfg_reg(Y15_1610_CAM_OUTCLK);
+
+ /* serial camera interface */
+ omap_cfg_reg(H19_1610_CAM_EXCLK);
+ omap_cfg_reg(W13_1610_CCP_CLKM);
+ omap_cfg_reg(Y12_1610_CCP_CLKP);
+ /* CCP_DATAM CONFLICTS WITH UART1.TX (and serial console) */
+ /* omap_cfg_reg(Y14_1610_CCP_DATAM); */
+ omap_cfg_reg(W14_1610_CCP_DATAP);
+
+ /* CAM_PWDN */
+ if (gpio_request(11, "cam_pwdn") == 0) {
+ omap_cfg_reg(N20_1610_GPIO11);
+ gpio_direction_output(11, 0);
+ } else
+ pr_debug("OSK+Mistral: CAM_PWDN is awol\n");
+
+
+ /* omap_cfg_reg(P19_1610_GPIO6); */ /* BUSY */
+ gpio_request(6, "ts_busy");
+ gpio_direction_input(6);
+
+ omap_cfg_reg(P20_1610_GPIO4); /* PENIRQ */
+ gpio_request(4, "ts_int");
+ gpio_direction_input(4);
+ irq_set_irq_type(gpio_to_irq(4), IRQ_TYPE_EDGE_FALLING);
+
+ spi_register_board_info(mistral_boardinfo,
+ ARRAY_SIZE(mistral_boardinfo));
+
+ /* the sideways button (SW1) is for use as a "wakeup" button
+ *
+ * NOTE: The Mistral board has the wakeup button (SW1) wired
+ * to the LCD 3.3V rail, which is powered down during suspend.
+ * To allow this button to wake up the omap, work around this
+ * HW bug by rewiring SW1 to use the main 3.3V rail.
+ */
+ omap_cfg_reg(N15_1610_MPUIO2);
+ if (gpio_request(OMAP_MPUIO(2), "wakeup") == 0) {
+ int ret = 0;
+ int irq = gpio_to_irq(OMAP_MPUIO(2));
+
+ gpio_direction_input(OMAP_MPUIO(2));
+ irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+#ifdef CONFIG_PM
+ /* share the IRQ in case someone wants to use the
+ * button for more than wakeup from system sleep.
+ */
+ ret = request_irq(irq,
+ &osk_mistral_wake_interrupt,
+ IRQF_SHARED, "mistral_wakeup",
+ &osk_mistral_wake_interrupt);
+ if (ret != 0) {
+ gpio_free(OMAP_MPUIO(2));
+ printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n",
+ ret);
+ } else
+ enable_irq_wake(irq);
+#endif
+ } else
+ printk(KERN_ERR "OSK+Mistral: wakeup button is awol\n");
+
+ /* LCD: backlight, and power; power controls other devices on the
+ * board, like the touchscreen, EEPROM, and wakeup (!) switch.
+ */
+ omap_cfg_reg(PWL);
+ if (gpio_request(2, "lcd_pwr") == 0)
+ gpio_direction_output(2, 1);
+
+ i2c_register_board_info(1, mistral_i2c_board_info,
+ ARRAY_SIZE(mistral_i2c_board_info));
+
+ platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices));
+}
+#else
+static void __init osk_mistral_init(void) { }
+#endif
+
+#define EMIFS_CS3_VAL (0x88013141)
+
+static void __init osk_init(void)
+{
+ u32 l;
+
+ osk_init_smc91x();
+ osk_init_cf();
+
+ /* 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 similar errors if you use NOR flash (e.g. with JFFS2)
+ */
+ l = omap_readl(EMIFS_CCS(3));
+ if (l != EMIFS_CS3_VAL)
+ omap_writel(EMIFS_CS3_VAL, EMIFS_CCS(3));
+
+ 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));
+ omap_board_config = osk_config;
+ omap_board_config_size = ARRAY_SIZE(osk_config);
+
+ l = omap_readl(USB_TRANSCEIVER_CTRL);
+ l |= (3 << 1);
+ omap_writel(l, USB_TRANSCEIVER_CTRL);
+
+ omap1_usb_init(&osk_usb_config);
+
+ /* irq for tps65010 chip */
+ /* bootloader effectively does: omap_cfg_reg(U19_1610_MPUIO1); */
+ if (gpio_request(OMAP_MPUIO(1), "tps65010") == 0)
+ gpio_direction_input(OMAP_MPUIO(1));
+
+ omap_serial_init();
+ omap_register_i2c_bus(1, 400, osk_i2c_board_info,
+ ARRAY_SIZE(osk_i2c_board_info));
+ osk_mistral_init();
+}
+
+static void __init osk_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(OMAP_OSK, "TI-OSK")
+ /* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
+ .boot_params = 0x10000100,
+ .map_io = osk_map_io,
+ .reserve = omap_reserve,
+ .init_irq = osk_init_irq,
+ .init_machine = osk_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
new file mode 100644
index 00000000..c9d38f47
--- /dev/null
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -0,0 +1,284 @@
+/*
+ * linux/arch/arm/mach-omap1/board-palmte.c
+ *
+ * Modified from board-generic.c
+ *
+ * Support for the Palm Tungsten E PDA.
+ *
+ * Original version : Laurent Gonzalez
+ *
+ * Maintainers : http://palmtelinux.sf.net
+ * palmtelinux-developpers@lists.sf.net
+ *
+ * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * 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/input.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/apm-emulation.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/gpio.h>
+#include <plat/flash.h>
+#include <plat/mux.h>
+#include <plat/usb.h>
+#include <plat/tc.h>
+#include <plat/dma.h>
+#include <plat/board.h>
+#include <plat/irda.h>
+#include <plat/keypad.h>
+#include <plat/common.h>
+
+#define PALMTE_USBDETECT_GPIO 0
+#define PALMTE_USB_OR_DC_GPIO 1
+#define PALMTE_TSC_GPIO 4
+#define PALMTE_PINTDAV_GPIO 6
+#define PALMTE_MMC_WP_GPIO 8
+#define PALMTE_MMC_POWER_GPIO 9
+#define PALMTE_HDQ_GPIO 11
+#define PALMTE_HEADPHONES_GPIO 14
+#define PALMTE_SPEAKER_GPIO 15
+#define PALMTE_DC_GPIO OMAP_MPUIO(2)
+#define PALMTE_MMC_SWITCH_GPIO OMAP_MPUIO(4)
+#define PALMTE_MMC1_GPIO OMAP_MPUIO(6)
+#define PALMTE_MMC2_GPIO OMAP_MPUIO(7)
+#define PALMTE_MMC3_GPIO OMAP_MPUIO(11)
+
+static void __init omap_palmte_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static const unsigned int palmte_keymap[] = {
+ KEY(0, 0, KEY_F1), /* Calendar */
+ KEY(1, 0, KEY_F2), /* Contacts */
+ KEY(2, 0, KEY_F3), /* Tasks List */
+ KEY(3, 0, KEY_F4), /* Note Pad */
+ KEY(4, 0, KEY_POWER),
+ KEY(0, 1, KEY_LEFT),
+ KEY(1, 1, KEY_DOWN),
+ KEY(2, 1, KEY_UP),
+ KEY(3, 1, KEY_RIGHT),
+ KEY(4, 1, KEY_ENTER),
+};
+
+static const struct matrix_keymap_data palmte_keymap_data = {
+ .keymap = palmte_keymap,
+ .keymap_size = ARRAY_SIZE(palmte_keymap),
+};
+
+static struct omap_kp_platform_data palmte_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &palmte_keymap_data,
+ .rep = true,
+ .delay = 12,
+};
+
+static struct resource palmte_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmte_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(palmte_kp_resources),
+ .resource = palmte_kp_resources,
+};
+
+static struct mtd_partition palmte_rom_partitions[] = {
+ /* PalmOS "Small ROM", contains the bootloader and the debugger */
+ {
+ .name = "smallrom",
+ .offset = 0,
+ .size = 0xa000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ /* PalmOS "Big ROM", a filesystem with all the OS code and data */
+ {
+ .name = "bigrom",
+ .offset = SZ_128K,
+ /*
+ * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
+ * 0x7b0000 bytes in the English-only ("enUS") version.
+ */
+ .size = 0x7b0000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+};
+
+static struct physmap_flash_data palmte_rom_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = palmte_rom_partitions,
+ .nr_parts = ARRAY_SIZE(palmte_rom_partitions),
+};
+
+static struct resource palmte_rom_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device palmte_rom_device = {
+ .name = "physmap-flash",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte_rom_data,
+ },
+ .num_resources = 1,
+ .resource = &palmte_rom_resource,
+};
+
+static struct platform_device palmte_lcd_device = {
+ .name = "lcd_palmte",
+ .id = -1,
+};
+
+static struct omap_backlight_config palmte_backlight_config = {
+ .default_intensity = 0xa0,
+};
+
+static struct platform_device palmte_backlight_device = {
+ .name = "omap-bl",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte_backlight_config,
+ },
+};
+
+static struct omap_irda_config palmte_irda_config = {
+ .transceiver_cap = IR_SIRMODE,
+ .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 palmte_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmte_irda_device = {
+ .name = "omapirda",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmte_irda_config,
+ },
+ .num_resources = ARRAY_SIZE(palmte_irda_resources),
+ .resource = palmte_irda_resources,
+};
+
+static struct platform_device *palmte_devices[] __initdata = {
+ &palmte_rom_device,
+ &palmte_kp_device,
+ &palmte_lcd_device,
+ &palmte_backlight_device,
+ &palmte_irda_device,
+};
+
+static struct omap_usb_config palmte_usb_config __initdata = {
+ .register_dev = 1, /* Mini-B only receptacle */
+ .hmc_mode = 0,
+ .pins[0] = 2,
+};
+
+static struct omap_lcd_config palmte_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel palmte_config[] __initdata = {
+ { OMAP_TAG_LCD, &palmte_lcd_config },
+};
+
+static struct spi_board_info palmte_spi_info[] __initdata = {
+ {
+ .modalias = "tsc2102",
+ .bus_num = 2, /* uWire (officially) */
+ .chip_select = 0, /* As opposed to 3 */
+ .irq = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
+ .max_speed_hz = 8000000,
+ },
+};
+
+static void __init palmte_misc_gpio_setup(void)
+{
+ /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
+ if (gpio_request(PALMTE_PINTDAV_GPIO, "TSC2102 PINTDAV") < 0) {
+ printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
+ return;
+ }
+ gpio_direction_input(PALMTE_PINTDAV_GPIO);
+
+ /* Set USB-or-DC-IN pin as input (unused) */
+ if (gpio_request(PALMTE_USB_OR_DC_GPIO, "USB/DC-IN") < 0) {
+ printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
+ return;
+ }
+ gpio_direction_input(PALMTE_USB_OR_DC_GPIO);
+}
+
+static void __init omap_palmte_init(void)
+{
+ /* mux pins for uarts */
+ omap_cfg_reg(UART1_TX);
+ omap_cfg_reg(UART1_RTS);
+ omap_cfg_reg(UART2_TX);
+ omap_cfg_reg(UART2_RTS);
+ omap_cfg_reg(UART3_TX);
+ omap_cfg_reg(UART3_RX);
+
+ omap_board_config = palmte_config;
+ omap_board_config_size = ARRAY_SIZE(palmte_config);
+
+ platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
+
+ spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
+ palmte_misc_gpio_setup();
+ omap_serial_init();
+ omap1_usb_init(&palmte_usb_config);
+ omap_register_i2c_bus(1, 100, NULL, 0);
+}
+
+static void __init omap_palmte_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
+ .boot_params = 0x10000100,
+ .map_io = omap_palmte_map_io,
+ .reserve = omap_reserve,
+ .init_irq = omap_palmte_init_irq,
+ .init_machine = omap_palmte_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
new file mode 100644
index 00000000..f04f2d36
--- /dev/null
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -0,0 +1,330 @@
+/*
+ * linux/arch/arm/mach-omap1/board-palmtt.c
+ *
+ * Modified from board-palmtt2.c
+ *
+ * Modified and amended for Palm Tungsten|T
+ * by Marek Vasut <marek.vasut@gmail.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/delay.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/notifier.h>
+#include <linux/clk.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/leds.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/led.h>
+#include <mach/gpio.h>
+#include <plat/flash.h>
+#include <plat/mux.h>
+#include <plat/usb.h>
+#include <plat/dma.h>
+#include <plat/tc.h>
+#include <plat/board.h>
+#include <plat/irda.h>
+#include <plat/keypad.h>
+#include <plat/common.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#define PALMTT_USBDETECT_GPIO 0
+#define PALMTT_CABLE_GPIO 1
+#define PALMTT_LED_GPIO 3
+#define PALMTT_PENIRQ_GPIO 6
+#define PALMTT_MMC_WP_GPIO 8
+#define PALMTT_HDQ_GPIO 11
+
+static const unsigned int palmtt_keymap[] = {
+ KEY(0, 0, KEY_ESC),
+ KEY(1, 0, KEY_SPACE),
+ KEY(2, 0, KEY_LEFTCTRL),
+ KEY(3, 0, KEY_TAB),
+ KEY(4, 0, KEY_ENTER),
+ KEY(0, 1, KEY_LEFT),
+ KEY(1, 1, KEY_DOWN),
+ KEY(2, 1, KEY_UP),
+ KEY(3, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_SLEEP),
+ KEY(4, 2, KEY_Y),
+};
+
+static struct mtd_partition palmtt_partitions[] = {
+ {
+ .name = "write8k",
+ .offset = 0,
+ .size = SZ_8K,
+ .mask_flags = 0,
+ },
+ {
+ .name = "PalmOS-BootLoader(ro)",
+ .offset = SZ_8K,
+ .size = 7 * SZ_8K,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "u-boot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 8 * SZ_8K,
+ .mask_flags = 0,
+ },
+ {
+ .name = "PalmOS-FS(ro)",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 7 * SZ_1M + 4 * SZ_64K - 16 * SZ_8K,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "u-boot(rez)",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0
+ },
+ {
+ .name = "empty",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct physmap_flash_data palmtt_flash_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = palmtt_partitions,
+ .nr_parts = ARRAY_SIZE(palmtt_partitions),
+};
+
+static struct resource palmtt_flash_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device palmtt_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &palmtt_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &palmtt_flash_resource,
+};
+
+static struct resource palmtt_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct matrix_keymap_data palmtt_keymap_data = {
+ .keymap = palmtt_keymap,
+ .keymap_size = ARRAY_SIZE(palmtt_keymap),
+};
+
+static struct omap_kp_platform_data palmtt_kp_data = {
+ .rows = 6,
+ .cols = 3,
+ .keymap_data = &palmtt_keymap_data,
+};
+
+static struct platform_device palmtt_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmtt_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(palmtt_kp_resources),
+ .resource = palmtt_kp_resources,
+};
+
+static struct platform_device palmtt_lcd_device = {
+ .name = "lcd_palmtt",
+ .id = -1,
+};
+static struct omap_irda_config palmtt_irda_config = {
+ .transceiver_cap = IR_SIRMODE,
+ .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 palmtt_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmtt_irda_device = {
+ .name = "omapirda",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmtt_irda_config,
+ },
+ .num_resources = ARRAY_SIZE(palmtt_irda_resources),
+ .resource = palmtt_irda_resources,
+};
+
+static struct platform_device palmtt_spi_device = {
+ .name = "spi_palmtt",
+ .id = -1,
+};
+
+static struct omap_backlight_config palmtt_backlight_config = {
+ .default_intensity = 0xa0,
+};
+
+static struct platform_device palmtt_backlight_device = {
+ .name = "omap-bl",
+ .id = -1,
+ .dev = {
+ .platform_data= &palmtt_backlight_config,
+ },
+};
+
+static struct omap_led_config palmtt_led_config[] = {
+ {
+ .cdev = {
+ .name = "palmtt:led0",
+ },
+ .gpio = PALMTT_LED_GPIO,
+ },
+};
+
+static struct omap_led_platform_data palmtt_led_data = {
+ .nr_leds = ARRAY_SIZE(palmtt_led_config),
+ .leds = palmtt_led_config,
+};
+
+static struct platform_device palmtt_led_device = {
+ .name = "omap-led",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmtt_led_data,
+ },
+};
+
+static struct platform_device *palmtt_devices[] __initdata = {
+ &palmtt_flash_device,
+ &palmtt_kp_device,
+ &palmtt_lcd_device,
+ &palmtt_irda_device,
+ &palmtt_spi_device,
+ &palmtt_backlight_device,
+ &palmtt_led_device,
+};
+
+static int palmtt_get_pendown_state(void)
+{
+ return !gpio_get_value(6);
+}
+
+static const struct ads7846_platform_data palmtt_ts_info = {
+ .model = 7846,
+ .vref_delay_usecs = 100, /* internal, no capacitor */
+ .x_plate_ohms = 419,
+ .y_plate_ohms = 486,
+ .get_pendown_state = palmtt_get_pendown_state,
+};
+
+static struct spi_board_info __initdata palmtt_boardinfo[] = {
+ {
+ /* MicroWire (bus 2) CS0 has an ads7846e */
+ .modalias = "ads7846",
+ .platform_data = &palmtt_ts_info,
+ .irq = OMAP_GPIO_IRQ(6),
+ .max_speed_hz = 120000 /* max sample rate at 3V */
+ * 26 /* command + data + overhead */,
+ .bus_num = 2,
+ .chip_select = 0,
+ }
+};
+
+static void __init omap_palmtt_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static struct omap_usb_config palmtt_usb_config __initdata = {
+ .register_dev = 1,
+ .hmc_mode = 0,
+ .pins[0] = 2,
+};
+
+static struct omap_lcd_config palmtt_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel palmtt_config[] __initdata = {
+ { OMAP_TAG_LCD, &palmtt_lcd_config },
+};
+
+static void __init omap_mpu_wdt_mode(int mode) {
+ if (mode)
+ omap_writew(0x8000, OMAP_WDT_TIMER_MODE);
+ else {
+ omap_writew(0x00f5, OMAP_WDT_TIMER_MODE);
+ omap_writew(0x00a0, OMAP_WDT_TIMER_MODE);
+ }
+}
+
+static void __init omap_palmtt_init(void)
+{
+ /* mux pins for uarts */
+ omap_cfg_reg(UART1_TX);
+ omap_cfg_reg(UART1_RTS);
+ omap_cfg_reg(UART2_TX);
+ omap_cfg_reg(UART2_RTS);
+ omap_cfg_reg(UART3_TX);
+ omap_cfg_reg(UART3_RX);
+
+ omap_mpu_wdt_mode(0);
+
+ omap_board_config = palmtt_config;
+ omap_board_config_size = ARRAY_SIZE(palmtt_config);
+
+ platform_add_devices(palmtt_devices, ARRAY_SIZE(palmtt_devices));
+
+ spi_register_board_info(palmtt_boardinfo,ARRAY_SIZE(palmtt_boardinfo));
+ omap_serial_init();
+ omap1_usb_init(&palmtt_usb_config);
+ omap_register_i2c_bus(1, 100, NULL, 0);
+}
+
+static void __init omap_palmtt_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(OMAP_PALMTT, "OMAP1510 based Palm Tungsten|T")
+ .boot_params = 0x10000100,
+ .map_io = omap_palmtt_map_io,
+ .reserve = omap_reserve,
+ .init_irq = omap_palmtt_init_irq,
+ .init_machine = omap_palmtt_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
new file mode 100644
index 00000000..45f01d2c
--- /dev/null
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -0,0 +1,350 @@
+/*
+ * linux/arch/arm/mach-omap1/board-palmz71.c
+ *
+ * Modified from board-generic.c
+ *
+ * Support for the Palm Zire71 PDA.
+ *
+ * Original version : Laurent Gonzalez
+ *
+ * Modified for zire71 : Marek Vasut
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/notifier.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/gpio.h>
+#include <plat/flash.h>
+#include <plat/mux.h>
+#include <plat/usb.h>
+#include <plat/dma.h>
+#include <plat/tc.h>
+#include <plat/board.h>
+#include <plat/irda.h>
+#include <plat/keypad.h>
+#include <plat/common.h>
+#include <plat/omap-alsa.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#define PALMZ71_USBDETECT_GPIO 0
+#define PALMZ71_PENIRQ_GPIO 6
+#define PALMZ71_MMC_WP_GPIO 8
+#define PALMZ71_HDQ_GPIO 11
+
+#define PALMZ71_HOTSYNC_GPIO OMAP_MPUIO(1)
+#define PALMZ71_CABLE_GPIO OMAP_MPUIO(2)
+#define PALMZ71_SLIDER_GPIO OMAP_MPUIO(3)
+#define PALMZ71_MMC_IN_GPIO OMAP_MPUIO(4)
+
+static void __init
+omap_palmz71_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static const unsigned int palmz71_keymap[] = {
+ KEY(0, 0, KEY_F1),
+ KEY(1, 0, KEY_F2),
+ KEY(2, 0, KEY_F3),
+ KEY(3, 0, KEY_F4),
+ KEY(4, 0, KEY_POWER),
+ KEY(0, 1, KEY_LEFT),
+ KEY(1, 1, KEY_DOWN),
+ KEY(2, 1, KEY_UP),
+ KEY(3, 1, KEY_RIGHT),
+ KEY(4, 1, KEY_ENTER),
+ KEY(0, 2, KEY_CAMERA),
+};
+
+static const struct matrix_keymap_data palmz71_keymap_data = {
+ .keymap = palmz71_keymap,
+ .keymap_size = ARRAY_SIZE(palmz71_keymap),
+};
+
+static struct omap_kp_platform_data palmz71_kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &palmz71_keymap_data,
+ .rep = true,
+ .delay = 80,
+};
+
+static struct resource palmz71_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmz71_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmz71_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(palmz71_kp_resources),
+ .resource = palmz71_kp_resources,
+};
+
+static struct mtd_partition palmz71_rom_partitions[] = {
+ /* PalmOS "Small ROM", contains the bootloader and the debugger */
+ {
+ .name = "smallrom",
+ .offset = 0,
+ .size = 0xa000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+ /* PalmOS "Big ROM", a filesystem with all the OS code and data */
+ {
+ .name = "bigrom",
+ .offset = SZ_128K,
+ /*
+ * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
+ * 0x7b0000 bytes in the English-only ("enUS") version.
+ */
+ .size = 0x7b0000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+};
+
+static struct physmap_flash_data palmz71_rom_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = palmz71_rom_partitions,
+ .nr_parts = ARRAY_SIZE(palmz71_rom_partitions),
+};
+
+static struct resource palmz71_rom_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device palmz71_rom_device = {
+ .name = "physmap-flash",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmz71_rom_data,
+ },
+ .num_resources = 1,
+ .resource = &palmz71_rom_resource,
+};
+
+static struct platform_device palmz71_lcd_device = {
+ .name = "lcd_palmz71",
+ .id = -1,
+};
+
+static struct omap_irda_config palmz71_irda_config = {
+ .transceiver_cap = IR_SIRMODE,
+ .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 palmz71_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device palmz71_irda_device = {
+ .name = "omapirda",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmz71_irda_config,
+ },
+ .num_resources = ARRAY_SIZE(palmz71_irda_resources),
+ .resource = palmz71_irda_resources,
+};
+
+static struct platform_device palmz71_spi_device = {
+ .name = "spi_palmz71",
+ .id = -1,
+};
+
+static struct omap_backlight_config palmz71_backlight_config = {
+ .default_intensity = 0xa0,
+};
+
+static struct platform_device palmz71_backlight_device = {
+ .name = "omap-bl",
+ .id = -1,
+ .dev = {
+ .platform_data = &palmz71_backlight_config,
+ },
+};
+
+static struct platform_device *devices[] __initdata = {
+ &palmz71_rom_device,
+ &palmz71_kp_device,
+ &palmz71_lcd_device,
+ &palmz71_irda_device,
+ &palmz71_spi_device,
+ &palmz71_backlight_device,
+};
+
+static int
+palmz71_get_pendown_state(void)
+{
+ return !gpio_get_value(PALMZ71_PENIRQ_GPIO);
+}
+
+static const struct ads7846_platform_data palmz71_ts_info = {
+ .model = 7846,
+ .vref_delay_usecs = 100, /* internal, no capacitor */
+ .x_plate_ohms = 419,
+ .y_plate_ohms = 486,
+ .get_pendown_state = palmz71_get_pendown_state,
+};
+
+static struct spi_board_info __initdata palmz71_boardinfo[] = { {
+ /* MicroWire (bus 2) CS0 has an ads7846e */
+ .modalias = "ads7846",
+ .platform_data = &palmz71_ts_info,
+ .irq = OMAP_GPIO_IRQ(PALMZ71_PENIRQ_GPIO),
+ .max_speed_hz = 120000 /* max sample rate at 3V */
+ * 26 /* command + data + overhead */,
+ .bus_num = 2,
+ .chip_select = 0,
+} };
+
+static struct omap_usb_config palmz71_usb_config __initdata = {
+ .register_dev = 1, /* Mini-B only receptacle */
+ .hmc_mode = 0,
+ .pins[0] = 2,
+};
+
+static struct omap_lcd_config palmz71_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel palmz71_config[] __initdata = {
+ {OMAP_TAG_LCD, &palmz71_lcd_config},
+};
+
+static irqreturn_t
+palmz71_powercable(int irq, void *dev_id)
+{
+ if (gpio_get_value(PALMZ71_USBDETECT_GPIO)) {
+ printk(KERN_INFO "PM: Power cable connected\n");
+ irq_set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
+ IRQ_TYPE_EDGE_FALLING);
+ } else {
+ printk(KERN_INFO "PM: Power cable disconnected\n");
+ irq_set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
+ IRQ_TYPE_EDGE_RISING);
+ }
+ return IRQ_HANDLED;
+}
+
+static void __init
+omap_mpu_wdt_mode(int mode)
+{
+ if (mode)
+ omap_writew(0x8000, OMAP_WDT_TIMER_MODE);
+ else {
+ omap_writew(0x00f5, OMAP_WDT_TIMER_MODE);
+ omap_writew(0x00a0, OMAP_WDT_TIMER_MODE);
+ }
+}
+
+static void __init
+palmz71_gpio_setup(int early)
+{
+ if (early) {
+ /* Only set GPIO1 so we have a working serial */
+ gpio_direction_output(1, 1);
+ } else {
+ /* Set MMC/SD host WP pin as input */
+ if (gpio_request(PALMZ71_MMC_WP_GPIO, "MMC WP") < 0) {
+ printk(KERN_ERR "Could not reserve WP GPIO!\n");
+ return;
+ }
+ gpio_direction_input(PALMZ71_MMC_WP_GPIO);
+
+ /* Monitor the Power-cable-connected signal */
+ if (gpio_request(PALMZ71_USBDETECT_GPIO, "USB detect") < 0) {
+ printk(KERN_ERR
+ "Could not reserve cable signal GPIO!\n");
+ return;
+ }
+ gpio_direction_input(PALMZ71_USBDETECT_GPIO);
+ if (request_irq(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
+ palmz71_powercable, IRQF_SAMPLE_RANDOM,
+ "palmz71-cable", 0))
+ printk(KERN_ERR
+ "IRQ request for power cable failed!\n");
+ palmz71_powercable(gpio_to_irq(PALMZ71_USBDETECT_GPIO), 0);
+ }
+}
+
+static void __init
+omap_palmz71_init(void)
+{
+ /* mux pins for uarts */
+ omap_cfg_reg(UART1_TX);
+ omap_cfg_reg(UART1_RTS);
+ omap_cfg_reg(UART2_TX);
+ omap_cfg_reg(UART2_RTS);
+ omap_cfg_reg(UART3_TX);
+ omap_cfg_reg(UART3_RX);
+
+ palmz71_gpio_setup(1);
+ omap_mpu_wdt_mode(0);
+
+ omap_board_config = palmz71_config;
+ omap_board_config_size = ARRAY_SIZE(palmz71_config);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ spi_register_board_info(palmz71_boardinfo,
+ ARRAY_SIZE(palmz71_boardinfo));
+ omap1_usb_init(&palmz71_usb_config);
+ omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
+ palmz71_gpio_setup(0);
+}
+
+static void __init
+omap_palmz71_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(OMAP_PALMZ71, "OMAP310 based Palm Zire71")
+ .boot_params = 0x10000100,
+ .map_io = omap_palmz71_map_io,
+ .reserve = omap_reserve,
+ .init_irq = omap_palmz71_init_irq,
+ .init_machine = omap_palmz71_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
new file mode 100644
index 00000000..3c8ee848
--- /dev/null
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -0,0 +1,359 @@
+/*
+ * linux/arch/arm/mach-omap1/board-perseus2.c
+ *
+ * Modified from board-generic.c
+ *
+ * Original OMAP730 support by Jean Pihet <j-pihet@ti.com>
+ * Updated for 2.6 by Kevin Hilman <kjh@hilman.org>
+ *
+ * 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/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/smc91x.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/tc.h>
+#include <mach/gpio.h>
+#include <plat/mux.h>
+#include <plat/fpga.h>
+#include <plat/flash.h>
+#include <plat/keypad.h>
+#include <plat/common.h>
+#include <plat/board.h>
+
+static const unsigned int p2_keymap[] = {
+ KEY(0, 0, KEY_UP),
+ KEY(1, 0, KEY_RIGHT),
+ KEY(2, 0, KEY_LEFT),
+ KEY(3, 0, KEY_DOWN),
+ KEY(4, 0, KEY_ENTER),
+ KEY(0, 1, KEY_F10),
+ KEY(1, 1, KEY_SEND),
+ KEY(2, 1, KEY_END),
+ KEY(3, 1, KEY_VOLUMEDOWN),
+ KEY(4, 1, KEY_VOLUMEUP),
+ KEY(5, 1, KEY_RECORD),
+ KEY(0, 2, KEY_F9),
+ KEY(1, 2, KEY_3),
+ KEY(2, 2, KEY_6),
+ KEY(3, 2, KEY_9),
+ KEY(4, 2, KEY_KPDOT),
+ KEY(0, 3, KEY_BACK),
+ KEY(1, 3, KEY_2),
+ KEY(2, 3, KEY_5),
+ KEY(3, 3, KEY_8),
+ KEY(4, 3, KEY_0),
+ KEY(5, 3, KEY_KPSLASH),
+ KEY(0, 4, KEY_HOME),
+ KEY(1, 4, KEY_1),
+ KEY(2, 4, KEY_4),
+ KEY(3, 4, KEY_7),
+ KEY(4, 4, KEY_KPASTERISK),
+ KEY(5, 4, KEY_POWER),
+};
+
+static struct smc91x_platdata smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+ .leda = RPC_LED_100_10,
+ .ledb = RPC_LED_TX_RX,
+};
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */
+ .end = H2P2_DBG_FPGA_ETHR_START + 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_7XX_MPU_EXT_NIRQ,
+ .end = 0,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ },
+};
+
+static struct mtd_partition nor_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* rest of flash is a file system */
+ {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ },
+};
+
+static struct physmap_flash_data nor_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = nor_partitions,
+ .nr_parts = ARRAY_SIZE(nor_partitions),
+};
+
+static struct resource nor_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nor_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &nor_data,
+ },
+ .num_resources = 1,
+ .resource = &nor_resource,
+};
+
+static void nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ unsigned long mask;
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ mask = (ctrl & NAND_CLE) ? 0x02 : 0;
+ if (ctrl & NAND_ALE)
+ mask |= 0x04;
+ writeb(cmd, (unsigned long)this->IO_ADDR_W | mask);
+}
+
+#define P2_NAND_RB_GPIO_PIN 62
+
+static int nand_dev_ready(struct mtd_info *mtd)
+{
+ return gpio_get_value(P2_NAND_RB_GPIO_PIN);
+}
+
+static const char *part_probes[] = { "cmdlinepart", NULL };
+
+static struct platform_nand_data nand_data = {
+ .chip = {
+ .nr_chips = 1,
+ .chip_offset = 0,
+ .options = NAND_SAMSUNG_LP_OPTIONS,
+ .part_probe_types = part_probes,
+ },
+ .ctrl = {
+ .cmd_ctrl = nand_cmd_ctl,
+ .dev_ready = nand_dev_ready,
+ },
+};
+
+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 = "gen_nand",
+ .id = 0,
+ .dev = {
+ .platform_data = &nand_data,
+ },
+ .num_resources = 1,
+ .resource = &nand_resource,
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .dev = {
+ .platform_data = &smc91x_info,
+ },
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static struct resource kp_resources[] = {
+ [0] = {
+ .start = INT_7XX_MPUIO_KEYPAD,
+ .end = INT_7XX_MPUIO_KEYPAD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct matrix_keymap_data p2_keymap_data = {
+ .keymap = p2_keymap,
+ .keymap_size = ARRAY_SIZE(p2_keymap),
+};
+
+static struct omap_kp_platform_data kp_data = {
+ .rows = 8,
+ .cols = 8,
+ .keymap_data = &p2_keymap_data,
+ .delay = 4,
+ .dbounce = true,
+};
+
+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 = {
+ &nor_device,
+ &nand_device,
+ &smc91x_device,
+ &kp_device,
+ &lcd_device,
+};
+
+static struct omap_lcd_config perseus2_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+static struct omap_board_config_kernel perseus2_config[] __initdata = {
+ { OMAP_TAG_LCD, &perseus2_lcd_config },
+};
+
+static void __init perseus2_init_smc91x(void)
+{
+ fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
+ mdelay(50);
+ fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
+ H2P2_DBG_FPGA_LAN_RESET);
+ mdelay(50);
+}
+
+static void __init omap_perseus2_init(void)
+{
+ perseus2_init_smc91x();
+
+ if (gpio_request(P2_NAND_RB_GPIO_PIN, "NAND ready") < 0)
+ BUG();
+ gpio_direction_input(P2_NAND_RB_GPIO_PIN);
+
+ omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
+ omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
+
+ /* Mux pins for keypad */
+ omap_cfg_reg(E2_7XX_KBR0);
+ omap_cfg_reg(J7_7XX_KBR1);
+ omap_cfg_reg(E1_7XX_KBR2);
+ omap_cfg_reg(F3_7XX_KBR3);
+ omap_cfg_reg(D2_7XX_KBR4);
+ omap_cfg_reg(C2_7XX_KBC0);
+ omap_cfg_reg(D3_7XX_KBC1);
+ omap_cfg_reg(E4_7XX_KBC2);
+ omap_cfg_reg(F4_7XX_KBC3);
+ omap_cfg_reg(E3_7XX_KBC4);
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+ omap_board_config = perseus2_config;
+ omap_board_config_size = ARRAY_SIZE(perseus2_config);
+ omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
+}
+
+static void __init omap_perseus2_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+/* Only FPGA needs to be mapped here. All others are done with ioremap */
+static struct map_desc omap_perseus2_io_desc[] __initdata = {
+ {
+ .virtual = H2P2_DBG_FPGA_BASE,
+ .pfn = __phys_to_pfn(H2P2_DBG_FPGA_START),
+ .length = H2P2_DBG_FPGA_SIZE,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init omap_perseus2_map_io(void)
+{
+ omap1_map_common_io();
+ iotable_init(omap_perseus2_io_desc,
+ ARRAY_SIZE(omap_perseus2_io_desc));
+
+ /* Early, board-dependent init */
+
+ /*
+ * Hold GSM Reset until needed
+ */
+ omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);
+
+ /*
+ * UARTs -> done automagically by 8250 driver
+ */
+
+ /*
+ * CSx timings, GPIO Mux ... setup
+ */
+
+ /* Flash: CS0 timings setup */
+ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
+ omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);
+
+ /*
+ * Ethernet support through the debug board
+ * CS1 timings setup
+ */
+ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
+ omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);
+
+ /*
+ * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
+ * It is used as the Ethernet controller interrupt
+ */
+ omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9);
+}
+
+MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
+ /* Maintainer: Kevin Hilman <kjh@hilman.org> */
+ .boot_params = 0x10000100,
+ .map_io = omap_perseus2_map_io,
+ .reserve = omap_reserve,
+ .init_irq = omap_perseus2_init_irq,
+ .init_machine = omap_perseus2_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c
new file mode 100644
index 00000000..e8ddd86e
--- /dev/null
+++ b/arch/arm/mach-omap1/board-sx1-mmc.c
@@ -0,0 +1,66 @@
+/*
+ * linux/arch/arm/mach-omap1/board-sx1-mmc.c
+ *
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ * Author: Carlos Eduardo Aguiar <carlos.aguiar@indt.org.br>
+ *
+ * This code is based on linux/arch/arm/mach-omap1/board-h2-mmc.c, which is:
+ * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
+ *
+ * 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/platform_device.h>
+
+#include <mach/hardware.h>
+#include <plat/mmc.h>
+#include <mach/gpio.h>
+#include <plat/board-sx1.h>
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+static int mmc_set_power(struct device *dev, int slot, int power_on,
+ int vdd)
+{
+ int err;
+ u8 dat = 0;
+
+ err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
+ if (err < 0)
+ return err;
+
+ if (power_on)
+ dat |= SOFIA_MMC_POWER;
+ else
+ dat &= ~SOFIA_MMC_POWER;
+
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
+}
+
+/* Cover switch is at OMAP_MPUIO(3) */
+static struct omap_mmc_platform_data mmc1_data = {
+ .nr_slots = 1,
+ .slots[0] = {
+ .set_power = mmc_set_power,
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+ .name = "mmcblk",
+ },
+};
+
+static struct omap_mmc_platform_data *mmc_data[OMAP15XX_NR_MMC];
+
+void __init sx1_mmc_init(void)
+{
+ mmc_data[0] = &mmc1_data;
+ omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC);
+}
+
+#else
+
+void __init sx1_mmc_init(void)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
new file mode 100644
index 00000000..0ad781db
--- /dev/null
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -0,0 +1,430 @@
+/*
+* linux/arch/arm/mach-omap1/board-sx1.c
+*
+* Modified from board-generic.c
+*
+* Support for the Siemens SX1 mobile phone.
+*
+* Original version : Vladimir Ananiev (Vovan888-at-gmail com)
+*
+* Maintainters : Vladimir Ananiev (aka Vovan888), Sergge
+* oslik.ru
+*
+* 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/input.h>
+#include <linux/platform_device.h>
+#include <linux/notifier.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/gpio.h>
+#include <plat/flash.h>
+#include <plat/mux.h>
+#include <plat/dma.h>
+#include <plat/irda.h>
+#include <plat/usb.h>
+#include <plat/tc.h>
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/keypad.h>
+#include <plat/board-sx1.h>
+
+/* Write to I2C device */
+int sx1_i2c_write_byte(u8 devaddr, u8 regoffset, u8 value)
+{
+ struct i2c_adapter *adap;
+ int err;
+ struct i2c_msg msg[1];
+ unsigned char data[2];
+
+ adap = i2c_get_adapter(0);
+ if (!adap)
+ return -ENODEV;
+ msg->addr = devaddr; /* I2C address of chip */
+ msg->flags = 0;
+ msg->len = 2;
+ msg->buf = data;
+ data[0] = regoffset; /* register num */
+ data[1] = value; /* register data */
+ err = i2c_transfer(adap, msg, 1);
+ i2c_put_adapter(adap);
+ if (err >= 0)
+ return 0;
+ return err;
+}
+
+/* Read from I2C device */
+int sx1_i2c_read_byte(u8 devaddr, u8 regoffset, u8 *value)
+{
+ struct i2c_adapter *adap;
+ int err;
+ struct i2c_msg msg[1];
+ unsigned char data[2];
+
+ adap = i2c_get_adapter(0);
+ if (!adap)
+ return -ENODEV;
+
+ msg->addr = devaddr; /* I2C address of chip */
+ msg->flags = 0;
+ msg->len = 1;
+ msg->buf = data;
+ data[0] = regoffset; /* register num */
+ err = i2c_transfer(adap, msg, 1);
+
+ msg->addr = devaddr; /* I2C address */
+ msg->flags = I2C_M_RD;
+ msg->len = 1;
+ msg->buf = data;
+ err = i2c_transfer(adap, msg, 1);
+ *value = data[0];
+ i2c_put_adapter(adap);
+
+ if (err >= 0)
+ return 0;
+ return err;
+}
+/* set keyboard backlight intensity */
+int sx1_setkeylight(u8 keylight)
+{
+ if (keylight > SOFIA_MAX_LIGHT_VAL)
+ keylight = SOFIA_MAX_LIGHT_VAL;
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
+}
+/* get current keylight intensity */
+int sx1_getkeylight(u8 * keylight)
+{
+ return sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
+}
+/* set LCD backlight intensity */
+int sx1_setbacklight(u8 backlight)
+{
+ if (backlight > SOFIA_MAX_LIGHT_VAL)
+ backlight = SOFIA_MAX_LIGHT_VAL;
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG,
+ backlight);
+}
+/* get current LCD backlight intensity */
+int sx1_getbacklight (u8 * backlight)
+{
+ return sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG,
+ backlight);
+}
+/* set LCD backlight power on/off */
+int sx1_setmmipower(u8 onoff)
+{
+ int err;
+ u8 dat = 0;
+ err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
+ if (err < 0)
+ return err;
+ if (onoff)
+ dat |= SOFIA_MMILIGHT_POWER;
+ else
+ dat &= ~SOFIA_MMILIGHT_POWER;
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
+}
+
+/* set USB power on/off */
+int sx1_setusbpower(u8 onoff)
+{
+ int err;
+ u8 dat = 0;
+ err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
+ if (err < 0)
+ return err;
+ if (onoff)
+ dat |= SOFIA_USB_POWER;
+ else
+ dat &= ~SOFIA_USB_POWER;
+ return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
+}
+
+EXPORT_SYMBOL(sx1_setkeylight);
+EXPORT_SYMBOL(sx1_getkeylight);
+EXPORT_SYMBOL(sx1_setbacklight);
+EXPORT_SYMBOL(sx1_getbacklight);
+EXPORT_SYMBOL(sx1_setmmipower);
+EXPORT_SYMBOL(sx1_setusbpower);
+
+/*----------- Keypad -------------------------*/
+
+static const unsigned int sx1_keymap[] = {
+ KEY(3, 5, GROUP_0 | 117), /* camera Qt::Key_F17 */
+ KEY(4, 0, GROUP_0 | 114), /* voice memo Qt::Key_F14 */
+ KEY(4, 1, GROUP_2 | 114), /* voice memo */
+ KEY(4, 2, GROUP_3 | 114), /* voice memo */
+ KEY(0, 0, GROUP_1 | KEY_F12), /* red button Qt::Key_Hangup */
+ KEY(3, 4, GROUP_1 | KEY_LEFT),
+ KEY(3, 2, GROUP_1 | KEY_DOWN),
+ KEY(3, 1, GROUP_1 | KEY_RIGHT),
+ KEY(3, 0, GROUP_1 | KEY_UP),
+ KEY(3, 3, GROUP_1 | KEY_POWER), /* joystick press or Qt::Key_Select */
+ KEY(0, 5, GROUP_1 | KEY_1),
+ KEY(0, 4, GROUP_1 | KEY_2),
+ KEY(0, 3, GROUP_1 | KEY_3),
+ KEY(4, 3, GROUP_1 | KEY_4),
+ KEY(4, 4, GROUP_1 | KEY_5),
+ KEY(4, 5, GROUP_1 | KEY_KPASTERISK),/* "*" */
+ KEY(1, 4, GROUP_1 | KEY_6),
+ KEY(1, 5, GROUP_1 | KEY_7),
+ KEY(1, 3, GROUP_1 | KEY_8),
+ KEY(2, 3, GROUP_1 | KEY_9),
+ KEY(2, 5, GROUP_1 | KEY_0),
+ KEY(2, 4, GROUP_1 | 113), /* # F13 Toggle input method Qt::Key_F13 */
+ KEY(1, 0, GROUP_1 | KEY_F11), /* green button Qt::Key_Call */
+ KEY(2, 1, GROUP_1 | KEY_YEN), /* left soft Qt::Key_Context1 */
+ KEY(2, 2, GROUP_1 | KEY_F8), /* right soft Qt::Key_Back */
+ KEY(1, 2, GROUP_1 | KEY_LEFTSHIFT), /* shift */
+ KEY(1, 1, GROUP_1 | KEY_BACKSPACE), /* C (clear) */
+ KEY(2, 0, GROUP_1 | KEY_F7), /* menu Qt::Key_Menu */
+};
+
+static struct resource sx1_kp_resources[] = {
+ [0] = {
+ .start = INT_KEYBOARD,
+ .end = INT_KEYBOARD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct matrix_keymap_data sx1_keymap_data = {
+ .keymap = sx1_keymap,
+ .keymap_size = ARRAY_SIZE(sx1_keymap),
+};
+
+static struct omap_kp_platform_data sx1_kp_data = {
+ .rows = 6,
+ .cols = 6,
+ .keymap_data = &sx1_keymap_data,
+ .delay = 80,
+};
+
+static struct platform_device sx1_kp_device = {
+ .name = "omap-keypad",
+ .id = -1,
+ .dev = {
+ .platform_data = &sx1_kp_data,
+ },
+ .num_resources = ARRAY_SIZE(sx1_kp_resources),
+ .resource = sx1_kp_resources,
+};
+
+/*----------- IRDA -------------------------*/
+
+static struct omap_irda_config sx1_irda_data = {
+ .transceiver_cap = IR_SIRMODE,
+ .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 sx1_irda_resources[] = {
+ [0] = {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 irda_dmamask = 0xffffffff;
+
+static struct platform_device sx1_irda_device = {
+ .name = "omapirda",
+ .id = 0,
+ .dev = {
+ .platform_data = &sx1_irda_data,
+ .dma_mask = &irda_dmamask,
+ },
+ .num_resources = ARRAY_SIZE(sx1_irda_resources),
+ .resource = sx1_irda_resources,
+};
+
+/*----------- MTD -------------------------*/
+
+static struct mtd_partition sx1_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0x01800000,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M - 2 * SZ_128K,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct physmap_flash_data sx1_flash_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+ .parts = sx1_partitions,
+ .nr_parts = ARRAY_SIZE(sx1_partitions),
+};
+
+#ifdef CONFIG_SX1_OLD_FLASH
+/* MTD Intel StrataFlash - old flashes */
+static struct resource sx1_old_flash_resource[] = {
+ [0] = {
+ .start = OMAP_CS0_PHYS, /* Physical */
+ .end = OMAP_CS0_PHYS + SZ_16M - 1,,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_CS1_PHYS,
+ .end = OMAP_CS1_PHYS + SZ_8M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device sx1_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &sx1_flash_data,
+ },
+ .num_resources = 2,
+ .resource = &sx1_old_flash_resource,
+};
+#else
+/* MTD Intel 4000 flash - new flashes */
+static struct resource sx1_new_flash_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device sx1_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &sx1_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &sx1_new_flash_resource,
+};
+#endif
+
+/*----------- USB -------------------------*/
+
+static struct omap_usb_config sx1_usb_config __initdata = {
+ .otg = 0,
+ .register_dev = 1,
+ .register_host = 0,
+ .hmc_mode = 0,
+ .pins[0] = 2,
+ .pins[1] = 0,
+ .pins[2] = 0,
+};
+
+/*----------- LCD -------------------------*/
+
+static struct platform_device sx1_lcd_device = {
+ .name = "lcd_sx1",
+ .id = -1,
+};
+
+static struct omap_lcd_config sx1_lcd_config __initdata = {
+ .ctrl_name = "internal",
+};
+
+/*-----------------------------------------*/
+static struct platform_device *sx1_devices[] __initdata = {
+ &sx1_flash_device,
+ &sx1_kp_device,
+ &sx1_lcd_device,
+ &sx1_irda_device,
+};
+/*-----------------------------------------*/
+
+static struct omap_board_config_kernel sx1_config[] __initdata = {
+ { OMAP_TAG_LCD, &sx1_lcd_config },
+};
+
+/*-----------------------------------------*/
+
+static void __init omap_sx1_init(void)
+{
+ /* mux pins for uarts */
+ omap_cfg_reg(UART1_TX);
+ omap_cfg_reg(UART1_RTS);
+ omap_cfg_reg(UART2_TX);
+ omap_cfg_reg(UART2_RTS);
+ omap_cfg_reg(UART3_TX);
+ omap_cfg_reg(UART3_RX);
+
+ platform_add_devices(sx1_devices, ARRAY_SIZE(sx1_devices));
+
+ omap_board_config = sx1_config;
+ omap_board_config_size = ARRAY_SIZE(sx1_config);
+ omap_serial_init();
+ omap_register_i2c_bus(1, 100, NULL, 0);
+ omap1_usb_init(&sx1_usb_config);
+ sx1_mmc_init();
+
+ /* turn on USB power */
+ /* sx1_setusbpower(1); can't do it here because i2c is not ready */
+ gpio_request(1, "A_IRDA_OFF");
+ gpio_request(11, "A_SWITCH");
+ gpio_request(15, "A_USB_ON");
+ gpio_direction_output(1, 1); /*A_IRDA_OFF = 1 */
+ gpio_direction_output(11, 0); /*A_SWITCH = 0 */
+ gpio_direction_output(15, 0); /*A_USB_ON = 0 */
+}
+/*----------------------------------------*/
+static void __init omap_sx1_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+/*----------------------------------------*/
+
+static void __init omap_sx1_map_io(void)
+{
+ omap1_map_common_io();
+}
+
+MACHINE_START(SX1, "OMAP310 based Siemens SX1")
+ .boot_params = 0x10000100,
+ .map_io = omap_sx1_map_io,
+ .reserve = omap_reserve,
+ .init_irq = omap_sx1_init_irq,
+ .init_machine = omap_sx1_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
new file mode 100644
index 00000000..65d24204
--- /dev/null
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -0,0 +1,310 @@
+/*
+ * linux/arch/arm/mach-omap1/board-voiceblue.c
+ *
+ * Modified from board-generic.c
+ *
+ * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
+ *
+ * Code for OMAP5910 based VoiceBlue board (VoIP to GSM gateway).
+ *
+ * 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/irq.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mtd/physmap.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
+#include <linux/smc91x.h>
+
+#include <mach/hardware.h>
+#include <mach/system.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/board-voiceblue.h>
+#include <plat/common.h>
+#include <mach/gpio.h>
+#include <plat/flash.h>
+#include <plat/mux.h>
+#include <plat/tc.h>
+#include <plat/usb.h>
+
+static struct plat_serial8250_port voiceblue_ports[] = {
+ {
+ .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x40000),
+ .irq = OMAP_GPIO_IRQ(12),
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = 3686400,
+ },
+ {
+ .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x50000),
+ .irq = OMAP_GPIO_IRQ(13),
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = 3686400,
+ },
+ {
+ .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x60000),
+ .irq = OMAP_GPIO_IRQ(14),
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = 3686400,
+ },
+ {
+ .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x70000),
+ .irq = OMAP_GPIO_IRQ(15),
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = 3686400,
+ },
+ { },
+};
+
+static struct platform_device serial_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM1,
+ .dev = {
+ .platform_data = voiceblue_ports,
+ },
+};
+
+static int __init ext_uart_init(void)
+{
+ if (!machine_is_voiceblue())
+ return -ENODEV;
+
+ return platform_device_register(&serial_device);
+}
+arch_initcall(ext_uart_init);
+
+static struct physmap_flash_data voiceblue_flash_data = {
+ .width = 2,
+ .set_vpp = omap1_set_vpp,
+};
+
+static struct resource voiceblue_flash_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device voiceblue_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &voiceblue_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &voiceblue_flash_resource,
+};
+
+static struct smc91x_platdata voiceblue_smc91x_info = {
+ .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+ .leda = RPC_LED_100_10,
+ .ledb = RPC_LED_TX_RX,
+};
+
+static struct resource voiceblue_smc91x_resources[] = {
+ [0] = {
+ .start = OMAP_CS2_PHYS + 0x300,
+ .end = OMAP_CS2_PHYS + 0x300 + 16,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(8),
+ .end = OMAP_GPIO_IRQ(8),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ },
+};
+
+static struct platform_device voiceblue_smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .dev = {
+ .platform_data = &voiceblue_smc91x_info,
+ },
+ .num_resources = ARRAY_SIZE(voiceblue_smc91x_resources),
+ .resource = voiceblue_smc91x_resources,
+};
+
+static struct platform_device *voiceblue_devices[] __initdata = {
+ &voiceblue_flash_device,
+ &voiceblue_smc91x_device,
+};
+
+static struct omap_usb_config voiceblue_usb_config __initdata = {
+ .hmc_mode = 3,
+ .register_host = 1,
+ .register_dev = 1,
+ .pins[0] = 2,
+ .pins[1] = 6,
+ .pins[2] = 6,
+};
+
+static struct omap_board_config_kernel voiceblue_config[] = {
+};
+
+static void __init voiceblue_init_irq(void)
+{
+ omap1_init_common_hw();
+ omap_init_irq();
+}
+
+static void __init voiceblue_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;
+
+ /* Flash power 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 voiceblue_setup(void)
+{
+ if (!machine_is_voiceblue())
+ return -ENODEV;
+
+ /* Setup panic notifier */
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+
+ return 0;
+}
+postcore_initcall(voiceblue_setup);
+
+static int wdt_gpio_state;
+
+void voiceblue_wdt_enable(void)
+{
+ gpio_direction_output(0, 0);
+ gpio_set_value(0, 1);
+ gpio_set_value(0, 0);
+ wdt_gpio_state = 0;
+}
+
+void voiceblue_wdt_disable(void)
+{
+ gpio_set_value(0, 0);
+ gpio_set_value(0, 1);
+ gpio_set_value(0, 0);
+ gpio_direction_input(0);
+}
+
+void voiceblue_wdt_ping(void)
+{
+ if (test_bit(MACHINE_REBOOT, &machine_state))
+ return;
+
+ wdt_gpio_state = !wdt_gpio_state;
+ gpio_set_value(0, wdt_gpio_state);
+}
+
+static void voiceblue_reset(char mode, const char *cmd)
+{
+ /*
+ * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28
+ * "Global Software Reset Affects Traffic Controller Frequency".
+ */
+ if (cpu_is_omap5912()) {
+ omap_writew(omap_readw(DPLL_CTL) & ~(1 << 4), DPLL_CTL);
+ omap_writew(0x8, ARM_RSTCT1);
+ }
+
+ set_bit(MACHINE_REBOOT, &machine_state);
+ voiceblue_wdt_enable();
+ while (1) ;
+}
+
+EXPORT_SYMBOL(voiceblue_wdt_enable);
+EXPORT_SYMBOL(voiceblue_wdt_disable);
+EXPORT_SYMBOL(voiceblue_wdt_ping);
+
+static void __init voiceblue_init(void)
+{
+ /* mux pins for uarts */
+ omap_cfg_reg(UART1_TX);
+ omap_cfg_reg(UART1_RTS);
+ omap_cfg_reg(UART2_TX);
+ omap_cfg_reg(UART2_RTS);
+ omap_cfg_reg(UART3_TX);
+ omap_cfg_reg(UART3_RX);
+
+ /* Watchdog */
+ gpio_request(0, "Watchdog");
+ /* smc91x reset */
+ gpio_request(7, "SMC91x reset");
+ gpio_direction_output(7, 1);
+ udelay(2); /* wait at least 100ns */
+ gpio_set_value(7, 0);
+ mdelay(50); /* 50ms until PHY ready */
+ /* smc91x interrupt pin */
+ gpio_request(8, "SMC91x irq");
+ /* 16C554 reset*/
+ gpio_request(6, "16C554 reset");
+ gpio_direction_output(6, 0);
+ /* 16C554 interrupt pins */
+ gpio_request(12, "16C554 irq");
+ gpio_request(13, "16C554 irq");
+ gpio_request(14, "16C554 irq");
+ gpio_request(15, "16C554 irq");
+ irq_set_irq_type(gpio_to_irq(12), IRQ_TYPE_EDGE_RISING);
+ irq_set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
+ irq_set_irq_type(gpio_to_irq(14), IRQ_TYPE_EDGE_RISING);
+ irq_set_irq_type(gpio_to_irq(15), IRQ_TYPE_EDGE_RISING);
+
+ platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
+ omap_board_config = voiceblue_config;
+ omap_board_config_size = ARRAY_SIZE(voiceblue_config);
+ omap_serial_init();
+ omap1_usb_init(&voiceblue_usb_config);
+ omap_register_i2c_bus(1, 100, NULL, 0);
+
+ /* There is a good chance board is going up, so enable power LED
+ * (it is connected through invertor) */
+ omap_writeb(0x00, OMAP_LPG1_LCR);
+ omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */
+
+ arch_reset = voiceblue_reset;
+}
+
+MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
+ /* Maintainer: Ladislav Michl <michl@2n.cz> */
+ .boot_params = 0x10000100,
+ .map_io = voiceblue_map_io,
+ .reserve = omap_reserve,
+ .init_irq = voiceblue_init_irq,
+ .init_machine = voiceblue_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
new file mode 100644
index 00000000..84ef7047
--- /dev/null
+++ b/arch/arm/mach-omap1/clock.c
@@ -0,0 +1,609 @@
+/*
+ * linux/arch/arm/mach-omap1/clock.c
+ *
+ * Copyright (C) 2004 - 2005, 2009-2010 Nokia Corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ * Modified to use omap shared clock framework by
+ * 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/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+
+#include <asm/mach-types.h>
+
+#include <plat/cpu.h>
+#include <plat/usb.h>
+#include <plat/clock.h>
+#include <plat/sram.h>
+#include <plat/clkdev_omap.h>
+
+#include "clock.h"
+#include "opp.h"
+
+__u32 arm_idlect1_mask;
+struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
+
+/*
+ * Omap1 specific clock functions
+ */
+
+unsigned long omap1_uart_recalc(struct clk *clk)
+{
+ unsigned int val = __raw_readl(clk->enable_reg);
+ return val & clk->enable_bit ? 48000000 : 12000000;
+}
+
+unsigned long omap1_sossi_recalc(struct clk *clk)
+{
+ u32 div = omap_readl(MOD_CONF_CTRL_1);
+
+ div = (div >> 17) & 0x7;
+ div++;
+
+ return clk->parent->rate / div;
+}
+
+static void omap1_clk_allow_idle(struct clk *clk)
+{
+ struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
+
+ if (!(clk->flags & CLOCK_IDLE_CONTROL))
+ return;
+
+ if (iclk->no_idle_count > 0 && !(--iclk->no_idle_count))
+ arm_idlect1_mask |= 1 << iclk->idlect_shift;
+}
+
+static void omap1_clk_deny_idle(struct clk *clk)
+{
+ struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;
+
+ if (!(clk->flags & CLOCK_IDLE_CONTROL))
+ return;
+
+ if (iclk->no_idle_count++ == 0)
+ arm_idlect1_mask &= ~(1 << iclk->idlect_shift);
+}
+
+static __u16 verify_ckctl_value(__u16 newval)
+{
+ /* This function checks for following limitations set
+ * by the hardware (all conditions must be true):
+ * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2
+ * ARM_CK >= TC_CK
+ * DSP_CK >= TC_CK
+ * DSPMMU_CK >= TC_CK
+ *
+ * In addition following rules are enforced:
+ * LCD_CK <= TC_CK
+ * ARMPER_CK <= TC_CK
+ *
+ * However, maximum frequencies are not checked for!
+ */
+ __u8 per_exp;
+ __u8 lcd_exp;
+ __u8 arm_exp;
+ __u8 dsp_exp;
+ __u8 tc_exp;
+ __u8 dspmmu_exp;
+
+ per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3;
+ lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3;
+ arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3;
+ dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3;
+ tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3;
+ dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3;
+
+ if (dspmmu_exp < dsp_exp)
+ dspmmu_exp = dsp_exp;
+ if (dspmmu_exp > dsp_exp+1)
+ dspmmu_exp = dsp_exp+1;
+ if (tc_exp < arm_exp)
+ tc_exp = arm_exp;
+ if (tc_exp < dspmmu_exp)
+ tc_exp = dspmmu_exp;
+ if (tc_exp > lcd_exp)
+ lcd_exp = tc_exp;
+ if (tc_exp > per_exp)
+ per_exp = tc_exp;
+
+ newval &= 0xf000;
+ newval |= per_exp << CKCTL_PERDIV_OFFSET;
+ newval |= lcd_exp << CKCTL_LCDDIV_OFFSET;
+ newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
+ newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
+ newval |= tc_exp << CKCTL_TCDIV_OFFSET;
+ newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
+
+ return newval;
+}
+
+static int calc_dsor_exp(struct clk *clk, unsigned long rate)
+{
+ /* Note: If target frequency is too low, this function will return 4,
+ * which is invalid value. Caller must check for this value and act
+ * accordingly.
+ *
+ * Note: This function does not check for following limitations set
+ * by the hardware (all conditions must be true):
+ * DSPMMU_CK == DSP_CK or DSPMMU_CK == DSP_CK/2
+ * ARM_CK >= TC_CK
+ * DSP_CK >= TC_CK
+ * DSPMMU_CK >= TC_CK
+ */
+ unsigned long realrate;
+ struct clk * parent;
+ unsigned dsor_exp;
+
+ parent = clk->parent;
+ if (unlikely(parent == NULL))
+ return -EIO;
+
+ realrate = parent->rate;
+ for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
+ if (realrate <= rate)
+ break;
+
+ realrate /= 2;
+ }
+
+ return dsor_exp;
+}
+
+unsigned long omap1_ckctl_recalc(struct clk *clk)
+{
+ /* Calculate divisor encoded as 2-bit exponent */
+ int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
+
+ return clk->parent->rate / dsor;
+}
+
+unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk)
+{
+ int dsor;
+
+ /* Calculate divisor encoded as 2-bit exponent
+ *
+ * The clock control bits are in DSP domain,
+ * so api_ck is needed for access.
+ * Note that DSP_CKCTL virt addr = phys addr, so
+ * we must use __raw_readw() instead of omap_readw().
+ */
+ omap1_clk_enable(api_ck_p);
+ dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
+ omap1_clk_disable(api_ck_p);
+
+ return clk->parent->rate / dsor;
+}
+
+/* MPU virtual clock functions */
+int omap1_select_table_rate(struct clk *clk, unsigned long rate)
+{
+ /* Find the highest supported frequency <= rate and switch to it */
+ struct mpu_rate * ptr;
+ unsigned long dpll1_rate, ref_rate;
+
+ dpll1_rate = ck_dpll1_p->rate;
+ ref_rate = ck_ref_p->rate;
+
+ for (ptr = omap1_rate_table; ptr->rate; ptr++) {
+ if (ptr->xtal != ref_rate)
+ continue;
+
+ /* DPLL1 cannot be reprogrammed without risking system crash */
+ if (likely(dpll1_rate != 0) && ptr->pll_rate != dpll1_rate)
+ continue;
+
+ /* Can check only after xtal frequency check */
+ if (ptr->rate <= rate)
+ break;
+ }
+
+ if (!ptr->rate)
+ return -EINVAL;
+
+ /*
+ * In most cases we should not need to reprogram DPLL.
+ * Reprogramming the DPLL is tricky, it must be done from SRAM.
+ * (on 730, bit 13 must always be 1)
+ */
+ if (cpu_is_omap7xx())
+ omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val | 0x2000);
+ else
+ omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
+
+ /* XXX Do we need to recalculate the tree below DPLL1 at this point? */
+ ck_dpll1_p->rate = ptr->pll_rate;
+
+ return 0;
+}
+
+int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate)
+{
+ int dsor_exp;
+ u16 regval;
+
+ dsor_exp = calc_dsor_exp(clk, rate);
+ if (dsor_exp > 3)
+ dsor_exp = -EINVAL;
+ if (dsor_exp < 0)
+ return dsor_exp;
+
+ regval = __raw_readw(DSP_CKCTL);
+ regval &= ~(3 << clk->rate_offset);
+ regval |= dsor_exp << clk->rate_offset;
+ __raw_writew(regval, DSP_CKCTL);
+ clk->rate = clk->parent->rate / (1 << dsor_exp);
+
+ return 0;
+}
+
+long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate)
+{
+ int dsor_exp = calc_dsor_exp(clk, rate);
+ if (dsor_exp < 0)
+ return dsor_exp;
+ if (dsor_exp > 3)
+ dsor_exp = 3;
+ return clk->parent->rate / (1 << dsor_exp);
+}
+
+int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate)
+{
+ int dsor_exp;
+ u16 regval;
+
+ dsor_exp = calc_dsor_exp(clk, rate);
+ if (dsor_exp > 3)
+ dsor_exp = -EINVAL;
+ if (dsor_exp < 0)
+ return dsor_exp;
+
+ regval = omap_readw(ARM_CKCTL);
+ regval &= ~(3 << clk->rate_offset);
+ regval |= dsor_exp << clk->rate_offset;
+ regval = verify_ckctl_value(regval);
+ omap_writew(regval, ARM_CKCTL);
+ clk->rate = clk->parent->rate / (1 << dsor_exp);
+ return 0;
+}
+
+long omap1_round_to_table_rate(struct clk *clk, unsigned long rate)
+{
+ /* Find the highest supported frequency <= rate */
+ struct mpu_rate * ptr;
+ long highest_rate;
+ unsigned long ref_rate;
+
+ ref_rate = ck_ref_p->rate;
+
+ highest_rate = -EINVAL;
+
+ for (ptr = omap1_rate_table; ptr->rate; ptr++) {
+ if (ptr->xtal != ref_rate)
+ continue;
+
+ highest_rate = ptr->rate;
+
+ /* Can check only after xtal frequency check */
+ if (ptr->rate <= rate)
+ break;
+ }
+
+ return highest_rate;
+}
+
+static unsigned calc_ext_dsor(unsigned long rate)
+{
+ unsigned dsor;
+
+ /* MCLK and BCLK divisor selection is not linear:
+ * freq = 96MHz / dsor
+ *
+ * RATIO_SEL range: dsor <-> RATIO_SEL
+ * 0..6: (RATIO_SEL+2) <-> (dsor-2)
+ * 6..48: (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6)
+ * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9
+ * can not be used.
+ */
+ for (dsor = 2; dsor < 96; ++dsor) {
+ if ((dsor & 1) && dsor > 8)
+ continue;
+ if (rate >= 96000000 / dsor)
+ break;
+ }
+ return dsor;
+}
+
+/* XXX Only needed on 1510 */
+int omap1_set_uart_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int val;
+
+ val = __raw_readl(clk->enable_reg);
+ if (rate == 12000000)
+ val &= ~(1 << clk->enable_bit);
+ else if (rate == 48000000)
+ val |= (1 << clk->enable_bit);
+ else
+ return -EINVAL;
+ __raw_writel(val, clk->enable_reg);
+ clk->rate = rate;
+
+ return 0;
+}
+
+/* External clock (MCLK & BCLK) functions */
+int omap1_set_ext_clk_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned dsor;
+ __u16 ratio_bits;
+
+ dsor = calc_ext_dsor(rate);
+ clk->rate = 96000000 / dsor;
+ if (dsor > 8)
+ ratio_bits = ((dsor - 8) / 2 + 6) << 2;
+ else
+ ratio_bits = (dsor - 2) << 2;
+
+ ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd;
+ __raw_writew(ratio_bits, clk->enable_reg);
+
+ return 0;
+}
+
+int omap1_set_sossi_rate(struct clk *clk, unsigned long rate)
+{
+ u32 l;
+ int div;
+ unsigned long p_rate;
+
+ p_rate = clk->parent->rate;
+ /* Round towards slower frequency */
+ div = (p_rate + rate - 1) / rate;
+ div--;
+ if (div < 0 || div > 7)
+ return -EINVAL;
+
+ l = omap_readl(MOD_CONF_CTRL_1);
+ l &= ~(7 << 17);
+ l |= div << 17;
+ omap_writel(l, MOD_CONF_CTRL_1);
+
+ clk->rate = p_rate / (div + 1);
+
+ return 0;
+}
+
+long omap1_round_ext_clk_rate(struct clk *clk, unsigned long rate)
+{
+ return 96000000 / calc_ext_dsor(rate);
+}
+
+void omap1_init_ext_clk(struct clk *clk)
+{
+ unsigned dsor;
+ __u16 ratio_bits;
+
+ /* Determine current rate and ensure clock is based on 96MHz APLL */
+ ratio_bits = __raw_readw(clk->enable_reg) & ~1;
+ __raw_writew(ratio_bits, clk->enable_reg);
+
+ ratio_bits = (ratio_bits & 0xfc) >> 2;
+ if (ratio_bits > 6)
+ dsor = (ratio_bits - 6) * 2 + 8;
+ else
+ dsor = ratio_bits + 2;
+
+ clk-> rate = 96000000 / dsor;
+}
+
+int omap1_clk_enable(struct clk *clk)
+{
+ int ret = 0;
+
+ if (clk->usecount++ == 0) {
+ if (clk->parent) {
+ ret = omap1_clk_enable(clk->parent);
+ if (ret)
+ goto err;
+
+ if (clk->flags & CLOCK_NO_IDLE_PARENT)
+ omap1_clk_deny_idle(clk->parent);
+ }
+
+ ret = clk->ops->enable(clk);
+ if (ret) {
+ if (clk->parent)
+ omap1_clk_disable(clk->parent);
+ goto err;
+ }
+ }
+ return ret;
+
+err:
+ clk->usecount--;
+ return ret;
+}
+
+void omap1_clk_disable(struct clk *clk)
+{
+ if (clk->usecount > 0 && !(--clk->usecount)) {
+ clk->ops->disable(clk);
+ if (likely(clk->parent)) {
+ omap1_clk_disable(clk->parent);
+ if (clk->flags & CLOCK_NO_IDLE_PARENT)
+ omap1_clk_allow_idle(clk->parent);
+ }
+ }
+}
+
+static int omap1_clk_enable_generic(struct clk *clk)
+{
+ __u16 regval16;
+ __u32 regval32;
+
+ if (unlikely(clk->enable_reg == NULL)) {
+ printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
+ clk->name);
+ return -EINVAL;
+ }
+
+ if (clk->flags & ENABLE_REG_32BIT) {
+ regval32 = __raw_readl(clk->enable_reg);
+ regval32 |= (1 << clk->enable_bit);
+ __raw_writel(regval32, clk->enable_reg);
+ } else {
+ regval16 = __raw_readw(clk->enable_reg);
+ regval16 |= (1 << clk->enable_bit);
+ __raw_writew(regval16, clk->enable_reg);
+ }
+
+ return 0;
+}
+
+static void omap1_clk_disable_generic(struct clk *clk)
+{
+ __u16 regval16;
+ __u32 regval32;
+
+ if (clk->enable_reg == NULL)
+ return;
+
+ if (clk->flags & ENABLE_REG_32BIT) {
+ regval32 = __raw_readl(clk->enable_reg);
+ regval32 &= ~(1 << clk->enable_bit);
+ __raw_writel(regval32, clk->enable_reg);
+ } else {
+ regval16 = __raw_readw(clk->enable_reg);
+ regval16 &= ~(1 << clk->enable_bit);
+ __raw_writew(regval16, clk->enable_reg);
+ }
+}
+
+const struct clkops clkops_generic = {
+ .enable = omap1_clk_enable_generic,
+ .disable = omap1_clk_disable_generic,
+};
+
+static int omap1_clk_enable_dsp_domain(struct clk *clk)
+{
+ int retval;
+
+ retval = omap1_clk_enable(api_ck_p);
+ if (!retval) {
+ retval = omap1_clk_enable_generic(clk);
+ omap1_clk_disable(api_ck_p);
+ }
+
+ return retval;
+}
+
+static void omap1_clk_disable_dsp_domain(struct clk *clk)
+{
+ if (omap1_clk_enable(api_ck_p) == 0) {
+ omap1_clk_disable_generic(clk);
+ omap1_clk_disable(api_ck_p);
+ }
+}
+
+const struct clkops clkops_dspck = {
+ .enable = omap1_clk_enable_dsp_domain,
+ .disable = omap1_clk_disable_dsp_domain,
+};
+
+/* XXX SYSC register handling does not belong in the clock framework */
+static int omap1_clk_enable_uart_functional_16xx(struct clk *clk)
+{
+ int ret;
+ struct uart_clk *uclk;
+
+ ret = omap1_clk_enable_generic(clk);
+ if (ret == 0) {
+ /* Set smart idle acknowledgement mode */
+ uclk = (struct uart_clk *)clk;
+ omap_writeb((omap_readb(uclk->sysc_addr) & ~0x10) | 8,
+ uclk->sysc_addr);
+ }
+
+ return ret;
+}
+
+/* XXX SYSC register handling does not belong in the clock framework */
+static void omap1_clk_disable_uart_functional_16xx(struct clk *clk)
+{
+ struct uart_clk *uclk;
+
+ /* Set force idle acknowledgement mode */
+ uclk = (struct uart_clk *)clk;
+ omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr);
+
+ omap1_clk_disable_generic(clk);
+}
+
+/* XXX SYSC register handling does not belong in the clock framework */
+const struct clkops clkops_uart_16xx = {
+ .enable = omap1_clk_enable_uart_functional_16xx,
+ .disable = omap1_clk_disable_uart_functional_16xx,
+};
+
+long omap1_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk->round_rate != NULL)
+ return clk->round_rate(clk, rate);
+
+ return clk->rate;
+}
+
+int omap1_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret = -EINVAL;
+
+ if (clk->set_rate)
+ ret = clk->set_rate(clk, rate);
+ return ret;
+}
+
+/*
+ * Omap1 clock reset and init functions
+ */
+
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+
+void omap1_clk_disable_unused(struct clk *clk)
+{
+ __u32 regval32;
+
+ /* Clocks in the DSP domain need api_ck. Just assume bootloader
+ * has not enabled any DSP clocks */
+ if (clk->enable_reg == DSP_IDLECT2) {
+ printk(KERN_INFO "Skipping reset check for DSP domain "
+ "clock \"%s\"\n", clk->name);
+ return;
+ }
+
+ /* Is the clock already disabled? */
+ if (clk->flags & ENABLE_REG_32BIT)
+ regval32 = __raw_readl(clk->enable_reg);
+ else
+ regval32 = __raw_readw(clk->enable_reg);
+
+ if ((regval32 & (1 << clk->enable_bit)) == 0)
+ return;
+
+ printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name);
+ clk->ops->disable(clk);
+ printk(" done\n");
+}
+
+#endif
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
new file mode 100644
index 00000000..eaf09efb
--- /dev/null
+++ b/arch/arm/mach-omap1/clock.h
@@ -0,0 +1,113 @@
+/*
+ * linux/arch/arm/mach-omap1/clock.h
+ *
+ * Copyright (C) 2004 - 2005, 2009 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H
+#define __ARCH_ARM_MACH_OMAP1_CLOCK_H
+
+#include <linux/clk.h>
+
+#include <plat/clock.h>
+
+extern int __init omap1_clk_init(void);
+extern int omap1_clk_enable(struct clk *clk);
+extern void omap1_clk_disable(struct clk *clk);
+extern long omap1_clk_round_rate(struct clk *clk, unsigned long rate);
+extern int omap1_clk_set_rate(struct clk *clk, unsigned long rate);
+extern unsigned long omap1_ckctl_recalc(struct clk *clk);
+extern int omap1_set_sossi_rate(struct clk *clk, unsigned long rate);
+extern unsigned long omap1_sossi_recalc(struct clk *clk);
+extern unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk);
+extern int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate);
+extern int omap1_set_uart_rate(struct clk *clk, unsigned long rate);
+extern unsigned long omap1_uart_recalc(struct clk *clk);
+extern int omap1_set_ext_clk_rate(struct clk *clk, unsigned long rate);
+extern long omap1_round_ext_clk_rate(struct clk *clk, unsigned long rate);
+extern void omap1_init_ext_clk(struct clk *clk);
+extern int omap1_select_table_rate(struct clk *clk, unsigned long rate);
+extern long omap1_round_to_table_rate(struct clk *clk, unsigned long rate);
+extern int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate);
+extern long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate);
+extern unsigned long omap1_watchdog_recalc(struct clk *clk);
+
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+extern void omap1_clk_disable_unused(struct clk *clk);
+#else
+#define omap1_clk_disable_unused NULL
+#endif
+
+struct uart_clk {
+ struct clk clk;
+ unsigned long sysc_addr;
+};
+
+/* Provide a method for preventing idling some ARM IDLECT clocks */
+struct arm_idlect1_clk {
+ struct clk clk;
+ unsigned long no_idle_count;
+ __u8 idlect_shift;
+};
+
+/* ARM_CKCTL bit shifts */
+#define CKCTL_PERDIV_OFFSET 0
+#define CKCTL_LCDDIV_OFFSET 2
+#define CKCTL_ARMDIV_OFFSET 4
+#define CKCTL_DSPDIV_OFFSET 6
+#define CKCTL_TCDIV_OFFSET 8
+#define CKCTL_DSPMMUDIV_OFFSET 10
+/*#define ARM_TIMXO 12*/
+#define EN_DSPCK 13
+/*#define ARM_INTHCK_SEL 14*/ /* Divide-by-2 for mpu inth_ck */
+/* DSP_CKCTL bit shifts */
+#define CKCTL_DSPPERDIV_OFFSET 0
+
+/* ARM_IDLECT2 bit shifts */
+#define EN_WDTCK 0
+#define EN_XORPCK 1
+#define EN_PERCK 2
+#define EN_LCDCK 3
+#define EN_LBCK 4 /* Not on 1610/1710 */
+/*#define EN_HSABCK 5*/
+#define EN_APICK 6
+#define EN_TIMCK 7
+#define DMACK_REQ 8
+#define EN_GPIOCK 9 /* Not on 1610/1710 */
+/*#define EN_LBFREECK 10*/
+#define EN_CKOUT_ARM 11
+
+/* ARM_IDLECT3 bit shifts */
+#define EN_OCPI_CK 0
+#define EN_TC1_CK 2
+#define EN_TC2_CK 4
+
+/* DSP_IDLECT2 bit shifts (0,1,2 are same as for ARM_IDLECT2) */
+#define EN_DSPTIMCK 5
+
+/* Various register defines for clock controls scattered around OMAP chip */
+#define SDW_MCLK_INV_BIT 2 /* In ULPD_CLKC_CTRL */
+#define USB_MCLK_EN_BIT 4 /* In ULPD_CLKC_CTRL */
+#define USB_HOST_HHC_UHOST_EN 9 /* In MOD_CONF_CTRL_0 */
+#define SWD_ULPD_PLL_CLK_REQ 1 /* In SWD_CLK_DIV_CTRL_SEL */
+#define COM_ULPD_PLL_CLK_REQ 1 /* In COM_CLK_DIV_CTRL_SEL */
+#define SWD_CLK_DIV_CTRL_SEL 0xfffe0874
+#define COM_CLK_DIV_CTRL_SEL 0xfffe0878
+#define SOFT_REQ_REG 0xfffe0834
+#define SOFT_REQ_REG2 0xfffe0880
+
+extern __u32 arm_idlect1_mask;
+extern struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
+
+extern const struct clkops clkops_dspck;
+extern const struct clkops clkops_dummy;
+extern const struct clkops clkops_uart_16xx;
+extern const struct clkops clkops_generic;
+
+#endif
diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
new file mode 100644
index 00000000..92400b9e
--- /dev/null
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -0,0 +1,927 @@
+/*
+ * linux/arch/arm/mach-omap1/clock_data.c
+ *
+ * Copyright (C) 2004 - 2005, 2009-2010 Nokia Corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, 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.
+ *
+ * To do:
+ * - Clocks that are only available on some chips should be marked with the
+ * chips that they are present on.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h> /* for machine_is_* */
+
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/clkdev_omap.h>
+#include <plat/usb.h> /* for OTG_BASE */
+
+#include "clock.h"
+
+/* Some ARM_IDLECT1 bit shifts - used in struct arm_idlect1_clk */
+#define IDL_CLKOUT_ARM_SHIFT 12
+#define IDLTIM_ARM_SHIFT 9
+#define IDLAPI_ARM_SHIFT 8
+#define IDLIF_ARM_SHIFT 6
+#define IDLLB_ARM_SHIFT 4 /* undocumented? */
+#define OMAP1510_IDLLCD_ARM_SHIFT 3 /* undocumented? */
+#define IDLPER_ARM_SHIFT 2
+#define IDLXORP_ARM_SHIFT 1
+#define IDLWDT_ARM_SHIFT 0
+
+/* Some MOD_CONF_CTRL_0 bit shifts - used in struct clk.enable_bit */
+#define CONF_MOD_UART3_CLK_MODE_R 31
+#define CONF_MOD_UART2_CLK_MODE_R 30
+#define CONF_MOD_UART1_CLK_MODE_R 29
+#define CONF_MOD_MMC_SD_CLK_REQ_R 23
+#define CONF_MOD_MCBSP3_AUXON 20
+
+/* Some MOD_CONF_CTRL_1 bit shifts - used in struct clk.enable_bit */
+#define CONF_MOD_SOSSI_CLK_EN_R 16
+
+/* Some OTG_SYSCON_2-specific bit fields */
+#define OTG_SYSCON_2_UHOST_EN_SHIFT 8
+
+/* Some SOFT_REQ_REG bit fields - used in struct clk.enable_bit */
+#define SOFT_MMC2_DPLL_REQ_SHIFT 13
+#define SOFT_MMC_DPLL_REQ_SHIFT 12
+#define SOFT_UART3_DPLL_REQ_SHIFT 11
+#define SOFT_UART2_DPLL_REQ_SHIFT 10
+#define SOFT_UART1_DPLL_REQ_SHIFT 9
+#define SOFT_USB_OTG_DPLL_REQ_SHIFT 8
+#define SOFT_CAM_DPLL_REQ_SHIFT 7
+#define SOFT_COM_MCKO_REQ_SHIFT 6
+#define SOFT_PERIPH_REQ_SHIFT 5 /* sys_ck gate for UART2 ? */
+#define USB_REQ_EN_SHIFT 4
+#define SOFT_USB_REQ_SHIFT 3 /* sys_ck gate for USB host? */
+#define SOFT_SDW_REQ_SHIFT 2 /* sys_ck gate for Bluetooth? */
+#define SOFT_COM_REQ_SHIFT 1 /* sys_ck gate for com proc? */
+#define SOFT_DPLL_REQ_SHIFT 0
+
+/*
+ * Omap1 clocks
+ */
+
+static struct clk ck_ref = {
+ .name = "ck_ref",
+ .ops = &clkops_null,
+ .rate = 12000000,
+};
+
+static struct clk ck_dpll1 = {
+ .name = "ck_dpll1",
+ .ops = &clkops_null,
+ .parent = &ck_ref,
+};
+
+/*
+ * FIXME: This clock seems to be necessary but no-one has asked for its
+ * activation. [ FIX: SoSSI, SSR ]
+ */
+static struct arm_idlect1_clk ck_dpll1out = {
+ .clk = {
+ .name = "ck_dpll1out",
+ .ops = &clkops_generic,
+ .parent = &ck_dpll1,
+ .flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT |
+ ENABLE_ON_INIT,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_CKOUT_ARM,
+ .recalc = &followparent_recalc,
+ },
+ .idlect_shift = IDL_CLKOUT_ARM_SHIFT,
+};
+
+static struct clk sossi_ck = {
+ .name = "ck_sossi",
+ .ops = &clkops_generic,
+ .parent = &ck_dpll1out.clk,
+ .flags = CLOCK_NO_IDLE_PARENT | ENABLE_REG_32BIT,
+ .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1),
+ .enable_bit = CONF_MOD_SOSSI_CLK_EN_R,
+ .recalc = &omap1_sossi_recalc,
+ .set_rate = &omap1_set_sossi_rate,
+};
+
+static struct clk arm_ck = {
+ .name = "arm_ck",
+ .ops = &clkops_null,
+ .parent = &ck_dpll1,
+ .rate_offset = CKCTL_ARMDIV_OFFSET,
+ .recalc = &omap1_ckctl_recalc,
+ .round_rate = omap1_clk_round_rate_ckctl_arm,
+ .set_rate = omap1_clk_set_rate_ckctl_arm,
+};
+
+static struct arm_idlect1_clk armper_ck = {
+ .clk = {
+ .name = "armper_ck",
+ .ops = &clkops_generic,
+ .parent = &ck_dpll1,
+ .flags = CLOCK_IDLE_CONTROL,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_PERCK,
+ .rate_offset = CKCTL_PERDIV_OFFSET,
+ .recalc = &omap1_ckctl_recalc,
+ .round_rate = omap1_clk_round_rate_ckctl_arm,
+ .set_rate = omap1_clk_set_rate_ckctl_arm,
+ },
+ .idlect_shift = IDLPER_ARM_SHIFT,
+};
+
+/*
+ * FIXME: This clock seems to be necessary but no-one has asked for its
+ * activation. [ GPIO code for 1510 ]
+ */
+static struct clk arm_gpio_ck = {
+ .name = "ick",
+ .ops = &clkops_generic,
+ .parent = &ck_dpll1,
+ .flags = ENABLE_ON_INIT,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_GPIOCK,
+ .recalc = &followparent_recalc,
+};
+
+static struct arm_idlect1_clk armxor_ck = {
+ .clk = {
+ .name = "armxor_ck",
+ .ops = &clkops_generic,
+ .parent = &ck_ref,
+ .flags = CLOCK_IDLE_CONTROL,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_XORPCK,
+ .recalc = &followparent_recalc,
+ },
+ .idlect_shift = IDLXORP_ARM_SHIFT,
+};
+
+static struct arm_idlect1_clk armtim_ck = {
+ .clk = {
+ .name = "armtim_ck",
+ .ops = &clkops_generic,
+ .parent = &ck_ref,
+ .flags = CLOCK_IDLE_CONTROL,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_TIMCK,
+ .recalc = &followparent_recalc,
+ },
+ .idlect_shift = IDLTIM_ARM_SHIFT,
+};
+
+static struct arm_idlect1_clk armwdt_ck = {
+ .clk = {
+ .name = "armwdt_ck",
+ .ops = &clkops_generic,
+ .parent = &ck_ref,
+ .flags = CLOCK_IDLE_CONTROL,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_WDTCK,
+ .fixed_div = 14,
+ .recalc = &omap_fixed_divisor_recalc,
+ },
+ .idlect_shift = IDLWDT_ARM_SHIFT,
+};
+
+static struct clk arminth_ck16xx = {
+ .name = "arminth_ck",
+ .ops = &clkops_null,
+ .parent = &arm_ck,
+ .recalc = &followparent_recalc,
+ /* Note: On 16xx the frequency can be divided by 2 by programming
+ * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
+ *
+ * 1510 version is in TC clocks.
+ */
+};
+
+static struct clk dsp_ck = {
+ .name = "dsp_ck",
+ .ops = &clkops_generic,
+ .parent = &ck_dpll1,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_CKCTL),
+ .enable_bit = EN_DSPCK,
+ .rate_offset = CKCTL_DSPDIV_OFFSET,
+ .recalc = &omap1_ckctl_recalc,
+ .round_rate = omap1_clk_round_rate_ckctl_arm,
+ .set_rate = omap1_clk_set_rate_ckctl_arm,
+};
+
+static struct clk dspmmu_ck = {
+ .name = "dspmmu_ck",
+ .ops = &clkops_null,
+ .parent = &ck_dpll1,
+ .rate_offset = CKCTL_DSPMMUDIV_OFFSET,
+ .recalc = &omap1_ckctl_recalc,
+ .round_rate = omap1_clk_round_rate_ckctl_arm,
+ .set_rate = omap1_clk_set_rate_ckctl_arm,
+};
+
+static struct clk dspper_ck = {
+ .name = "dspper_ck",
+ .ops = &clkops_dspck,
+ .parent = &ck_dpll1,
+ .enable_reg = DSP_IDLECT2,
+ .enable_bit = EN_PERCK,
+ .rate_offset = CKCTL_PERDIV_OFFSET,
+ .recalc = &omap1_ckctl_recalc_dsp_domain,
+ .round_rate = omap1_clk_round_rate_ckctl_arm,
+ .set_rate = &omap1_clk_set_rate_dsp_domain,
+};
+
+static struct clk dspxor_ck = {
+ .name = "dspxor_ck",
+ .ops = &clkops_dspck,
+ .parent = &ck_ref,
+ .enable_reg = DSP_IDLECT2,
+ .enable_bit = EN_XORPCK,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk dsptim_ck = {
+ .name = "dsptim_ck",
+ .ops = &clkops_dspck,
+ .parent = &ck_ref,
+ .enable_reg = DSP_IDLECT2,
+ .enable_bit = EN_DSPTIMCK,
+ .recalc = &followparent_recalc,
+};
+
+static struct arm_idlect1_clk tc_ck = {
+ .clk = {
+ .name = "tc_ck",
+ .ops = &clkops_null,
+ .parent = &ck_dpll1,
+ .flags = CLOCK_IDLE_CONTROL,
+ .rate_offset = CKCTL_TCDIV_OFFSET,
+ .recalc = &omap1_ckctl_recalc,
+ .round_rate = omap1_clk_round_rate_ckctl_arm,
+ .set_rate = omap1_clk_set_rate_ckctl_arm,
+ },
+ .idlect_shift = IDLIF_ARM_SHIFT,
+};
+
+static struct clk arminth_ck1510 = {
+ .name = "arminth_ck",
+ .ops = &clkops_null,
+ .parent = &tc_ck.clk,
+ .recalc = &followparent_recalc,
+ /* Note: On 1510 the frequency follows TC_CK
+ *
+ * 16xx version is in MPU clocks.
+ */
+};
+
+static struct clk tipb_ck = {
+ /* No-idle controlled by "tc_ck" */
+ .name = "tipb_ck",
+ .ops = &clkops_null,
+ .parent = &tc_ck.clk,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk l3_ocpi_ck = {
+ /* No-idle controlled by "tc_ck" */
+ .name = "l3_ocpi_ck",
+ .ops = &clkops_generic,
+ .parent = &tc_ck.clk,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
+ .enable_bit = EN_OCPI_CK,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk tc1_ck = {
+ .name = "tc1_ck",
+ .ops = &clkops_generic,
+ .parent = &tc_ck.clk,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
+ .enable_bit = EN_TC1_CK,
+ .recalc = &followparent_recalc,
+};
+
+/*
+ * FIXME: This clock seems to be necessary but no-one has asked for its
+ * activation. [ pm.c (SRAM), CCP, Camera ]
+ */
+static struct clk tc2_ck = {
+ .name = "tc2_ck",
+ .ops = &clkops_generic,
+ .parent = &tc_ck.clk,
+ .flags = ENABLE_ON_INIT,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
+ .enable_bit = EN_TC2_CK,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk dma_ck = {
+ /* No-idle controlled by "tc_ck" */
+ .name = "dma_ck",
+ .ops = &clkops_null,
+ .parent = &tc_ck.clk,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk dma_lcdfree_ck = {
+ .name = "dma_lcdfree_ck",
+ .ops = &clkops_null,
+ .parent = &tc_ck.clk,
+ .recalc = &followparent_recalc,
+};
+
+static struct arm_idlect1_clk api_ck = {
+ .clk = {
+ .name = "api_ck",
+ .ops = &clkops_generic,
+ .parent = &tc_ck.clk,
+ .flags = CLOCK_IDLE_CONTROL,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_APICK,
+ .recalc = &followparent_recalc,
+ },
+ .idlect_shift = IDLAPI_ARM_SHIFT,
+};
+
+static struct arm_idlect1_clk lb_ck = {
+ .clk = {
+ .name = "lb_ck",
+ .ops = &clkops_generic,
+ .parent = &tc_ck.clk,
+ .flags = CLOCK_IDLE_CONTROL,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_LBCK,
+ .recalc = &followparent_recalc,
+ },
+ .idlect_shift = IDLLB_ARM_SHIFT,
+};
+
+static struct clk rhea1_ck = {
+ .name = "rhea1_ck",
+ .ops = &clkops_null,
+ .parent = &tc_ck.clk,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk rhea2_ck = {
+ .name = "rhea2_ck",
+ .ops = &clkops_null,
+ .parent = &tc_ck.clk,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk lcd_ck_16xx = {
+ .name = "lcd_ck",
+ .ops = &clkops_generic,
+ .parent = &ck_dpll1,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_LCDCK,
+ .rate_offset = CKCTL_LCDDIV_OFFSET,
+ .recalc = &omap1_ckctl_recalc,
+ .round_rate = omap1_clk_round_rate_ckctl_arm,
+ .set_rate = omap1_clk_set_rate_ckctl_arm,
+};
+
+static struct arm_idlect1_clk lcd_ck_1510 = {
+ .clk = {
+ .name = "lcd_ck",
+ .ops = &clkops_generic,
+ .parent = &ck_dpll1,
+ .flags = CLOCK_IDLE_CONTROL,
+ .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
+ .enable_bit = EN_LCDCK,
+ .rate_offset = CKCTL_LCDDIV_OFFSET,
+ .recalc = &omap1_ckctl_recalc,
+ .round_rate = omap1_clk_round_rate_ckctl_arm,
+ .set_rate = omap1_clk_set_rate_ckctl_arm,
+ },
+ .idlect_shift = OMAP1510_IDLLCD_ARM_SHIFT,
+};
+
+/*
+ * XXX The enable_bit here is misused - it simply switches between 12MHz
+ * and 48MHz. Reimplement with clksel.
+ *
+ * XXX does this need SYSC register handling?
+ */
+static struct clk uart1_1510 = {
+ .name = "uart1_ck",
+ .ops = &clkops_null,
+ /* Direct from ULPD, no real parent */
+ .parent = &armper_ck.clk,
+ .rate = 12000000,
+ .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
+ .enable_bit = CONF_MOD_UART1_CLK_MODE_R,
+ .set_rate = &omap1_set_uart_rate,
+ .recalc = &omap1_uart_recalc,
+};
+
+/*
+ * XXX The enable_bit here is misused - it simply switches between 12MHz
+ * and 48MHz. Reimplement with clksel.
+ *
+ * XXX SYSC register handling does not belong in the clock framework
+ */
+static struct uart_clk uart1_16xx = {
+ .clk = {
+ .name = "uart1_ck",
+ .ops = &clkops_uart_16xx,
+ /* Direct from ULPD, no real parent */
+ .parent = &armper_ck.clk,
+ .rate = 48000000,
+ .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
+ .enable_bit = CONF_MOD_UART1_CLK_MODE_R,
+ },
+ .sysc_addr = 0xfffb0054,
+};
+
+/*
+ * XXX The enable_bit here is misused - it simply switches between 12MHz
+ * and 48MHz. Reimplement with clksel.
+ *
+ * XXX does this need SYSC register handling?
+ */
+static struct clk uart2_ck = {
+ .name = "uart2_ck",
+ .ops = &clkops_null,
+ /* Direct from ULPD, no real parent */
+ .parent = &armper_ck.clk,
+ .rate = 12000000,
+ .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
+ .enable_bit = CONF_MOD_UART2_CLK_MODE_R,
+ .set_rate = &omap1_set_uart_rate,
+ .recalc = &omap1_uart_recalc,
+};
+
+/*
+ * XXX The enable_bit here is misused - it simply switches between 12MHz
+ * and 48MHz. Reimplement with clksel.
+ *
+ * XXX does this need SYSC register handling?
+ */
+static struct clk uart3_1510 = {
+ .name = "uart3_ck",
+ .ops = &clkops_null,
+ /* Direct from ULPD, no real parent */
+ .parent = &armper_ck.clk,
+ .rate = 12000000,
+ .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
+ .enable_bit = CONF_MOD_UART3_CLK_MODE_R,
+ .set_rate = &omap1_set_uart_rate,
+ .recalc = &omap1_uart_recalc,
+};
+
+/*
+ * XXX The enable_bit here is misused - it simply switches between 12MHz
+ * and 48MHz. Reimplement with clksel.
+ *
+ * XXX SYSC register handling does not belong in the clock framework
+ */
+static struct uart_clk uart3_16xx = {
+ .clk = {
+ .name = "uart3_ck",
+ .ops = &clkops_uart_16xx,
+ /* Direct from ULPD, no real parent */
+ .parent = &armper_ck.clk,
+ .rate = 48000000,
+ .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
+ .enable_bit = CONF_MOD_UART3_CLK_MODE_R,
+ },
+ .sysc_addr = 0xfffb9854,
+};
+
+static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
+ .name = "usb_clko",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent */
+ .rate = 6000000,
+ .flags = ENABLE_REG_32BIT,
+ .enable_reg = OMAP1_IO_ADDRESS(ULPD_CLOCK_CTRL),
+ .enable_bit = USB_MCLK_EN_BIT,
+};
+
+static struct clk usb_hhc_ck1510 = {
+ .name = "usb_hhc_ck",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent */
+ .rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
+ .flags = ENABLE_REG_32BIT,
+ .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
+ .enable_bit = USB_HOST_HHC_UHOST_EN,
+};
+
+static struct clk usb_hhc_ck16xx = {
+ .name = "usb_hhc_ck",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent */
+ .rate = 48000000,
+ /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
+ .flags = ENABLE_REG_32BIT,
+ .enable_reg = OMAP1_IO_ADDRESS(OTG_BASE + 0x08), /* OTG_SYSCON_2 */
+ .enable_bit = OTG_SYSCON_2_UHOST_EN_SHIFT
+};
+
+static struct clk usb_dc_ck = {
+ .name = "usb_dc_ck",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent */
+ .rate = 48000000,
+ .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
+ .enable_bit = USB_REQ_EN_SHIFT,
+};
+
+static struct clk usb_dc_ck7xx = {
+ .name = "usb_dc_ck",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent */
+ .rate = 48000000,
+ .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
+ .enable_bit = SOFT_USB_OTG_DPLL_REQ_SHIFT,
+};
+
+static struct clk uart1_7xx = {
+ .name = "uart1_ck",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent */
+ .rate = 12000000,
+ .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
+ .enable_bit = 9,
+};
+
+static struct clk uart2_7xx = {
+ .name = "uart2_ck",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent */
+ .rate = 12000000,
+ .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
+ .enable_bit = 11,
+};
+
+static struct clk mclk_1510 = {
+ .name = "mclk",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .rate = 12000000,
+ .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
+ .enable_bit = SOFT_COM_MCKO_REQ_SHIFT,
+};
+
+static struct clk mclk_16xx = {
+ .name = "mclk",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .enable_reg = OMAP1_IO_ADDRESS(COM_CLK_DIV_CTRL_SEL),
+ .enable_bit = COM_ULPD_PLL_CLK_REQ,
+ .set_rate = &omap1_set_ext_clk_rate,
+ .round_rate = &omap1_round_ext_clk_rate,
+ .init = &omap1_init_ext_clk,
+};
+
+static struct clk bclk_1510 = {
+ .name = "bclk",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .rate = 12000000,
+};
+
+static struct clk bclk_16xx = {
+ .name = "bclk",
+ .ops = &clkops_generic,
+ /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .enable_reg = OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL),
+ .enable_bit = SWD_ULPD_PLL_CLK_REQ,
+ .set_rate = &omap1_set_ext_clk_rate,
+ .round_rate = &omap1_round_ext_clk_rate,
+ .init = &omap1_init_ext_clk,
+};
+
+static struct clk mmc1_ck = {
+ .name = "mmc1_ck",
+ .ops = &clkops_generic,
+ /* Functional clock is direct from ULPD, interface clock is ARMPER */
+ .parent = &armper_ck.clk,
+ .rate = 48000000,
+ .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
+ .enable_bit = CONF_MOD_MMC_SD_CLK_REQ_R,
+};
+
+/*
+ * XXX MOD_CONF_CTRL_0 bit 20 is defined in the 1510 TRM as
+ * CONF_MOD_MCBSP3_AUXON ??
+ */
+static struct clk mmc2_ck = {
+ .name = "mmc2_ck",
+ .ops = &clkops_generic,
+ /* Functional clock is direct from ULPD, interface clock is ARMPER */
+ .parent = &armper_ck.clk,
+ .rate = 48000000,
+ .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
+ .enable_bit = 20,
+};
+
+static struct clk mmc3_ck = {
+ .name = "mmc3_ck",
+ .ops = &clkops_generic,
+ /* Functional clock is direct from ULPD, interface clock is ARMPER */
+ .parent = &armper_ck.clk,
+ .rate = 48000000,
+ .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
+ .enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
+ .enable_bit = SOFT_MMC_DPLL_REQ_SHIFT,
+};
+
+static struct clk virtual_ck_mpu = {
+ .name = "mpu",
+ .ops = &clkops_null,
+ .parent = &arm_ck, /* Is smarter alias for */
+ .recalc = &followparent_recalc,
+ .set_rate = &omap1_select_table_rate,
+ .round_rate = &omap1_round_to_table_rate,
+};
+
+/* 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",
+ .ops = &clkops_null,
+ .flags = CLOCK_NO_IDLE_PARENT,
+ .parent = &armxor_ck.clk,
+ .recalc = &followparent_recalc,
+};
+
+static struct clk i2c_ick = {
+ .name = "i2c_ick",
+ .ops = &clkops_null,
+ .flags = CLOCK_NO_IDLE_PARENT,
+ .parent = &armper_ck.clk,
+ .recalc = &followparent_recalc,
+};
+
+/*
+ * clkdev integration
+ */
+
+static struct omap_clk omap_clks[] = {
+ /* non-ULPD clocks */
+ CLK(NULL, "ck_ref", &ck_ref, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK(NULL, "ck_dpll1", &ck_dpll1, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ /* CK_GEN1 clocks */
+ CLK(NULL, "ck_dpll1out", &ck_dpll1out.clk, CK_16XX),
+ CLK(NULL, "ck_sossi", &sossi_ck, CK_16XX),
+ CLK(NULL, "arm_ck", &arm_ck, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "armper_ck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310),
+ CLK("omap_gpio.0", "ick", &arm_gpio_ck, CK_1510 | CK_310),
+ CLK(NULL, "armxor_ck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK(NULL, "armtim_ck", &armtim_ck.clk, CK_16XX | CK_1510 | CK_310),
+ CLK("omap_wdt", "fck", &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310),
+ CLK("omap_wdt", "ick", &armper_ck.clk, CK_16XX),
+ CLK("omap_wdt", "ick", &dummy_ck, CK_1510 | CK_310),
+ CLK(NULL, "arminth_ck", &arminth_ck1510, CK_1510 | CK_310),
+ CLK(NULL, "arminth_ck", &arminth_ck16xx, CK_16XX),
+ /* CK_GEN2 clocks */
+ CLK(NULL, "dsp_ck", &dsp_ck, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dspmmu_ck", &dspmmu_ck, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dspper_ck", &dspper_ck, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dspxor_ck", &dspxor_ck, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dsptim_ck", &dsptim_ck, CK_16XX | CK_1510 | CK_310),
+ /* CK_GEN3 clocks */
+ CLK(NULL, "tc_ck", &tc_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK(NULL, "tipb_ck", &tipb_ck, CK_1510 | CK_310),
+ CLK(NULL, "l3_ocpi_ck", &l3_ocpi_ck, CK_16XX | CK_7XX),
+ CLK(NULL, "tc1_ck", &tc1_ck, CK_16XX),
+ CLK(NULL, "tc2_ck", &tc2_ck, CK_16XX),
+ CLK(NULL, "dma_ck", &dma_ck, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dma_lcdfree_ck", &dma_lcdfree_ck, CK_16XX),
+ CLK(NULL, "api_ck", &api_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK(NULL, "lb_ck", &lb_ck.clk, CK_1510 | CK_310),
+ CLK(NULL, "rhea1_ck", &rhea1_ck, CK_16XX),
+ CLK(NULL, "rhea2_ck", &rhea2_ck, CK_16XX),
+ CLK(NULL, "lcd_ck", &lcd_ck_16xx, CK_16XX | CK_7XX),
+ CLK(NULL, "lcd_ck", &lcd_ck_1510.clk, CK_1510 | CK_310),
+ /* ULPD clocks */
+ CLK(NULL, "uart1_ck", &uart1_1510, CK_1510 | CK_310),
+ CLK(NULL, "uart1_ck", &uart1_16xx.clk, CK_16XX),
+ CLK(NULL, "uart1_ck", &uart1_7xx, CK_7XX),
+ CLK(NULL, "uart2_ck", &uart2_ck, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "uart2_ck", &uart2_7xx, CK_7XX),
+ CLK(NULL, "uart3_ck", &uart3_1510, CK_1510 | CK_310),
+ CLK(NULL, "uart3_ck", &uart3_16xx.clk, CK_16XX),
+ CLK(NULL, "usb_clko", &usb_clko, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "usb_hhc_ck", &usb_hhc_ck1510, CK_1510 | CK_310),
+ CLK(NULL, "usb_hhc_ck", &usb_hhc_ck16xx, CK_16XX),
+ CLK(NULL, "usb_dc_ck", &usb_dc_ck, CK_16XX),
+ CLK(NULL, "usb_dc_ck", &usb_dc_ck7xx, CK_7XX),
+ CLK(NULL, "mclk", &mclk_1510, CK_1510 | CK_310),
+ CLK(NULL, "mclk", &mclk_16xx, CK_16XX),
+ CLK(NULL, "bclk", &bclk_1510, CK_1510 | CK_310),
+ CLK(NULL, "bclk", &bclk_16xx, CK_16XX),
+ CLK("mmci-omap.0", "fck", &mmc1_ck, CK_16XX | CK_1510 | CK_310),
+ CLK("mmci-omap.0", "fck", &mmc3_ck, CK_7XX),
+ CLK("mmci-omap.0", "ick", &armper_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK("mmci-omap.1", "fck", &mmc2_ck, CK_16XX),
+ CLK("mmci-omap.1", "ick", &armper_ck.clk, CK_16XX),
+ /* Virtual clocks */
+ CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310),
+ CLK("omap_i2c.1", "fck", &i2c_fck, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK("omap_i2c.1", "ick", &i2c_ick, CK_16XX),
+ CLK("omap_i2c.1", "ick", &dummy_ck, CK_1510 | CK_310 | CK_7XX),
+ CLK("omap1_spi100k.1", "fck", &dummy_ck, CK_7XX),
+ CLK("omap1_spi100k.1", "ick", &dummy_ck, CK_7XX),
+ CLK("omap1_spi100k.2", "fck", &dummy_ck, CK_7XX),
+ CLK("omap1_spi100k.2", "ick", &dummy_ck, CK_7XX),
+ CLK("omap_uwire", "fck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310),
+ CLK("omap-mcbsp.1", "ick", &dspper_ck, CK_16XX),
+ CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_1510 | CK_310),
+ CLK("omap-mcbsp.2", "ick", &armper_ck.clk, CK_16XX),
+ CLK("omap-mcbsp.2", "ick", &dummy_ck, CK_1510 | CK_310),
+ CLK("omap-mcbsp.3", "ick", &dspper_ck, CK_16XX),
+ CLK("omap-mcbsp.3", "ick", &dummy_ck, CK_1510 | CK_310),
+ CLK("omap-mcbsp.1", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310),
+ CLK("omap-mcbsp.2", "fck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310),
+ CLK("omap-mcbsp.3", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310),
+};
+
+/*
+ * init
+ */
+
+static struct clk_functions omap1_clk_functions = {
+ .clk_enable = omap1_clk_enable,
+ .clk_disable = omap1_clk_disable,
+ .clk_round_rate = omap1_clk_round_rate,
+ .clk_set_rate = omap1_clk_set_rate,
+ .clk_disable_unused = omap1_clk_disable_unused,
+};
+
+int __init omap1_clk_init(void)
+{
+ struct omap_clk *c;
+ const struct omap_clock_config *info;
+ int crystal_type = 0; /* Default 12 MHz */
+ u32 reg, cpu_mask;
+
+#ifdef CONFIG_DEBUG_LL
+ /*
+ * Resets some clocks that may be left on from bootloader,
+ * but leaves serial clocks on.
+ */
+ omap_writel(0x3 << 29, MOD_CONF_CTRL_0);
+#endif
+
+ /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
+ reg = omap_readw(SOFT_REQ_REG) & (1 << 4);
+ omap_writew(reg, SOFT_REQ_REG);
+ if (!cpu_is_omap15xx())
+ omap_writew(0, SOFT_REQ_REG2);
+
+ clk_init(&omap1_clk_functions);
+
+ /* By default all idlect1 clocks are allowed to idle */
+ arm_idlect1_mask = ~0;
+
+ for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
+ clk_preinit(c->lk.clk);
+
+ cpu_mask = 0;
+ if (cpu_is_omap16xx())
+ cpu_mask |= CK_16XX;
+ if (cpu_is_omap1510())
+ cpu_mask |= CK_1510;
+ if (cpu_is_omap7xx())
+ cpu_mask |= CK_7XX;
+ if (cpu_is_omap310())
+ cpu_mask |= CK_310;
+
+ for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
+ if (c->cpu & cpu_mask) {
+ clkdev_add(&c->lk);
+ clk_register(c->lk.clk);
+ }
+
+ /* Pointers to these clocks are needed by code in clock.c */
+ api_ck_p = clk_get(NULL, "api_ck");
+ ck_dpll1_p = clk_get(NULL, "ck_dpll1");
+ ck_ref_p = clk_get(NULL, "ck_ref");
+
+ info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
+ if (info != NULL) {
+ if (!cpu_is_omap15xx())
+ crystal_type = info->system_clock_type;
+ }
+
+ if (cpu_is_omap7xx())
+ ck_ref.rate = 13000000;
+ if (cpu_is_omap16xx() && crystal_type == 2)
+ ck_ref.rate = 19200000;
+
+ pr_info("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: "
+ "0x%04x\n", omap_readw(ARM_SYSST), omap_readw(DPLL_CTL),
+ omap_readw(ARM_CKCTL));
+
+ /* We want to be in syncronous scalable mode */
+ omap_writew(0x1000, ARM_SYSST);
+
+#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER
+ /* Use values set by bootloader. Determine PLL rate and recalculate
+ * dependent clocks as if kernel had changed PLL or divisors.
+ */
+ {
+ unsigned pll_ctl_val = omap_readw(DPLL_CTL);
+
+ ck_dpll1.rate = ck_ref.rate; /* Base xtal rate */
+ if (pll_ctl_val & 0x10) {
+ /* PLL enabled, apply multiplier and divisor */
+ if (pll_ctl_val & 0xf80)
+ ck_dpll1.rate *= (pll_ctl_val & 0xf80) >> 7;
+ ck_dpll1.rate /= ((pll_ctl_val & 0x60) >> 5) + 1;
+ } else {
+ /* PLL disabled, apply bypass divisor */
+ switch (pll_ctl_val & 0xc) {
+ case 0:
+ break;
+ case 0x4:
+ ck_dpll1.rate /= 2;
+ break;
+ default:
+ ck_dpll1.rate /= 4;
+ break;
+ }
+ }
+ }
+#else
+ /* Find the highest supported frequency and enable it */
+ if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
+ printk(KERN_ERR "System frequencies not set. Check your config.\n");
+ /* Guess sane values (60MHz) */
+ omap_writew(0x2290, DPLL_CTL);
+ omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL);
+ ck_dpll1.rate = 60000000;
+ }
+#endif
+ propagate_rate(&ck_dpll1);
+ /* Cache rates for clocks connected to ck_ref (not dpll1) */
+ propagate_rate(&ck_ref);
+ printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
+ "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
+ ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
+ ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
+ arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
+
+ if (machine_is_omap_perseus2() || machine_is_omap_fsample()) {
+ /* Select slicer output as OMAP input clock */
+ omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1,
+ OMAP7XX_PCC_UPLD_CTRL);
+ }
+
+ /* Amstrad Delta wants BCLK high when inactive */
+ if (machine_is_ams_delta())
+ omap_writel(omap_readl(ULPD_CLOCK_CTRL) |
+ (1 << SDW_MCLK_INV_BIT),
+ ULPD_CLOCK_CTRL);
+
+ /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */
+ /* (on 730, bit 13 must not be cleared) */
+ if (cpu_is_omap7xx())
+ omap_writew(omap_readw(ARM_CKCTL) & 0x2fff, ARM_CKCTL);
+ else
+ omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
+
+ /* Put DSP/MPUI into reset until needed */
+ omap_writew(0, ARM_RSTCT1);
+ omap_writew(1, ARM_RSTCT2);
+ omap_writew(0x400, ARM_IDLECT1);
+
+ /*
+ * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
+ * of the ARM_IDLECT2 register must be set to zero. The power-on
+ * default value of this bit is one.
+ */
+ omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */
+
+ /*
+ * Only enable those clocks we will need, let the drivers
+ * enable other clocks as necessary
+ */
+ clk_enable(&armper_ck.clk);
+ clk_enable(&armxor_ck.clk);
+ clk_enable(&armtim_ck.clk); /* This should be done by timer code */
+
+ if (cpu_is_omap15xx())
+ clk_enable(&arm_gpio_ck);
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
new file mode 100644
index 00000000..36f26c3f
--- /dev/null
+++ b/arch/arm/mach-omap1/devices.c
@@ -0,0 +1,333 @@
+/*
+ * linux/arch/arm/mach-omap1/devices.c
+ *
+ * OMAP1 platform device setup/initialization
+ *
+ * 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/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+
+#include <mach/camera.h>
+#include <mach/hardware.h>
+#include <asm/mach/map.h>
+
+#include <plat/tc.h>
+#include <plat/board.h>
+#include <plat/mux.h>
+#include <mach/gpio.h>
+#include <plat/mmc.h>
+#include <plat/omap7xx.h>
+#include <plat/mcbsp.h>
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE)
+
+#define OMAP_RTC_BASE 0xfffb4800
+
+static struct resource rtc_resources[] = {
+ {
+ .start = OMAP_RTC_BASE,
+ .end = OMAP_RTC_BASE + 0x5f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_RTC_TIMER,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = INT_RTC_ALARM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device omap_rtc_device = {
+ .name = "omap_rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+static void omap_init_rtc(void)
+{
+ (void) platform_device_register(&omap_rtc_device);
+}
+#else
+static inline void omap_init_rtc(void) {}
+#endif
+
+static inline void omap_init_mbox(void) { }
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+static inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
+ int controller_nr)
+{
+ if (controller_nr == 0) {
+ if (cpu_is_omap7xx()) {
+ omap_cfg_reg(MMC_7XX_CMD);
+ omap_cfg_reg(MMC_7XX_CLK);
+ omap_cfg_reg(MMC_7XX_DAT0);
+ } else {
+ omap_cfg_reg(MMC_CMD);
+ omap_cfg_reg(MMC_CLK);
+ omap_cfg_reg(MMC_DAT0);
+ }
+
+ if (cpu_is_omap1710()) {
+ omap_cfg_reg(M15_1710_MMC_CLKI);
+ omap_cfg_reg(P19_1710_MMC_CMDDIR);
+ omap_cfg_reg(P20_1710_MMC_DATDIR0);
+ }
+ if (mmc_controller->slots[0].wires == 4 && !cpu_is_omap7xx()) {
+ omap_cfg_reg(MMC_DAT1);
+ /* NOTE: DAT2 can be on W10 (here) or M15 */
+ if (!mmc_controller->slots[0].nomux)
+ omap_cfg_reg(MMC_DAT2);
+ omap_cfg_reg(MMC_DAT3);
+ }
+ }
+
+ /* Block 2 is on newer chips, and has many pinout options */
+ if (cpu_is_omap16xx() && controller_nr == 1) {
+ if (!mmc_controller->slots[1].nomux) {
+ omap_cfg_reg(Y8_1610_MMC2_CMD);
+ omap_cfg_reg(Y10_1610_MMC2_CLK);
+ omap_cfg_reg(R18_1610_MMC2_CLKIN);
+ omap_cfg_reg(W8_1610_MMC2_DAT0);
+ if (mmc_controller->slots[1].wires == 4) {
+ omap_cfg_reg(V8_1610_MMC2_DAT1);
+ omap_cfg_reg(W15_1610_MMC2_DAT2);
+ omap_cfg_reg(R10_1610_MMC2_DAT3);
+ }
+
+ /* These are needed for the level shifter */
+ omap_cfg_reg(V9_1610_MMC2_CMDDIR);
+ omap_cfg_reg(V5_1610_MMC2_DATDIR0);
+ omap_cfg_reg(W19_1610_MMC2_DATDIR1);
+ }
+
+ /* Feedback clock must be set on OMAP-1710 MMC2 */
+ if (cpu_is_omap1710())
+ omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
+ MOD_CONF_CTRL_1);
+ }
+}
+
+void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
+ int nr_controllers)
+{
+ int i;
+
+ for (i = 0; i < nr_controllers; i++) {
+ unsigned long base, size;
+ unsigned int irq = 0;
+
+ if (!mmc_data[i])
+ continue;
+
+ omap1_mmc_mux(mmc_data[i], i);
+
+ switch (i) {
+ case 0:
+ base = OMAP1_MMC1_BASE;
+ irq = INT_MMC;
+ break;
+ case 1:
+ if (!cpu_is_omap16xx())
+ return;
+ base = OMAP1_MMC2_BASE;
+ irq = INT_1610_MMC2;
+ break;
+ default:
+ continue;
+ }
+ size = OMAP1_MMC_SIZE;
+
+ omap_mmc_add("mmci-omap", i, base, size, irq, mmc_data[i]);
+ };
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* OMAP7xx SPI support */
+#if defined(CONFIG_SPI_OMAP_100K) || defined(CONFIG_SPI_OMAP_100K_MODULE)
+
+struct platform_device omap_spi1 = {
+ .name = "omap1_spi100k",
+ .id = 1,
+};
+
+struct platform_device omap_spi2 = {
+ .name = "omap1_spi100k",
+ .id = 2,
+};
+
+static void omap_init_spi100k(void)
+{
+ omap_spi1.dev.platform_data = ioremap(OMAP7XX_SPI1_BASE, 0x7ff);
+ if (omap_spi1.dev.platform_data)
+ platform_device_register(&omap_spi1);
+
+ omap_spi2.dev.platform_data = ioremap(OMAP7XX_SPI2_BASE, 0x7ff);
+ if (omap_spi2.dev.platform_data)
+ platform_device_register(&omap_spi2);
+}
+
+#else
+static inline void omap_init_spi100k(void)
+{
+}
+#endif
+
+
+#define OMAP1_CAMERA_BASE 0xfffb6800
+#define OMAP1_CAMERA_IOSIZE 0x1c
+
+static struct resource omap1_camera_resources[] = {
+ [0] = {
+ .start = OMAP1_CAMERA_BASE,
+ .end = OMAP1_CAMERA_BASE + OMAP1_CAMERA_IOSIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_CAMERA,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 omap1_camera_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device omap1_camera_device = {
+ .name = "omap1-camera",
+ .id = 0, /* This is used to put cameras on this interface */
+ .dev = {
+ .dma_mask = &omap1_camera_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(omap1_camera_resources),
+ .resource = omap1_camera_resources,
+};
+
+void __init omap1_camera_init(void *info)
+{
+ struct platform_device *dev = &omap1_camera_device;
+ int ret;
+
+ dev->dev.platform_data = info;
+
+ ret = platform_device_register(dev);
+ if (ret)
+ dev_err(&dev->dev, "unable to register device: %d\n", ret);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static inline void omap_init_sti(void) {}
+
+#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE)
+
+static struct platform_device omap_pcm = {
+ .name = "omap-pcm-audio",
+ .id = -1,
+};
+
+OMAP_MCBSP_PLATFORM_DEVICE(1);
+OMAP_MCBSP_PLATFORM_DEVICE(2);
+OMAP_MCBSP_PLATFORM_DEVICE(3);
+
+static void omap_init_audio(void)
+{
+ platform_device_register(&omap_mcbsp1);
+ platform_device_register(&omap_mcbsp2);
+ if (!cpu_is_omap7xx())
+ platform_device_register(&omap_mcbsp3);
+ platform_device_register(&omap_pcm);
+}
+
+#else
+static inline void omap_init_audio(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):
+ *
+ * (a) Does any "standard config" pin muxing needed. Board-specific
+ * code will have muxed GPIO pins and done "nonstandard" setup;
+ * that code could live in the boot loader.
+ * (b) Populating board-specific platform_data with the data drivers
+ * rely on to handle wiring variations.
+ * (c) Creating platform devices as meaningful on this board and
+ * with this kernel configuration.
+ *
+ * Claiming GPIOs, and setting their direction and initial values, is the
+ * responsibility of the device drivers. So is responding to probe().
+ *
+ * Board-specific knowledge like creating devices or pin setup is to be
+ * kept out of drivers as much as possible. In particular, pin setup
+ * may be handled by the boot loader, and drivers should expect it will
+ * normally have been done by the time they're probed.
+ */
+static int __init omap1_init_devices(void)
+{
+ if (!cpu_class_is_omap1())
+ return -ENODEV;
+
+ /* please keep these calls, and their implementations above,
+ * in alphabetical order so they're easier to sort through.
+ */
+
+ omap_init_mbox();
+ omap_init_rtc();
+ omap_init_spi100k();
+ omap_init_sti();
+ omap_init_audio();
+
+ return 0;
+}
+arch_initcall(omap1_init_devices);
+
+#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
+
+static struct resource wdt_resources[] = {
+ {
+ .start = 0xfffeb000,
+ .end = 0xfffeb07F,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device omap_wdt_device = {
+ .name = "omap_wdt",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(wdt_resources),
+ .resource = wdt_resources,
+};
+
+static int __init omap_init_wdt(void)
+{
+ if (!cpu_is_omap16xx())
+ return -ENODEV;
+
+ return platform_device_register(&omap_wdt_device);
+}
+subsys_initcall(omap_init_wdt);
+#endif
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
new file mode 100644
index 00000000..f5a52204
--- /dev/null
+++ b/arch/arm/mach-omap1/dma.c
@@ -0,0 +1,391 @@
+/*
+ * OMAP1/OMAP7xx - specific DMA driver
+ *
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
+ * Graphics DMA and LCD DMA graphics tranformations
+ * by Imre Deak <imre.deak@nokia.com>
+ * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
+ * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Converted DMA library into platform driver
+ * - G, Manjunath Kondaiah <manjugk@ti.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/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <plat/dma.h>
+#include <plat/tc.h>
+#include <plat/irqs.h>
+
+#define OMAP1_DMA_BASE (0xfffed800)
+#define OMAP1_LOGICAL_DMA_CH_COUNT 17
+#define OMAP1_DMA_STRIDE 0x40
+
+static u32 errata;
+static u32 enable_1510_mode;
+static u8 dma_stride;
+static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end;
+
+static u16 reg_map[] = {
+ [GCR] = 0x400,
+ [GSCR] = 0x404,
+ [GRST1] = 0x408,
+ [HW_ID] = 0x442,
+ [PCH2_ID] = 0x444,
+ [PCH0_ID] = 0x446,
+ [PCH1_ID] = 0x448,
+ [PCHG_ID] = 0x44a,
+ [PCHD_ID] = 0x44c,
+ [CAPS_0] = 0x44e,
+ [CAPS_1] = 0x452,
+ [CAPS_2] = 0x456,
+ [CAPS_3] = 0x458,
+ [CAPS_4] = 0x45a,
+ [PCH2_SR] = 0x460,
+ [PCH0_SR] = 0x480,
+ [PCH1_SR] = 0x482,
+ [PCHD_SR] = 0x4c0,
+
+ /* Common Registers */
+ [CSDP] = 0x00,
+ [CCR] = 0x02,
+ [CICR] = 0x04,
+ [CSR] = 0x06,
+ [CEN] = 0x10,
+ [CFN] = 0x12,
+ [CSFI] = 0x14,
+ [CSEI] = 0x16,
+ [CPC] = 0x18, /* 15xx only */
+ [CSAC] = 0x18,
+ [CDAC] = 0x1a,
+ [CDEI] = 0x1c,
+ [CDFI] = 0x1e,
+ [CLNK_CTRL] = 0x28,
+
+ /* Channel specific register offsets */
+ [CSSA] = 0x08,
+ [CDSA] = 0x0c,
+ [COLOR] = 0x20,
+ [CCR2] = 0x24,
+ [LCH_CTRL] = 0x2a,
+};
+
+static struct resource res[] __initdata = {
+ [0] = {
+ .start = OMAP1_DMA_BASE,
+ .end = OMAP1_DMA_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "0",
+ .start = INT_DMA_CH0_6,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .name = "1",
+ .start = INT_DMA_CH1_7,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .name = "2",
+ .start = INT_DMA_CH2_8,
+ .flags = IORESOURCE_IRQ,
+ },
+ [4] = {
+ .name = "3",
+ .start = INT_DMA_CH3,
+ .flags = IORESOURCE_IRQ,
+ },
+ [5] = {
+ .name = "4",
+ .start = INT_DMA_CH4,
+ .flags = IORESOURCE_IRQ,
+ },
+ [6] = {
+ .name = "5",
+ .start = INT_DMA_CH5,
+ .flags = IORESOURCE_IRQ,
+ },
+ /* Handled in lcd_dma.c */
+ [7] = {
+ .name = "6",
+ .start = INT_1610_DMA_CH6,
+ .flags = IORESOURCE_IRQ,
+ },
+ /* irq's for omap16xx and omap7xx */
+ [8] = {
+ .name = "7",
+ .start = INT_1610_DMA_CH7,
+ .flags = IORESOURCE_IRQ,
+ },
+ [9] = {
+ .name = "8",
+ .start = INT_1610_DMA_CH8,
+ .flags = IORESOURCE_IRQ,
+ },
+ [10] = {
+ .name = "9",
+ .start = INT_1610_DMA_CH9,
+ .flags = IORESOURCE_IRQ,
+ },
+ [11] = {
+ .name = "10",
+ .start = INT_1610_DMA_CH10,
+ .flags = IORESOURCE_IRQ,
+ },
+ [12] = {
+ .name = "11",
+ .start = INT_1610_DMA_CH11,
+ .flags = IORESOURCE_IRQ,
+ },
+ [13] = {
+ .name = "12",
+ .start = INT_1610_DMA_CH12,
+ .flags = IORESOURCE_IRQ,
+ },
+ [14] = {
+ .name = "13",
+ .start = INT_1610_DMA_CH13,
+ .flags = IORESOURCE_IRQ,
+ },
+ [15] = {
+ .name = "14",
+ .start = INT_1610_DMA_CH14,
+ .flags = IORESOURCE_IRQ,
+ },
+ [16] = {
+ .name = "15",
+ .start = INT_1610_DMA_CH15,
+ .flags = IORESOURCE_IRQ,
+ },
+ [17] = {
+ .name = "16",
+ .start = INT_DMA_LCD,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static void __iomem *dma_base;
+static inline void dma_write(u32 val, int reg, int lch)
+{
+ u8 stride;
+ u32 offset;
+
+ stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+ offset = reg_map[reg] + (stride * lch);
+
+ __raw_writew(val, dma_base + offset);
+ if ((reg > CLNK_CTRL && reg < CCEN) ||
+ (reg > PCHD_ID && reg < CAPS_2)) {
+ u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+ __raw_writew(val >> 16, dma_base + offset2);
+ }
+}
+
+static inline u32 dma_read(int reg, int lch)
+{
+ u8 stride;
+ u32 offset, val;
+
+ stride = (reg >= dma_common_ch_start) ? dma_stride : 0;
+ offset = reg_map[reg] + (stride * lch);
+
+ val = __raw_readw(dma_base + offset);
+ if ((reg > CLNK_CTRL && reg < CCEN) ||
+ (reg > PCHD_ID && reg < CAPS_2)) {
+ u16 upper;
+ u32 offset2 = reg_map[reg] + 2 + (stride * lch);
+ upper = __raw_readw(dma_base + offset2);
+ val |= (upper << 16);
+ }
+ return val;
+}
+
+static void omap1_clear_lch_regs(int lch)
+{
+ int i = dma_common_ch_start;
+
+ for (; i <= dma_common_ch_end; i += 1)
+ dma_write(0, i, lch);
+}
+
+static void omap1_clear_dma(int lch)
+{
+ u32 l;
+
+ l = dma_read(CCR, lch);
+ l &= ~OMAP_DMA_CCR_EN;
+ dma_write(l, CCR, lch);
+
+ /* Clear pending interrupts */
+ l = dma_read(CSR, lch);
+}
+
+static void omap1_show_dma_caps(void)
+{
+ if (enable_1510_mode) {
+ printk(KERN_INFO "DMA support for OMAP15xx initialized\n");
+ } else {
+ u16 w;
+ printk(KERN_INFO "OMAP DMA hardware version %d\n",
+ dma_read(HW_ID, 0));
+ printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
+ dma_read(CAPS_0, 0), dma_read(CAPS_1, 0),
+ dma_read(CAPS_2, 0), dma_read(CAPS_3, 0),
+ dma_read(CAPS_4, 0));
+
+ /* Disable OMAP 3.0/3.1 compatibility mode. */
+ w = dma_read(GSCR, 0);
+ w |= 1 << 3;
+ dma_write(w, GSCR, 0);
+ }
+ return;
+}
+
+static u32 configure_dma_errata(void)
+{
+
+ /*
+ * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is
+ * read before the DMA controller finished disabling the channel.
+ */
+ if (!cpu_is_omap15xx())
+ SET_DMA_ERRATA(DMA_ERRATA_3_3);
+
+ return errata;
+}
+
+static int __init omap1_system_dma_init(void)
+{
+ struct omap_system_dma_plat_info *p;
+ struct omap_dma_dev_attr *d;
+ struct platform_device *pdev;
+ int ret;
+
+ pdev = platform_device_alloc("omap_dma_system", 0);
+ if (!pdev) {
+ pr_err("%s: Unable to device alloc for dma\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ dma_base = ioremap(res[0].start, resource_size(&res[0]));
+ if (!dma_base) {
+ pr_err("%s: Unable to ioremap\n", __func__);
+ ret = -ENODEV;
+ goto exit_device_put;
+ }
+
+ ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+ __func__, pdev->name, pdev->id);
+ goto exit_device_put;
+ }
+
+ p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL);
+ if (!p) {
+ dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n",
+ __func__, pdev->name);
+ ret = -ENOMEM;
+ goto exit_device_del;
+ }
+
+ d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL);
+ if (!d) {
+ dev_err(&pdev->dev, "%s: Unable to allocate 'd' for %s\n",
+ __func__, pdev->name);
+ ret = -ENOMEM;
+ goto exit_release_p;
+ }
+
+ d->lch_count = OMAP1_LOGICAL_DMA_CH_COUNT;
+
+ /* Valid attributes for omap1 plus processors */
+ if (cpu_is_omap15xx())
+ d->dev_caps = ENABLE_1510_MODE;
+ enable_1510_mode = d->dev_caps & ENABLE_1510_MODE;
+
+ d->dev_caps |= SRC_PORT;
+ d->dev_caps |= DST_PORT;
+ d->dev_caps |= SRC_INDEX;
+ d->dev_caps |= DST_INDEX;
+ d->dev_caps |= IS_BURST_ONLY4;
+ d->dev_caps |= CLEAR_CSR_ON_READ;
+ d->dev_caps |= IS_WORD_16;
+
+
+ d->chan = kzalloc(sizeof(struct omap_dma_lch) *
+ (d->lch_count), GFP_KERNEL);
+ if (!d->chan) {
+ dev_err(&pdev->dev, "%s: Memory allocation failed"
+ "for d->chan!!!\n", __func__);
+ goto exit_release_d;
+ }
+
+ if (cpu_is_omap15xx())
+ d->chan_count = 9;
+ else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
+ if (!(d->dev_caps & ENABLE_1510_MODE))
+ d->chan_count = 16;
+ else
+ d->chan_count = 9;
+ }
+
+ p->dma_attr = d;
+
+ p->show_dma_caps = omap1_show_dma_caps;
+ p->clear_lch_regs = omap1_clear_lch_regs;
+ p->clear_dma = omap1_clear_dma;
+ p->dma_write = dma_write;
+ p->dma_read = dma_read;
+ p->disable_irq_lch = NULL;
+
+ p->errata = configure_dma_errata();
+
+ ret = platform_device_add_data(pdev, p, sizeof(*p));
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+ __func__, pdev->name, pdev->id);
+ goto exit_release_chan;
+ }
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n",
+ __func__, pdev->name, pdev->id);
+ goto exit_release_chan;
+ }
+
+ dma_stride = OMAP1_DMA_STRIDE;
+ dma_common_ch_start = CPC;
+ dma_common_ch_end = COLOR;
+
+ return ret;
+
+exit_release_chan:
+ kfree(d->chan);
+exit_release_d:
+ kfree(d);
+exit_release_p:
+ kfree(p);
+exit_device_del:
+ platform_device_del(pdev);
+exit_device_put:
+ platform_device_put(pdev);
+
+ return ret;
+}
+arch_initcall(omap1_system_dma_init);
diff --git a/arch/arm/mach-omap1/flash.c b/arch/arm/mach-omap1/flash.c
new file mode 100644
index 00000000..1749cb37
--- /dev/null
+++ b/arch/arm/mach-omap1/flash.c
@@ -0,0 +1,34 @@
+/*
+ * Flash support 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/mtd/mtd.h>
+#include <linux/mtd/map.h>
+
+#include <plat/io.h>
+#include <plat/tc.h>
+#include <plat/flash.h>
+
+void omap1_set_vpp(struct platform_device *pdev, int enable)
+{
+ static int count;
+ u32 l;
+
+ if (enable) {
+ if (count++ == 0) {
+ l = omap_readl(EMIFS_CONFIG);
+ l |= OMAP_EMIFS_CONFIG_WP;
+ omap_writel(l, EMIFS_CONFIG);
+ }
+ } else {
+ if (count && (--count == 0)) {
+ l = omap_readl(EMIFS_CONFIG);
+ l &= ~OMAP_EMIFS_CONFIG_WP;
+ omap_writel(l, EMIFS_CONFIG);
+ }
+ }
+}
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
new file mode 100644
index 00000000..cddbf8b0
--- /dev/null
+++ b/arch/arm/mach-omap1/fpga.c
@@ -0,0 +1,188 @@
+/*
+ * linux/arch/arm/mach-omap1/fpga.c
+ *
+ * Interrupt handler for OMAP-1510 Innovator FPGA
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ *
+ * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
+ * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <plat/fpga.h>
+#include <mach/gpio.h>
+
+static void fpga_mask_irq(struct irq_data *d)
+{
+ unsigned int irq = d->irq - OMAP_FPGA_IRQ_BASE;
+
+ if (irq < 8)
+ __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO)
+ & ~(1 << irq)), OMAP1510_FPGA_IMR_LO);
+ else if (irq < 16)
+ __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_HI)
+ & ~(1 << (irq - 8))), OMAP1510_FPGA_IMR_HI);
+ else
+ __raw_writeb((__raw_readb(INNOVATOR_FPGA_IMR2)
+ & ~(1 << (irq - 16))), INNOVATOR_FPGA_IMR2);
+}
+
+
+static inline u32 get_fpga_unmasked_irqs(void)
+{
+ return
+ ((__raw_readb(OMAP1510_FPGA_ISR_LO) &
+ __raw_readb(OMAP1510_FPGA_IMR_LO))) |
+ ((__raw_readb(OMAP1510_FPGA_ISR_HI) &
+ __raw_readb(OMAP1510_FPGA_IMR_HI)) << 8) |
+ ((__raw_readb(INNOVATOR_FPGA_ISR2) &
+ __raw_readb(INNOVATOR_FPGA_IMR2)) << 16);
+}
+
+
+static void fpga_ack_irq(struct irq_data *d)
+{
+ /* Don't need to explicitly ACK FPGA interrupts */
+}
+
+static void fpga_unmask_irq(struct irq_data *d)
+{
+ unsigned int irq = d->irq - OMAP_FPGA_IRQ_BASE;
+
+ if (irq < 8)
+ __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) | (1 << irq)),
+ OMAP1510_FPGA_IMR_LO);
+ else if (irq < 16)
+ __raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_HI)
+ | (1 << (irq - 8))), OMAP1510_FPGA_IMR_HI);
+ else
+ __raw_writeb((__raw_readb(INNOVATOR_FPGA_IMR2)
+ | (1 << (irq - 16))), INNOVATOR_FPGA_IMR2);
+}
+
+static void fpga_mask_ack_irq(struct irq_data *d)
+{
+ fpga_mask_irq(d);
+ fpga_ack_irq(d);
+}
+
+void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc)
+{
+ u32 stat;
+ int fpga_irq;
+
+ stat = get_fpga_unmasked_irqs();
+
+ if (!stat)
+ return;
+
+ for (fpga_irq = OMAP_FPGA_IRQ_BASE;
+ (fpga_irq < OMAP_FPGA_IRQ_END) && stat;
+ fpga_irq++, stat >>= 1) {
+ if (stat & 1) {
+ generic_handle_irq(fpga_irq);
+ }
+ }
+}
+
+static struct irq_chip omap_fpga_irq_ack = {
+ .name = "FPGA-ack",
+ .irq_ack = fpga_mask_ack_irq,
+ .irq_mask = fpga_mask_irq,
+ .irq_unmask = fpga_unmask_irq,
+};
+
+
+static struct irq_chip omap_fpga_irq = {
+ .name = "FPGA",
+ .irq_ack = fpga_ack_irq,
+ .irq_mask = fpga_mask_irq,
+ .irq_unmask = fpga_unmask_irq,
+};
+
+/*
+ * All of the FPGA interrupt request inputs except for the touchscreen are
+ * edge-sensitive; the touchscreen is level-sensitive. The edge-sensitive
+ * interrupts are acknowledged as a side-effect of reading the interrupt
+ * status register from the FPGA. The edge-sensitive interrupt inputs
+ * cause a problem with level interrupt requests, such as Ethernet. The
+ * problem occurs when a level interrupt request is asserted while its
+ * interrupt input is masked in the FPGA, which results in a missed
+ * interrupt.
+ *
+ * In an attempt to workaround the problem with missed interrupts, the
+ * mask_ack routine for all of the FPGA interrupts has been changed from
+ * fpga_mask_ack_irq() to fpga_ack_irq() so that the specific FPGA interrupt
+ * being serviced is left unmasked. We can do this because the FPGA cascade
+ * interrupt is installed with the IRQF_DISABLED flag, which leaves all
+ * interrupts masked at the CPU while an FPGA interrupt handler executes.
+ *
+ * Limited testing indicates that this workaround appears to be effective
+ * for the smc9194 Ethernet driver used on the Innovator. It should work
+ * on other FPGA interrupts as well, but any drivers that explicitly mask
+ * interrupts at the interrupt controller via disable_irq/enable_irq
+ * could pose a problem.
+ */
+void omap1510_fpga_init_irq(void)
+{
+ int i, res;
+
+ __raw_writeb(0, OMAP1510_FPGA_IMR_LO);
+ __raw_writeb(0, OMAP1510_FPGA_IMR_HI);
+ __raw_writeb(0, INNOVATOR_FPGA_IMR2);
+
+ for (i = OMAP_FPGA_IRQ_BASE; i < OMAP_FPGA_IRQ_END; i++) {
+
+ if (i == OMAP1510_INT_FPGA_TS) {
+ /*
+ * The touchscreen interrupt is level-sensitive, so
+ * we'll use the regular mask_ack routine for it.
+ */
+ irq_set_chip(i, &omap_fpga_irq_ack);
+ }
+ else {
+ /*
+ * All FPGA interrupts except the touchscreen are
+ * edge-sensitive, so we won't mask them.
+ */
+ irq_set_chip(i, &omap_fpga_irq);
+ }
+
+ irq_set_handler(i, handle_edge_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+
+ /*
+ * The FPGA interrupt line is connected to GPIO13. Claim this pin for
+ * the ARM.
+ *
+ * NOTE: For general GPIO/MPUIO access and interrupts, please see
+ * gpio.[ch]
+ */
+ res = gpio_request(13, "FPGA irq");
+ if (res) {
+ pr_err("%s failed to get gpio\n", __func__);
+ return;
+ }
+ gpio_direction_input(13);
+ irq_set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
+ irq_set_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
+}
diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c
new file mode 100644
index 00000000..364137c2
--- /dev/null
+++ b/arch/arm/mach-omap1/gpio15xx.c
@@ -0,0 +1,99 @@
+/*
+ * OMAP15xx specific gpio init
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author:
+ * Charulatha V <charu@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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/gpio.h>
+
+#define OMAP1_MPUIO_VBASE OMAP1_MPUIO_BASE
+#define OMAP1510_GPIO_BASE 0xFFFCE000
+
+/* gpio1 */
+static struct __initdata resource omap15xx_mpu_gpio_resources[] = {
+ {
+ .start = OMAP1_MPUIO_VBASE,
+ .end = OMAP1_MPUIO_VBASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_MPUIO,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = {
+ .virtual_irq_start = IH_MPUIO_BASE,
+ .bank_type = METHOD_MPUIO,
+ .bank_width = 16,
+ .bank_stride = 1,
+};
+
+static struct platform_device omap15xx_mpu_gpio = {
+ .name = "omap_gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &omap15xx_mpu_gpio_config,
+ },
+ .num_resources = ARRAY_SIZE(omap15xx_mpu_gpio_resources),
+ .resource = omap15xx_mpu_gpio_resources,
+};
+
+/* gpio2 */
+static struct __initdata resource omap15xx_gpio_resources[] = {
+ {
+ .start = OMAP1510_GPIO_BASE,
+ .end = OMAP1510_GPIO_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_GPIO_BANK1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = {
+ .virtual_irq_start = IH_GPIO_BASE,
+ .bank_type = METHOD_GPIO_1510,
+ .bank_width = 16,
+};
+
+static struct platform_device omap15xx_gpio = {
+ .name = "omap_gpio",
+ .id = 1,
+ .dev = {
+ .platform_data = &omap15xx_gpio_config,
+ },
+ .num_resources = ARRAY_SIZE(omap15xx_gpio_resources),
+ .resource = omap15xx_gpio_resources,
+};
+
+/*
+ * omap15xx_gpio_init needs to be done before
+ * machine_init functions access gpio APIs.
+ * Hence omap15xx_gpio_init is a postcore_initcall.
+ */
+static int __init omap15xx_gpio_init(void)
+{
+ if (!cpu_is_omap15xx())
+ return -EINVAL;
+
+ platform_device_register(&omap15xx_mpu_gpio);
+ platform_device_register(&omap15xx_gpio);
+
+ gpio_bank_count = 2;
+ return 0;
+}
+postcore_initcall(omap15xx_gpio_init);
diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c
new file mode 100644
index 00000000..293a246e
--- /dev/null
+++ b/arch/arm/mach-omap1/gpio16xx.c
@@ -0,0 +1,200 @@
+/*
+ * OMAP16xx specific gpio init
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author:
+ * Charulatha V <charu@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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/gpio.h>
+
+#define OMAP1610_GPIO1_BASE 0xfffbe400
+#define OMAP1610_GPIO2_BASE 0xfffbec00
+#define OMAP1610_GPIO3_BASE 0xfffbb400
+#define OMAP1610_GPIO4_BASE 0xfffbbc00
+#define OMAP1_MPUIO_VBASE OMAP1_MPUIO_BASE
+
+/* mpu gpio */
+static struct __initdata resource omap16xx_mpu_gpio_resources[] = {
+ {
+ .start = OMAP1_MPUIO_VBASE,
+ .end = OMAP1_MPUIO_VBASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_MPUIO,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = {
+ .virtual_irq_start = IH_MPUIO_BASE,
+ .bank_type = METHOD_MPUIO,
+ .bank_width = 16,
+ .bank_stride = 1,
+};
+
+static struct platform_device omap16xx_mpu_gpio = {
+ .name = "omap_gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &omap16xx_mpu_gpio_config,
+ },
+ .num_resources = ARRAY_SIZE(omap16xx_mpu_gpio_resources),
+ .resource = omap16xx_mpu_gpio_resources,
+};
+
+/* gpio1 */
+static struct __initdata resource omap16xx_gpio1_resources[] = {
+ {
+ .start = OMAP1610_GPIO1_BASE,
+ .end = OMAP1610_GPIO1_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_GPIO_BANK1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = {
+ .virtual_irq_start = IH_GPIO_BASE,
+ .bank_type = METHOD_GPIO_1610,
+ .bank_width = 16,
+};
+
+static struct platform_device omap16xx_gpio1 = {
+ .name = "omap_gpio",
+ .id = 1,
+ .dev = {
+ .platform_data = &omap16xx_gpio1_config,
+ },
+ .num_resources = ARRAY_SIZE(omap16xx_gpio1_resources),
+ .resource = omap16xx_gpio1_resources,
+};
+
+/* gpio2 */
+static struct __initdata resource omap16xx_gpio2_resources[] = {
+ {
+ .start = OMAP1610_GPIO2_BASE,
+ .end = OMAP1610_GPIO2_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_1610_GPIO_BANK2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = {
+ .virtual_irq_start = IH_GPIO_BASE + 16,
+ .bank_type = METHOD_GPIO_1610,
+ .bank_width = 16,
+};
+
+static struct platform_device omap16xx_gpio2 = {
+ .name = "omap_gpio",
+ .id = 2,
+ .dev = {
+ .platform_data = &omap16xx_gpio2_config,
+ },
+ .num_resources = ARRAY_SIZE(omap16xx_gpio2_resources),
+ .resource = omap16xx_gpio2_resources,
+};
+
+/* gpio3 */
+static struct __initdata resource omap16xx_gpio3_resources[] = {
+ {
+ .start = OMAP1610_GPIO3_BASE,
+ .end = OMAP1610_GPIO3_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_1610_GPIO_BANK3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = {
+ .virtual_irq_start = IH_GPIO_BASE + 32,
+ .bank_type = METHOD_GPIO_1610,
+ .bank_width = 16,
+};
+
+static struct platform_device omap16xx_gpio3 = {
+ .name = "omap_gpio",
+ .id = 3,
+ .dev = {
+ .platform_data = &omap16xx_gpio3_config,
+ },
+ .num_resources = ARRAY_SIZE(omap16xx_gpio3_resources),
+ .resource = omap16xx_gpio3_resources,
+};
+
+/* gpio4 */
+static struct __initdata resource omap16xx_gpio4_resources[] = {
+ {
+ .start = OMAP1610_GPIO4_BASE,
+ .end = OMAP1610_GPIO4_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_1610_GPIO_BANK4,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = {
+ .virtual_irq_start = IH_GPIO_BASE + 48,
+ .bank_type = METHOD_GPIO_1610,
+ .bank_width = 16,
+};
+
+static struct platform_device omap16xx_gpio4 = {
+ .name = "omap_gpio",
+ .id = 4,
+ .dev = {
+ .platform_data = &omap16xx_gpio4_config,
+ },
+ .num_resources = ARRAY_SIZE(omap16xx_gpio4_resources),
+ .resource = omap16xx_gpio4_resources,
+};
+
+static struct __initdata platform_device * omap16xx_gpio_dev[] = {
+ &omap16xx_mpu_gpio,
+ &omap16xx_gpio1,
+ &omap16xx_gpio2,
+ &omap16xx_gpio3,
+ &omap16xx_gpio4,
+};
+
+/*
+ * omap16xx_gpio_init needs to be done before
+ * machine_init functions access gpio APIs.
+ * Hence omap16xx_gpio_init is a postcore_initcall.
+ */
+static int __init omap16xx_gpio_init(void)
+{
+ int i;
+
+ if (!cpu_is_omap16xx())
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(omap16xx_gpio_dev); i++)
+ platform_device_register(omap16xx_gpio_dev[i]);
+
+ gpio_bank_count = ARRAY_SIZE(omap16xx_gpio_dev);
+
+ return 0;
+}
+postcore_initcall(omap16xx_gpio_init);
diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c
new file mode 100644
index 00000000..c6ad248d
--- /dev/null
+++ b/arch/arm/mach-omap1/gpio7xx.c
@@ -0,0 +1,262 @@
+/*
+ * OMAP7xx specific gpio init
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author:
+ * Charulatha V <charu@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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/gpio.h>
+
+#define OMAP7XX_GPIO1_BASE 0xfffbc000
+#define OMAP7XX_GPIO2_BASE 0xfffbc800
+#define OMAP7XX_GPIO3_BASE 0xfffbd000
+#define OMAP7XX_GPIO4_BASE 0xfffbd800
+#define OMAP7XX_GPIO5_BASE 0xfffbe000
+#define OMAP7XX_GPIO6_BASE 0xfffbe800
+#define OMAP1_MPUIO_VBASE OMAP1_MPUIO_BASE
+
+/* mpu gpio */
+static struct __initdata resource omap7xx_mpu_gpio_resources[] = {
+ {
+ .start = OMAP1_MPUIO_VBASE,
+ .end = OMAP1_MPUIO_VBASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_7XX_MPUIO,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = {
+ .virtual_irq_start = IH_MPUIO_BASE,
+ .bank_type = METHOD_MPUIO,
+ .bank_width = 32,
+ .bank_stride = 2,
+};
+
+static struct platform_device omap7xx_mpu_gpio = {
+ .name = "omap_gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &omap7xx_mpu_gpio_config,
+ },
+ .num_resources = ARRAY_SIZE(omap7xx_mpu_gpio_resources),
+ .resource = omap7xx_mpu_gpio_resources,
+};
+
+/* gpio1 */
+static struct __initdata resource omap7xx_gpio1_resources[] = {
+ {
+ .start = OMAP7XX_GPIO1_BASE,
+ .end = OMAP7XX_GPIO1_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_7XX_GPIO_BANK1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = {
+ .virtual_irq_start = IH_GPIO_BASE,
+ .bank_type = METHOD_GPIO_7XX,
+ .bank_width = 32,
+};
+
+static struct platform_device omap7xx_gpio1 = {
+ .name = "omap_gpio",
+ .id = 1,
+ .dev = {
+ .platform_data = &omap7xx_gpio1_config,
+ },
+ .num_resources = ARRAY_SIZE(omap7xx_gpio1_resources),
+ .resource = omap7xx_gpio1_resources,
+};
+
+/* gpio2 */
+static struct __initdata resource omap7xx_gpio2_resources[] = {
+ {
+ .start = OMAP7XX_GPIO2_BASE,
+ .end = OMAP7XX_GPIO2_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_7XX_GPIO_BANK2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = {
+ .virtual_irq_start = IH_GPIO_BASE + 32,
+ .bank_type = METHOD_GPIO_7XX,
+ .bank_width = 32,
+};
+
+static struct platform_device omap7xx_gpio2 = {
+ .name = "omap_gpio",
+ .id = 2,
+ .dev = {
+ .platform_data = &omap7xx_gpio2_config,
+ },
+ .num_resources = ARRAY_SIZE(omap7xx_gpio2_resources),
+ .resource = omap7xx_gpio2_resources,
+};
+
+/* gpio3 */
+static struct __initdata resource omap7xx_gpio3_resources[] = {
+ {
+ .start = OMAP7XX_GPIO3_BASE,
+ .end = OMAP7XX_GPIO3_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_7XX_GPIO_BANK3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = {
+ .virtual_irq_start = IH_GPIO_BASE + 64,
+ .bank_type = METHOD_GPIO_7XX,
+ .bank_width = 32,
+};
+
+static struct platform_device omap7xx_gpio3 = {
+ .name = "omap_gpio",
+ .id = 3,
+ .dev = {
+ .platform_data = &omap7xx_gpio3_config,
+ },
+ .num_resources = ARRAY_SIZE(omap7xx_gpio3_resources),
+ .resource = omap7xx_gpio3_resources,
+};
+
+/* gpio4 */
+static struct __initdata resource omap7xx_gpio4_resources[] = {
+ {
+ .start = OMAP7XX_GPIO4_BASE,
+ .end = OMAP7XX_GPIO4_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_7XX_GPIO_BANK4,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = {
+ .virtual_irq_start = IH_GPIO_BASE + 96,
+ .bank_type = METHOD_GPIO_7XX,
+ .bank_width = 32,
+};
+
+static struct platform_device omap7xx_gpio4 = {
+ .name = "omap_gpio",
+ .id = 4,
+ .dev = {
+ .platform_data = &omap7xx_gpio4_config,
+ },
+ .num_resources = ARRAY_SIZE(omap7xx_gpio4_resources),
+ .resource = omap7xx_gpio4_resources,
+};
+
+/* gpio5 */
+static struct __initdata resource omap7xx_gpio5_resources[] = {
+ {
+ .start = OMAP7XX_GPIO5_BASE,
+ .end = OMAP7XX_GPIO5_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_7XX_GPIO_BANK5,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = {
+ .virtual_irq_start = IH_GPIO_BASE + 128,
+ .bank_type = METHOD_GPIO_7XX,
+ .bank_width = 32,
+};
+
+static struct platform_device omap7xx_gpio5 = {
+ .name = "omap_gpio",
+ .id = 5,
+ .dev = {
+ .platform_data = &omap7xx_gpio5_config,
+ },
+ .num_resources = ARRAY_SIZE(omap7xx_gpio5_resources),
+ .resource = omap7xx_gpio5_resources,
+};
+
+/* gpio6 */
+static struct __initdata resource omap7xx_gpio6_resources[] = {
+ {
+ .start = OMAP7XX_GPIO6_BASE,
+ .end = OMAP7XX_GPIO6_BASE + SZ_2K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_7XX_GPIO_BANK6,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = {
+ .virtual_irq_start = IH_GPIO_BASE + 160,
+ .bank_type = METHOD_GPIO_7XX,
+ .bank_width = 32,
+};
+
+static struct platform_device omap7xx_gpio6 = {
+ .name = "omap_gpio",
+ .id = 6,
+ .dev = {
+ .platform_data = &omap7xx_gpio6_config,
+ },
+ .num_resources = ARRAY_SIZE(omap7xx_gpio6_resources),
+ .resource = omap7xx_gpio6_resources,
+};
+
+static struct __initdata platform_device * omap7xx_gpio_dev[] = {
+ &omap7xx_mpu_gpio,
+ &omap7xx_gpio1,
+ &omap7xx_gpio2,
+ &omap7xx_gpio3,
+ &omap7xx_gpio4,
+ &omap7xx_gpio5,
+ &omap7xx_gpio6,
+};
+
+/*
+ * omap7xx_gpio_init needs to be done before
+ * machine_init functions access gpio APIs.
+ * Hence omap7xx_gpio_init is a postcore_initcall.
+ */
+static int __init omap7xx_gpio_init(void)
+{
+ int i;
+
+ if (!cpu_is_omap7xx())
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(omap7xx_gpio_dev); i++)
+ platform_device_register(omap7xx_gpio_dev[i]);
+
+ gpio_bank_count = ARRAY_SIZE(omap7xx_gpio_dev);
+
+ return 0;
+}
+postcore_initcall(omap7xx_gpio_init);
diff --git a/arch/arm/mach-omap1/i2c.c b/arch/arm/mach-omap1/i2c.c
new file mode 100644
index 00000000..5446c991
--- /dev/null
+++ b/arch/arm/mach-omap1/i2c.c
@@ -0,0 +1,35 @@
+/*
+ * Helper module for board specific I2C bus registration
+ *
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * 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.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <plat/i2c.h>
+#include <plat/mux.h>
+#include <plat/cpu.h>
+
+void __init omap1_i2c_mux_pins(int bus_id)
+{
+ if (cpu_is_omap7xx()) {
+ omap_cfg_reg(I2C_7XX_SDA);
+ omap_cfg_reg(I2C_7XX_SCL);
+ } else {
+ omap_cfg_reg(I2C_SDA);
+ omap_cfg_reg(I2C_SCL);
+ }
+}
diff --git a/arch/arm/mach-omap1/id.c b/arch/arm/mach-omap1/id.c
new file mode 100644
index 00000000..a0e3560b
--- /dev/null
+++ b/arch/arm/mach-omap1/id.c
@@ -0,0 +1,204 @@
+/*
+ * linux/arch/arm/mach-omap1/id.c
+ *
+ * OMAP1 CPU identification code
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Written by 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <plat/cpu.h>
+
+#define OMAP_DIE_ID_0 0xfffe1800
+#define OMAP_DIE_ID_1 0xfffe1804
+#define OMAP_PRODUCTION_ID_0 0xfffe2000
+#define OMAP_PRODUCTION_ID_1 0xfffe2004
+#define OMAP32_ID_0 0xfffed400
+#define OMAP32_ID_1 0xfffed404
+
+struct omap_id {
+ u16 jtag_id; /* Used to determine OMAP type */
+ u8 die_rev; /* Processor revision */
+ u32 omap_id; /* OMAP revision */
+ u32 type; /* Cpu id bits [31:08], cpu class bits [07:00] */
+};
+
+static unsigned int omap_revision;
+
+/* Register values to detect the OMAP version */
+static struct omap_id omap_ids[] __initdata = {
+ { .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000},
+ { .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
+ { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
+ { .jtag_id = 0xb62c, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x08500000},
+ { .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
+ { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000},
+ { .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000},
+ { .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00},
+ { .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00},
+ { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
+ { .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
+ { .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000},
+ { .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00},
+ { .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00},
+ { .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300},
+ { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300},
+ { .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300},
+ { .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000},
+ { .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000},
+ { .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000},
+};
+
+unsigned int omap_rev(void)
+{
+ return omap_revision;
+}
+EXPORT_SYMBOL(omap_rev);
+
+/*
+ * Get OMAP type from PROD_ID.
+ * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM.
+ * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense.
+ * Undocumented register in TEST BLOCK is used as fallback; This seems to
+ * work on 1510, 1610 & 1710. The official way hopefully will work in future
+ * processors.
+ */
+static u16 __init omap_get_jtag_id(void)
+{
+ u32 prod_id, omap_id;
+
+ prod_id = omap_readl(OMAP_PRODUCTION_ID_1);
+ omap_id = omap_readl(OMAP32_ID_1);
+
+ /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730/850 */
+ if (((prod_id >> 20) == 0) || (prod_id == omap_id))
+ prod_id = 0;
+ else
+ prod_id &= 0xffff;
+
+ if (prod_id)
+ return prod_id;
+
+ /* Use OMAP32_ID_1 as fallback */
+ prod_id = ((omap_id >> 12) & 0xffff);
+
+ return prod_id;
+}
+
+/*
+ * Get OMAP revision from DIE_REV.
+ * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID.
+ * Undocumented register in the TEST BLOCK is used as fallback.
+ * REVISIT: This does not seem to work on 1510
+ */
+static u8 __init omap_get_die_rev(void)
+{
+ u32 die_rev;
+
+ die_rev = omap_readl(OMAP_DIE_ID_1);
+
+ /* Check for broken OMAP_DIE_ID on early 1710 */
+ if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id())
+ die_rev = 0;
+
+ die_rev = (die_rev >> 17) & 0xf;
+ if (die_rev)
+ return die_rev;
+
+ die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf;
+
+ return die_rev;
+}
+
+void __init omap_check_revision(void)
+{
+ int i;
+ u16 jtag_id;
+ u8 die_rev;
+ u32 omap_id;
+ u8 cpu_type;
+
+ jtag_id = omap_get_jtag_id();
+ die_rev = omap_get_die_rev();
+ omap_id = omap_readl(OMAP32_ID_0);
+
+#ifdef DEBUG
+ printk(KERN_DEBUG "OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0));
+ printk(KERN_DEBUG "OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n",
+ omap_readl(OMAP_DIE_ID_1),
+ (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf);
+ printk(KERN_DEBUG "OMAP_PRODUCTION_ID_0: 0x%08x\n",
+ omap_readl(OMAP_PRODUCTION_ID_0));
+ printk(KERN_DEBUG "OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n",
+ omap_readl(OMAP_PRODUCTION_ID_1),
+ omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff);
+ printk(KERN_DEBUG "OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0));
+ printk(KERN_DEBUG "OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1));
+ printk(KERN_DEBUG "JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev);
+#endif
+
+ system_serial_high = omap_readl(OMAP_DIE_ID_0);
+ system_serial_low = omap_readl(OMAP_DIE_ID_1);
+
+ /* First check only the major version in a safe way */
+ for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
+ if (jtag_id == (omap_ids[i].jtag_id)) {
+ omap_revision = omap_ids[i].type;
+ break;
+ }
+ }
+
+ /* Check if we can find the die revision */
+ for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
+ if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) {
+ omap_revision = omap_ids[i].type;
+ break;
+ }
+ }
+
+ /* Finally check also the omap_id */
+ for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
+ if (jtag_id == omap_ids[i].jtag_id
+ && die_rev == omap_ids[i].die_rev
+ && omap_id == omap_ids[i].omap_id) {
+ omap_revision = omap_ids[i].type;
+ break;
+ }
+ }
+
+ /* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */
+ cpu_type = omap_revision >> 24;
+
+ switch (cpu_type) {
+ case 0x07:
+ case 0x08:
+ omap_revision |= 0x07;
+ break;
+ case 0x03:
+ case 0x15:
+ omap_revision |= 0x15;
+ break;
+ case 0x16:
+ case 0x17:
+ omap_revision |= 0x16;
+ break;
+ default:
+ printk(KERN_INFO "Unknown OMAP cpu type: 0x%02x\n", cpu_type);
+ }
+
+ printk(KERN_INFO "OMAP%04x", omap_revision >> 16);
+ if ((omap_revision >> 8) & 0xff)
+ printk(KERN_INFO "%x", (omap_revision >> 8) & 0xff);
+ printk(KERN_INFO " revision %i handled as %02xxx id: %08x%08x\n",
+ die_rev, omap_revision & 0xff, system_serial_low,
+ system_serial_high);
+}
+
diff --git a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
new file mode 100644
index 00000000..23eed003
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
@@ -0,0 +1,79 @@
+/*
+ * arch/arm/mach-omap1/include/ams-delta-fiq.h
+ *
+ * Taken from the original Amstrad modifications to fiq.h
+ *
+ * Copyright (c) 2004 Amstrad Plc
+ * Copyright (c) 2006 Matt Callow
+ * Copyright (c) 2010 Janusz Krzysztofik
+ *
+ * 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.
+ */
+#ifndef __AMS_DELTA_FIQ_H
+#define __AMS_DELTA_FIQ_H
+
+#include <plat/irqs.h>
+
+/*
+ * Interrupt number used for passing control from FIQ to IRQ.
+ * IRQ12, described as reserved, has been selected.
+ */
+#define INT_DEFERRED_FIQ INT_1510_RES12
+/*
+ * Base address of an interrupt handler that the INT_DEFERRED_FIQ belongs to.
+ */
+#if (INT_DEFERRED_FIQ < IH2_BASE)
+#define DEFERRED_FIQ_IH_BASE OMAP_IH1_BASE
+#else
+#define DEFERRED_FIQ_IH_BASE OMAP_IH2_BASE
+#endif
+
+/*
+ * These are the offsets from the beginning of the fiq_buffer. They are put here
+ * since the buffer and header need to be accessed by drivers servicing devices
+ * which generate GPIO interrupts - e.g. keyboard, modem, hook switch.
+ */
+#define FIQ_MASK 0
+#define FIQ_STATE 1
+#define FIQ_KEYS_CNT 2
+#define FIQ_TAIL_OFFSET 3
+#define FIQ_HEAD_OFFSET 4
+#define FIQ_BUF_LEN 5
+#define FIQ_KEY 6
+#define FIQ_MISSED_KEYS 7
+#define FIQ_BUFFER_START 8
+#define FIQ_GPIO_INT_MASK 9
+#define FIQ_KEYS_HICNT 10
+#define FIQ_IRQ_PEND 11
+#define FIQ_SIR_CODE_L1 12
+#define IRQ_SIR_CODE_L2 13
+
+#define FIQ_CNT_INT_00 14
+#define FIQ_CNT_INT_KEY 15
+#define FIQ_CNT_INT_MDM 16
+#define FIQ_CNT_INT_03 17
+#define FIQ_CNT_INT_HSW 18
+#define FIQ_CNT_INT_05 19
+#define FIQ_CNT_INT_06 20
+#define FIQ_CNT_INT_07 21
+#define FIQ_CNT_INT_08 22
+#define FIQ_CNT_INT_09 23
+#define FIQ_CNT_INT_10 24
+#define FIQ_CNT_INT_11 25
+#define FIQ_CNT_INT_12 26
+#define FIQ_CNT_INT_13 27
+#define FIQ_CNT_INT_14 28
+#define FIQ_CNT_INT_15 29
+
+#define FIQ_CIRC_BUFF 30 /*Start of circular buffer */
+
+#ifndef __ASSEMBLER__
+extern unsigned int fiq_buffer[];
+extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;
+
+extern void __init ams_delta_init_fiq(void);
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/camera.h b/arch/arm/mach-omap1/include/mach/camera.h
new file mode 100644
index 00000000..847d00f0
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/camera.h
@@ -0,0 +1,13 @@
+#ifndef __ASM_ARCH_CAMERA_H_
+#define __ASM_ARCH_CAMERA_H_
+
+#include <media/omap1_camera.h>
+
+void omap1_camera_init(void *);
+
+static inline void omap1_set_camera_info(struct omap1_cam_platform_data *info)
+{
+ omap1_camera_init(info);
+}
+
+#endif /* __ASM_ARCH_CAMERA_H_ */
diff --git a/arch/arm/mach-omap1/include/mach/clkdev.h b/arch/arm/mach-omap1/include/mach/clkdev.h
new file mode 100644
index 00000000..ea8640e4
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/clkdev.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/clkdev.h
+ */
+
+#include <plat/clkdev.h>
diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S
new file mode 100644
index 00000000..62856044
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/debug-macro.S
@@ -0,0 +1,107 @@
+/* arch/arm/mach-omap1/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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/serial_reg.h>
+
+#include <asm/memory.h>
+
+#include <plat/serial.h>
+
+#define omap_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define omap_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
+ .pushsection .data
+omap_uart_phys: .word 0x0
+omap_uart_virt: .word 0x0
+ .popsection
+
+ /*
+ * Note that this code won't work if the bootloader passes
+ * a wrong machine ID number in r1. To debug, just hardcode
+ * the desired UART phys and virt addresses temporarily into
+ * the omap_uart_phys and omap_uart_virt above.
+ */
+ .macro addruart, rp, rv
+
+ /* Use omap_uart_phys/virt if already configured */
+9: mrc p15, 0, \rp, c1, c0
+ tst \rp, #1 @ MMU enabled?
+ ldreq \rp, =omap_uart_v2p(omap_uart_phys) @ MMU disabled
+ ldrne \rp, =omap_uart_phys @ MMU enabled
+ add \rv, \rp, #4 @ omap_uart_virt
+ ldr \rp, [\rp, #0]
+ ldr \rv, [\rv, #0]
+ cmp \rp, #0 @ is port configured?
+ cmpne \rv, #0
+ bne 99f @ already configured
+
+ /* Check the debug UART configuration set in uncompress.h */
+ mrc p15, 0, \rp, c1, c0
+ tst \rp, #1 @ MMU enabled?
+ ldreq \rp, =OMAP_UART_INFO @ MMU not enabled
+ ldrne \rp, =omap_uart_p2v(OMAP_UART_INFO) @ MMU enabled
+ ldr \rp, [\rp, #0]
+
+ /* Select the UART to use based on the UART1 scratchpad value */
+10: cmp \rp, #0 @ no port configured?
+ beq 11f @ if none, try to use UART1
+ cmp \rp, #OMAP1UART1
+ beq 11f @ configure OMAP1UART1
+ cmp \rp, #OMAP1UART2
+ beq 12f @ configure OMAP1UART2
+ cmp \rp, #OMAP1UART3
+ beq 13f @ configure OMAP2UART3
+
+ /* Configure the UART offset from the phys/virt base */
+11: mov \rp, #0x00fb0000 @ OMAP1UART1
+ b 98f
+12: mov \rp, #0x00fb0000 @ OMAP1UART1
+ orr \rp, \rp, #0x00000800 @ OMAP1UART2
+ b 98f
+13: mov \rp, #0x00fb0000 @ OMAP1UART1
+ orr \rp, \rp, #0x00000800 @ OMAP1UART2
+ orr \rp, \rp, #0x00009000 @ OMAP1UART3
+
+ /* Store both phys and virt address for the uart */
+98: add \rp, \rp, #0xff000000 @ phys base
+ mrc p15, 0, \rv, c1, c0
+ tst \rv, #1 @ MMU enabled?
+ ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled
+ ldrne \rv, =omap_uart_phys @ MMU enabled
+ str \rp, [\rv, #0]
+ sub \rp, \rp, #0xff000000 @ phys base
+ add \rp, \rp, #0xfe000000 @ virt base
+ add \rv, \rv, #4 @ omap_uart_lsr
+ str \rp, [\rv, #0]
+ b 9b
+99:
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx]
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldrb \rd, [\rx, #(UART_LSR << OMAP_PORT_SHIFT)]
+ and \rd, \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
+ teq \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
+ beq 1002f
+ ldrb \rd, [\rx, #(UART_LSR << OMAP7XX_PORT_SHIFT)]
+ and \rd, \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
+ teq \rd, #(UART_LSR_TEMT | UART_LSR_THRE)
+ bne 1001b
+1002:
+ .endm
+
+ .macro waituart,rd,rx
+ .endm
diff --git a/arch/arm/mach-omap1/include/mach/entry-macro.S b/arch/arm/mach-omap1/include/mach/entry-macro.S
new file mode 100644
index 00000000..bfb4fb1d
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/entry-macro.S
@@ -0,0 +1,46 @@
+/*
+ * arch/arm/mach-omap1/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for OMAP-based platforms
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <mach/hardware.h>
+#include <mach/io.h>
+#include <mach/irqs.h>
+#include <asm/hardware/gic.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, =OMAP1_IO_ADDRESS(OMAP_IH1_BASE)
+ ldr \irqnr, [\base, #IRQ_ITR_REG_OFFSET]
+ ldr \tmp, [\base, #IRQ_MIR_REG_OFFSET]
+ mov \irqstat, #0xffffffff
+ bic \tmp, \irqstat, \tmp
+ tst \irqnr, \tmp
+ beq 1510f
+
+ ldr \irqnr, [\base, #IRQ_SIR_FIQ_REG_OFFSET]
+ ldr \tmp, =omap_irq_flags @ irq flags address
+ ldr \tmp, [\tmp, #0] @ irq flags value
+ cmp \irqnr, #0
+ ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
+ cmpeq \irqnr, \tmp
+ ldreq \base, =OMAP1_IO_ADDRESS(OMAP_IH2_BASE)
+ ldreq \irqnr, [\base, #IRQ_SIR_IRQ_REG_OFFSET]
+ addeqs \irqnr, \irqnr, #32
+1510:
+ .endm
+
diff --git a/arch/arm/mach-omap1/include/mach/gpio.h b/arch/arm/mach-omap1/include/mach/gpio.h
new file mode 100644
index 00000000..e737706a
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/gpio.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/gpio.h
+ */
+
+#include <plat/gpio.h>
diff --git a/arch/arm/mach-omap1/include/mach/hardware.h b/arch/arm/mach-omap1/include/mach/hardware.h
new file mode 100644
index 00000000..a3f6287b
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/hardware.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/hardware.h
+ */
+
+#include <plat/hardware.h>
diff --git a/arch/arm/mach-omap1/include/mach/io.h b/arch/arm/mach-omap1/include/mach/io.h
new file mode 100644
index 00000000..57bdf74a
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/io.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/io.h
+ */
+
+#include <plat/io.h>
diff --git a/arch/arm/mach-omap1/include/mach/irqs.h b/arch/arm/mach-omap1/include/mach/irqs.h
new file mode 100644
index 00000000..9292fdc1
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/irqs.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/irqs.h
+ */
+
+#include <plat/irqs.h>
diff --git a/arch/arm/mach-omap1/include/mach/lcd_dma.h b/arch/arm/mach-omap1/include/mach/lcd_dma.h
new file mode 100644
index 00000000..d7a457bb
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/lcd_dma.h
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-omap1/include/mach/lcd_dma.h
+ *
+ * Extracted from arch/arm/plat-omap/include/plat/dma.h
+ * Copyright (C) 2003 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.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
+ */
+#ifndef __MACH_OMAP1_LCD_DMA_H__
+#define __MACH_OMAP1_LCD_DMA_H__
+
+/* Hardware registers for LCD DMA */
+#define OMAP1510_DMA_LCD_BASE (0xfffedb00)
+#define OMAP1510_DMA_LCD_CTRL (OMAP1510_DMA_LCD_BASE + 0x00)
+#define OMAP1510_DMA_LCD_TOP_F1_L (OMAP1510_DMA_LCD_BASE + 0x02)
+#define OMAP1510_DMA_LCD_TOP_F1_U (OMAP1510_DMA_LCD_BASE + 0x04)
+#define OMAP1510_DMA_LCD_BOT_F1_L (OMAP1510_DMA_LCD_BASE + 0x06)
+#define OMAP1510_DMA_LCD_BOT_F1_U (OMAP1510_DMA_LCD_BASE + 0x08)
+
+#define OMAP1610_DMA_LCD_BASE (0xfffee300)
+#define OMAP1610_DMA_LCD_CSDP (OMAP1610_DMA_LCD_BASE + 0xc0)
+#define OMAP1610_DMA_LCD_CCR (OMAP1610_DMA_LCD_BASE + 0xc2)
+#define OMAP1610_DMA_LCD_CTRL (OMAP1610_DMA_LCD_BASE + 0xc4)
+#define OMAP1610_DMA_LCD_TOP_B1_L (OMAP1610_DMA_LCD_BASE + 0xc8)
+#define OMAP1610_DMA_LCD_TOP_B1_U (OMAP1610_DMA_LCD_BASE + 0xca)
+#define OMAP1610_DMA_LCD_BOT_B1_L (OMAP1610_DMA_LCD_BASE + 0xcc)
+#define OMAP1610_DMA_LCD_BOT_B1_U (OMAP1610_DMA_LCD_BASE + 0xce)
+#define OMAP1610_DMA_LCD_TOP_B2_L (OMAP1610_DMA_LCD_BASE + 0xd0)
+#define OMAP1610_DMA_LCD_TOP_B2_U (OMAP1610_DMA_LCD_BASE + 0xd2)
+#define OMAP1610_DMA_LCD_BOT_B2_L (OMAP1610_DMA_LCD_BASE + 0xd4)
+#define OMAP1610_DMA_LCD_BOT_B2_U (OMAP1610_DMA_LCD_BASE + 0xd6)
+#define OMAP1610_DMA_LCD_SRC_EI_B1 (OMAP1610_DMA_LCD_BASE + 0xd8)
+#define OMAP1610_DMA_LCD_SRC_FI_B1_L (OMAP1610_DMA_LCD_BASE + 0xda)
+#define OMAP1610_DMA_LCD_SRC_EN_B1 (OMAP1610_DMA_LCD_BASE + 0xe0)
+#define OMAP1610_DMA_LCD_SRC_FN_B1 (OMAP1610_DMA_LCD_BASE + 0xe4)
+#define OMAP1610_DMA_LCD_LCH_CTRL (OMAP1610_DMA_LCD_BASE + 0xea)
+#define OMAP1610_DMA_LCD_SRC_FI_B1_U (OMAP1610_DMA_LCD_BASE + 0xf4)
+
+/* LCD DMA block numbers */
+enum {
+ OMAP_LCD_DMA_B1_TOP,
+ OMAP_LCD_DMA_B1_BOTTOM,
+ OMAP_LCD_DMA_B2_TOP,
+ OMAP_LCD_DMA_B2_BOTTOM
+};
+
+/* LCD DMA functions */
+extern int omap_request_lcd_dma(void (*callback)(u16 status, void *data),
+ void *data);
+extern void omap_free_lcd_dma(void);
+extern void omap_setup_lcd_dma(void);
+extern void omap_enable_lcd_dma(void);
+extern void omap_stop_lcd_dma(void);
+extern void omap_set_lcd_dma_ext_controller(int external);
+extern void omap_set_lcd_dma_single_transfer(int single);
+extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
+ int data_type);
+extern void omap_set_lcd_dma_b1_rotation(int rotate);
+extern void omap_set_lcd_dma_b1_vxres(unsigned long vxres);
+extern void omap_set_lcd_dma_b1_mirror(int mirror);
+extern void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale);
+
+extern int omap_lcd_dma_running(void);
+
+#endif /* __MACH_OMAP1_LCD_DMA_H__ */
diff --git a/arch/arm/mach-omap1/include/mach/lcdc.h b/arch/arm/mach-omap1/include/mach/lcdc.h
new file mode 100644
index 00000000..89bd703a
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/lcdc.h
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-omap1/include/mach/lcdc.h
+ *
+ * Extracted from drivers/video/omap/lcdc.c
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.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.
+ */
+#ifndef __MACH_LCDC_H__
+#define __MACH_LCDC_H__
+
+#define OMAP_LCDC_BASE 0xfffec000
+#define OMAP_LCDC_SIZE 256
+#define OMAP_LCDC_IRQ INT_LCD_CTRL
+
+#define OMAP_LCDC_CONTROL (OMAP_LCDC_BASE + 0x00)
+#define OMAP_LCDC_TIMING0 (OMAP_LCDC_BASE + 0x04)
+#define OMAP_LCDC_TIMING1 (OMAP_LCDC_BASE + 0x08)
+#define OMAP_LCDC_TIMING2 (OMAP_LCDC_BASE + 0x0c)
+#define OMAP_LCDC_STATUS (OMAP_LCDC_BASE + 0x10)
+#define OMAP_LCDC_SUBPANEL (OMAP_LCDC_BASE + 0x14)
+#define OMAP_LCDC_LINE_INT (OMAP_LCDC_BASE + 0x18)
+#define OMAP_LCDC_DISPLAY_STATUS (OMAP_LCDC_BASE + 0x1c)
+
+#define OMAP_LCDC_STAT_DONE (1 << 0)
+#define OMAP_LCDC_STAT_VSYNC (1 << 1)
+#define OMAP_LCDC_STAT_SYNC_LOST (1 << 2)
+#define OMAP_LCDC_STAT_ABC (1 << 3)
+#define OMAP_LCDC_STAT_LINE_INT (1 << 4)
+#define OMAP_LCDC_STAT_FUF (1 << 5)
+#define OMAP_LCDC_STAT_LOADED_PALETTE (1 << 6)
+
+#define OMAP_LCDC_CTRL_LCD_EN (1 << 0)
+#define OMAP_LCDC_CTRL_LCD_TFT (1 << 7)
+#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL (1 << 10)
+
+#define OMAP_LCDC_IRQ_VSYNC (1 << 2)
+#define OMAP_LCDC_IRQ_DONE (1 << 3)
+#define OMAP_LCDC_IRQ_LOADED_PALETTE (1 << 4)
+#define OMAP_LCDC_IRQ_LINE_NIRQ (1 << 5)
+#define OMAP_LCDC_IRQ_LINE (1 << 6)
+#define OMAP_LCDC_IRQ_MASK (((1 << 5) - 1) << 2)
+
+#endif /* __MACH_LCDC_H__ */
diff --git a/arch/arm/mach-omap1/include/mach/memory.h b/arch/arm/mach-omap1/include/mach/memory.h
new file mode 100644
index 00000000..e9b600c1
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/memory.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/memory.h
+ */
+
+#include <plat/memory.h>
diff --git a/arch/arm/mach-omap1/include/mach/mtd-xip.h b/arch/arm/mach-omap1/include/mach/mtd-xip.h
new file mode 100644
index 00000000..f82a8dca
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/mtd-xip.h
@@ -0,0 +1,61 @@
+/*
+ * MTD primitives for XIP support. Architecture specific functions.
+ *
+ * Do not include this file directly. It's included from linux/mtd/xip.h
+ *
+ * Author: Vladimir Barinov <vbarinov@embeddedalley.com>
+ *
+ * (c) 2005 MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express or
+ * implied.
+ */
+
+#ifndef __ARCH_OMAP_MTD_XIP_H__
+#define __ARCH_OMAP_MTD_XIP_H__
+
+#include <mach/hardware.h>
+#define OMAP_MPU_TIMER_BASE (0xfffec500)
+#define OMAP_MPU_TIMER_OFFSET 0x100
+
+typedef struct {
+ u32 cntl; /* CNTL_TIMER, R/W */
+ u32 load_tim; /* LOAD_TIM, W */
+ u32 read_tim; /* READ_TIM, R */
+} xip_omap_mpu_timer_regs_t;
+
+#define xip_omap_mpu_timer_base(n) \
+((volatile xip_omap_mpu_timer_regs_t*)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE + \
+ (n)*OMAP_MPU_TIMER_OFFSET))
+
+static inline unsigned long xip_omap_mpu_timer_read(int nr)
+{
+ volatile xip_omap_mpu_timer_regs_t* timer = xip_omap_mpu_timer_base(nr);
+ return timer->read_tim;
+}
+
+#define xip_irqpending() \
+ (omap_readl(OMAP_IH1_ITR) & ~omap_readl(OMAP_IH1_MIR))
+#define xip_currtime() (~xip_omap_mpu_timer_read(0))
+
+/*
+ * It's permitted to do approxmation for xip_elapsed_since macro
+ * (see linux/mtd/xip.h)
+ */
+
+#ifdef CONFIG_MACH_OMAP_PERSEUS2
+#define xip_elapsed_since(x) (signed)((~xip_omap_mpu_timer_read(0) - (x)) / 7)
+#else
+#define xip_elapsed_since(x) (signed)((~xip_omap_mpu_timer_read(0) - (x)) / 6)
+#endif
+
+/*
+ * xip_cpu_idle() is used when waiting for a delay equal or larger than
+ * the system timer tick period. This should put the CPU into idle mode
+ * to save power and to be woken up only when some interrupts are pending.
+ * As above, this should not rely upon standard kernel code.
+ */
+
+#define xip_cpu_idle() asm volatile ("mcr p15, 0, %0, c7, c0, 4" :: "r" (1))
+
+#endif /* __ARCH_OMAP_MTD_XIP_H__ */
diff --git a/arch/arm/mach-omap1/include/mach/smp.h b/arch/arm/mach-omap1/include/mach/smp.h
new file mode 100644
index 00000000..80a371c0
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/smp.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/smp.h
+ */
+
+#include <plat/smp.h>
diff --git a/arch/arm/mach-omap1/include/mach/system.h b/arch/arm/mach-omap1/include/mach/system.h
new file mode 100644
index 00000000..a6c1b3a1
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/system.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/system.h
+ */
+
+#include <plat/system.h>
diff --git a/arch/arm/mach-omap1/include/mach/timex.h b/arch/arm/mach-omap1/include/mach/timex.h
new file mode 100644
index 00000000..4793790d
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/timex.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/timex.h
+ */
+
+#include <plat/timex.h>
diff --git a/arch/arm/mach-omap1/include/mach/uncompress.h b/arch/arm/mach-omap1/include/mach/uncompress.h
new file mode 100644
index 00000000..0ff22dc0
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/uncompress.h
@@ -0,0 +1,5 @@
+/*
+ * arch/arm/mach-omap1/include/mach/uncompress.h
+ */
+
+#include <plat/uncompress.h>
diff --git a/arch/arm/mach-omap1/include/mach/vmalloc.h b/arch/arm/mach-omap1/include/mach/vmalloc.h
new file mode 100644
index 00000000..22ec4a47
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/mach-omap1/include/mach/vmalloc.h
+ *
+ * Copyright (C) 2000 Russell King.
+ *
+ * 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
+ */
+#define VMALLOC_END 0xd8000000UL
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
new file mode 100644
index 00000000..870886a2
--- /dev/null
+++ b/arch/arm/mach-omap1/io.c
@@ -0,0 +1,183 @@
+/*
+ * linux/arch/arm/mach-omap1/io.c
+ *
+ * OMAP1 I/O mapping code
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/tlb.h>
+#include <asm/mach/map.h>
+#include <plat/mux.h>
+#include <plat/tc.h>
+
+#include "clock.h"
+
+extern void omap_check_revision(void);
+extern void omap_sram_init(void);
+
+/*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+ */
+static struct map_desc omap_io_desc[] __initdata = {
+ {
+ .virtual = OMAP1_IO_VIRT,
+ .pfn = __phys_to_pfn(OMAP1_IO_PHYS),
+ .length = OMAP1_IO_SIZE,
+ .type = MT_DEVICE
+ }
+};
+
+#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
+static struct map_desc omap7xx_io_desc[] __initdata = {
+ {
+ .virtual = OMAP7XX_DSP_BASE,
+ .pfn = __phys_to_pfn(OMAP7XX_DSP_START),
+ .length = OMAP7XX_DSP_SIZE,
+ .type = MT_DEVICE
+ }, {
+ .virtual = OMAP7XX_DSPREG_BASE,
+ .pfn = __phys_to_pfn(OMAP7XX_DSPREG_START),
+ .length = OMAP7XX_DSPREG_SIZE,
+ .type = MT_DEVICE
+ }
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP15XX
+static struct map_desc omap1510_io_desc[] __initdata = {
+ {
+ .virtual = OMAP1510_DSP_BASE,
+ .pfn = __phys_to_pfn(OMAP1510_DSP_START),
+ .length = OMAP1510_DSP_SIZE,
+ .type = MT_DEVICE
+ }, {
+ .virtual = OMAP1510_DSPREG_BASE,
+ .pfn = __phys_to_pfn(OMAP1510_DSPREG_START),
+ .length = OMAP1510_DSPREG_SIZE,
+ .type = MT_DEVICE
+ }
+};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+static struct map_desc omap16xx_io_desc[] __initdata = {
+ {
+ .virtual = OMAP16XX_DSP_BASE,
+ .pfn = __phys_to_pfn(OMAP16XX_DSP_START),
+ .length = OMAP16XX_DSP_SIZE,
+ .type = MT_DEVICE
+ }, {
+ .virtual = OMAP16XX_DSPREG_BASE,
+ .pfn = __phys_to_pfn(OMAP16XX_DSPREG_START),
+ .length = OMAP16XX_DSPREG_SIZE,
+ .type = MT_DEVICE
+ }
+};
+#endif
+
+/*
+ * Maps common IO regions for omap1. This should only get called from
+ * board specific init.
+ */
+void __init omap1_map_common_io(void)
+{
+ iotable_init(omap_io_desc, ARRAY_SIZE(omap_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();
+
+ /* We want to check CPU revision early for cpu_is_omapxxxx() macros.
+ * IO space mapping must be initialized before we can do that.
+ */
+ omap_check_revision();
+
+#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
+ if (cpu_is_omap7xx()) {
+ iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc));
+ }
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ if (cpu_is_omap15xx()) {
+ iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
+ }
+#endif
+#if defined(CONFIG_ARCH_OMAP16XX)
+ if (cpu_is_omap16xx()) {
+ iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc));
+ }
+#endif
+
+ omap_sram_init();
+}
+
+/*
+ * Common low-level hardware init for omap1. This should only get called from
+ * board specific init.
+ */
+void __init omap1_init_common_hw(void)
+{
+ /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort
+ * on a Posted Write in the TIPB Bridge".
+ */
+ omap_writew(0x0, MPU_PUBLIC_TIPB_CNTL);
+ omap_writew(0x0, MPU_PRIVATE_TIPB_CNTL);
+
+ /* Must init clocks early to assure that timer interrupt works
+ */
+ omap1_clk_init();
+
+ omap1_mux_init();
+}
+
+/*
+ * NOTE: Please use ioremap + __raw_read/write where possible instead of these
+ */
+
+u8 omap_readb(u32 pa)
+{
+ return __raw_readb(OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_readb);
+
+u16 omap_readw(u32 pa)
+{
+ return __raw_readw(OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_readw);
+
+u32 omap_readl(u32 pa)
+{
+ return __raw_readl(OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_readl);
+
+void omap_writeb(u8 v, u32 pa)
+{
+ __raw_writeb(v, OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_writeb);
+
+void omap_writew(u16 v, u32 pa)
+{
+ __raw_writew(v, OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_writew);
+
+void omap_writel(u32 v, u32 pa)
+{
+ __raw_writel(v, OMAP1_IO_ADDRESS(pa));
+}
+EXPORT_SYMBOL(omap_writel);
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
new file mode 100644
index 00000000..5d3da7a6
--- /dev/null
+++ b/arch/arm/mach-omap1/irq.c
@@ -0,0 +1,247 @@
+/*
+ * linux/arch/arm/mach-omap1/irq.c
+ *
+ * Interrupt handler for all OMAP boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ * Major cleanups by Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * Completely re-written to support various OMAP chips with bank specific
+ * interrupt handlers.
+ *
+ * Some snippets of the code taken from the older OMAP interrupt handler
+ * Copyright (C) 2001 RidgeRun, Inc. Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * GPIO interrupt handler moved to gpio.c by Juha Yrjola
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <mach/gpio.h>
+#include <plat/cpu.h>
+
+#define IRQ_BANK(irq) ((irq) >> 5)
+#define IRQ_BIT(irq) ((irq) & 0x1f)
+
+struct omap_irq_bank {
+ unsigned long base_reg;
+ unsigned long trigger_map;
+ unsigned long wake_enable;
+};
+
+u32 omap_irq_flags;
+static unsigned int irq_bank_count;
+static struct omap_irq_bank *irq_banks;
+
+static inline unsigned int irq_bank_readl(int bank, int offset)
+{
+ return omap_readl(irq_banks[bank].base_reg + offset);
+}
+
+static inline void irq_bank_writel(unsigned long value, int bank, int offset)
+{
+ omap_writel(value, irq_banks[bank].base_reg + offset);
+}
+
+static void omap_ack_irq(struct irq_data *d)
+{
+ if (d->irq > 31)
+ omap_writel(0x1, OMAP_IH2_BASE + IRQ_CONTROL_REG_OFFSET);
+
+ omap_writel(0x1, OMAP_IH1_BASE + IRQ_CONTROL_REG_OFFSET);
+}
+
+static void omap_mask_irq(struct irq_data *d)
+{
+ int bank = IRQ_BANK(d->irq);
+ u32 l;
+
+ l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
+ l |= 1 << IRQ_BIT(d->irq);
+ omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
+}
+
+static void omap_unmask_irq(struct irq_data *d)
+{
+ int bank = IRQ_BANK(d->irq);
+ u32 l;
+
+ l = omap_readl(irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
+ l &= ~(1 << IRQ_BIT(d->irq));
+ omap_writel(l, irq_banks[bank].base_reg + IRQ_MIR_REG_OFFSET);
+}
+
+static void omap_mask_ack_irq(struct irq_data *d)
+{
+ omap_mask_irq(d);
+ omap_ack_irq(d);
+}
+
+static int omap_wake_irq(struct irq_data *d, unsigned int enable)
+{
+ int bank = IRQ_BANK(d->irq);
+
+ if (enable)
+ irq_banks[bank].wake_enable |= IRQ_BIT(d->irq);
+ else
+ irq_banks[bank].wake_enable &= ~IRQ_BIT(d->irq);
+
+ return 0;
+}
+
+
+/*
+ * Allows tuning the IRQ type and priority
+ *
+ * NOTE: There is currently no OMAP fiq handler for Linux. Read the
+ * mailing list threads on FIQ handlers if you are planning to
+ * add a FIQ handler for OMAP.
+ */
+static void omap_irq_set_cfg(int irq, int fiq, int priority, int trigger)
+{
+ signed int bank;
+ unsigned long val, offset;
+
+ bank = IRQ_BANK(irq);
+ /* FIQ is only available on bank 0 interrupts */
+ fiq = bank ? 0 : (fiq & 0x1);
+ val = fiq | ((priority & 0x1f) << 2) | ((trigger & 0x1) << 1);
+ offset = IRQ_ILR0_REG_OFFSET + IRQ_BIT(irq) * 0x4;
+ irq_bank_writel(val, bank, offset);
+}
+
+#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850)
+static struct omap_irq_bank omap7xx_irq_banks[] = {
+ { .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 },
+};
+static struct omap_irq_bank omap310_irq_banks[] = {
+ { .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_IH2_BASE + 0x100, .trigger_map = 0xffffb7ff },
+ { .base_reg = OMAP_IH2_BASE + 0x200, .trigger_map = 0xffffffff },
+};
+#endif
+
+static struct irq_chip omap_irq_chip = {
+ .name = "MPU",
+ .irq_ack = omap_mask_ack_irq,
+ .irq_mask = omap_mask_irq,
+ .irq_unmask = omap_unmask_irq,
+ .irq_set_wake = omap_wake_irq,
+};
+
+void __init omap_init_irq(void)
+{
+ int i, j;
+
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ if (cpu_is_omap7xx()) {
+ omap_irq_flags = INT_7XX_IH2_IRQ;
+ irq_banks = omap7xx_irq_banks;
+ irq_bank_count = ARRAY_SIZE(omap7xx_irq_banks);
+ }
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ if (cpu_is_omap1510()) {
+ omap_irq_flags = INT_1510_IH2_IRQ;
+ irq_banks = omap1510_irq_banks;
+ irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
+ }
+ if (cpu_is_omap310()) {
+ omap_irq_flags = INT_1510_IH2_IRQ;
+ irq_banks = omap310_irq_banks;
+ irq_bank_count = ARRAY_SIZE(omap310_irq_banks);
+ }
+#endif
+#if defined(CONFIG_ARCH_OMAP16XX)
+ if (cpu_is_omap16xx()) {
+ omap_irq_flags = INT_1510_IH2_IRQ;
+ irq_banks = omap1610_irq_banks;
+ irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
+ }
+#endif
+ printk("Total of %i interrupts in %i interrupt banks\n",
+ irq_bank_count * 32, irq_bank_count);
+
+ /* Mask and clear all interrupts */
+ for (i = 0; i < irq_bank_count; i++) {
+ irq_bank_writel(~0x0, i, IRQ_MIR_REG_OFFSET);
+ irq_bank_writel(0x0, i, IRQ_ITR_REG_OFFSET);
+ }
+
+ /* Clear any pending interrupts */
+ irq_bank_writel(0x03, 0, IRQ_CONTROL_REG_OFFSET);
+ irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET);
+
+ /* Enable interrupts in global mask */
+ if (cpu_is_omap7xx())
+ irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET);
+
+ /* Install the interrupt handlers for each bank */
+ for (i = 0; i < irq_bank_count; i++) {
+ for (j = i * 32; j < (i + 1) * 32; j++) {
+ int irq_trigger;
+
+ irq_trigger = irq_banks[i].trigger_map >> IRQ_BIT(j);
+ omap_irq_set_cfg(j, 0, 0, irq_trigger);
+
+ irq_set_chip_and_handler(j, &omap_irq_chip,
+ handle_level_irq);
+ set_irq_flags(j, IRQF_VALID);
+ }
+ }
+
+ /* Unmask level 2 handler */
+
+ if (cpu_is_omap7xx())
+ omap_unmask_irq(irq_get_irq_data(INT_7XX_IH2_IRQ));
+ else if (cpu_is_omap15xx())
+ omap_unmask_irq(irq_get_irq_data(INT_1510_IH2_IRQ));
+ else if (cpu_is_omap16xx())
+ omap_unmask_irq(irq_get_irq_data(INT_1610_IH2_IRQ));
+}
diff --git a/arch/arm/mach-omap1/lcd_dma.c b/arch/arm/mach-omap1/lcd_dma.c
new file mode 100644
index 00000000..45380935
--- /dev/null
+++ b/arch/arm/mach-omap1/lcd_dma.c
@@ -0,0 +1,451 @@
+/*
+ * linux/arch/arm/mach-omap1/lcd_dma.c
+ *
+ * Extracted from arch/arm/plat-omap/dma.c
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ * Author: Juha Yrjölä <juha.yrjola@nokia.com>
+ * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
+ * Graphics DMA and LCD DMA graphics tranformations
+ * by Imre Deak <imre.deak@nokia.com>
+ * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
+ * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com>
+ * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * Support functions for the OMAP internal DMA channels.
+ *
+ * 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/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/lcdc.h>
+#include <plat/dma.h>
+
+int omap_lcd_dma_running(void)
+{
+ /*
+ * On OMAP1510, internal LCD controller will start the transfer
+ * when it gets enabled, so assume DMA running if LCD enabled.
+ */
+ if (cpu_is_omap15xx())
+ if (omap_readw(OMAP_LCDC_CONTROL) & OMAP_LCDC_CTRL_LCD_EN)
+ return 1;
+
+ /* Check if LCD DMA is running */
+ if (cpu_is_omap16xx())
+ if (omap_readw(OMAP1610_DMA_LCD_CCR) & OMAP_DMA_CCR_EN)
+ return 1;
+
+ return 0;
+}
+
+static struct lcd_dma_info {
+ spinlock_t lock;
+ int reserved;
+ void (*callback)(u16 status, void *data);
+ void *cb_data;
+
+ int active;
+ unsigned long addr, size;
+ int rotate, data_type, xres, yres;
+ int vxres;
+ int mirror;
+ int xscale, yscale;
+ int ext_ctrl;
+ int src_port;
+ int single_transfer;
+} lcd_dma;
+
+void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
+ int data_type)
+{
+ lcd_dma.addr = addr;
+ lcd_dma.data_type = data_type;
+ lcd_dma.xres = fb_xres;
+ lcd_dma.yres = fb_yres;
+}
+EXPORT_SYMBOL(omap_set_lcd_dma_b1);
+
+void omap_set_lcd_dma_src_port(int port)
+{
+ lcd_dma.src_port = port;
+}
+
+void omap_set_lcd_dma_ext_controller(int external)
+{
+ lcd_dma.ext_ctrl = external;
+}
+EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
+
+void omap_set_lcd_dma_single_transfer(int single)
+{
+ lcd_dma.single_transfer = single;
+}
+EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
+
+void omap_set_lcd_dma_b1_rotation(int rotate)
+{
+ if (cpu_is_omap15xx()) {
+ printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n");
+ BUG();
+ return;
+ }
+ lcd_dma.rotate = rotate;
+}
+EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation);
+
+void omap_set_lcd_dma_b1_mirror(int mirror)
+{
+ if (cpu_is_omap15xx()) {
+ printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n");
+ BUG();
+ }
+ lcd_dma.mirror = mirror;
+}
+EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror);
+
+void omap_set_lcd_dma_b1_vxres(unsigned long vxres)
+{
+ if (cpu_is_omap15xx()) {
+ printk(KERN_ERR "DMA virtual resulotion is not supported "
+ "in 1510 mode\n");
+ BUG();
+ }
+ lcd_dma.vxres = vxres;
+}
+EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres);
+
+void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale)
+{
+ if (cpu_is_omap15xx()) {
+ printk(KERN_ERR "DMA scale is not supported in 1510 mode\n");
+ BUG();
+ }
+ lcd_dma.xscale = xscale;
+ lcd_dma.yscale = yscale;
+}
+EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale);
+
+static void set_b1_regs(void)
+{
+ unsigned long top, bottom;
+ int es;
+ u16 w;
+ unsigned long en, fn;
+ long ei, fi;
+ unsigned long vxres;
+ unsigned int xscale, yscale;
+
+ switch (lcd_dma.data_type) {
+ case OMAP_DMA_DATA_TYPE_S8:
+ es = 1;
+ break;
+ case OMAP_DMA_DATA_TYPE_S16:
+ es = 2;
+ break;
+ case OMAP_DMA_DATA_TYPE_S32:
+ es = 4;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres;
+ xscale = lcd_dma.xscale ? lcd_dma.xscale : 1;
+ yscale = lcd_dma.yscale ? lcd_dma.yscale : 1;
+ BUG_ON(vxres < lcd_dma.xres);
+
+#define PIXADDR(x, y) (lcd_dma.addr + \
+ ((y) * vxres * yscale + (x) * xscale) * es)
+#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1)
+
+ switch (lcd_dma.rotate) {
+ case 0:
+ if (!lcd_dma.mirror) {
+ top = PIXADDR(0, 0);
+ bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
+ /* 1510 DMA requires the bottom address to be 2 more
+ * than the actual last memory access location. */
+ if (cpu_is_omap15xx() &&
+ lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32)
+ bottom += 2;
+ ei = PIXSTEP(0, 0, 1, 0);
+ fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1);
+ } else {
+ top = PIXADDR(lcd_dma.xres - 1, 0);
+ bottom = PIXADDR(0, lcd_dma.yres - 1);
+ ei = PIXSTEP(1, 0, 0, 0);
+ fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1);
+ }
+ en = lcd_dma.xres;
+ fn = lcd_dma.yres;
+ break;
+ case 90:
+ if (!lcd_dma.mirror) {
+ top = PIXADDR(0, lcd_dma.yres - 1);
+ bottom = PIXADDR(lcd_dma.xres - 1, 0);
+ ei = PIXSTEP(0, 1, 0, 0);
+ fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1);
+ } else {
+ top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
+ bottom = PIXADDR(0, 0);
+ ei = PIXSTEP(0, 1, 0, 0);
+ fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1);
+ }
+ en = lcd_dma.yres;
+ fn = lcd_dma.xres;
+ break;
+ case 180:
+ if (!lcd_dma.mirror) {
+ top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
+ bottom = PIXADDR(0, 0);
+ ei = PIXSTEP(1, 0, 0, 0);
+ fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0);
+ } else {
+ top = PIXADDR(0, lcd_dma.yres - 1);
+ bottom = PIXADDR(lcd_dma.xres - 1, 0);
+ ei = PIXSTEP(0, 0, 1, 0);
+ fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0);
+ }
+ en = lcd_dma.xres;
+ fn = lcd_dma.yres;
+ break;
+ case 270:
+ if (!lcd_dma.mirror) {
+ top = PIXADDR(lcd_dma.xres - 1, 0);
+ bottom = PIXADDR(0, lcd_dma.yres - 1);
+ ei = PIXSTEP(0, 0, 0, 1);
+ fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0);
+ } else {
+ top = PIXADDR(0, 0);
+ bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
+ ei = PIXSTEP(0, 0, 0, 1);
+ fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0);
+ }
+ en = lcd_dma.yres;
+ fn = lcd_dma.xres;
+ break;
+ default:
+ BUG();
+ return; /* Suppress warning about uninitialized vars */
+ }
+
+ if (cpu_is_omap15xx()) {
+ omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U);
+ omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L);
+ omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U);
+ omap_writew(bottom, OMAP1510_DMA_LCD_BOT_F1_L);
+
+ return;
+ }
+
+ /* 1610 regs */
+ omap_writew(top >> 16, OMAP1610_DMA_LCD_TOP_B1_U);
+ omap_writew(top, OMAP1610_DMA_LCD_TOP_B1_L);
+ omap_writew(bottom >> 16, OMAP1610_DMA_LCD_BOT_B1_U);
+ omap_writew(bottom, OMAP1610_DMA_LCD_BOT_B1_L);
+
+ omap_writew(en, OMAP1610_DMA_LCD_SRC_EN_B1);
+ omap_writew(fn, OMAP1610_DMA_LCD_SRC_FN_B1);
+
+ w = omap_readw(OMAP1610_DMA_LCD_CSDP);
+ w &= ~0x03;
+ w |= lcd_dma.data_type;
+ omap_writew(w, OMAP1610_DMA_LCD_CSDP);
+
+ w = omap_readw(OMAP1610_DMA_LCD_CTRL);
+ /* Always set the source port as SDRAM for now*/
+ w &= ~(0x03 << 6);
+ if (lcd_dma.callback != NULL)
+ w |= 1 << 1; /* Block interrupt enable */
+ else
+ w &= ~(1 << 1);
+ omap_writew(w, OMAP1610_DMA_LCD_CTRL);
+
+ if (!(lcd_dma.rotate || lcd_dma.mirror ||
+ lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale))
+ return;
+
+ w = omap_readw(OMAP1610_DMA_LCD_CCR);
+ /* Set the double-indexed addressing mode */
+ w |= (0x03 << 12);
+ omap_writew(w, OMAP1610_DMA_LCD_CCR);
+
+ omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1);
+ omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U);
+ omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L);
+}
+
+static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id)
+{
+ u16 w;
+
+ w = omap_readw(OMAP1610_DMA_LCD_CTRL);
+ if (unlikely(!(w & (1 << 3)))) {
+ printk(KERN_WARNING "Spurious LCD DMA IRQ\n");
+ return IRQ_NONE;
+ }
+ /* Ack the IRQ */
+ w |= (1 << 3);
+ omap_writew(w, OMAP1610_DMA_LCD_CTRL);
+ lcd_dma.active = 0;
+ if (lcd_dma.callback != NULL)
+ lcd_dma.callback(w, lcd_dma.cb_data);
+
+ return IRQ_HANDLED;
+}
+
+int omap_request_lcd_dma(void (*callback)(u16 status, void *data),
+ void *data)
+{
+ spin_lock_irq(&lcd_dma.lock);
+ if (lcd_dma.reserved) {
+ spin_unlock_irq(&lcd_dma.lock);
+ printk(KERN_ERR "LCD DMA channel already reserved\n");
+ BUG();
+ return -EBUSY;
+ }
+ lcd_dma.reserved = 1;
+ spin_unlock_irq(&lcd_dma.lock);
+ lcd_dma.callback = callback;
+ lcd_dma.cb_data = data;
+ lcd_dma.active = 0;
+ lcd_dma.single_transfer = 0;
+ lcd_dma.rotate = 0;
+ lcd_dma.vxres = 0;
+ lcd_dma.mirror = 0;
+ lcd_dma.xscale = 0;
+ lcd_dma.yscale = 0;
+ lcd_dma.ext_ctrl = 0;
+ lcd_dma.src_port = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_request_lcd_dma);
+
+void omap_free_lcd_dma(void)
+{
+ spin_lock(&lcd_dma.lock);
+ if (!lcd_dma.reserved) {
+ spin_unlock(&lcd_dma.lock);
+ printk(KERN_ERR "LCD DMA is not reserved\n");
+ BUG();
+ return;
+ }
+ if (!cpu_is_omap15xx())
+ omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1,
+ OMAP1610_DMA_LCD_CCR);
+ lcd_dma.reserved = 0;
+ spin_unlock(&lcd_dma.lock);
+}
+EXPORT_SYMBOL(omap_free_lcd_dma);
+
+void omap_enable_lcd_dma(void)
+{
+ u16 w;
+
+ /*
+ * Set the Enable bit only if an external controller is
+ * connected. Otherwise the OMAP internal controller will
+ * start the transfer when it gets enabled.
+ */
+ if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl)
+ return;
+
+ w = omap_readw(OMAP1610_DMA_LCD_CTRL);
+ w |= 1 << 8;
+ omap_writew(w, OMAP1610_DMA_LCD_CTRL);
+
+ lcd_dma.active = 1;
+
+ w = omap_readw(OMAP1610_DMA_LCD_CCR);
+ w |= 1 << 7;
+ omap_writew(w, OMAP1610_DMA_LCD_CCR);
+}
+EXPORT_SYMBOL(omap_enable_lcd_dma);
+
+void omap_setup_lcd_dma(void)
+{
+ BUG_ON(lcd_dma.active);
+ if (!cpu_is_omap15xx()) {
+ /* Set some reasonable defaults */
+ omap_writew(0x5440, OMAP1610_DMA_LCD_CCR);
+ omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP);
+ omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL);
+ }
+ set_b1_regs();
+ if (!cpu_is_omap15xx()) {
+ u16 w;
+
+ w = omap_readw(OMAP1610_DMA_LCD_CCR);
+ /*
+ * If DMA was already active set the end_prog bit to have
+ * the programmed register set loaded into the active
+ * register set.
+ */
+ w |= 1 << 11; /* End_prog */
+ if (!lcd_dma.single_transfer)
+ w |= (3 << 8); /* Auto_init, repeat */
+ omap_writew(w, OMAP1610_DMA_LCD_CCR);
+ }
+}
+EXPORT_SYMBOL(omap_setup_lcd_dma);
+
+void omap_stop_lcd_dma(void)
+{
+ u16 w;
+
+ lcd_dma.active = 0;
+ if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl)
+ return;
+
+ w = omap_readw(OMAP1610_DMA_LCD_CCR);
+ w &= ~(1 << 7);
+ omap_writew(w, OMAP1610_DMA_LCD_CCR);
+
+ w = omap_readw(OMAP1610_DMA_LCD_CTRL);
+ w &= ~(1 << 8);
+ omap_writew(w, OMAP1610_DMA_LCD_CTRL);
+}
+EXPORT_SYMBOL(omap_stop_lcd_dma);
+
+static int __init omap_init_lcd_dma(void)
+{
+ int r;
+
+ if (!cpu_class_is_omap1())
+ return -ENODEV;
+
+ if (cpu_is_omap16xx()) {
+ u16 w;
+
+ /* this would prevent OMAP sleep */
+ w = omap_readw(OMAP1610_DMA_LCD_CTRL);
+ w &= ~(1 << 8);
+ omap_writew(w, OMAP1610_DMA_LCD_CTRL);
+ }
+
+ spin_lock_init(&lcd_dma.lock);
+
+ r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0,
+ "LCD DMA", NULL);
+ if (r != 0)
+ printk(KERN_ERR "unable to request IRQ for LCD DMA "
+ "(error %d)\n", r);
+
+ return r;
+}
+
+arch_initcall(omap_init_lcd_dma);
+
diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c
new file mode 100644
index 00000000..b4f9be52
--- /dev/null
+++ b/arch/arm/mach-omap1/leds-h2p2-debug.c
@@ -0,0 +1,167 @@
+/*
+ * linux/arch/arm/mach-omap1/leds-h2p2-debug.c
+ *
+ * Copyright 2003 by Texas Instruments Incorporated
+ *
+ * There are 16 LEDs on the debug board (all green); four may be used
+ * for logical 'green', 'amber', 'red', and 'blue' (after "claiming").
+ *
+ * The "surfer" expansion board and H2 sample board also have two-color
+ * green+red LEDs (in parallel), used here for timer and idle indicators.
+ */
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#include <plat/fpga.h>
+#include <mach/gpio.h>
+
+#include "leds.h"
+
+
+#define GPIO_LED_RED 3
+#define GPIO_LED_GREEN OMAP_MPUIO(4)
+
+
+#define LED_STATE_ENABLED 0x01
+#define LED_STATE_CLAIMED 0x02
+#define LED_TIMER_ON 0x04
+
+#define GPIO_IDLE GPIO_LED_GREEN
+#define GPIO_TIMER GPIO_LED_RED
+
+
+void h2p2_dbg_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ static struct h2p2_dbg_fpga __iomem *fpga;
+ static u16 led_state, hw_led_state;
+
+ local_irq_save(flags);
+
+ if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
+ goto done;
+
+ switch (evt) {
+ case led_start:
+ if (!fpga)
+ fpga = ioremap(H2P2_DBG_FPGA_START,
+ H2P2_DBG_FPGA_SIZE);
+ if (fpga) {
+ led_state |= LED_STATE_ENABLED;
+ __raw_writew(~0, &fpga->leds);
+ }
+ break;
+
+ case led_stop:
+ case led_halted:
+ /* all leds off during suspend or shutdown */
+
+ if (! machine_is_omap_perseus2()) {
+ gpio_set_value(GPIO_TIMER, 0);
+ gpio_set_value(GPIO_IDLE, 0);
+ }
+
+ __raw_writew(~0, &fpga->leds);
+ led_state &= ~LED_STATE_ENABLED;
+ if (evt == led_halted) {
+ iounmap(fpga);
+ fpga = NULL;
+ }
+
+ goto done;
+
+ case led_claim:
+ led_state |= LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ break;
+
+ case led_release:
+ led_state &= ~LED_STATE_CLAIMED;
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer:
+ led_state ^= LED_TIMER_ON;
+
+ if (machine_is_omap_perseus2())
+ hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER;
+ else {
+ gpio_set_value(GPIO_TIMER, led_state & LED_TIMER_ON);
+ goto done;
+ }
+
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start:
+ if (machine_is_omap_perseus2())
+ hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE;
+ else {
+ gpio_set_value(GPIO_IDLE, 1);
+ goto done;
+ }
+
+ break;
+
+ case led_idle_end:
+ if (machine_is_omap_perseus2())
+ hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE;
+ else {
+ gpio_set_value(GPIO_IDLE, 0);
+ goto done;
+ }
+
+ break;
+#endif
+
+ case led_green_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_GREEN;
+ break;
+ case led_green_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN;
+ break;
+
+ case led_amber_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_AMBER;
+ break;
+ case led_amber_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER;
+ break;
+
+ case led_red_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_RED;
+ break;
+ case led_red_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_RED;
+ break;
+
+ case led_blue_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_BLUE;
+ break;
+ case led_blue_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE;
+ break;
+
+ default:
+ break;
+ }
+
+
+ /*
+ * Actually burn the LEDs
+ */
+ if (led_state & LED_STATE_ENABLED)
+ __raw_writew(~hw_led_state, &fpga->leds);
+
+done:
+ local_irq_restore(flags);
+}
diff --git a/arch/arm/mach-omap1/leds-innovator.c b/arch/arm/mach-omap1/leds-innovator.c
new file mode 100644
index 00000000..9b99c289
--- /dev/null
+++ b/arch/arm/mach-omap1/leds-innovator.c
@@ -0,0 +1,99 @@
+/*
+ * linux/arch/arm/mach-omap1/leds-innovator.c
+ */
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include "leds.h"
+
+
+#define LED_STATE_ENABLED 1
+#define LED_STATE_CLAIMED 2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+void innovator_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ switch (evt) {
+ case led_start:
+ hw_led_state = 0;
+ led_state = LED_STATE_ENABLED;
+ break;
+
+ case led_stop:
+ led_state &= ~LED_STATE_ENABLED;
+ hw_led_state = 0;
+ break;
+
+ case led_claim:
+ led_state |= LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ break;
+
+ case led_release:
+ led_state &= ~LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state ^= 0;
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state |= 0;
+ break;
+
+ case led_idle_end:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state &= ~0;
+ break;
+#endif
+
+ case led_halted:
+ break;
+
+ case led_green_on:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state &= ~0;
+ break;
+
+ case led_green_off:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state |= 0;
+ break;
+
+ case led_amber_on:
+ break;
+
+ case led_amber_off:
+ break;
+
+ case led_red_on:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state &= ~0;
+ break;
+
+ case led_red_off:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state |= 0;
+ break;
+
+ default:
+ break;
+ }
+
+ local_irq_restore(flags);
+}
diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c
new file mode 100644
index 00000000..499d7ad8
--- /dev/null
+++ b/arch/arm/mach-omap1/leds-osk.c
@@ -0,0 +1,115 @@
+/*
+ * linux/arch/arm/mach-omap1/leds-osk.c
+ *
+ * LED driver for OSK with optional Mistral QVGA board
+ */
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <mach/gpio.h>
+
+#include "leds.h"
+
+
+#define LED_STATE_ENABLED (1 << 0)
+#define LED_STATE_CLAIMED (1 << 1)
+static u8 led_state;
+
+#define TIMER_LED (1 << 3) /* Mistral board */
+#define IDLE_LED (1 << 4) /* Mistral board */
+static u8 hw_led_state;
+
+
+#ifdef CONFIG_OMAP_OSK_MISTRAL
+
+/* For now, all system indicators require the Mistral board, since that
+ * LED can be manipulated without a task context. This LED is either red,
+ * or green, but not both; it can't give the full "disco led" effect.
+ */
+
+#define GPIO_LED_RED 3
+#define GPIO_LED_GREEN OMAP_MPUIO(4)
+
+static void mistral_setled(void)
+{
+ int red = 0;
+ int green = 0;
+
+ if (hw_led_state & TIMER_LED)
+ red = 1;
+ else if (hw_led_state & IDLE_LED)
+ green = 1;
+ /* else both sides are disabled */
+
+ gpio_set_value(GPIO_LED_GREEN, green);
+ gpio_set_value(GPIO_LED_RED, red);
+}
+
+#endif
+
+void osk_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+ u16 leds;
+
+ local_irq_save(flags);
+
+ if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
+ goto done;
+
+ leds = hw_led_state;
+ switch (evt) {
+ case led_start:
+ led_state |= LED_STATE_ENABLED;
+ hw_led_state = 0;
+ leds = ~0;
+ break;
+
+ case led_halted:
+ case led_stop:
+ led_state &= ~LED_STATE_ENABLED;
+ hw_led_state = 0;
+ break;
+
+ case led_claim:
+ led_state |= LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ leds = ~0;
+ break;
+
+ case led_release:
+ led_state &= ~LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ break;
+
+#ifdef CONFIG_OMAP_OSK_MISTRAL
+
+ case led_timer:
+ hw_led_state ^= TIMER_LED;
+ mistral_setled();
+ break;
+
+ case led_idle_start: /* idle == off */
+ hw_led_state &= ~IDLE_LED;
+ mistral_setled();
+ break;
+
+ case led_idle_end:
+ hw_led_state |= IDLE_LED;
+ mistral_setled();
+ break;
+
+#endif /* CONFIG_OMAP_OSK_MISTRAL */
+
+ default:
+ break;
+ }
+
+ leds ^= hw_led_state;
+
+done:
+ local_irq_restore(flags);
+}
diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c
new file mode 100644
index 00000000..22eb11dd
--- /dev/null
+++ b/arch/arm/mach-omap1/leds.c
@@ -0,0 +1,69 @@
+/*
+ * linux/arch/arm/mach-omap1/leds.c
+ *
+ * OMAP LEDs dispatcher
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include <mach/gpio.h>
+#include <plat/mux.h>
+
+#include "leds.h"
+
+static int __init
+omap_leds_init(void)
+{
+ if (!cpu_class_is_omap1())
+ return -ENODEV;
+
+ if (machine_is_omap_innovator())
+ leds_event = innovator_leds_event;
+
+ else if (machine_is_omap_h2()
+ || machine_is_omap_h3()
+ || machine_is_omap_perseus2())
+ leds_event = h2p2_dbg_leds_event;
+
+ else if (machine_is_omap_osk())
+ leds_event = osk_leds_event;
+
+ else
+ return -1;
+
+ if (machine_is_omap_h2()
+ || machine_is_omap_h3()
+#ifdef CONFIG_OMAP_OSK_MISTRAL
+ || machine_is_omap_osk()
+#endif
+ ) {
+
+ /* LED1/LED2 pins can be used as GPIO (as done here), or by
+ * the LPG (works even in deep sleep!), to drive a bicolor
+ * LED on the H2 sample board, and another on the H2/P2
+ * "surfer" expansion board.
+ *
+ * The same pins drive a LED on the OSK Mistral board, but
+ * that's a different kind of LED (just one color at a time).
+ */
+ omap_cfg_reg(P18_1610_GPIO3);
+ if (gpio_request(3, "LED red") == 0)
+ gpio_direction_output(3, 1);
+ else
+ printk(KERN_WARNING "LED: can't get GPIO3/red?\n");
+
+ omap_cfg_reg(MPUIO4);
+ if (gpio_request(OMAP_MPUIO(4), "LED green") == 0)
+ gpio_direction_output(OMAP_MPUIO(4), 1);
+ else
+ printk(KERN_WARNING "LED: can't get MPUIO4/green?\n");
+ }
+
+ leds_event(led_start);
+ return 0;
+}
+
+__initcall(omap_leds_init);
diff --git a/arch/arm/mach-omap1/leds.h b/arch/arm/mach-omap1/leds.h
new file mode 100644
index 00000000..a1e9fedc
--- /dev/null
+++ b/arch/arm/mach-omap1/leds.h
@@ -0,0 +1,3 @@
+extern void innovator_leds_event(led_event_t evt);
+extern void h2p2_dbg_leds_event(led_event_t evt);
+extern void osk_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c
new file mode 100644
index 00000000..c0e1f48a
--- /dev/null
+++ b/arch/arm/mach-omap1/mailbox.c
@@ -0,0 +1,198 @@
+/*
+ * Mailbox reservation modules for OMAP1
+ *
+ * Copyright (C) 2006-2009 Nokia Corporation
+ * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <plat/mailbox.h>
+
+#define MAILBOX_ARM2DSP1 0x00
+#define MAILBOX_ARM2DSP1b 0x04
+#define MAILBOX_DSP2ARM1 0x08
+#define MAILBOX_DSP2ARM1b 0x0c
+#define MAILBOX_DSP2ARM2 0x10
+#define MAILBOX_DSP2ARM2b 0x14
+#define MAILBOX_ARM2DSP1_Flag 0x18
+#define MAILBOX_DSP2ARM1_Flag 0x1c
+#define MAILBOX_DSP2ARM2_Flag 0x20
+
+static void __iomem *mbox_base;
+
+struct omap_mbox1_fifo {
+ unsigned long cmd;
+ unsigned long data;
+ unsigned long flag;
+};
+
+struct omap_mbox1_priv {
+ struct omap_mbox1_fifo tx_fifo;
+ struct omap_mbox1_fifo rx_fifo;
+};
+
+static inline int mbox_read_reg(size_t ofs)
+{
+ return __raw_readw(mbox_base + ofs);
+}
+
+static inline void mbox_write_reg(u32 val, size_t ofs)
+{
+ __raw_writew(val, mbox_base + ofs);
+}
+
+/* msg */
+static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
+{
+ struct omap_mbox1_fifo *fifo =
+ &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
+ mbox_msg_t msg;
+
+ msg = mbox_read_reg(fifo->data);
+ msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
+
+ return msg;
+}
+
+static void
+omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+ struct omap_mbox1_fifo *fifo =
+ &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
+
+ mbox_write_reg(msg & 0xffff, fifo->data);
+ mbox_write_reg(msg >> 16, fifo->cmd);
+}
+
+static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
+{
+ return 0;
+}
+
+static int omap1_mbox_fifo_full(struct omap_mbox *mbox)
+{
+ struct omap_mbox1_fifo *fifo =
+ &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
+
+ return mbox_read_reg(fifo->flag);
+}
+
+/* irq */
+static void
+omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
+{
+ if (irq == IRQ_RX)
+ enable_irq(mbox->irq);
+}
+
+static void
+omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
+{
+ if (irq == IRQ_RX)
+ disable_irq(mbox->irq);
+}
+
+static int
+omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
+{
+ if (irq == IRQ_TX)
+ return 0;
+ return 1;
+}
+
+static struct omap_mbox_ops omap1_mbox_ops = {
+ .type = OMAP_MBOX_TYPE1,
+ .fifo_read = omap1_mbox_fifo_read,
+ .fifo_write = omap1_mbox_fifo_write,
+ .fifo_empty = omap1_mbox_fifo_empty,
+ .fifo_full = omap1_mbox_fifo_full,
+ .enable_irq = omap1_mbox_enable_irq,
+ .disable_irq = omap1_mbox_disable_irq,
+ .is_irq = omap1_mbox_is_irq,
+};
+
+/* FIXME: the following struct should be created automatically by the user id */
+
+/* DSP */
+static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
+ .tx_fifo = {
+ .cmd = MAILBOX_ARM2DSP1b,
+ .data = MAILBOX_ARM2DSP1,
+ .flag = MAILBOX_ARM2DSP1_Flag,
+ },
+ .rx_fifo = {
+ .cmd = MAILBOX_DSP2ARM1b,
+ .data = MAILBOX_DSP2ARM1,
+ .flag = MAILBOX_DSP2ARM1_Flag,
+ },
+};
+
+static struct omap_mbox mbox_dsp_info = {
+ .name = "dsp",
+ .ops = &omap1_mbox_ops,
+ .priv = &omap1_mbox_dsp_priv,
+};
+
+static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
+
+static int __devinit omap1_mbox_probe(struct platform_device *pdev)
+{
+ struct resource *mem;
+ int ret;
+ struct omap_mbox **list;
+
+ list = omap1_mboxes;
+ list[0]->irq = platform_get_irq_byname(pdev, "dsp");
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mbox_base = ioremap(mem->start, resource_size(mem));
+ if (!mbox_base)
+ return -ENOMEM;
+
+ ret = omap_mbox_register(&pdev->dev, list);
+ if (ret) {
+ iounmap(mbox_base);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devexit omap1_mbox_remove(struct platform_device *pdev)
+{
+ omap_mbox_unregister();
+ iounmap(mbox_base);
+ return 0;
+}
+
+static struct platform_driver omap1_mbox_driver = {
+ .probe = omap1_mbox_probe,
+ .remove = __devexit_p(omap1_mbox_remove),
+ .driver = {
+ .name = "omap-mailbox",
+ },
+};
+
+static int __init omap1_mbox_init(void)
+{
+ return platform_driver_register(&omap1_mbox_driver);
+}
+
+static void __exit omap1_mbox_exit(void)
+{
+ platform_driver_unregister(&omap1_mbox_driver);
+}
+
+module_init(omap1_mbox_init);
+module_exit(omap1_mbox_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
+MODULE_ALIAS("platform:omap1-mailbox");
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
new file mode 100644
index 00000000..d9af9811
--- /dev/null
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -0,0 +1,410 @@
+/*
+ * linux/arch/arm/mach-omap1/mcbsp.c
+ *
+ * Copyright (C) 2008 Instituto Nokia de Tecnologia
+ * Contact: Eduardo Valentin <eduardo.valentin@indt.org.br>
+ *
+ * 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.
+ *
+ * Multichannel mode not supported.
+ */
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <mach/irqs.h>
+#include <plat/dma.h>
+#include <plat/mux.h>
+#include <plat/cpu.h>
+#include <plat/mcbsp.h>
+
+#define DPS_RSTCT2_PER_EN (1 << 0)
+#define DSP_RSTCT2_WD_PER_EN (1 << 1)
+
+static int dsp_use;
+static struct clk *api_clk;
+static struct clk *dsp_clk;
+
+static void omap1_mcbsp_request(unsigned int id)
+{
+ /*
+ * On 1510, 1610 and 1710, McBSP1 and McBSP3
+ * are DSP public peripherals.
+ */
+ if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
+ if (dsp_use++ == 0) {
+ api_clk = clk_get(NULL, "api_ck");
+ dsp_clk = clk_get(NULL, "dsp_ck");
+ if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
+ clk_enable(api_clk);
+ clk_enable(dsp_clk);
+
+ /*
+ * DSP external peripheral reset
+ * FIXME: This should be moved to dsp code
+ */
+ __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
+ DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
+ }
+ }
+ }
+}
+
+static void omap1_mcbsp_free(unsigned int id)
+{
+ if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
+ if (--dsp_use == 0) {
+ if (!IS_ERR(api_clk)) {
+ clk_disable(api_clk);
+ clk_put(api_clk);
+ }
+ if (!IS_ERR(dsp_clk)) {
+ clk_disable(dsp_clk);
+ clk_put(dsp_clk);
+ }
+ }
+ }
+}
+
+static struct omap_mcbsp_ops omap1_mcbsp_ops = {
+ .request = omap1_mcbsp_request,
+ .free = omap1_mcbsp_free,
+};
+
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+struct resource omap7xx_mcbsp_res[][6] = {
+ {
+ {
+ .start = OMAP7XX_MCBSP1_BASE,
+ .end = OMAP7XX_MCBSP1_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "rx",
+ .start = INT_7XX_McBSP1RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "tx",
+ .start = INT_7XX_McBSP1TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = OMAP_DMA_MCBSP1_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "tx",
+ .start = OMAP_DMA_MCBSP1_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ },
+ {
+ {
+ .start = OMAP7XX_MCBSP2_BASE,
+ .end = OMAP7XX_MCBSP2_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "rx",
+ .start = INT_7XX_McBSP2RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "tx",
+ .start = INT_7XX_McBSP2TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = OMAP_DMA_MCBSP3_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "tx",
+ .start = OMAP_DMA_MCBSP3_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ },
+};
+
+#define omap7xx_mcbsp_res_0 omap7xx_mcbsp_res[0]
+
+static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
+ {
+ .ops = &omap1_mcbsp_ops,
+ },
+ {
+ .ops = &omap1_mcbsp_ops,
+ },
+};
+#define OMAP7XX_MCBSP_RES_SZ ARRAY_SIZE(omap7xx_mcbsp_res[1])
+#define OMAP7XX_MCBSP_COUNT ARRAY_SIZE(omap7xx_mcbsp_res)
+#else
+#define omap7xx_mcbsp_res_0 NULL
+#define omap7xx_mcbsp_pdata NULL
+#define OMAP7XX_MCBSP_RES_SZ 0
+#define OMAP7XX_MCBSP_COUNT 0
+#endif
+
+#ifdef CONFIG_ARCH_OMAP15XX
+struct resource omap15xx_mcbsp_res[][6] = {
+ {
+ {
+ .start = OMAP1510_MCBSP1_BASE,
+ .end = OMAP1510_MCBSP1_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "rx",
+ .start = INT_McBSP1RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "tx",
+ .start = INT_McBSP1TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = OMAP_DMA_MCBSP1_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "tx",
+ .start = OMAP_DMA_MCBSP1_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ },
+ {
+ {
+ .start = OMAP1510_MCBSP2_BASE,
+ .end = OMAP1510_MCBSP2_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "rx",
+ .start = INT_1510_SPI_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "tx",
+ .start = INT_1510_SPI_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = OMAP_DMA_MCBSP2_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "tx",
+ .start = OMAP_DMA_MCBSP2_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ },
+ {
+ {
+ .start = OMAP1510_MCBSP3_BASE,
+ .end = OMAP1510_MCBSP3_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "rx",
+ .start = INT_McBSP3RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "tx",
+ .start = INT_McBSP3TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = OMAP_DMA_MCBSP3_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "tx",
+ .start = OMAP_DMA_MCBSP3_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ },
+};
+
+#define omap15xx_mcbsp_res_0 omap15xx_mcbsp_res[0]
+
+static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
+ {
+ .ops = &omap1_mcbsp_ops,
+ },
+ {
+ .ops = &omap1_mcbsp_ops,
+ },
+ {
+ .ops = &omap1_mcbsp_ops,
+ },
+};
+#define OMAP15XX_MCBSP_RES_SZ ARRAY_SIZE(omap15xx_mcbsp_res[1])
+#define OMAP15XX_MCBSP_COUNT ARRAY_SIZE(omap15xx_mcbsp_res)
+#else
+#define omap15xx_mcbsp_res_0 NULL
+#define omap15xx_mcbsp_pdata NULL
+#define OMAP15XX_MCBSP_RES_SZ 0
+#define OMAP15XX_MCBSP_COUNT 0
+#endif
+
+#ifdef CONFIG_ARCH_OMAP16XX
+struct resource omap16xx_mcbsp_res[][6] = {
+ {
+ {
+ .start = OMAP1610_MCBSP1_BASE,
+ .end = OMAP1610_MCBSP1_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "rx",
+ .start = INT_McBSP1RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "tx",
+ .start = INT_McBSP1TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = OMAP_DMA_MCBSP1_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "tx",
+ .start = OMAP_DMA_MCBSP1_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ },
+ {
+ {
+ .start = OMAP1610_MCBSP2_BASE,
+ .end = OMAP1610_MCBSP2_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "rx",
+ .start = INT_1610_McBSP2_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "tx",
+ .start = INT_1610_McBSP2_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = OMAP_DMA_MCBSP2_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "tx",
+ .start = OMAP_DMA_MCBSP2_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ },
+ {
+ {
+ .start = OMAP1610_MCBSP3_BASE,
+ .end = OMAP1610_MCBSP3_BASE + SZ_256,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "rx",
+ .start = INT_McBSP3RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "tx",
+ .start = INT_McBSP3TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = OMAP_DMA_MCBSP3_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ {
+ .name = "tx",
+ .start = OMAP_DMA_MCBSP3_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ },
+};
+
+#define omap16xx_mcbsp_res_0 omap16xx_mcbsp_res[0]
+
+static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
+ {
+ .ops = &omap1_mcbsp_ops,
+ },
+ {
+ .ops = &omap1_mcbsp_ops,
+ },
+ {
+ .ops = &omap1_mcbsp_ops,
+ },
+};
+#define OMAP16XX_MCBSP_RES_SZ ARRAY_SIZE(omap16xx_mcbsp_res[1])
+#define OMAP16XX_MCBSP_COUNT ARRAY_SIZE(omap16xx_mcbsp_res)
+#else
+#define omap16xx_mcbsp_res_0 NULL
+#define omap16xx_mcbsp_pdata NULL
+#define OMAP16XX_MCBSP_RES_SZ 0
+#define OMAP16XX_MCBSP_COUNT 0
+#endif
+
+static int __init omap1_mcbsp_init(void)
+{
+ if (!cpu_class_is_omap1())
+ return -ENODEV;
+
+ if (cpu_is_omap7xx())
+ omap_mcbsp_count = OMAP7XX_MCBSP_COUNT;
+ else if (cpu_is_omap15xx())
+ omap_mcbsp_count = OMAP15XX_MCBSP_COUNT;
+ else if (cpu_is_omap16xx())
+ omap_mcbsp_count = OMAP16XX_MCBSP_COUNT;
+
+ mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
+ GFP_KERNEL);
+ if (!mcbsp_ptr)
+ return -ENOMEM;
+
+ if (cpu_is_omap7xx())
+ omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
+ OMAP7XX_MCBSP_RES_SZ,
+ omap7xx_mcbsp_pdata,
+ OMAP7XX_MCBSP_COUNT);
+
+ if (cpu_is_omap15xx())
+ omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
+ OMAP15XX_MCBSP_RES_SZ,
+ omap15xx_mcbsp_pdata,
+ OMAP15XX_MCBSP_COUNT);
+
+ if (cpu_is_omap16xx())
+ omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
+ OMAP16XX_MCBSP_RES_SZ,
+ omap16xx_mcbsp_pdata,
+ OMAP16XX_MCBSP_COUNT);
+
+ return omap_mcbsp_init();
+}
+
+arch_initcall(omap1_mcbsp_init);
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
new file mode 100644
index 00000000..5fdef7a3
--- /dev/null
+++ b/arch/arm/mach-omap1/mux.c
@@ -0,0 +1,471 @@
+/*
+ * linux/arch/arm/mach-omap1/mux.c
+ *
+ * OMAP1 pin multiplexing configurations
+ *
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ *
+ * Written by Tony Lindgren
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm/system.h>
+
+#include <plat/mux.h>
+
+#ifdef CONFIG_OMAP_MUX
+
+static struct omap_mux_cfg arch_mux_cfg;
+
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+static struct pin_config __initdata_or_module omap7xx_pins[] = {
+MUX_CFG_7XX("E2_7XX_KBR0", 12, 21, 0, 20, 1, 0)
+MUX_CFG_7XX("J7_7XX_KBR1", 12, 25, 0, 24, 1, 0)
+MUX_CFG_7XX("E1_7XX_KBR2", 12, 29, 0, 28, 1, 0)
+MUX_CFG_7XX("F3_7XX_KBR3", 13, 1, 0, 0, 1, 0)
+MUX_CFG_7XX("D2_7XX_KBR4", 13, 5, 0, 4, 1, 0)
+MUX_CFG_7XX("C2_7XX_KBC0", 13, 9, 0, 8, 1, 0)
+MUX_CFG_7XX("D3_7XX_KBC1", 13, 13, 0, 12, 1, 0)
+MUX_CFG_7XX("E4_7XX_KBC2", 13, 17, 0, 16, 1, 0)
+MUX_CFG_7XX("F4_7XX_KBC3", 13, 21, 0, 20, 1, 0)
+MUX_CFG_7XX("E3_7XX_KBC4", 13, 25, 0, 24, 1, 0)
+
+MUX_CFG_7XX("AA17_7XX_USB_DM", 2, 21, 0, 20, 0, 0)
+MUX_CFG_7XX("W16_7XX_USB_PU_EN", 2, 25, 0, 24, 0, 0)
+MUX_CFG_7XX("W17_7XX_USB_VBUSI", 2, 29, 6, 28, 1, 0)
+MUX_CFG_7XX("W18_7XX_USB_DMCK_OUT",3, 3, 1, 2, 0, 0)
+MUX_CFG_7XX("W19_7XX_USB_DCRST", 3, 7, 1, 6, 0, 0)
+
+/* MMC Pins */
+MUX_CFG_7XX("MMC_7XX_CMD", 2, 9, 0, 8, 1, 0)
+MUX_CFG_7XX("MMC_7XX_CLK", 2, 13, 0, 12, 1, 0)
+MUX_CFG_7XX("MMC_7XX_DAT0", 2, 17, 0, 16, 1, 0)
+
+/* I2C interface */
+MUX_CFG_7XX("I2C_7XX_SCL", 5, 1, 0, 0, 1, 0)
+MUX_CFG_7XX("I2C_7XX_SDA", 5, 5, 0, 0, 1, 0)
+
+/* SPI pins */
+MUX_CFG_7XX("SPI_7XX_1", 6, 5, 4, 4, 1, 0)
+MUX_CFG_7XX("SPI_7XX_2", 6, 9, 4, 8, 1, 0)
+MUX_CFG_7XX("SPI_7XX_3", 6, 13, 4, 12, 1, 0)
+MUX_CFG_7XX("SPI_7XX_4", 6, 17, 4, 16, 1, 0)
+MUX_CFG_7XX("SPI_7XX_5", 8, 25, 0, 24, 0, 0)
+MUX_CFG_7XX("SPI_7XX_6", 9, 5, 0, 4, 0, 0)
+
+/* UART pins */
+MUX_CFG_7XX("UART_7XX_1", 3, 21, 0, 20, 0, 0)
+MUX_CFG_7XX("UART_7XX_2", 8, 1, 6, 0, 0, 0)
+};
+#define OMAP7XX_PINS_SZ ARRAY_SIZE(omap7xx_pins)
+#else
+#define omap7xx_pins NULL
+#define OMAP7XX_PINS_SZ 0
+#endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */
+
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+static struct pin_config __initdata_or_module omap1xxx_pins[] = {
+/*
+ * description mux mode mux pull pull pull pu_pd pu dbg
+ * reg offset mode reg bit ena reg
+ */
+MUX_CFG("UART1_TX", 9, 21, 1, 2, 3, 0, NA, 0, 0)
+MUX_CFG("UART1_RTS", 9, 12, 1, 2, 0, 0, NA, 0, 0)
+
+/* UART2 (COM_UART_GATING), conflicts with USB2 */
+MUX_CFG("UART2_TX", C, 27, 1, 3, 3, 0, NA, 0, 0)
+MUX_CFG("UART2_RX", C, 18, 0, 3, 1, 1, NA, 0, 0)
+MUX_CFG("UART2_CTS", C, 21, 0, 3, 1, 1, NA, 0, 0)
+MUX_CFG("UART2_RTS", C, 24, 1, 3, 2, 0, NA, 0, 0)
+
+/* UART3 (GIGA_UART_GATING) */
+MUX_CFG("UART3_TX", 6, 0, 1, 0, 30, 0, NA, 0, 0)
+MUX_CFG("UART3_RX", 6, 3, 0, 0, 31, 1, NA, 0, 0)
+MUX_CFG("UART3_CTS", 5, 12, 2, 0, 24, 0, NA, 0, 0)
+MUX_CFG("UART3_RTS", 5, 15, 2, 0, 25, 0, NA, 0, 0)
+MUX_CFG("UART3_CLKREQ", 9, 27, 0, 2, 5, 0, NA, 0, 0)
+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)
+
+/* USB internal master generic */
+MUX_CFG("R18_USB_VBUS", 7, 9, 2, 1, 11, 0, NA, 0, 1)
+MUX_CFG("R18_1510_USB_GPIO0", 7, 9, 0, 1, 11, 1, NA, 0, 1)
+/* works around erratum: W4_USB_PUEN and W4_USB_PUDIS are switched! */
+MUX_CFG("W4_USB_PUEN", D, 3, 3, 3, 5, 1, NA, 0, 1)
+MUX_CFG("W4_USB_CLKO", D, 3, 1, 3, 5, 0, NA, 0, 1)
+MUX_CFG("W4_USB_HIGHZ", D, 3, 4, 3, 5, 0, 3, 0, 1)
+MUX_CFG("W4_GPIO58", D, 3, 7, 3, 5, 0, 3, 0, 1)
+
+/* USB1 master */
+MUX_CFG("USB1_SUSP", 8, 27, 2, 1, 27, 0, NA, 0, 1)
+MUX_CFG("USB1_SE0", 9, 0, 2, 1, 28, 0, NA, 0, 1)
+MUX_CFG("W13_1610_USB1_SE0", 9, 0, 4, 1, 28, 0, NA, 0, 1)
+MUX_CFG("USB1_TXEN", 9, 3, 2, 1, 29, 0, NA, 0, 1)
+MUX_CFG("USB1_TXD", 9, 24, 1, 2, 4, 0, NA, 0, 1)
+MUX_CFG("USB1_VP", A, 3, 1, 2, 7, 0, NA, 0, 1)
+MUX_CFG("USB1_VM", A, 6, 1, 2, 8, 0, NA, 0, 1)
+MUX_CFG("USB1_RCV", A, 9, 1, 2, 9, 0, NA, 0, 1)
+MUX_CFG("USB1_SPEED", A, 12, 2, 2, 10, 0, NA, 0, 1)
+MUX_CFG("R13_1610_USB1_SPEED", A, 12, 5, 2, 10, 0, NA, 0, 1)
+MUX_CFG("R13_1710_USB1_SEO", A, 12, 5, 2, 10, 0, NA, 0, 1)
+
+/* USB2 master */
+MUX_CFG("USB2_SUSP", B, 3, 1, 2, 17, 0, NA, 0, 1)
+MUX_CFG("USB2_VP", B, 6, 1, 2, 18, 0, NA, 0, 1)
+MUX_CFG("USB2_TXEN", B, 9, 1, 2, 19, 0, NA, 0, 1)
+MUX_CFG("USB2_VM", C, 18, 1, 3, 0, 0, NA, 0, 1)
+MUX_CFG("USB2_RCV", C, 21, 1, 3, 1, 0, NA, 0, 1)
+MUX_CFG("USB2_SE0", C, 24, 2, 3, 2, 0, NA, 0, 1)
+MUX_CFG("USB2_TXD", C, 27, 2, 3, 3, 0, NA, 0, 1)
+
+/* OMAP-1510 GPIO */
+MUX_CFG("R18_1510_GPIO0", 7, 9, 0, 1, 11, 1, 0, 0, 1)
+MUX_CFG("R19_1510_GPIO1", 7, 6, 0, 1, 10, 1, 0, 0, 1)
+MUX_CFG("M14_1510_GPIO2", 7, 3, 0, 1, 9, 1, 0, 0, 1)
+
+/* OMAP1610 GPIO */
+MUX_CFG("P18_1610_GPIO3", 7, 0, 0, 1, 8, 0, NA, 0, 1)
+MUX_CFG("Y15_1610_GPIO17", A, 0, 7, 2, 6, 0, NA, 0, 1)
+
+/* OMAP-1710 GPIO */
+MUX_CFG("R18_1710_GPIO0", 7, 9, 0, 1, 11, 1, 1, 1, 1)
+MUX_CFG("V2_1710_GPIO10", F, 27, 1, 4, 3, 1, 4, 1, 1)
+MUX_CFG("N21_1710_GPIO14", 6, 9, 0, 1, 1, 1, 1, 1, 1)
+MUX_CFG("W15_1710_GPIO40", 9, 27, 7, 2, 5, 1, 2, 1, 1)
+
+/* MPUIO */
+MUX_CFG("MPUIO2", 7, 18, 0, 1, 14, 1, NA, 0, 1)
+MUX_CFG("N15_1610_MPUIO2", 7, 18, 0, 1, 14, 1, 1, 0, 1)
+MUX_CFG("MPUIO4", 7, 15, 0, 1, 13, 1, NA, 0, 1)
+MUX_CFG("MPUIO5", 7, 12, 0, 1, 12, 1, NA, 0, 1)
+
+MUX_CFG("T20_1610_MPUIO5", 7, 12, 0, 1, 12, 0, 3, 0, 1)
+MUX_CFG("W11_1610_MPUIO6", 10, 15, 2, 3, 8, 0, 3, 0, 1)
+MUX_CFG("V10_1610_MPUIO7", A, 24, 2, 2, 14, 0, 2, 0, 1)
+MUX_CFG("W11_1610_MPUIO9", 10, 15, 1, 3, 8, 0, 3, 0, 1)
+MUX_CFG("V10_1610_MPUIO10", A, 24, 1, 2, 14, 0, 2, 0, 1)
+MUX_CFG("W10_1610_MPUIO11", A, 18, 2, 2, 11, 0, 2, 0, 1)
+MUX_CFG("E20_1610_MPUIO13", 3, 21, 1, 0, 7, 0, 0, 0, 1)
+MUX_CFG("U20_1610_MPUIO14", 9, 6, 6, 0, 30, 0, 0, 0, 1)
+MUX_CFG("E19_1610_MPUIO15", 3, 18, 1, 0, 6, 0, 0, 0, 1)
+
+/* MCBSP2 */
+MUX_CFG("MCBSP2_CLKR", C, 6, 0, 2, 27, 1, NA, 0, 1)
+MUX_CFG("MCBSP2_CLKX", C, 9, 0, 2, 29, 1, NA, 0, 1)
+MUX_CFG("MCBSP2_DR", C, 0, 0, 2, 26, 1, NA, 0, 1)
+MUX_CFG("MCBSP2_DX", C, 15, 0, 2, 31, 1, NA, 0, 1)
+MUX_CFG("MCBSP2_FSR", C, 12, 0, 2, 30, 1, NA, 0, 1)
+MUX_CFG("MCBSP2_FSX", C, 3, 0, 2, 27, 1, NA, 0, 1)
+
+/* MCBSP3 NOTE: Mode must 1 for clock */
+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)
+
+/* OMAP-1610 MMC2 */
+MUX_CFG("W8_1610_MMC2_DAT0", B, 21, 6, 2, 23, 1, 2, 1, 1)
+MUX_CFG("V8_1610_MMC2_DAT1", B, 27, 6, 2, 25, 1, 2, 1, 1)
+MUX_CFG("W15_1610_MMC2_DAT2", 9, 12, 6, 2, 5, 1, 2, 1, 1)
+MUX_CFG("R10_1610_MMC2_DAT3", B, 18, 6, 2, 22, 1, 2, 1, 1)
+MUX_CFG("Y10_1610_MMC2_CLK", B, 3, 6, 2, 17, 0, 2, 0, 1)
+MUX_CFG("Y8_1610_MMC2_CMD", B, 24, 6, 2, 24, 1, 2, 1, 1)
+MUX_CFG("V9_1610_MMC2_CMDDIR", B, 12, 6, 2, 20, 0, 2, 1, 1)
+MUX_CFG("V5_1610_MMC2_DATDIR0", B, 15, 6, 2, 21, 0, 2, 1, 1)
+MUX_CFG("W19_1610_MMC2_DATDIR1", 8, 15, 6, 1, 23, 0, 1, 1, 1)
+MUX_CFG("R18_1610_MMC2_CLKIN", 7, 9, 6, 1, 11, 0, 1, 11, 1)
+
+/* OMAP-1610 External Trace Interface */
+MUX_CFG("M19_1610_ETM_PSTAT0", 5, 27, 1, 0, 29, 0, 0, 0, 1)
+MUX_CFG("L15_1610_ETM_PSTAT1", 5, 24, 1, 0, 28, 0, 0, 0, 1)
+MUX_CFG("L18_1610_ETM_PSTAT2", 5, 21, 1, 0, 27, 0, 0, 0, 1)
+MUX_CFG("L19_1610_ETM_D0", 5, 18, 1, 0, 26, 0, 0, 0, 1)
+MUX_CFG("J19_1610_ETM_D6", 5, 0, 1, 0, 20, 0, 0, 0, 1)
+MUX_CFG("J18_1610_ETM_D7", 5, 27, 1, 0, 19, 0, 0, 0, 1)
+
+/* OMAP16XX GPIO */
+MUX_CFG("P20_1610_GPIO4", 6, 27, 0, 1, 7, 0, 1, 1, 1)
+MUX_CFG("V9_1610_GPIO7", B, 12, 1, 2, 20, 0, 2, 1, 1)
+MUX_CFG("W8_1610_GPIO9", B, 21, 0, 2, 23, 0, 2, 1, 1)
+MUX_CFG("N20_1610_GPIO11", 6, 18, 0, 1, 4, 0, 1, 1, 1)
+MUX_CFG("N19_1610_GPIO13", 6, 12, 0, 1, 2, 0, 1, 1, 1)
+MUX_CFG("P10_1610_GPIO22", C, 0, 7, 2, 26, 0, 2, 1, 1)
+MUX_CFG("V5_1610_GPIO24", B, 15, 7, 2, 21, 0, 2, 1, 1)
+MUX_CFG("AA20_1610_GPIO_41", 9, 9, 7, 1, 31, 0, 1, 1, 1)
+MUX_CFG("W19_1610_GPIO48", 8, 15, 7, 1, 23, 1, 1, 0, 1)
+MUX_CFG("M7_1610_GPIO62", 10, 0, 0, 4, 24, 0, 4, 0, 1)
+MUX_CFG("V14_16XX_GPIO37", 9, 18, 7, 2, 2, 0, 2, 2, 0)
+MUX_CFG("R9_16XX_GPIO18", C, 18, 7, 3, 0, 0, 3, 0, 0)
+MUX_CFG("L14_16XX_GPIO49", 6, 3, 7, 0, 31, 0, 0, 31, 0)
+
+/* OMAP-1610 uWire */
+MUX_CFG("V19_1610_UWIRE_SCLK", 8, 6, 0, 1, 20, 0, 1, 1, 1)
+MUX_CFG("U18_1610_UWIRE_SDI", 8, 0, 0, 1, 18, 0, 1, 1, 1)
+MUX_CFG("W21_1610_UWIRE_SDO", 8, 3, 0, 1, 19, 0, 1, 1, 1)
+MUX_CFG("N14_1610_UWIRE_CS0", 8, 9, 1, 1, 21, 0, 1, 1, 1)
+MUX_CFG("P15_1610_UWIRE_CS3", 8, 12, 1, 1, 22, 0, 1, 1, 1)
+MUX_CFG("N15_1610_UWIRE_CS1", 7, 18, 2, 1, 14, 0, NA, 0, 1)
+
+/* OMAP-1610 SPI */
+MUX_CFG("U19_1610_SPIF_SCK", 7, 21, 6, 1, 15, 0, 1, 1, 1)
+MUX_CFG("U18_1610_SPIF_DIN", 8, 0, 6, 1, 18, 1, 1, 0, 1)
+MUX_CFG("P20_1610_SPIF_DIN", 6, 27, 4, 1, 7, 1, 1, 0, 1)
+MUX_CFG("W21_1610_SPIF_DOUT", 8, 3, 6, 1, 19, 0, 1, 0, 1)
+MUX_CFG("R18_1610_SPIF_DOUT", 7, 9, 3, 1, 11, 0, 1, 0, 1)
+MUX_CFG("N14_1610_SPIF_CS0", 8, 9, 6, 1, 21, 0, 1, 1, 1)
+MUX_CFG("N15_1610_SPIF_CS1", 7, 18, 6, 1, 14, 0, 1, 1, 1)
+MUX_CFG("T19_1610_SPIF_CS2", 7, 15, 4, 1, 13, 0, 1, 1, 1)
+MUX_CFG("P15_1610_SPIF_CS3", 8, 12, 3, 1, 22, 0, 1, 1, 1)
+
+/* OMAP-1610 Flash */
+MUX_CFG("L3_1610_FLASH_CS2B_OE",10, 6, 1, NA, 0, 0, NA, 0, 1)
+MUX_CFG("M8_1610_FLASH_CS2B_WE",10, 3, 1, NA, 0, 0, NA, 0, 1)
+
+/* First MMC interface, same on 1510, 1610 and 1710 */
+MUX_CFG("MMC_CMD", A, 27, 0, 2, 15, 1, 2, 1, 1)
+MUX_CFG("MMC_DAT1", A, 24, 0, 2, 14, 1, 2, 1, 1)
+MUX_CFG("MMC_DAT2", A, 18, 0, 2, 12, 1, 2, 1, 1)
+MUX_CFG("MMC_DAT0", B, 0, 0, 2, 16, 1, 2, 1, 1)
+MUX_CFG("MMC_CLK", A, 21, 0, NA, 0, 0, NA, 0, 1)
+MUX_CFG("MMC_DAT3", 10, 15, 0, 3, 8, 1, 3, 1, 1)
+MUX_CFG("M15_1710_MMC_CLKI", 6, 21, 2, 0, 0, 0, NA, 0, 1)
+MUX_CFG("P19_1710_MMC_CMDDIR", 6, 24, 6, 0, 0, 0, NA, 0, 1)
+MUX_CFG("P20_1710_MMC_DATDIR0", 6, 27, 5, 0, 0, 0, NA, 0, 1)
+
+/* OMAP-1610 USB0 alternate configuration */
+MUX_CFG("W9_USB0_TXEN", B, 9, 5, 2, 19, 0, 2, 0, 1)
+MUX_CFG("AA9_USB0_VP", B, 6, 5, 2, 18, 0, 2, 0, 1)
+MUX_CFG("Y5_USB0_RCV", C, 21, 5, 3, 1, 0, 1, 0, 1)
+MUX_CFG("R9_USB0_VM", C, 18, 5, 3, 0, 0, 3, 0, 1)
+MUX_CFG("V6_USB0_TXD", C, 27, 5, 3, 3, 0, 3, 0, 1)
+MUX_CFG("W5_USB0_SE0", C, 24, 5, 3, 2, 0, 3, 0, 1)
+MUX_CFG("V9_USB0_SPEED", B, 12, 5, 2, 20, 0, 2, 0, 1)
+MUX_CFG("Y10_USB0_SUSP", B, 3, 5, 2, 17, 0, 2, 0, 1)
+
+/* USB2 interface */
+MUX_CFG("W9_USB2_TXEN", B, 9, 1, NA, 0, 0, NA, 0, 1)
+MUX_CFG("AA9_USB2_VP", B, 6, 1, NA, 0, 0, NA, 0, 1)
+MUX_CFG("Y5_USB2_RCV", C, 21, 1, NA, 0, 0, NA, 0, 1)
+MUX_CFG("R9_USB2_VM", C, 18, 1, NA, 0, 0, NA, 0, 1)
+MUX_CFG("V6_USB2_TXD", C, 27, 2, NA, 0, 0, NA, 0, 1)
+MUX_CFG("W5_USB2_SE0", C, 24, 2, NA, 0, 0, NA, 0, 1)
+
+/* 16XX UART */
+MUX_CFG("R13_1610_UART1_TX", A, 12, 6, 2, 10, 0, 2, 10, 1)
+MUX_CFG("V14_16XX_UART1_RX", 9, 18, 0, 2, 2, 0, 2, 2, 1)
+MUX_CFG("R14_1610_UART1_CTS", 9, 15, 0, 2, 1, 0, 2, 1, 1)
+MUX_CFG("AA15_1610_UART1_RTS", 9, 12, 1, 2, 0, 0, 2, 0, 1)
+MUX_CFG("R9_16XX_UART2_RX", C, 18, 0, 3, 0, 0, 3, 0, 1)
+MUX_CFG("L14_16XX_UART3_RX", 6, 3, 0, 0, 31, 0, 0, 31, 1)
+
+/* I2C interface */
+MUX_CFG("I2C_SCL", 7, 24, 0, NA, 0, 0, NA, 0, 0)
+MUX_CFG("I2C_SDA", 7, 27, 0, NA, 0, 0, NA, 0, 0)
+
+/* Keypad */
+MUX_CFG("F18_1610_KBC0", 3, 15, 0, 0, 5, 1, 0, 0, 0)
+MUX_CFG("D20_1610_KBC1", 3, 12, 0, 0, 4, 1, 0, 0, 0)
+MUX_CFG("D19_1610_KBC2", 3, 9, 0, 0, 3, 1, 0, 0, 0)
+MUX_CFG("E18_1610_KBC3", 3, 6, 0, 0, 2, 1, 0, 0, 0)
+MUX_CFG("C21_1610_KBC4", 3, 3, 0, 0, 1, 1, 0, 0, 0)
+MUX_CFG("G18_1610_KBR0", 4, 0, 0, 0, 10, 1, 0, 1, 0)
+MUX_CFG("F19_1610_KBR1", 3, 27, 0, 0, 9, 1, 0, 1, 0)
+MUX_CFG("H14_1610_KBR2", 3, 24, 0, 0, 8, 1, 0, 1, 0)
+MUX_CFG("E20_1610_KBR3", 3, 21, 0, 0, 7, 1, 0, 1, 0)
+MUX_CFG("E19_1610_KBR4", 3, 18, 0, 0, 6, 1, 0, 1, 0)
+MUX_CFG("N19_1610_KBR5", 6, 12, 1, 1, 2, 1, 1, 1, 0)
+
+/* Power management */
+MUX_CFG("T20_1610_LOW_PWR", 7, 12, 1, NA, 0, 0, NA, 0, 0)
+
+/* MCLK Settings */
+MUX_CFG("V5_1710_MCLK_ON", B, 15, 0, NA, 0, 0, NA, 0, 0)
+MUX_CFG("V5_1710_MCLK_OFF", B, 15, 6, NA, 0, 0, NA, 0, 0)
+MUX_CFG("R10_1610_MCLK_ON", B, 18, 0, NA, 22, 0, NA, 1, 0)
+MUX_CFG("R10_1610_MCLK_OFF", B, 18, 6, 2, 22, 1, 2, 1, 1)
+
+/* CompactFlash controller, conflicts with MMC1 */
+MUX_CFG("P11_1610_CF_CD2", A, 27, 3, 2, 15, 1, 2, 1, 1)
+MUX_CFG("R11_1610_CF_IOIS16", B, 0, 3, 2, 16, 1, 2, 1, 1)
+MUX_CFG("V10_1610_CF_IREQ", A, 24, 3, 2, 14, 0, 2, 0, 1)
+MUX_CFG("W10_1610_CF_RESET", A, 18, 3, 2, 12, 1, 2, 1, 1)
+MUX_CFG("W11_1610_CF_CD1", 10, 15, 3, 3, 8, 1, 3, 1, 1)
+
+/* parallel camera */
+MUX_CFG("J15_1610_CAM_LCLK", 4, 24, 0, 0, 18, 1, 0, 0, 0)
+MUX_CFG("J18_1610_CAM_D7", 4, 27, 0, 0, 19, 1, 0, 0, 0)
+MUX_CFG("J19_1610_CAM_D6", 5, 0, 0, 0, 20, 1, 0, 0, 0)
+MUX_CFG("J14_1610_CAM_D5", 5, 3, 0, 0, 21, 1, 0, 0, 0)
+MUX_CFG("K18_1610_CAM_D4", 5, 6, 0, 0, 22, 1, 0, 0, 0)
+MUX_CFG("K19_1610_CAM_D3", 5, 9, 0, 0, 23, 1, 0, 0, 0)
+MUX_CFG("K15_1610_CAM_D2", 5, 12, 0, 0, 24, 1, 0, 0, 0)
+MUX_CFG("K14_1610_CAM_D1", 5, 15, 0, 0, 25, 1, 0, 0, 0)
+MUX_CFG("L19_1610_CAM_D0", 5, 18, 0, 0, 26, 1, 0, 0, 0)
+MUX_CFG("L18_1610_CAM_VS", 5, 21, 0, 0, 27, 1, 0, 0, 0)
+MUX_CFG("L15_1610_CAM_HS", 5, 24, 0, 0, 28, 1, 0, 0, 0)
+MUX_CFG("M19_1610_CAM_RSTZ", 5, 27, 0, 0, 29, 0, 0, 0, 0)
+MUX_CFG("Y15_1610_CAM_OUTCLK", A, 0, 6, 2, 6, 0, 2, 0, 0)
+
+/* serial camera */
+MUX_CFG("H19_1610_CAM_EXCLK", 4, 21, 0, 0, 17, 0, 0, 0, 0)
+ /* REVISIT 5912 spec sez CCP_* can't pullup or pulldown ... ? */
+MUX_CFG("Y12_1610_CCP_CLKP", 8, 18, 6, 1, 24, 1, 1, 0, 0)
+MUX_CFG("W13_1610_CCP_CLKM", 9, 0, 6, 1, 28, 1, 1, 0, 0)
+MUX_CFG("W14_1610_CCP_DATAP", 9, 24, 6, 2, 4, 1, 2, 0, 0)
+MUX_CFG("Y14_1610_CCP_DATAM", 9, 21, 6, 2, 3, 1, 2, 0, 0)
+};
+#define OMAP1XXX_PINS_SZ ARRAY_SIZE(omap1xxx_pins)
+#else
+#define omap1xxx_pins NULL
+#define OMAP1XXX_PINS_SZ 0
+#endif /* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */
+
+static int __init_or_module omap1_cfg_reg(const struct pin_config *cfg)
+{
+ static DEFINE_SPINLOCK(mux_spin_lock);
+ unsigned long flags;
+ unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
+ pull_orig = 0, pull = 0;
+ unsigned int mask, warn = 0;
+
+ /* Check the mux register in question */
+ if (cfg->mux_reg) {
+ unsigned tmp1, tmp2;
+
+ spin_lock_irqsave(&mux_spin_lock, flags);
+ reg_orig = omap_readl(cfg->mux_reg);
+
+ /* The mux registers always seem to be 3 bits long */
+ mask = (0x7 << cfg->mask_offset);
+ tmp1 = reg_orig & mask;
+ reg = reg_orig & ~mask;
+
+ tmp2 = (cfg->mask << cfg->mask_offset);
+ reg |= tmp2;
+
+ if (tmp1 != tmp2)
+ warn = 1;
+
+ omap_writel(reg, cfg->mux_reg);
+ spin_unlock_irqrestore(&mux_spin_lock, flags);
+ }
+
+ /* Check for pull up or pull down selection on 1610 */
+ if (!cpu_is_omap15xx()) {
+ if (cfg->pu_pd_reg && cfg->pull_val) {
+ spin_lock_irqsave(&mux_spin_lock, flags);
+ pu_pd_orig = omap_readl(cfg->pu_pd_reg);
+ mask = 1 << cfg->pull_bit;
+
+ if (cfg->pu_pd_val) {
+ if (!(pu_pd_orig & mask))
+ warn = 1;
+ /* Use pull up */
+ pu_pd = pu_pd_orig | mask;
+ } else {
+ if (pu_pd_orig & mask)
+ warn = 1;
+ /* Use pull down */
+ pu_pd = pu_pd_orig & ~mask;
+ }
+ omap_writel(pu_pd, cfg->pu_pd_reg);
+ spin_unlock_irqrestore(&mux_spin_lock, flags);
+ }
+ }
+
+ /* Check for an associated pull down register */
+ if (cfg->pull_reg) {
+ spin_lock_irqsave(&mux_spin_lock, flags);
+ pull_orig = omap_readl(cfg->pull_reg);
+ mask = 1 << cfg->pull_bit;
+
+ if (cfg->pull_val) {
+ if (pull_orig & mask)
+ warn = 1;
+ /* Low bit = pull enabled */
+ pull = pull_orig & ~mask;
+ } else {
+ if (!(pull_orig & mask))
+ warn = 1;
+ /* High bit = pull disabled */
+ pull = pull_orig | mask;
+ }
+
+ omap_writel(pull, cfg->pull_reg);
+ spin_unlock_irqrestore(&mux_spin_lock, flags);
+ }
+
+ if (warn) {
+#ifdef CONFIG_OMAP_MUX_WARNINGS
+ printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
+#endif
+ }
+
+#ifdef CONFIG_OMAP_MUX_DEBUG
+ if (cfg->debug || warn) {
+ printk("MUX: Setting register %s\n", cfg->name);
+ printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
+ cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
+
+ if (!cpu_is_omap15xx()) {
+ if (cfg->pu_pd_reg && cfg->pull_val) {
+ printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
+ cfg->pu_pd_name, cfg->pu_pd_reg,
+ pu_pd_orig, pu_pd);
+ }
+ }
+
+ if (cfg->pull_reg)
+ printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
+ cfg->pull_name, cfg->pull_reg, pull_orig, pull);
+ }
+#endif
+
+#ifdef CONFIG_OMAP_MUX_WARNINGS
+ return warn ? -ETXTBSY : 0;
+#else
+ return 0;
+#endif
+}
+
+int __init omap1_mux_init(void)
+{
+ if (cpu_is_omap7xx()) {
+ arch_mux_cfg.pins = omap7xx_pins;
+ arch_mux_cfg.size = OMAP7XX_PINS_SZ;
+ arch_mux_cfg.cfg_reg = omap1_cfg_reg;
+ }
+
+ if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
+ arch_mux_cfg.pins = omap1xxx_pins;
+ arch_mux_cfg.size = OMAP1XXX_PINS_SZ;
+ arch_mux_cfg.cfg_reg = omap1_cfg_reg;
+ }
+
+ return omap_mux_register(&arch_mux_cfg);
+}
+
+#endif
diff --git a/arch/arm/mach-omap1/opp.h b/arch/arm/mach-omap1/opp.h
new file mode 100644
index 00000000..07074d79
--- /dev/null
+++ b/arch/arm/mach-omap1/opp.h
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/arm/mach-omap1/opp.h
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP1_OPP_H
+#define __ARCH_ARM_MACH_OMAP1_OPP_H
+
+#include <linux/types.h>
+
+struct mpu_rate {
+ unsigned long rate;
+ unsigned long xtal;
+ unsigned long pll_rate;
+ __u16 ckctl_val;
+ __u16 dpllctl_val;
+};
+
+extern struct mpu_rate omap1_rate_table[];
+
+#endif
diff --git a/arch/arm/mach-omap1/opp_data.c b/arch/arm/mach-omap1/opp_data.c
new file mode 100644
index 00000000..75a54651
--- /dev/null
+++ b/arch/arm/mach-omap1/opp_data.c
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/arm/mach-omap1/opp_data.c
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, 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 "opp.h"
+
+/*-------------------------------------------------------------------------
+ * Omap1 MPU rate table
+ *-------------------------------------------------------------------------*/
+struct mpu_rate omap1_rate_table[] = {
+ /* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL
+ * NOTE: Comment order here is different from bits in CKCTL value:
+ * armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv
+ */
+#if defined(CONFIG_OMAP_ARM_216MHZ)
+ { 216000000, 12000000, 216000000, 0x050d, 0x2910 }, /* 1/1/2/2/2/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_195MHZ)
+ { 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_192MHZ)
+ { 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */
+ { 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */
+ { 96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */
+ { 48000000, 12000000, 192000000, 0x0baf, 0x2810 }, /* 4/4/4/8/8/8 */
+ { 24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_182MHZ)
+ { 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_168MHZ)
+ { 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_150MHZ)
+ { 150000000, 12000000, 150000000, 0x010a, 0x2cb0 }, /* 1/1/1/2/4/4 */
+#endif
+#if defined(CONFIG_OMAP_ARM_120MHZ)
+ { 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */
+#endif
+#if defined(CONFIG_OMAP_ARM_96MHZ)
+ { 96000000, 12000000, 96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */
+#endif
+#if defined(CONFIG_OMAP_ARM_60MHZ)
+ { 60000000, 12000000, 60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */
+#endif
+#if defined(CONFIG_OMAP_ARM_30MHZ)
+ { 30000000, 12000000, 60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */
+#endif
+ { 0, 0, 0, 0, 0 },
+};
+
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
new file mode 100644
index 00000000..98ba9784
--- /dev/null
+++ b/arch/arm/mach-omap1/pm.c
@@ -0,0 +1,730 @@
+/*
+ * 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/suspend.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+
+#include <plat/cpu.h>
+#include <mach/irqs.h>
+#include <plat/clock.h>
+#include <plat/sram.h>
+#include <plat/tc.h>
+#include <plat/mux.h>
+#include <plat/dma.h>
+#include <plat/dmtimer.h>
+
+#include "pm.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 mpui7xx_sleep_save[MPUI7XX_SLEEP_SAVE_SIZE];
+static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
+static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+
+#ifdef CONFIG_OMAP_32K_TIMER
+
+static unsigned short enable_dyn_sleep = 1;
+
+static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%hu\n", enable_dyn_sleep);
+}
+
+static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
+ 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 kobj_attribute sleep_while_idle_attr =
+ __ATTR(sleep_while_idle, 0644, idle_show, idle_store);
+
+#endif
+
+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 omap1_pm_idle(void)
+{
+ extern __u32 arm_idlect1_mask;
+ __u32 use_idlect1 = arm_idlect1_mask;
+ int do_sleep = 0;
+
+ local_irq_disable();
+ local_fiq_disable();
+ if (need_resched()) {
+ local_fiq_enable();
+ local_irq_enable();
+ return;
+ }
+
+#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
+
+ while (enable_dyn_sleep) {
+
+#ifdef CONFIG_CBUS_TAHVO_USB
+ extern int vbus_active;
+ /* Clock requirements? */
+ if (vbus_active)
+ break;
+#endif
+ do_sleep = 1;
+ break;
+ }
+
+#endif
+
+#ifdef CONFIG_OMAP_DM_TIMER
+ use_idlect1 = omap_dm_timer_modify_idlect_mask(use_idlect1);
+#endif
+
+ if (omap_dma_running())
+ use_idlect1 &= ~(1 << 6);
+
+ /* 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));
+
+ 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_omap7xx())
+ level1_wake = OMAP_IRQ_BIT(INT_7XX_GPIO_BANK1) |
+ OMAP_IRQ_BIT(INT_7XX_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_omap7xx()) {
+ omap_writel(~level2_wake, OMAP_IH2_0_MIR);
+ omap_writel(~(OMAP_IRQ_BIT(INT_7XX_WAKE_UP_REQ) |
+ OMAP_IRQ_BIT(INT_7XX_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 omap1_pm_suspend(void)
+{
+ unsigned long arg0 = 0, arg1 = 0;
+
+ printk(KERN_INFO "PM: OMAP%x is trying to enter deep sleep...\n",
+ omap_rev());
+
+ omap_serial_wake_trigger(1);
+
+ if (!cpu_is_omap15xx())
+ 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_omap7xx()) {
+ MPUI7XX_SAVE(OMAP_IH1_MIR);
+ MPUI7XX_SAVE(OMAP_IH2_0_MIR);
+ MPUI7XX_SAVE(OMAP_IH2_1_MIR);
+ MPUI7XX_SAVE(MPUI_CTRL);
+ MPUI7XX_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI7XX_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI7XX_SAVE(EMIFS_CONFIG);
+ MPUI7XX_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 */
+ if (!cpu_is_omap7xx())
+ 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_omap7xx()) {
+ MPUI7XX_RESTORE(EMIFS_CONFIG);
+ MPUI7XX_RESTORE(EMIFF_SDRAM_CONFIG);
+ MPUI7XX_RESTORE(OMAP_IH1_MIR);
+ MPUI7XX_RESTORE(OMAP_IH2_0_MIR);
+ MPUI7XX_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);
+ }
+
+ if (!cpu_is_omap15xx())
+ omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG);
+
+ /*
+ * Re-enable interrupts
+ */
+
+ local_irq_enable();
+ local_fiq_enable();
+
+ omap_serial_wake_trigger(0);
+
+ printk(KERN_INFO "PM: OMAP%x is re-starting from deep sleep...\n",
+ omap_rev());
+}
+
+#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_omap7xx()) {
+ MPUI7XX_SAVE(MPUI_CTRL);
+ MPUI7XX_SAVE(MPUI_DSP_STATUS);
+ MPUI7XX_SAVE(MPUI_DSP_BOOT_CONFIG);
+ MPUI7XX_SAVE(MPUI_DSP_API_CONFIG);
+ MPUI7XX_SAVE(EMIFF_SDRAM_CONFIG);
+ MPUI7XX_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_omap7xx()) {
+ my_buffer_offset += sprintf(my_base + my_buffer_offset,
+ "MPUI7XX_CTRL_REG 0x%-8x \n"
+ "MPUI7XX_DSP_STATUS_REG: 0x%-8x \n"
+ "MPUI7XX_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+ "MPUI7XX_DSP_API_CONFIG_REG: 0x%-8x \n"
+ "MPUI7XX_SDRAM_CONFIG_REG: 0x%-8x \n"
+ "MPUI7XX_EMIFS_CONFIG_REG: 0x%-8x \n",
+ MPUI7XX_SHOW(MPUI_CTRL),
+ MPUI7XX_SHOW(MPUI_DSP_STATUS),
+ MPUI7XX_SHOW(MPUI_DSP_BOOT_CONFIG),
+ MPUI7XX_SHOW(MPUI_DSP_API_CONFIG),
+ MPUI7XX_SHOW(EMIFF_SDRAM_CONFIG),
+ MPUI7XX_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.
+ *
+ */
+static int omap_pm_prepare(void)
+{
+ /* We cannot sleep in idle until we have resumed */
+ saved_idle = pm_idle;
+ pm_idle = NULL;
+
+ return 0;
+}
+
+
+/*
+ * 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:
+ omap1_pm_suspend();
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/**
+ * omap_pm_finish - Finish up suspend sequence.
+ *
+ * This is called after we wake back up (or if entering the sleep state
+ * failed).
+ */
+
+static void omap_pm_finish(void)
+{
+ pm_idle = saved_idle;
+}
+
+
+static irqreturn_t omap_wakeup_interrupt(int irq, void *dev)
+{
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap_wakeup_irq = {
+ .name = "peripheral wakeup",
+ .flags = IRQF_DISABLED,
+ .handler = omap_wakeup_interrupt
+};
+
+
+
+static const struct platform_suspend_ops omap_pm_ops = {
+ .prepare = omap_pm_prepare,
+ .enter = omap_pm_enter,
+ .finish = omap_pm_finish,
+ .valid = suspend_valid_only_mem,
+};
+
+static int __init omap_pm_init(void)
+{
+
+#ifdef CONFIG_OMAP_32K_TIMER
+ int error;
+#endif
+
+ if (!cpu_class_is_omap1())
+ return -ENODEV;
+
+ 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_omap7xx()) {
+ omap_sram_suspend = omap_sram_push(omap7xx_cpu_suspend,
+ omap7xx_cpu_suspend_sz);
+ } else if (cpu_is_omap15xx()) {
+ omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend,
+ omap1510_cpu_suspend_sz);
+ } else if (cpu_is_omap16xx()) {
+ omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend,
+ omap1610_cpu_suspend_sz);
+ }
+
+ if (omap_sram_suspend == NULL) {
+ printk(KERN_ERR "PM not initialized: Missing SRAM support\n");
+ return -ENODEV;
+ }
+
+ pm_idle = omap1_pm_idle;
+
+ if (cpu_is_omap7xx())
+ setup_irq(INT_7XX_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_omap7xx())
+ omap_writel(OMAP7XX_IDLECT3_VAL, OMAP7XX_IDLECT3);
+ else if (cpu_is_omap16xx())
+ omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3);
+
+ suspend_set_ops(&omap_pm_ops);
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+ omap_pm_init_proc();
+#endif
+
+#ifdef CONFIG_OMAP_32K_TIMER
+ error = sysfs_create_file(power_kobj, &sleep_while_idle_attr.attr);
+ if (error)
+ printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
+#endif
+
+ 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/pm.h b/arch/arm/mach-omap1/pm.h
new file mode 100644
index 00000000..cd926dcb
--- /dev/null
+++ b/arch/arm/mach-omap1/pm.h
@@ -0,0 +1,281 @@
+/*
+ * arch/arm/mach-omap1/pm.h
+ *
+ * Header file for OMAP1 Power Management Routines
+ *
+ * Author: MontaVista Software, Inc.
+ * support@mvista.com
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ *
+ * Cleanup 2004 for Linux 2.6 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP1_PM_H
+#define __ARCH_ARM_MACH_OMAP1_PM_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * Register and offset definitions to be used in PM assembler code
+ * ----------------------------------------------------------------------------
+ */
+#define CLKGEN_REG_ASM_BASE OMAP1_IO_ADDRESS(0xfffece00)
+#define ARM_IDLECT1_ASM_OFFSET 0x04
+#define ARM_IDLECT2_ASM_OFFSET 0x08
+
+#define TCMIF_ASM_BASE OMAP1_IO_ADDRESS(0xfffecc00)
+#define EMIFS_CONFIG_ASM_OFFSET 0x0c
+#define EMIFF_SDRAM_CONFIG_ASM_OFFSET 0x20
+
+/*
+ * ----------------------------------------------------------------------------
+ * Power management bitmasks
+ * ----------------------------------------------------------------------------
+ */
+#define IDLE_WAIT_CYCLES 0x00000fff
+#define PERIPHERAL_ENABLE 0x2
+
+#define SELF_REFRESH_MODE 0x0c000001
+#define IDLE_EMIFS_REQUEST 0xc
+#define MODEM_32K_EN 0x1
+#define PER_EN 0x1
+
+#define CPU_SUSPEND_SIZE 200
+#define ULPD_LOW_PWR_EN 0x0001
+#define ULPD_DEEP_SLEEP_TRANSITION_EN 0x0010
+#define ULPD_SETUP_ANALOG_CELL_3_VAL 0
+#define ULPD_POWER_CTRL_REG_VAL 0x0219
+
+#define DSP_IDLE_DELAY 10
+#define DSP_IDLE 0x0040
+#define DSP_RST 0x0004
+#define DSP_ENABLE 0x0002
+#define SUFFICIENT_DSP_RESET_TIME 1000
+#define DEFAULT_MPUI_CONFIG 0x05cf
+#define ENABLE_XORCLK 0x2
+#define DSP_CLOCK_ENABLE 0x2000
+#define DSP_IDLE_MODE 0x2
+#define TC_IDLE_REQUEST (0x0000000c)
+
+#define IRQ_LEVEL2 (1<<0)
+#define IRQ_KEYBOARD (1<<1)
+#define IRQ_UART2 (1<<15)
+
+#define PDE_BIT 0x08
+#define PWD_EN_BIT 0x04
+#define EN_PERCK_BIT 0x04
+
+#define OMAP1510_DEEP_SLEEP_REQUEST 0x0ec7
+#define OMAP1510_BIG_SLEEP_REQUEST 0x0cc5
+#define OMAP1510_IDLE_LOOP_REQUEST 0x0c00
+#define OMAP1510_IDLE_CLOCK_DOMAINS 0x2
+
+/* Both big sleep and deep sleep use same values. Difference is in ULPD. */
+#define OMAP1610_IDLECT1_SLEEP_VAL 0x13c7
+#define OMAP1610_IDLECT2_SLEEP_VAL 0x09c7
+#define OMAP1610_IDLECT3_VAL 0x3f
+#define OMAP1610_IDLECT3_SLEEP_ORMASK 0x2c
+#define OMAP1610_IDLECT3 0xfffece24
+#define OMAP1610_IDLE_LOOP_REQUEST 0x0400
+
+#define OMAP7XX_IDLECT1_SLEEP_VAL 0x16c7
+#define OMAP7XX_IDLECT2_SLEEP_VAL 0x09c7
+#define OMAP7XX_IDLECT3_VAL 0x3f
+#define OMAP7XX_IDLECT3 0xfffece24
+#define OMAP7XX_IDLE_LOOP_REQUEST 0x0C00
+
+#if !defined(CONFIG_ARCH_OMAP730) && \
+ !defined(CONFIG_ARCH_OMAP850) && \
+ !defined(CONFIG_ARCH_OMAP15XX) && \
+ !defined(CONFIG_ARCH_OMAP16XX)
+#warning "Power management for this processor not implemented yet"
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <linux/clk.h>
+
+extern struct kset power_subsys;
+
+extern void prevent_idle_sleep(void);
+extern void allow_idle_sleep(void);
+
+extern void omap1_pm_idle(void);
+extern void omap1_pm_suspend(void);
+
+extern void omap7xx_cpu_suspend(unsigned long, unsigned long);
+extern void omap1510_cpu_suspend(unsigned long, unsigned long);
+extern void omap1610_cpu_suspend(unsigned long, unsigned long);
+extern void omap7xx_idle_loop_suspend(void);
+extern void omap1510_idle_loop_suspend(void);
+extern void omap1610_idle_loop_suspend(void);
+
+extern unsigned int omap7xx_cpu_suspend_sz;
+extern unsigned int omap1510_cpu_suspend_sz;
+extern unsigned int omap1610_cpu_suspend_sz;
+extern unsigned int omap7xx_idle_loop_suspend_sz;
+extern unsigned int omap1510_idle_loop_suspend_sz;
+extern unsigned int omap1610_idle_loop_suspend_sz;
+
+#ifdef CONFIG_OMAP_SERIAL_WAKE
+extern void omap_serial_wake_trigger(int enable);
+#else
+#define omap_serial_wakeup_init() {}
+#define omap_serial_wake_trigger(x) {}
+#endif /* CONFIG_OMAP_SERIAL_WAKE */
+
+#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x)
+#define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x))
+#define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x]
+
+#define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x)
+#define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x))
+#define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x]
+
+#define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x)
+#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
+#define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
+
+#define MPUI7XX_SAVE(x) mpui7xx_sleep_save[MPUI7XX_SLEEP_SAVE_##x] = omap_readl(x)
+#define MPUI7XX_RESTORE(x) omap_writel((mpui7xx_sleep_save[MPUI7XX_SLEEP_SAVE_##x]), (x))
+#define MPUI7XX_SHOW(x) mpui7xx_sleep_save[MPUI7XX_SLEEP_SAVE_##x]
+
+#define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x)
+#define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x))
+#define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]
+
+#define MPUI1610_SAVE(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] = omap_readl(x)
+#define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x))
+#define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]
+
+/*
+ * List of global OMAP registers to preserve.
+ * More ones like CP and general purpose register values are preserved
+ * with the stack pointer in sleep.S.
+ */
+
+enum arm_save_state {
+ ARM_SLEEP_SAVE_START = 0,
+ /*
+ * MPU control registers 32 bits
+ */
+ ARM_SLEEP_SAVE_ARM_CKCTL,
+ ARM_SLEEP_SAVE_ARM_IDLECT1,
+ ARM_SLEEP_SAVE_ARM_IDLECT2,
+ ARM_SLEEP_SAVE_ARM_IDLECT3,
+ ARM_SLEEP_SAVE_ARM_EWUPCT,
+ ARM_SLEEP_SAVE_ARM_RSTCT1,
+ ARM_SLEEP_SAVE_ARM_RSTCT2,
+ ARM_SLEEP_SAVE_ARM_SYSST,
+ ARM_SLEEP_SAVE_SIZE
+};
+
+enum dsp_save_state {
+ DSP_SLEEP_SAVE_START = 0,
+ /*
+ * DSP registers 16 bits
+ */
+ DSP_SLEEP_SAVE_DSP_IDLECT2,
+ DSP_SLEEP_SAVE_SIZE
+};
+
+enum ulpd_save_state {
+ ULPD_SLEEP_SAVE_START = 0,
+ /*
+ * ULPD registers 16 bits
+ */
+ ULPD_SLEEP_SAVE_ULPD_IT_STATUS,
+ ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL,
+ ULPD_SLEEP_SAVE_ULPD_SOFT_REQ,
+ ULPD_SLEEP_SAVE_ULPD_STATUS_REQ,
+ ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL,
+ ULPD_SLEEP_SAVE_ULPD_POWER_CTRL,
+ ULPD_SLEEP_SAVE_SIZE
+};
+
+enum mpui1510_save_state {
+ MPUI1510_SLEEP_SAVE_START = 0,
+ /*
+ * MPUI registers 32 bits
+ */
+ MPUI1510_SLEEP_SAVE_MPUI_CTRL,
+ MPUI1510_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
+ MPUI1510_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
+ MPUI1510_SLEEP_SAVE_MPUI_DSP_STATUS,
+ MPUI1510_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
+ MPUI1510_SLEEP_SAVE_EMIFS_CONFIG,
+ MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR,
+ MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR,
+#if defined(CONFIG_ARCH_OMAP15XX)
+ MPUI1510_SLEEP_SAVE_SIZE
+#else
+ MPUI1510_SLEEP_SAVE_SIZE = 0
+#endif
+};
+
+enum mpui7xx_save_state {
+ MPUI7XX_SLEEP_SAVE_START = 0,
+ /*
+ * MPUI registers 32 bits
+ */
+ MPUI7XX_SLEEP_SAVE_MPUI_CTRL,
+ MPUI7XX_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
+ MPUI7XX_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
+ MPUI7XX_SLEEP_SAVE_MPUI_DSP_STATUS,
+ MPUI7XX_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
+ MPUI7XX_SLEEP_SAVE_EMIFS_CONFIG,
+ MPUI7XX_SLEEP_SAVE_OMAP_IH1_MIR,
+ MPUI7XX_SLEEP_SAVE_OMAP_IH2_0_MIR,
+ MPUI7XX_SLEEP_SAVE_OMAP_IH2_1_MIR,
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ MPUI7XX_SLEEP_SAVE_SIZE
+#else
+ MPUI7XX_SLEEP_SAVE_SIZE = 0
+#endif
+};
+
+enum mpui1610_save_state {
+ MPUI1610_SLEEP_SAVE_START = 0,
+ /*
+ * MPUI registers 32 bits
+ */
+ MPUI1610_SLEEP_SAVE_MPUI_CTRL,
+ MPUI1610_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
+ MPUI1610_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
+ MPUI1610_SLEEP_SAVE_MPUI_DSP_STATUS,
+ MPUI1610_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
+ MPUI1610_SLEEP_SAVE_EMIFS_CONFIG,
+ MPUI1610_SLEEP_SAVE_OMAP_IH1_MIR,
+ MPUI1610_SLEEP_SAVE_OMAP_IH2_0_MIR,
+ MPUI1610_SLEEP_SAVE_OMAP_IH2_1_MIR,
+ MPUI1610_SLEEP_SAVE_OMAP_IH2_2_MIR,
+ MPUI1610_SLEEP_SAVE_OMAP_IH2_3_MIR,
+#if defined(CONFIG_ARCH_OMAP16XX)
+ MPUI1610_SLEEP_SAVE_SIZE
+#else
+ MPUI1610_SLEEP_SAVE_SIZE = 0
+#endif
+};
+
+#endif /* ASSEMBLER */
+#endif /* __ASM_ARCH_OMAP_PM_H */
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
new file mode 100644
index 00000000..334fb887
--- /dev/null
+++ b/arch/arm/mach-omap1/pm_bus.c
@@ -0,0 +1,79 @@
+/*
+ * Runtime PM support code for OMAP1
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#ifdef CONFIG_PM_RUNTIME
+static int omap1_pm_runtime_suspend(struct device *dev)
+{
+ int ret;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ ret = pm_generic_runtime_suspend(dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_clk_suspend(dev);
+ if (ret) {
+ pm_generic_runtime_resume(dev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int omap1_pm_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "%s\n", __func__);
+
+ pm_runtime_clk_resume(dev);
+ return pm_generic_runtime_resume(dev);
+}
+
+static struct dev_power_domain default_power_domain = {
+ .ops = {
+ .runtime_suspend = omap1_pm_runtime_suspend,
+ .runtime_resume = omap1_pm_runtime_resume,
+ USE_PLATFORM_PM_SLEEP_OPS
+ },
+};
+#define OMAP1_PWR_DOMAIN (&default_power_domain)
+#else
+#define OMAP1_PWR_DOMAIN NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static struct pm_clk_notifier_block platform_bus_notifier = {
+ .pwr_domain = OMAP1_PWR_DOMAIN,
+ .con_ids = { "ick", "fck", NULL, },
+};
+
+static int __init omap1_pm_runtime_init(void)
+{
+ if (!cpu_class_is_omap1())
+ return -ENODEV;
+
+ pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+
+ return 0;
+}
+core_initcall(omap1_pm_runtime_init);
+
diff --git a/arch/arm/mach-omap1/reset.c b/arch/arm/mach-omap1/reset.c
new file mode 100644
index 00000000..ad951ee6
--- /dev/null
+++ b/arch/arm/mach-omap1/reset.c
@@ -0,0 +1,25 @@
+/*
+ * OMAP1 reset support
+ */
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/system.h>
+#include <plat/prcm.h>
+
+void omap1_arch_reset(char mode, const char *cmd)
+{
+ /*
+ * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28
+ * "Global Software Reset Affects Traffic Controller Frequency".
+ */
+ if (cpu_is_omap5912()) {
+ omap_writew(omap_readw(DPLL_CTL) & ~(1 << 4), DPLL_CTL);
+ omap_writew(0x8, ARM_RSTCT1);
+ }
+
+ omap_writew(1, ARM_RSTCT1);
+}
+
+void (*arch_reset)(char, const char *) = omap1_arch_reset;
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
new file mode 100644
index 00000000..550ca9d9
--- /dev/null
+++ b/arch/arm/mach-omap1/serial.c
@@ -0,0 +1,266 @@
+/*
+ * linux/arch/arm/mach-omap1/serial.c
+ *
+ * OMAP1 serial support.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+
+#include <plat/board.h>
+#include <plat/mux.h>
+#include <mach/gpio.h>
+#include <plat/fpga.h>
+
+#include "pm.h"
+
+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)
+{
+ offset <<= up->regshift;
+ return (unsigned int)__raw_readb(up->membase + offset);
+}
+
+static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset,
+ int value)
+{
+ offset <<= p->regshift;
+ __raw_writeb(value, p->membase + offset);
+}
+
+/*
+ * Internal UARTs need to be initialized for the 8250 autoconfig to work
+ * properly. Note that the TX watermark initialization may not be needed
+ * once the 8250.c watermark handling code is merged.
+ */
+static void __init omap_serial_reset(struct plat_serial8250_port *p)
+{
+ omap_serial_outp(p, UART_OMAP_MDR1,
+ UART_OMAP_MDR1_DISABLE); /* disable UART */
+ omap_serial_outp(p, UART_OMAP_SCR, 0x08); /* TX watermark */
+ omap_serial_outp(p, UART_OMAP_MDR1,
+ UART_OMAP_MDR1_16X_MODE); /* enable UART */
+
+ if (!cpu_is_omap15xx()) {
+ omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
+ while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01));
+ }
+}
+
+static struct plat_serial8250_port serial_platform_data[] = {
+ {
+ .mapbase = OMAP1_UART1_BASE,
+ .irq = INT_UART1,
+ .flags = UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = OMAP16XX_BASE_BAUD * 16,
+ },
+ {
+ .mapbase = OMAP1_UART2_BASE,
+ .irq = INT_UART2,
+ .flags = UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = OMAP16XX_BASE_BAUD * 16,
+ },
+ {
+ .mapbase = OMAP1_UART3_BASE,
+ .irq = INT_UART3,
+ .flags = UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = OMAP16XX_BASE_BAUD * 16,
+ },
+ { },
+};
+
+static struct platform_device serial_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = serial_platform_data,
+ },
+};
+
+/*
+ * Note that on Innovator-1510 UART2 pins conflict with USB2.
+ * By default UART2 does not work on Innovator-1510 if you have
+ * USB OHCI enabled. To use UART2, you must disable USB2 first.
+ */
+void __init omap_serial_init(void)
+{
+ int i;
+
+ if (cpu_is_omap7xx()) {
+ serial_platform_data[0].regshift = 0;
+ serial_platform_data[1].regshift = 0;
+ serial_platform_data[0].irq = INT_7XX_UART_MODEM_1;
+ serial_platform_data[1].irq = INT_7XX_UART_MODEM_IRDA_2;
+ }
+
+ if (cpu_is_omap15xx()) {
+ serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
+ serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
+ serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(serial_platform_data) - 1; i++) {
+
+ /* Don't look at UARTs higher than 2 for omap7xx */
+ if (cpu_is_omap7xx() && i > 1) {
+ serial_platform_data[i].membase = NULL;
+ serial_platform_data[i].mapbase = 0;
+ continue;
+ }
+
+ /* Static mapping, never released */
+ serial_platform_data[i].membase =
+ ioremap(serial_platform_data[i].mapbase, SZ_2K);
+ if (!serial_platform_data[i].membase) {
+ printk(KERN_ERR "Could not ioremap uart%i\n", i);
+ continue;
+ }
+ switch (i) {
+ case 0:
+ uart1_ck = clk_get(NULL, "uart1_ck");
+ if (IS_ERR(uart1_ck))
+ printk("Could not get uart1_ck\n");
+ else {
+ clk_enable(uart1_ck);
+ if (cpu_is_omap15xx())
+ clk_set_rate(uart1_ck, 12000000);
+ }
+ break;
+ case 1:
+ uart2_ck = clk_get(NULL, "uart2_ck");
+ if (IS_ERR(uart2_ck))
+ printk("Could not get uart2_ck\n");
+ else {
+ clk_enable(uart2_ck);
+ if (cpu_is_omap15xx())
+ clk_set_rate(uart2_ck, 12000000);
+ else
+ clk_set_rate(uart2_ck, 48000000);
+ }
+ break;
+ case 2:
+ uart3_ck = clk_get(NULL, "uart3_ck");
+ if (IS_ERR(uart3_ck))
+ printk("Could not get uart3_ck\n");
+ else {
+ clk_enable(uart3_ck);
+ if (cpu_is_omap15xx())
+ clk_set_rate(uart3_ck, 12000000);
+ }
+ break;
+ }
+ omap_serial_reset(&serial_platform_data[i]);
+ }
+}
+
+#ifdef CONFIG_OMAP_SERIAL_WAKE
+
+static irqreturn_t omap_serial_wake_interrupt(int irq, void *dev_id)
+{
+ /* 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 = gpio_request(gpio_nr, "UART wake");
+ if (ret < 0) {
+ printk(KERN_ERR "Could not request UART wake GPIO: %i\n",
+ gpio_nr);
+ return;
+ }
+ gpio_direction_input(gpio_nr);
+ ret = request_irq(gpio_to_irq(gpio_nr), &omap_serial_wake_interrupt,
+ IRQF_TRIGGER_RISING, "serial wakeup", NULL);
+ if (ret) {
+ gpio_free(gpio_nr);
+ printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n",
+ gpio_nr);
+ return;
+ }
+ enable_irq_wake(gpio_to_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)
+{
+ if (!cpu_class_is_omap1())
+ return -ENODEV;
+
+ return platform_device_register(&serial_device);
+}
+arch_initcall(omap_init);
diff --git a/arch/arm/mach-omap1/sleep.S b/arch/arm/mach-omap1/sleep.S
new file mode 100644
index 00000000..c875bdc9
--- /dev/null
+++ b/arch/arm/mach-omap1/sleep.S
@@ -0,0 +1,366 @@
+/*
+ * linux/arch/arm/mach-omap1/sleep.S
+ *
+ * Low-level OMAP7XX/1510/1610 sleep/wakeUp support
+ *
+ * Initial SA1110 code:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * Adapted for PXA by Nicolas Pitre:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Support 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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/io.h>
+#include "pm.h"
+
+ .text
+
+
+/*
+ * Forces OMAP into deep sleep state
+ *
+ * omapXXXX_cpu_suspend()
+ *
+ * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed
+ * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1
+ * in register r1.
+ *
+ * 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.
+ *
+ * Note: Because of errata work arounds we have processor specific functions
+ * here. They are mostly the same, but slightly different.
+ *
+ */
+
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ .align 3
+ENTRY(omap7xx_cpu_suspend)
+
+ @ save registers on stack
+ stmfd sp!, {r0 - r12, lr}
+
+ @ Drain write cache
+ mov r4, #0
+ mcr p15, 0, r0, c7, c10, 4
+ nop
+
+ @ 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
+ 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
+ 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
+ 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)
+ mov r5, #OMAP7XX_IDLECT2_SLEEP_VAL & 0xff
+ orr r5, r5, #OMAP7XX_IDLECT2_SLEEP_VAL & 0xff00
+ strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+
+ @ request ARM idle
+ mov r3, #OMAP7XX_IDLECT1_SLEEP_VAL & 0xff
+ orr r3, r3, #OMAP7XX_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
+/*
+ * omap7xx_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.
+ strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+ strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+ @ Restore EMIFF controls
+ str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+ str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+ @ restore regs and return
+ ldmfd sp!, {r0 - r12, pc}
+
+ENTRY(omap7xx_cpu_suspend_sz)
+ .word . - omap7xx_cpu_suspend
+#endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */
+
+#ifdef CONFIG_ARCH_OMAP15XX
+ .align 3
+ENTRY(omap1510_cpu_suspend)
+
+ @ save registers on stack
+ stmfd sp!, {r0 - r12, lr}
+
+ @ load base address of Traffic Controller
+ mov r4, #TCMIF_ASM_BASE & 0xff000000
+ orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
+ orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
+
+ @ work around errata of OMAP1510 PDE bit for TC shut down
+ @ clear PDE bit
+ ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+ bic r5, r5, #PDE_BIT & 0xff
+ str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+ @ set PWD_EN bit
+ and r5, r5, #PWD_EN_BIT & 0xff
+ str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+ @ prepare to put SDRAM into self-refresh manually
+ ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+ orr r5, r5, #SELF_REFRESH_MODE & 0xff000000
+ orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff
+ str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+
+ @ prepare to put EMIFS to Sleep
+ ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+ orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff
+ str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+ @ 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
+ mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
+ orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
+ strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+
+ @ request ARM idle
+ mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff
+ orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00
+ strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+ mov r5, #IDLE_WAIT_CYCLES & 0xff
+ orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+l_1510_2:
+ subs r5, r5, #1
+ bne l_1510_2
+/*
+ * 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
+/*
+ * omap1510_cpu_suspend()'s resume point.
+ *
+ * It will just start executing here, so we'll restore stuff from the
+ * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
+ */
+ strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+ strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+ @ restore regs and return
+ ldmfd sp!, {r0 - r12, pc}
+
+ENTRY(omap1510_cpu_suspend_sz)
+ .word . - omap1510_cpu_suspend
+#endif /* CONFIG_ARCH_OMAP15XX */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+ .align 3
+ENTRY(omap1610_cpu_suspend)
+
+ @ save registers on stack
+ stmfd sp!, {r0 - r12, lr}
+
+ @ Drain write cache
+ mov r4, #0
+ mcr p15, 0, r0, c7, c10, 4
+ nop
+
+ @ 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
+ 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
+ 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
+ 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)
+ 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
+ mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
+ orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
+ strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+/*
+ * 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.
+ */
+ @ Restore the ARM_IDLECT1 and ARM_IDLECT2.
+ strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+ strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+ @ Restore EMIFF controls
+ str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+ str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+ @ Restore regs and return
+ ldmfd sp!, {r0 - r12, pc}
+
+ENTRY(omap1610_cpu_suspend_sz)
+ .word . - omap1610_cpu_suspend
+#endif /* CONFIG_ARCH_OMAP16XX */
diff --git a/arch/arm/mach-omap1/sram.S b/arch/arm/mach-omap1/sram.S
new file mode 100644
index 00000000..692587d0
--- /dev/null
+++ b/arch/arm/mach-omap1/sram.S
@@ -0,0 +1,58 @@
+/*
+ * linux/arch/arm/plat-omap/sram-fn.S
+ *
+ * Functions that need to be run in internal SRAM
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/io.h>
+#include <mach/hardware.h>
+
+ .text
+
+/*
+ * Reprograms ULPD and CKCTL.
+ */
+ .align 3
+ENTRY(omap1_sram_reprogram_clock)
+ stmfd sp!, {r0 - r12, lr} @ save registers on stack
+
+ mov r2, #OMAP1_IO_ADDRESS(DPLL_CTL) & 0xff000000
+ orr r2, r2, #OMAP1_IO_ADDRESS(DPLL_CTL) & 0x00ff0000
+ orr r2, r2, #OMAP1_IO_ADDRESS(DPLL_CTL) & 0x0000ff00
+
+ mov r3, #OMAP1_IO_ADDRESS(ARM_CKCTL) & 0xff000000
+ orr r3, r3, #OMAP1_IO_ADDRESS(ARM_CKCTL) & 0x00ff0000
+ orr r3, r3, #OMAP1_IO_ADDRESS(ARM_CKCTL) & 0x0000ff00
+
+ tst r0, #1 << 4 @ want lock mode?
+ beq newck @ nope
+ bic r0, r0, #1 << 4 @ else clear lock bit
+ strh r0, [r2] @ set dpll into bypass mode
+ orr r0, r0, #1 << 4 @ set lock bit again
+
+newck:
+ strh r1, [r3] @ write new ckctl value
+ strh r0, [r2] @ write new dpll value
+
+ mov r4, #0x0700 @ let the clocks settle
+ orr r4, r4, #0x00ff
+delay: sub r4, r4, #1
+ cmp r4, #0
+ bne delay
+
+lock: ldrh r4, [r2], #0 @ read back dpll value
+ tst r0, #1 << 4 @ want lock mode?
+ beq out @ nope
+ tst r4, #1 << 0 @ dpll rate locked?
+ beq lock @ try again
+
+out:
+ ldmfd sp!, {r0 - r12, pc} @ restore regs and return
+ENTRY(omap1_sram_reprogram_clock_sz)
+ .word . - omap1_sram_reprogram_clock
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
new file mode 100644
index 00000000..03e1e106
--- /dev/null
+++ b/arch/arm/mach-omap1/time.c
@@ -0,0 +1,312 @@
+/*
+ * linux/arch/arm/mach-omap1/time.c
+ *
+ * OMAP Timers
+ *
+ * Copyright (C) 2004 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/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <mach/hardware.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/sched_clock.h>
+
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+#include <plat/common.h>
+
+#ifdef CONFIG_OMAP_MPU_TIMER
+
+#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE
+#define OMAP_MPU_TIMER_OFFSET 0x100
+
+typedef struct {
+ u32 cntl; /* CNTL_TIMER, R/W */
+ u32 load_tim; /* LOAD_TIM, W */
+ u32 read_tim; /* READ_TIM, R */
+} omap_mpu_timer_regs_t;
+
+#define omap_mpu_timer_base(n) \
+((omap_mpu_timer_regs_t __iomem *)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE + \
+ (n)*OMAP_MPU_TIMER_OFFSET))
+
+static inline unsigned long notrace omap_mpu_timer_read(int nr)
+{
+ omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
+ return readl(&timer->read_tim);
+}
+
+static inline void omap_mpu_set_autoreset(int nr)
+{
+ omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
+
+ writel(readl(&timer->cntl) | MPU_TIMER_AR, &timer->cntl);
+}
+
+static inline void omap_mpu_remove_autoreset(int nr)
+{
+ omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
+
+ writel(readl(&timer->cntl) & ~MPU_TIMER_AR, &timer->cntl);
+}
+
+static inline void omap_mpu_timer_start(int nr, unsigned long load_val,
+ int autoreset)
+{
+ omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
+ unsigned int timerflags = MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_ST;
+
+ if (autoreset)
+ timerflags |= MPU_TIMER_AR;
+
+ writel(MPU_TIMER_CLOCK_ENABLE, &timer->cntl);
+ udelay(1);
+ writel(load_val, &timer->load_tim);
+ udelay(1);
+ writel(timerflags, &timer->cntl);
+}
+
+static inline void omap_mpu_timer_stop(int nr)
+{
+ omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
+
+ writel(readl(&timer->cntl) & ~MPU_TIMER_ST, &timer->cntl);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * MPU timer 1 ... count down to zero, interrupt, reload
+ * ---------------------------------------------------------------------------
+ */
+static int omap_mpu_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ omap_mpu_timer_start(0, cycles, 0);
+ return 0;
+}
+
+static void omap_mpu_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ omap_mpu_set_autoreset(0);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ omap_mpu_timer_stop(0);
+ omap_mpu_remove_autoreset(0);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static struct clock_event_device clockevent_mpu_timer1 = {
+ .name = "mpu_timer1",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_next_event = omap_mpu_set_next_event,
+ .set_mode = omap_mpu_set_mode,
+};
+
+static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &clockevent_mpu_timer1;
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap_mpu_timer1_irq = {
+ .name = "mpu_timer1",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = omap_mpu_timer1_interrupt,
+};
+
+static __init void omap_init_mpu_timer(unsigned long rate)
+{
+ setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
+ omap_mpu_timer_start(0, (rate / HZ) - 1, 1);
+
+ clockevent_mpu_timer1.mult = div_sc(rate, NSEC_PER_SEC,
+ clockevent_mpu_timer1.shift);
+ clockevent_mpu_timer1.max_delta_ns =
+ clockevent_delta2ns(-1, &clockevent_mpu_timer1);
+ clockevent_mpu_timer1.min_delta_ns =
+ clockevent_delta2ns(1, &clockevent_mpu_timer1);
+
+ clockevent_mpu_timer1.cpumask = cpumask_of(0);
+ clockevents_register_device(&clockevent_mpu_timer1);
+}
+
+
+/*
+ * ---------------------------------------------------------------------------
+ * MPU timer 2 ... free running 32-bit clock source and scheduler clock
+ * ---------------------------------------------------------------------------
+ */
+
+static DEFINE_CLOCK_DATA(cd);
+
+static inline unsigned long long notrace _omap_mpu_sched_clock(void)
+{
+ u32 cyc = ~omap_mpu_timer_read(1);
+ return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+#ifndef CONFIG_OMAP_32K_TIMER
+unsigned long long notrace sched_clock(void)
+{
+ return _omap_mpu_sched_clock();
+}
+#else
+static unsigned long long notrace omap_mpu_sched_clock(void)
+{
+ return _omap_mpu_sched_clock();
+}
+#endif
+
+static void notrace mpu_update_sched_clock(void)
+{
+ u32 cyc = ~omap_mpu_timer_read(1);
+ update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void __init omap_init_clocksource(unsigned long rate)
+{
+ omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(1);
+ static char err[] __initdata = KERN_ERR
+ "%s: can't register clocksource!\n";
+
+ omap_mpu_timer_start(1, ~0, 1);
+ init_sched_clock(&cd, mpu_update_sched_clock, 32, rate);
+
+ if (clocksource_mmio_init(&timer->read_tim, "mpu_timer2", rate,
+ 300, 32, clocksource_mmio_readl_down))
+ printk(err, "mpu_timer2");
+}
+
+static void __init omap_mpu_timer_init(void)
+{
+ struct clk *ck_ref = clk_get(NULL, "ck_ref");
+ unsigned long rate;
+
+ BUG_ON(IS_ERR(ck_ref));
+
+ rate = clk_get_rate(ck_ref);
+ clk_put(ck_ref);
+
+ /* PTV = 0 */
+ rate /= 2;
+
+ omap_init_mpu_timer(rate);
+ omap_init_clocksource(rate);
+}
+
+#else
+static inline void omap_mpu_timer_init(void)
+{
+ pr_err("Bogus timer, should not happen\n");
+}
+#endif /* CONFIG_OMAP_MPU_TIMER */
+
+#if defined(CONFIG_OMAP_MPU_TIMER) && defined(CONFIG_OMAP_32K_TIMER)
+static unsigned long long (*preferred_sched_clock)(void);
+
+unsigned long long notrace sched_clock(void)
+{
+ if (!preferred_sched_clock)
+ return 0;
+
+ return preferred_sched_clock();
+}
+
+static inline void preferred_sched_clock_init(bool use_32k_sched_clock)
+{
+ if (use_32k_sched_clock)
+ preferred_sched_clock = omap_32k_sched_clock;
+ else
+ preferred_sched_clock = omap_mpu_sched_clock;
+}
+#else
+static inline void preferred_sched_clock_init(bool use_32k_sched_clcok)
+{
+}
+#endif
+
+static inline int omap_32k_timer_usable(void)
+{
+ int res = false;
+
+ if (cpu_is_omap730() || cpu_is_omap15xx())
+ return res;
+
+#ifdef CONFIG_OMAP_32K_TIMER
+ res = omap_32k_timer_init();
+#endif
+
+ return res;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+static void __init omap_timer_init(void)
+{
+ if (omap_32k_timer_usable()) {
+ preferred_sched_clock_init(1);
+ } else {
+ omap_mpu_timer_init();
+ preferred_sched_clock_init(0);
+ }
+}
+
+struct sys_timer omap_timer = {
+ .init = omap_timer_init,
+};
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
new file mode 100644
index 00000000..13d7b8f1
--- /dev/null
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -0,0 +1,193 @@
+/*
+ * linux/arch/arm/mach-omap1/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>
+ * OMAP Dual-mode timer framework support by Timo Teras
+ *
+ * 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/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 <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <mach/hardware.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <plat/common.h>
+#include <plat/dmtimer.h>
+
+/*
+ * ---------------------------------------------------------------------------
+ * 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.
+ * ---------------------------------------------------------------------------
+ */
+
+/* 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
+
+#define OMAP_32K_TICKS_PER_SEC (32768)
+
+/*
+ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+ * so with HZ = 128, TVR = 255.
+ */
+#define OMAP_32K_TIMER_TICK_PERIOD ((OMAP_32K_TICKS_PER_SEC / 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)
+{
+ omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
+}
+
+static inline unsigned long omap_32k_timer_read(int reg)
+{
+ return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
+}
+
+static inline void omap_32k_timer_start(unsigned long load_val)
+{
+ if (!load_val)
+ load_val = 1;
+ omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
+ omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
+}
+
+static inline void omap_32k_timer_stop(void)
+{
+ omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
+}
+
+#define omap_32k_timer_ack_irq()
+
+static int omap_32k_timer_set_next_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ omap_32k_timer_start(delta);
+
+ return 0;
+}
+
+static void omap_32k_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ omap_32k_timer_stop();
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ }
+}
+
+static struct clock_event_device clockevent_32k_timer = {
+ .name = "32k-timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_next_event = omap_32k_timer_set_next_event,
+ .set_mode = omap_32k_timer_set_mode,
+};
+
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &clockevent_32k_timer;
+ omap_32k_timer_ack_irq();
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap_32k_timer_irq = {
+ .name = "32KHz timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = omap_32k_timer_interrupt,
+};
+
+static __init void omap_init_32k_timer(void)
+{
+ setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+
+ clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC,
+ NSEC_PER_SEC,
+ clockevent_32k_timer.shift);
+ clockevent_32k_timer.max_delta_ns =
+ clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer);
+ clockevent_32k_timer.min_delta_ns =
+ clockevent_delta2ns(1, &clockevent_32k_timer);
+
+ clockevent_32k_timer.cpumask = cpumask_of(0);
+ clockevents_register_device(&clockevent_32k_timer);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Timer initialization
+ * ---------------------------------------------------------------------------
+ */
+bool __init omap_32k_timer_init(void)
+{
+ omap_init_clocksource_32k();
+
+#ifdef CONFIG_OMAP_DM_TIMER
+ omap_dm_timer_init();
+#endif
+ omap_init_32k_timer();
+
+ return true;
+}
diff --git a/arch/arm/mach-omap1/usb.c b/arch/arm/mach-omap1/usb.c
new file mode 100644
index 00000000..19de03b0
--- /dev/null
+++ b/arch/arm/mach-omap1/usb.c
@@ -0,0 +1,530 @@
+/*
+ * Platform level USB initialization for FS USB OTG controller on omap1 and 24xx
+ *
+ * Copyright (C) 2004 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+
+#include <plat/mux.h>
+#include <plat/usb.h>
+
+/* These routines should handle the standard chip-specific modes
+ * for usb0/1/2 ports, covering basic mux and transceiver setup.
+ *
+ * Some board-*.c files will need to set up additional mux options,
+ * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
+ */
+
+/* TESTED ON:
+ * - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables
+ * - 5912 OSK OHCI (with usb0 standard-A), standard A-to-B cables
+ * - 5912 OSK UDC, with *nonstandard* A-to-A cable
+ * - 1510 Innovator UDC with bundled usb0 cable
+ * - 1510 Innovator OHCI with bundled usb1/usb2 cable
+ * - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS
+ * - 1710 custom development board using alternate pin group
+ * - 1710 H3 (with usb1 mini-AB) using standard Mini-B or OTG cables
+ */
+
+#define INT_USB_IRQ_GEN IH2_BASE + 20
+#define INT_USB_IRQ_NISO IH2_BASE + 30
+#define INT_USB_IRQ_ISO IH2_BASE + 29
+#define INT_USB_IRQ_HGEN INT_USB_HHC_1
+#define INT_USB_IRQ_OTG IH2_BASE + 8
+
+#ifdef CONFIG_USB_GADGET_OMAP
+
+static struct resource udc_resources[] = {
+ /* order is significant! */
+ { /* registers */
+ .start = UDC_BASE,
+ .end = UDC_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ }, { /* general IRQ */
+ .start = INT_USB_IRQ_GEN,
+ .flags = IORESOURCE_IRQ,
+ }, { /* PIO IRQ */
+ .start = INT_USB_IRQ_NISO,
+ .flags = IORESOURCE_IRQ,
+ }, { /* SOF IRQ */
+ .start = INT_USB_IRQ_ISO,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 udc_dmamask = ~(u32)0;
+
+static struct platform_device udc_device = {
+ .name = "omap_udc",
+ .id = -1,
+ .dev = {
+ .dma_mask = &udc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(udc_resources),
+ .resource = udc_resources,
+};
+
+static inline void udc_device_init(struct omap_usb_config *pdata)
+{
+ /* IRQ numbers for omap7xx */
+ if(cpu_is_omap7xx()) {
+ udc_resources[1].start = INT_7XX_USB_GENI;
+ udc_resources[2].start = INT_7XX_USB_NON_ISO;
+ udc_resources[3].start = INT_7XX_USB_ISO;
+ }
+ pdata->udc_device = &udc_device;
+}
+
+#else
+
+static inline void udc_device_init(struct omap_usb_config *pdata)
+{
+}
+
+#endif
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+
+/* The dmamask must be set for OHCI to work */
+static u64 ohci_dmamask = ~(u32)0;
+
+static struct resource ohci_resources[] = {
+ {
+ .start = OMAP_OHCI_BASE,
+ .end = OMAP_OHCI_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_USB_IRQ_HGEN,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ohci_device = {
+ .name = "ohci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(ohci_resources),
+ .resource = ohci_resources,
+};
+
+static inline void ohci_device_init(struct omap_usb_config *pdata)
+{
+ if (cpu_is_omap7xx())
+ ohci_resources[1].start = INT_7XX_USB_HHC_1;
+ pdata->ohci_device = &ohci_device;
+}
+
+#else
+
+static inline void ohci_device_init(struct omap_usb_config *pdata)
+{
+}
+
+#endif
+
+#if defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG)
+
+static struct resource otg_resources[] = {
+ /* order is significant! */
+ {
+ .start = OTG_BASE,
+ .end = OTG_BASE + 0xff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = INT_USB_IRQ_OTG,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device otg_device = {
+ .name = "omap_otg",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(otg_resources),
+ .resource = otg_resources,
+};
+
+static inline void otg_device_init(struct omap_usb_config *pdata)
+{
+ if (cpu_is_omap7xx())
+ otg_resources[1].start = INT_7XX_USB_OTG;
+ pdata->otg_device = &otg_device;
+}
+
+#else
+
+static inline void otg_device_init(struct omap_usb_config *pdata)
+{
+}
+
+#endif
+
+u32 __init omap1_usb0_init(unsigned nwires, unsigned is_device)
+{
+ u32 syscon1 = 0;
+
+ if (nwires == 0) {
+ if (!cpu_is_omap15xx()) {
+ u32 l;
+
+ /* pulldown D+/D- */
+ l = omap_readl(USB_TRANSCEIVER_CTRL);
+ l &= ~(3 << 1);
+ omap_writel(l, USB_TRANSCEIVER_CTRL);
+ }
+ return 0;
+ }
+
+ if (is_device) {
+ if (cpu_is_omap7xx()) {
+ omap_cfg_reg(AA17_7XX_USB_DM);
+ omap_cfg_reg(W16_7XX_USB_PU_EN);
+ omap_cfg_reg(W17_7XX_USB_VBUSI);
+ omap_cfg_reg(W18_7XX_USB_DMCK_OUT);
+ omap_cfg_reg(W19_7XX_USB_DCRST);
+ } else
+ omap_cfg_reg(W4_USB_PUEN);
+ }
+
+ if (nwires == 2) {
+ u32 l;
+
+ // omap_cfg_reg(P9_USB_DP);
+ // omap_cfg_reg(R8_USB_DM);
+
+ if (cpu_is_omap15xx()) {
+ /* This works on 1510-Innovator */
+ return 0;
+ }
+
+ /* NOTES:
+ * - peripheral should configure VBUS detection!
+ * - only peripherals may use the internal D+/D- pulldowns
+ * - OTG support on this port not yet written
+ */
+
+ /* Don't do this for omap7xx -- it causes USB to not work correctly */
+ if (!cpu_is_omap7xx()) {
+ l = omap_readl(USB_TRANSCEIVER_CTRL);
+ l &= ~(7 << 4);
+ if (!is_device)
+ l |= (3 << 1);
+ omap_writel(l, USB_TRANSCEIVER_CTRL);
+ }
+
+ return 3 << 16;
+ }
+
+ /* alternate pin config, external transceiver */
+ if (cpu_is_omap15xx()) {
+ printk(KERN_ERR "no usb0 alt pin config on 15xx\n");
+ return 0;
+ }
+
+ omap_cfg_reg(V6_USB0_TXD);
+ omap_cfg_reg(W9_USB0_TXEN);
+ omap_cfg_reg(W5_USB0_SE0);
+ if (nwires != 3)
+ omap_cfg_reg(Y5_USB0_RCV);
+
+ /* NOTE: SPEED and SUSP aren't configured here. OTG hosts
+ * may be able to use I2C requests to set those bits along
+ * with VBUS switching and overcurrent detection.
+ */
+
+ if (nwires != 6) {
+ u32 l;
+
+ l = omap_readl(USB_TRANSCEIVER_CTRL);
+ l &= ~CONF_USB2_UNI_R;
+ omap_writel(l, USB_TRANSCEIVER_CTRL);
+ }
+
+ switch (nwires) {
+ case 3:
+ syscon1 = 2;
+ break;
+ case 4:
+ syscon1 = 1;
+ break;
+ case 6:
+ syscon1 = 3;
+ {
+ u32 l;
+
+ omap_cfg_reg(AA9_USB0_VP);
+ omap_cfg_reg(R9_USB0_VM);
+ l = omap_readl(USB_TRANSCEIVER_CTRL);
+ l |= CONF_USB2_UNI_R;
+ omap_writel(l, USB_TRANSCEIVER_CTRL);
+ }
+ break;
+ default:
+ printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+ 0, nwires);
+ }
+
+ return syscon1 << 16;
+}
+
+u32 __init omap1_usb1_init(unsigned nwires)
+{
+ u32 syscon1 = 0;
+
+ if (!cpu_is_omap15xx() && nwires != 6) {
+ u32 l;
+
+ l = omap_readl(USB_TRANSCEIVER_CTRL);
+ l &= ~CONF_USB1_UNI_R;
+ omap_writel(l, USB_TRANSCEIVER_CTRL);
+ }
+ if (nwires == 0)
+ return 0;
+
+ /* external transceiver */
+ omap_cfg_reg(USB1_TXD);
+ omap_cfg_reg(USB1_TXEN);
+ if (nwires != 3)
+ omap_cfg_reg(USB1_RCV);
+
+ if (cpu_is_omap15xx()) {
+ omap_cfg_reg(USB1_SEO);
+ omap_cfg_reg(USB1_SPEED);
+ // SUSP
+ } else if (cpu_is_omap1610() || cpu_is_omap5912()) {
+ omap_cfg_reg(W13_1610_USB1_SE0);
+ omap_cfg_reg(R13_1610_USB1_SPEED);
+ // SUSP
+ } else if (cpu_is_omap1710()) {
+ omap_cfg_reg(R13_1710_USB1_SE0);
+ // SUSP
+ } else {
+ pr_debug("usb%d cpu unrecognized\n", 1);
+ return 0;
+ }
+
+ switch (nwires) {
+ case 2:
+ goto bad;
+ case 3:
+ syscon1 = 2;
+ break;
+ case 4:
+ syscon1 = 1;
+ break;
+ case 6:
+ syscon1 = 3;
+ omap_cfg_reg(USB1_VP);
+ omap_cfg_reg(USB1_VM);
+ if (!cpu_is_omap15xx()) {
+ u32 l;
+
+ l = omap_readl(USB_TRANSCEIVER_CTRL);
+ l |= CONF_USB1_UNI_R;
+ omap_writel(l, USB_TRANSCEIVER_CTRL);
+ }
+ break;
+ default:
+bad:
+ printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+ 1, nwires);
+ }
+
+ return syscon1 << 20;
+}
+
+u32 __init omap1_usb2_init(unsigned nwires, unsigned alt_pingroup)
+{
+ u32 syscon1 = 0;
+
+ /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */
+ if (alt_pingroup || nwires == 0)
+ return 0;
+
+ if (!cpu_is_omap15xx() && nwires != 6) {
+ u32 l;
+
+ l = omap_readl(USB_TRANSCEIVER_CTRL);
+ l &= ~CONF_USB2_UNI_R;
+ omap_writel(l, USB_TRANSCEIVER_CTRL);
+ }
+
+ /* external transceiver */
+ if (cpu_is_omap15xx()) {
+ omap_cfg_reg(USB2_TXD);
+ omap_cfg_reg(USB2_TXEN);
+ omap_cfg_reg(USB2_SEO);
+ if (nwires != 3)
+ omap_cfg_reg(USB2_RCV);
+ /* there is no USB2_SPEED */
+ } else if (cpu_is_omap16xx()) {
+ omap_cfg_reg(V6_USB2_TXD);
+ omap_cfg_reg(W9_USB2_TXEN);
+ omap_cfg_reg(W5_USB2_SE0);
+ if (nwires != 3)
+ omap_cfg_reg(Y5_USB2_RCV);
+ // FIXME omap_cfg_reg(USB2_SPEED);
+ } else {
+ pr_debug("usb%d cpu unrecognized\n", 1);
+ return 0;
+ }
+
+ // omap_cfg_reg(USB2_SUSP);
+
+ switch (nwires) {
+ case 2:
+ goto bad;
+ case 3:
+ syscon1 = 2;
+ break;
+ case 4:
+ syscon1 = 1;
+ break;
+ case 5:
+ goto bad;
+ case 6:
+ syscon1 = 3;
+ if (cpu_is_omap15xx()) {
+ omap_cfg_reg(USB2_VP);
+ omap_cfg_reg(USB2_VM);
+ } else {
+ u32 l;
+
+ omap_cfg_reg(AA9_USB2_VP);
+ omap_cfg_reg(R9_USB2_VM);
+ l = omap_readl(USB_TRANSCEIVER_CTRL);
+ l |= CONF_USB2_UNI_R;
+ omap_writel(l, USB_TRANSCEIVER_CTRL);
+ }
+ break;
+ default:
+bad:
+ printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
+ 2, nwires);
+ }
+
+ return syscon1 << 24;
+}
+
+#ifdef CONFIG_ARCH_OMAP15XX
+
+/* ULPD_DPLL_CTRL */
+#define DPLL_IOB (1 << 13)
+#define DPLL_PLL_ENABLE (1 << 4)
+#define DPLL_LOCK (1 << 0)
+
+/* ULPD_APLL_CTRL */
+#define APLL_NDPLL_SWITCH (1 << 0)
+
+static void __init omap_1510_usb_init(struct omap_usb_config *config)
+{
+ unsigned int val;
+ u16 w;
+
+ config->usb0_init(config->pins[0], is_usb0_device(config));
+ config->usb1_init(config->pins[1]);
+ config->usb2_init(config->pins[2], 0);
+
+ val = omap_readl(MOD_CONF_CTRL_0) & ~(0x3f << 1);
+ val |= (config->hmc_mode << 1);
+ omap_writel(val, MOD_CONF_CTRL_0);
+
+ printk("USB: hmc %d", config->hmc_mode);
+ if (config->pins[0])
+ printk(", usb0 %d wires%s", config->pins[0],
+ is_usb0_device(config) ? " (dev)" : "");
+ if (config->pins[1])
+ printk(", usb1 %d wires", config->pins[1]);
+ if (config->pins[2])
+ printk(", usb2 %d wires", config->pins[2]);
+ printk("\n");
+
+ /* use DPLL for 48 MHz function clock */
+ pr_debug("APLL %04x DPLL %04x REQ %04x\n", omap_readw(ULPD_APLL_CTRL),
+ omap_readw(ULPD_DPLL_CTRL), omap_readw(ULPD_SOFT_REQ));
+
+ w = omap_readw(ULPD_APLL_CTRL);
+ w &= ~APLL_NDPLL_SWITCH;
+ omap_writew(w, ULPD_APLL_CTRL);
+
+ w = omap_readw(ULPD_DPLL_CTRL);
+ w |= DPLL_IOB | DPLL_PLL_ENABLE;
+ omap_writew(w, ULPD_DPLL_CTRL);
+
+ w = omap_readw(ULPD_SOFT_REQ);
+ w |= SOFT_UDC_REQ | SOFT_DPLL_REQ;
+ omap_writew(w, ULPD_SOFT_REQ);
+
+ while (!(omap_readw(ULPD_DPLL_CTRL) & DPLL_LOCK))
+ cpu_relax();
+
+#ifdef CONFIG_USB_GADGET_OMAP
+ if (config->register_dev) {
+ int status;
+
+ udc_device.dev.platform_data = config;
+ status = platform_device_register(&udc_device);
+ if (status)
+ pr_debug("can't register UDC device, %d\n", status);
+ /* udc driver gates 48MHz by D+ pullup */
+ }
+#endif
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+ if (config->register_host) {
+ int status;
+
+ ohci_device.dev.platform_data = config;
+ status = platform_device_register(&ohci_device);
+ if (status)
+ pr_debug("can't register OHCI device, %d\n", status);
+ /* hcd explicitly gates 48MHz */
+ }
+#endif
+}
+
+#else
+static inline void omap_1510_usb_init(struct omap_usb_config *config) {}
+#endif
+
+void __init omap1_usb_init(struct omap_usb_config *pdata)
+{
+ pdata->usb0_init = omap1_usb0_init;
+ pdata->usb1_init = omap1_usb1_init;
+ pdata->usb2_init = omap1_usb2_init;
+ udc_device_init(pdata);
+ ohci_device_init(pdata);
+ otg_device_init(pdata);
+
+ if (cpu_is_omap7xx() || cpu_is_omap16xx())
+ omap_otg_init(pdata);
+ else if (cpu_is_omap15xx())
+ omap_1510_usb_init(pdata);
+ else
+ printk(KERN_ERR "USB: No init for your chip yet\n");
+}