aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/mach-omap1/Kconfig7
-rw-r--r--arch/arm/mach-omap1/Makefile1
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c7
-rw-r--r--arch/arm/mach-omap1/board-fsample.c319
-rw-r--r--arch/arm/mach-omap1/board-innovator.c75
-rw-r--r--arch/arm/mach-omap1/board-osk.c147
-rw-r--r--arch/arm/mach-omap1/clock.c18
-rw-r--r--arch/arm/mach-omap1/pm.c7
-rw-r--r--arch/arm/mach-omap1/time.c2
-rw-r--r--arch/arm/mach-omap2/Kconfig1
-rw-r--r--arch/arm/mach-omap2/Makefile5
-rw-r--r--arch/arm/mach-omap2/clock.c37
-rw-r--r--arch/arm/mach-omap2/clock.h2
-rw-r--r--arch/arm/mach-omap2/devices.c46
-rw-r--r--arch/arm/mach-omap2/gpmc.c209
-rw-r--r--arch/arm/mach-omap2/io.c2
-rw-r--r--arch/arm/mach-omap2/mux.c38
-rw-r--r--arch/arm/mach-omap2/pm-domain.c300
-rw-r--r--arch/arm/mach-omap2/pm.c271
-rw-r--r--arch/arm/mach-omap2/timer-gp.c86
-rw-r--r--arch/arm/plat-omap/Kconfig2
-rw-r--r--arch/arm/plat-omap/clock.c4
-rw-r--r--arch/arm/plat-omap/cpu-omap.c18
-rw-r--r--arch/arm/plat-omap/devices.c2
-rw-r--r--arch/arm/plat-omap/dma.c84
-rw-r--r--arch/arm/plat-omap/dmtimer.c428
-rw-r--r--arch/arm/plat-omap/gpio.c103
-rw-r--r--arch/arm/plat-omap/sram.c9
-rw-r--r--arch/arm/plat-omap/timer32k.c121
30 files changed, 1965 insertions, 388 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9716db00058d..d28d2571f080 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -678,7 +678,7 @@ config XIP_PHYS_ADDR
678 678
679endmenu 679endmenu
680 680
681if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP1) 681if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP)
682 682
683menu "CPU Frequency scaling" 683menu "CPU Frequency scaling"
684 684
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
index f8d716ccc1df..d135568dc9e7 100644
--- a/arch/arm/mach-omap1/Kconfig
+++ b/arch/arm/mach-omap1/Kconfig
@@ -62,6 +62,13 @@ config MACH_OMAP_PERSEUS2
62 Support for TI OMAP 730 Perseus2 board. Say Y here if you have such 62 Support for TI OMAP 730 Perseus2 board. Say Y here if you have such
63 a board. 63 a board.
64 64
65config MACH_OMAP_FSAMPLE
66 bool "TI F-Sample"
67 depends on ARCH_OMAP1 && ARCH_OMAP730
68 help
69 Support for TI OMAP 850 F-Sample board. Say Y here if you have such
70 a board.
71
65config MACH_VOICEBLUE 72config MACH_VOICEBLUE
66 bool "Voiceblue" 73 bool "Voiceblue"
67 depends on ARCH_OMAP1 && ARCH_OMAP15XX 74 depends on ARCH_OMAP1 && ARCH_OMAP15XX
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 9ea719550ad3..7165f74f78da 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o
17obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o 17obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
18obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o 18obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
19obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o 19obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
20obj-$(CONFIG_MACH_OMAP_FSAMPLE) += board-fsample.o
20obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o 21obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
21obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o 22obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
22obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o 23obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 73df32aac4c4..8437d065ada5 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -80,8 +80,15 @@ static struct omap_uart_config ams_delta_uart_config __initdata = {
80 .enabled_uarts = 1, 80 .enabled_uarts = 1,
81}; 81};
82 82
83static struct omap_usb_config ams_delta_usb_config __initdata = {
84 .register_host = 1,
85 .hmc_mode = 16,
86 .pins[0] = 2,
87};
88
83static struct omap_board_config_kernel ams_delta_config[] = { 89static struct omap_board_config_kernel ams_delta_config[] = {
84 { OMAP_TAG_UART, &ams_delta_uart_config }, 90 { OMAP_TAG_UART, &ams_delta_uart_config },
91 { OMAP_TAG_USB, &ams_delta_usb_config },
85}; 92};
86 93
87static struct platform_device ams_delta_led_device = { 94static struct platform_device ams_delta_led_device = {
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
new file mode 100644
index 000000000000..c753a3c5aadd
--- /dev/null
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -0,0 +1,319 @@
1/*
2 * linux/arch/arm/mach-omap1/board-fsample.c
3 *
4 * Modified from board-perseus2.c
5 *
6 * Original OMAP730 support by Jean Pihet <j-pihet@ti.com>
7 * Updated for 2.6 by Kevin Hilman <kjh@hilman.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/platform_device.h>
17#include <linux/delay.h>
18#include <linux/mtd/mtd.h>
19#include <linux/mtd/nand.h>
20#include <linux/mtd/partitions.h>
21#include <linux/input.h>
22
23#include <asm/hardware.h>
24#include <asm/mach-types.h>
25#include <asm/mach/arch.h>
26#include <asm/mach/flash.h>
27#include <asm/mach/map.h>
28
29#include <asm/arch/tc.h>
30#include <asm/arch/gpio.h>
31#include <asm/arch/mux.h>
32#include <asm/arch/fpga.h>
33#include <asm/arch/keypad.h>
34#include <asm/arch/common.h>
35#include <asm/arch/board.h>
36#include <asm/arch/board-fsample.h>
37
38static int fsample_keymap[] = {
39 KEY(0,0,KEY_UP),
40 KEY(0,1,KEY_RIGHT),
41 KEY(0,2,KEY_LEFT),
42 KEY(0,3,KEY_DOWN),
43 KEY(0,4,KEY_CENTER),
44 KEY(0,5,KEY_0_5),
45 KEY(1,0,KEY_SOFT2),
46 KEY(1,1,KEY_SEND),
47 KEY(1,2,KEY_END),
48 KEY(1,3,KEY_VOLUMEDOWN),
49 KEY(1,4,KEY_VOLUMEUP),
50 KEY(1,5,KEY_RECORD),
51 KEY(2,0,KEY_SOFT1),
52 KEY(2,1,KEY_3),
53 KEY(2,2,KEY_6),
54 KEY(2,3,KEY_9),
55 KEY(2,4,KEY_SHARP),
56 KEY(2,5,KEY_2_5),
57 KEY(3,0,KEY_BACK),
58 KEY(3,1,KEY_2),
59 KEY(3,2,KEY_5),
60 KEY(3,3,KEY_8),
61 KEY(3,4,KEY_0),
62 KEY(3,5,KEY_HEADSETHOOK),
63 KEY(4,0,KEY_HOME),
64 KEY(4,1,KEY_1),
65 KEY(4,2,KEY_4),
66 KEY(4,3,KEY_7),
67 KEY(4,4,KEY_STAR),
68 KEY(4,5,KEY_POWER),
69 0
70};
71
72static struct resource smc91x_resources[] = {
73 [0] = {
74 .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */
75 .end = H2P2_DBG_FPGA_ETHR_START + 0xf,
76 .flags = IORESOURCE_MEM,
77 },
78 [1] = {
79 .start = INT_730_MPU_EXT_NIRQ,
80 .end = 0,
81 .flags = IORESOURCE_IRQ,
82 },
83};
84
85static struct mtd_partition nor_partitions[] = {
86 /* bootloader (U-Boot, etc) in first sector */
87 {
88 .name = "bootloader",
89 .offset = 0,
90 .size = SZ_128K,
91 .mask_flags = MTD_WRITEABLE, /* force read-only */
92 },
93 /* bootloader params in the next sector */
94 {
95 .name = "params",
96 .offset = MTDPART_OFS_APPEND,
97 .size = SZ_128K,
98 .mask_flags = 0,
99 },
100 /* kernel */
101 {
102 .name = "kernel",
103 .offset = MTDPART_OFS_APPEND,
104 .size = SZ_2M,
105 .mask_flags = 0
106 },
107 /* rest of flash is a file system */
108 {
109 .name = "rootfs",
110 .offset = MTDPART_OFS_APPEND,
111 .size = MTDPART_SIZ_FULL,
112 .mask_flags = 0
113 },
114};
115
116static struct flash_platform_data nor_data = {
117 .map_name = "cfi_probe",
118 .width = 2,
119 .parts = nor_partitions,
120 .nr_parts = ARRAY_SIZE(nor_partitions),
121};
122
123static struct resource nor_resource = {
124 .start = OMAP_CS0_PHYS,
125 .end = OMAP_CS0_PHYS + SZ_32M - 1,
126 .flags = IORESOURCE_MEM,
127};
128
129static struct platform_device nor_device = {
130 .name = "omapflash",
131 .id = 0,
132 .dev = {
133 .platform_data = &nor_data,
134 },
135 .num_resources = 1,
136 .resource = &nor_resource,
137};
138
139static struct nand_platform_data nand_data = {
140 .options = NAND_SAMSUNG_LP_OPTIONS,
141};
142
143static struct resource nand_resource = {
144 .start = OMAP_CS3_PHYS,
145 .end = OMAP_CS3_PHYS + SZ_4K - 1,
146 .flags = IORESOURCE_MEM,
147};
148
149static struct platform_device nand_device = {
150 .name = "omapnand",
151 .id = 0,
152 .dev = {
153 .platform_data = &nand_data,
154 },
155 .num_resources = 1,
156 .resource = &nand_resource,
157};
158
159static struct platform_device smc91x_device = {
160 .name = "smc91x",
161 .id = 0,
162 .num_resources = ARRAY_SIZE(smc91x_resources),
163 .resource = smc91x_resources,
164};
165
166static struct resource kp_resources[] = {
167 [0] = {
168 .start = INT_730_MPUIO_KEYPAD,
169 .end = INT_730_MPUIO_KEYPAD,
170 .flags = IORESOURCE_IRQ,
171 },
172};
173
174static struct omap_kp_platform_data kp_data = {
175 .rows = 8,
176 .cols = 8,
177 .keymap = fsample_keymap,
178};
179
180static struct platform_device kp_device = {
181 .name = "omap-keypad",
182 .id = -1,
183 .dev = {
184 .platform_data = &kp_data,
185 },
186 .num_resources = ARRAY_SIZE(kp_resources),
187 .resource = kp_resources,
188};
189
190static struct platform_device lcd_device = {
191 .name = "lcd_p2",
192 .id = -1,
193};
194
195static struct platform_device *devices[] __initdata = {
196 &nor_device,
197 &nand_device,
198 &smc91x_device,
199 &kp_device,
200 &lcd_device,
201};
202
203#define P2_NAND_RB_GPIO_PIN 62
204
205static int nand_dev_ready(struct nand_platform_data *data)
206{
207 return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN);
208}
209
210static struct omap_uart_config fsample_uart_config __initdata = {
211 .enabled_uarts = ((1 << 0) | (1 << 1)),
212};
213
214static struct omap_lcd_config fsample_lcd_config __initdata = {
215 .ctrl_name = "internal",
216};
217
218static struct omap_board_config_kernel fsample_config[] = {
219 { OMAP_TAG_UART, &fsample_uart_config },
220 { OMAP_TAG_LCD, &fsample_lcd_config },
221};
222
223static void __init omap_fsample_init(void)
224{
225 if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN)))
226 nand_data.dev_ready = nand_dev_ready;
227
228 omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
229 omap_cfg_reg(M8_1610_FLASH_CS2B_WE);
230
231 platform_add_devices(devices, ARRAY_SIZE(devices));
232
233 omap_board_config = fsample_config;
234 omap_board_config_size = ARRAY_SIZE(fsample_config);
235 omap_serial_init();
236}
237
238static void __init fsample_init_smc91x(void)
239{
240 fpga_write(1, H2P2_DBG_FPGA_LAN_RESET);
241 mdelay(50);
242 fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1,
243 H2P2_DBG_FPGA_LAN_RESET);
244 mdelay(50);
245}
246
247void omap_fsample_init_irq(void)
248{
249 omap1_init_common_hw();
250 omap_init_irq();
251 omap_gpio_init();
252 fsample_init_smc91x();
253}
254
255/* Only FPGA needs to be mapped here. All others are done with ioremap */
256static struct map_desc omap_fsample_io_desc[] __initdata = {
257 {
258 .virtual = H2P2_DBG_FPGA_BASE,
259 .pfn = __phys_to_pfn(H2P2_DBG_FPGA_START),
260 .length = H2P2_DBG_FPGA_SIZE,
261 .type = MT_DEVICE
262 },
263 {
264 .virtual = FSAMPLE_CPLD_BASE,
265 .pfn = __phys_to_pfn(FSAMPLE_CPLD_START),
266 .length = FSAMPLE_CPLD_SIZE,
267 .type = MT_DEVICE
268 }
269};
270
271static void __init omap_fsample_map_io(void)
272{
273 omap1_map_common_io();
274 iotable_init(omap_fsample_io_desc,
275 ARRAY_SIZE(omap_fsample_io_desc));
276
277 /* Early, board-dependent init */
278
279 /*
280 * Hold GSM Reset until needed
281 */
282 omap_writew(omap_readw(OMAP730_DSP_M_CTL) & ~1, OMAP730_DSP_M_CTL);
283
284 /*
285 * UARTs -> done automagically by 8250 driver
286 */
287
288 /*
289 * CSx timings, GPIO Mux ... setup
290 */
291
292 /* Flash: CS0 timings setup */
293 omap_writel(0x0000fff3, OMAP730_FLASH_CFG_0);
294 omap_writel(0x00000088, OMAP730_FLASH_ACFG_0);
295
296 /*
297 * Ethernet support through the debug board
298 * CS1 timings setup
299 */
300 omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1);
301 omap_writel(0x00000000, OMAP730_FLASH_ACFG_1);
302
303 /*
304 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
305 * It is used as the Ethernet controller interrupt
306 */
307 omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9);
308}
309
310MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
311/* Maintainer: Brian Swetland <swetland@google.com> */
312 .phys_io = 0xfff00000,
313 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
314 .boot_params = 0x10000100,
315 .map_io = omap_fsample_map_io,
316 .init_irq = omap_fsample_init_irq,
317 .init_machine = omap_fsample_init,
318 .timer = &omap_timer,
319MACHINE_END
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index e90c137a4cf3..4cbc62db5b5d 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -37,6 +37,8 @@
37#include <asm/arch/usb.h> 37#include <asm/arch/usb.h>
38#include <asm/arch/keypad.h> 38#include <asm/arch/keypad.h>
39#include <asm/arch/common.h> 39#include <asm/arch/common.h>
40#include <asm/arch/mcbsp.h>
41#include <asm/arch/omap-alsa.h>
40 42
41static int innovator_keymap[] = { 43static int innovator_keymap[] = {
42 KEY(0, 0, KEY_F1), 44 KEY(0, 0, KEY_F1),
@@ -112,6 +114,42 @@ static struct platform_device innovator_flash_device = {
112 .resource = &innovator_flash_resource, 114 .resource = &innovator_flash_resource,
113}; 115};
114 116
117#define DEFAULT_BITPERSAMPLE 16
118
119static struct omap_mcbsp_reg_cfg mcbsp_regs = {
120 .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
121 .spcr1 = RINTM(3) | RRST,
122 .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
123 RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
124 .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
125 .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
126 XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
127 .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
128 .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
129 .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
130 /*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */
131 .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
132};
133
134static struct omap_alsa_codec_config alsa_config = {
135 .name = "OMAP Innovator AIC23",
136 .mcbsp_regs_alsa = &mcbsp_regs,
137 .codec_configure_dev = NULL, // aic23_configure,
138 .codec_set_samplerate = NULL, // aic23_set_samplerate,
139 .codec_clock_setup = NULL, // aic23_clock_setup,
140 .codec_clock_on = NULL, // aic23_clock_on,
141 .codec_clock_off = NULL, // aic23_clock_off,
142 .get_default_samplerate = NULL, // aic23_get_default_samplerate,
143};
144
145static struct platform_device innovator_mcbsp1_device = {
146 .name = "omap_alsa_mcbsp",
147 .id = 1,
148 .dev = {
149 .platform_data = &alsa_config,
150 },
151};
152
115static struct resource innovator_kp_resources[] = { 153static struct resource innovator_kp_resources[] = {
116 [0] = { 154 [0] = {
117 .start = INT_KEYBOARD, 155 .start = INT_KEYBOARD,
@@ -139,6 +177,10 @@ static struct platform_device innovator_kp_device = {
139 177
140#ifdef CONFIG_ARCH_OMAP15XX 178#ifdef CONFIG_ARCH_OMAP15XX
141 179
180#include <linux/spi/spi.h>
181#include <linux/spi/ads7846.h>
182
183
142/* Only FPGA needs to be mapped here. All others are done with ioremap */ 184/* Only FPGA needs to be mapped here. All others are done with ioremap */
143static struct map_desc innovator1510_io_desc[] __initdata = { 185static struct map_desc innovator1510_io_desc[] __initdata = {
144 { 186 {
@@ -174,13 +216,44 @@ static struct platform_device innovator1510_lcd_device = {
174 .id = -1, 216 .id = -1,
175}; 217};
176 218
219static struct platform_device innovator1510_spi_device = {
220 .name = "spi_inn1510",
221 .id = -1,
222};
223
177static struct platform_device *innovator1510_devices[] __initdata = { 224static struct platform_device *innovator1510_devices[] __initdata = {
178 &innovator_flash_device, 225 &innovator_flash_device,
179 &innovator1510_smc91x_device, 226 &innovator1510_smc91x_device,
227 &innovator_mcbsp1_device,
180 &innovator_kp_device, 228 &innovator_kp_device,
181 &innovator1510_lcd_device, 229 &innovator1510_lcd_device,
230 &innovator1510_spi_device,
182}; 231};
183 232
233static int innovator_get_pendown_state(void)
234{
235 return !(fpga_read(OMAP1510_FPGA_TOUCHSCREEN) & (1 << 5));
236}
237
238static const struct ads7846_platform_data innovator1510_ts_info = {
239 .model = 7846,
240 .vref_delay_usecs = 100, /* internal, no capacitor */
241 .x_plate_ohms = 419,
242 .y_plate_ohms = 486,
243 .get_pendown_state = innovator_get_pendown_state,
244};
245
246static struct spi_board_info __initdata innovator1510_boardinfo[] = { {
247 /* FPGA (bus "10") CS0 has an ads7846e */
248 .modalias = "ads7846",
249 .platform_data = &innovator1510_ts_info,
250 .irq = OMAP1510_INT_FPGA_TS,
251 .max_speed_hz = 120000 /* max sample rate at 3V */
252 * 26 /* command + data + overhead */,
253 .bus_num = 10,
254 .chip_select = 0,
255} };
256
184#endif /* CONFIG_ARCH_OMAP15XX */ 257#endif /* CONFIG_ARCH_OMAP15XX */
185 258
186#ifdef CONFIG_ARCH_OMAP16XX 259#ifdef CONFIG_ARCH_OMAP16XX
@@ -311,6 +384,8 @@ static void __init innovator_init(void)
311#ifdef CONFIG_ARCH_OMAP15XX 384#ifdef CONFIG_ARCH_OMAP15XX
312 if (cpu_is_omap1510()) { 385 if (cpu_is_omap1510()) {
313 platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices)); 386 platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
387 spi_register_board_info(innovator1510_boardinfo,
388 ARRAY_SIZE(innovator1510_boardinfo));
314 } 389 }
315#endif 390#endif
316#ifdef CONFIG_ARCH_OMAP16XX 391#ifdef CONFIG_ARCH_OMAP16XX
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 1160093e8ef6..e0711d23a6b0 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -33,7 +33,6 @@
33 33
34#include <linux/mtd/mtd.h> 34#include <linux/mtd/mtd.h>
35#include <linux/mtd/partitions.h> 35#include <linux/mtd/partitions.h>
36#include <linux/input.h>
37 36
38#include <asm/hardware.h> 37#include <asm/hardware.h>
39#include <asm/mach-types.h> 38#include <asm/mach-types.h>
@@ -45,25 +44,10 @@
45#include <asm/arch/usb.h> 44#include <asm/arch/usb.h>
46#include <asm/arch/mux.h> 45#include <asm/arch/mux.h>
47#include <asm/arch/tc.h> 46#include <asm/arch/tc.h>
48#include <asm/arch/keypad.h>
49#include <asm/arch/common.h> 47#include <asm/arch/common.h>
50#include <asm/arch/mcbsp.h> 48#include <asm/arch/mcbsp.h>
51#include <asm/arch/omap-alsa.h> 49#include <asm/arch/omap-alsa.h>
52 50
53static int osk_keymap[] = {
54 KEY(0, 0, KEY_F1),
55 KEY(0, 3, KEY_UP),
56 KEY(1, 1, KEY_LEFTCTRL),
57 KEY(1, 2, KEY_LEFT),
58 KEY(2, 0, KEY_SPACE),
59 KEY(2, 1, KEY_ESC),
60 KEY(2, 2, KEY_DOWN),
61 KEY(3, 2, KEY_ENTER),
62 KEY(3, 3, KEY_RIGHT),
63 0
64};
65
66
67static struct mtd_partition osk_partitions[] = { 51static struct mtd_partition osk_partitions[] = {
68 /* bootloader (U-Boot, etc) in first sector */ 52 /* bootloader (U-Boot, etc) in first sector */
69 { 53 {
@@ -181,48 +165,17 @@ static struct omap_alsa_codec_config alsa_config = {
181 165
182static struct platform_device osk5912_mcbsp1_device = { 166static struct platform_device osk5912_mcbsp1_device = {
183 .name = "omap_alsa_mcbsp", 167 .name = "omap_alsa_mcbsp",
184 .id = 1, 168 .id = 1,
185 .dev = { 169 .dev = {
186 .platform_data = &alsa_config, 170 .platform_data = &alsa_config,
187 }, 171 },
188}; 172};
189 173
190static struct resource osk5912_kp_resources[] = {
191 [0] = {
192 .start = INT_KEYBOARD,
193 .end = INT_KEYBOARD,
194 .flags = IORESOURCE_IRQ,
195 },
196};
197
198static struct omap_kp_platform_data osk_kp_data = {
199 .rows = 8,
200 .cols = 8,
201 .keymap = osk_keymap,
202};
203
204static struct platform_device osk5912_kp_device = {
205 .name = "omap-keypad",
206 .id = -1,
207 .dev = {
208 .platform_data = &osk_kp_data,
209 },
210 .num_resources = ARRAY_SIZE(osk5912_kp_resources),
211 .resource = osk5912_kp_resources,
212};
213
214static struct platform_device osk5912_lcd_device = {
215 .name = "lcd_osk",
216 .id = -1,
217};
218
219static struct platform_device *osk5912_devices[] __initdata = { 174static struct platform_device *osk5912_devices[] __initdata = {
220 &osk5912_flash_device, 175 &osk5912_flash_device,
221 &osk5912_smc91x_device, 176 &osk5912_smc91x_device,
222 &osk5912_cf_device, 177 &osk5912_cf_device,
223 &osk5912_mcbsp1_device, 178 &osk5912_mcbsp1_device,
224 &osk5912_kp_device,
225 &osk5912_lcd_device,
226}; 179};
227 180
228static void __init osk_init_smc91x(void) 181static void __init osk_init_smc91x(void)
@@ -276,18 +229,100 @@ static struct omap_uart_config osk_uart_config __initdata = {
276 .enabled_uarts = (1 << 0), 229 .enabled_uarts = (1 << 0),
277}; 230};
278 231
232#ifdef CONFIG_OMAP_OSK_MISTRAL
279static struct omap_lcd_config osk_lcd_config __initdata = { 233static struct omap_lcd_config osk_lcd_config __initdata = {
280 .ctrl_name = "internal", 234 .ctrl_name = "internal",
281}; 235};
236#endif
282 237
283static struct omap_board_config_kernel osk_config[] = { 238static struct omap_board_config_kernel osk_config[] = {
284 { OMAP_TAG_USB, &osk_usb_config }, 239 { OMAP_TAG_USB, &osk_usb_config },
285 { OMAP_TAG_UART, &osk_uart_config }, 240 { OMAP_TAG_UART, &osk_uart_config },
241#ifdef CONFIG_OMAP_OSK_MISTRAL
286 { OMAP_TAG_LCD, &osk_lcd_config }, 242 { OMAP_TAG_LCD, &osk_lcd_config },
243#endif
287}; 244};
288 245
289#ifdef CONFIG_OMAP_OSK_MISTRAL 246#ifdef CONFIG_OMAP_OSK_MISTRAL
290 247
248#include <linux/input.h>
249#include <linux/spi/spi.h>
250#include <linux/spi/ads7846.h>
251
252#include <asm/arch/keypad.h>
253
254static const int osk_keymap[] = {
255 /* KEY(col, row, code) */
256 KEY(0, 0, KEY_F1), /* SW4 */
257 KEY(0, 3, KEY_UP), /* (sw2/up) */
258 KEY(1, 1, KEY_LEFTCTRL), /* SW5 */
259 KEY(1, 2, KEY_LEFT), /* (sw2/left) */
260 KEY(2, 0, KEY_SPACE), /* SW3 */
261 KEY(2, 1, KEY_ESC), /* SW6 */
262 KEY(2, 2, KEY_DOWN), /* (sw2/down) */
263 KEY(3, 2, KEY_ENTER), /* (sw2/select) */
264 KEY(3, 3, KEY_RIGHT), /* (sw2/right) */
265 0
266};
267
268static struct omap_kp_platform_data osk_kp_data = {
269 .rows = 8,
270 .cols = 8,
271 .keymap = (int *) osk_keymap,
272};
273
274static struct resource osk5912_kp_resources[] = {
275 [0] = {
276 .start = INT_KEYBOARD,
277 .end = INT_KEYBOARD,
278 .flags = IORESOURCE_IRQ,
279 },
280};
281
282static struct platform_device osk5912_kp_device = {
283 .name = "omap-keypad",
284 .id = -1,
285 .dev = {
286 .platform_data = &osk_kp_data,
287 },
288 .num_resources = ARRAY_SIZE(osk5912_kp_resources),
289 .resource = osk5912_kp_resources,
290};
291
292static struct platform_device osk5912_lcd_device = {
293 .name = "lcd_osk",
294 .id = -1,
295};
296
297static struct platform_device *mistral_devices[] __initdata = {
298 &osk5912_kp_device,
299 &osk5912_lcd_device,
300};
301
302static int mistral_get_pendown_state(void)
303{
304 return !omap_get_gpio_datain(4);
305}
306
307static const struct ads7846_platform_data mistral_ts_info = {
308 .model = 7846,
309 .vref_delay_usecs = 100, /* internal, no capacitor */
310 .x_plate_ohms = 419,
311 .y_plate_ohms = 486,
312 .get_pendown_state = mistral_get_pendown_state,
313};
314
315static struct spi_board_info __initdata mistral_boardinfo[] = { {
316 /* MicroWire (bus 2) CS0 has an ads7846e */
317 .modalias = "ads7846",
318 .platform_data = &mistral_ts_info,
319 .irq = OMAP_GPIO_IRQ(4),
320 .max_speed_hz = 120000 /* max sample rate at 3V */
321 * 26 /* command + data + overhead */,
322 .bus_num = 2,
323 .chip_select = 0,
324} };
325
291#ifdef CONFIG_PM 326#ifdef CONFIG_PM
292static irqreturn_t 327static irqreturn_t
293osk_mistral_wake_interrupt(int irq, void *ignored, struct pt_regs *regs) 328osk_mistral_wake_interrupt(int irq, void *ignored, struct pt_regs *regs)
@@ -298,14 +333,18 @@ osk_mistral_wake_interrupt(int irq, void *ignored, struct pt_regs *regs)
298 333
299static void __init osk_mistral_init(void) 334static void __init osk_mistral_init(void)
300{ 335{
301 /* FIXME here's where to feed in framebuffer, touchpad, and 336 /* NOTE: we could actually tell if there's a Mistral board
302 * keyboard setup ... not in the drivers for those devices!
303 *
304 * NOTE: we could actually tell if there's a Mistral board
305 * attached, e.g. by trying to read something from the ads7846. 337 * attached, e.g. by trying to read something from the ads7846.
306 * But this is too early for that... 338 * But this arch_init() code is too early for that, since we
339 * can't talk to the ads or even the i2c eeprom.
307 */ 340 */
308 341
342 // omap_cfg_reg(P19_1610_GPIO6); // BUSY
343 omap_cfg_reg(P20_1610_GPIO4); // PENIRQ
344 set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
345 spi_register_board_info(mistral_boardinfo,
346 ARRAY_SIZE(mistral_boardinfo));
347
309 /* the sideways button (SW1) is for use as a "wakeup" button */ 348 /* the sideways button (SW1) is for use as a "wakeup" button */
310 omap_cfg_reg(N15_1610_MPUIO2); 349 omap_cfg_reg(N15_1610_MPUIO2);
311 if (omap_request_gpio(OMAP_MPUIO(2)) == 0) { 350 if (omap_request_gpio(OMAP_MPUIO(2)) == 0) {
@@ -329,6 +368,8 @@ static void __init osk_mistral_init(void)
329#endif 368#endif
330 } else 369 } else
331 printk(KERN_ERR "OSK+Mistral: wakeup button is awol\n"); 370 printk(KERN_ERR "OSK+Mistral: wakeup button is awol\n");
371
372 platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices));
332} 373}
333#else 374#else
334static void __init osk_mistral_init(void) { } 375static void __init osk_mistral_init(void) { }
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 619db18144ea..f1958e882e86 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -1,3 +1,4 @@
1//kernel/linux-omap-fsample/arch/arm/mach-omap1/clock.c#2 - edit change 3808 (text)
1/* 2/*
2 * linux/arch/arm/mach-omap1/clock.c 3 * linux/arch/arm/mach-omap1/clock.c
3 * 4 *
@@ -20,6 +21,7 @@
20 21
21#include <asm/io.h> 22#include <asm/io.h>
22 23
24#include <asm/arch/cpu.h>
23#include <asm/arch/usb.h> 25#include <asm/arch/usb.h>
24#include <asm/arch/clock.h> 26#include <asm/arch/clock.h>
25#include <asm/arch/sram.h> 27#include <asm/arch/sram.h>
@@ -270,8 +272,12 @@ static int omap1_select_table_rate(struct clk * clk, unsigned long rate)
270 /* 272 /*
271 * In most cases we should not need to reprogram DPLL. 273 * In most cases we should not need to reprogram DPLL.
272 * Reprogramming the DPLL is tricky, it must be done from SRAM. 274 * Reprogramming the DPLL is tricky, it must be done from SRAM.
275 * (on 730, bit 13 must always be 1)
273 */ 276 */
274 omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); 277 if (cpu_is_omap730())
278 omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val | 0x2000);
279 else
280 omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val);
275 281
276 ck_dpll1.rate = ptr->pll_rate; 282 ck_dpll1.rate = ptr->pll_rate;
277 propagate_rate(&ck_dpll1); 283 propagate_rate(&ck_dpll1);
@@ -748,7 +754,7 @@ int __init omap1_clk_init(void)
748 printk(KERN_ERR "System frequencies not set. Check your config.\n"); 754 printk(KERN_ERR "System frequencies not set. Check your config.\n");
749 /* Guess sane values (60MHz) */ 755 /* Guess sane values (60MHz) */
750 omap_writew(0x2290, DPLL_CTL); 756 omap_writew(0x2290, DPLL_CTL);
751 omap_writew(0x1005, ARM_CKCTL); 757 omap_writew(cpu_is_omap730() ? 0x3005 : 0x1005, ARM_CKCTL);
752 ck_dpll1.rate = 60000000; 758 ck_dpll1.rate = 60000000;
753 propagate_rate(&ck_dpll1); 759 propagate_rate(&ck_dpll1);
754 } 760 }
@@ -761,13 +767,17 @@ int __init omap1_clk_init(void)
761 ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10, 767 ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
762 arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10); 768 arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
763 769
764#ifdef CONFIG_MACH_OMAP_PERSEUS2 770#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE)
765 /* Select slicer output as OMAP input clock */ 771 /* Select slicer output as OMAP input clock */
766 omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL); 772 omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
767#endif 773#endif
768 774
769 /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ 775 /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */
770 omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL); 776 /* (on 730, bit 13 must not be cleared) */
777 if (cpu_is_omap730())
778 omap_writew(omap_readw(ARM_CKCTL) & 0x2fff, ARM_CKCTL);
779 else
780 omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
771 781
772 /* Put DSP/MPUI into reset until needed */ 782 /* Put DSP/MPUI into reset until needed */
773 omap_writew(0, ARM_RSTCT1); 783 omap_writew(0, ARM_RSTCT1);
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index ddf6b07dc9c7..1b4e1d57afb1 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -1,3 +1,4 @@
1//kernel/linux-omap-fsample/arch/arm/mach-omap1/pm.c#3 - integrate change 4545 (text)
1/* 2/*
2 * linux/arch/arm/mach-omap1/pm.c 3 * linux/arch/arm/mach-omap1/pm.c
3 * 4 *
@@ -50,6 +51,7 @@
50#include <asm/mach/irq.h> 51#include <asm/mach/irq.h>
51#include <asm/mach-types.h> 52#include <asm/mach-types.h>
52 53
54#include <asm/arch/cpu.h>
53#include <asm/arch/irqs.h> 55#include <asm/arch/irqs.h>
54#include <asm/arch/clock.h> 56#include <asm/arch/clock.h>
55#include <asm/arch/sram.h> 57#include <asm/arch/sram.h>
@@ -326,8 +328,9 @@ void omap_pm_suspend(void)
326 /* stop DSP */ 328 /* stop DSP */
327 omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1); 329 omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1);
328 330
329 /* shut down dsp_ck */ 331 /* shut down dsp_ck */
330 omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL); 332 if (!cpu_is_omap730())
333 omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL);
331 334
332 /* temporarily enabling api_ck to access DSP registers */ 335 /* temporarily enabling api_ck to access DSP registers */
333 omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2); 336 omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2);
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index a85fe6066bc4..64c2d69c615c 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -94,7 +94,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
94 * will break. On P2, the timer count rate is 6.5 MHz after programming PTV 94 * will break. On P2, the timer count rate is 6.5 MHz after programming PTV
95 * with 0. This divides the 13MHz input by 2, and is undocumented. 95 * with 0. This divides the 13MHz input by 2, and is undocumented.
96 */ 96 */
97#ifdef CONFIG_MACH_OMAP_PERSEUS2 97#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE)
98/* REVISIT: This ifdef construct should be replaced by a query to clock 98/* REVISIT: This ifdef construct should be replaced by a query to clock
99 * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz. 99 * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz.
100 */ 100 */
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 537dd2e6d380..aab97ccf1e63 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -8,6 +8,7 @@ config ARCH_OMAP24XX
8config ARCH_OMAP2420 8config ARCH_OMAP2420
9 bool "OMAP2420 support" 9 bool "OMAP2420 support"
10 depends on ARCH_OMAP24XX 10 depends on ARCH_OMAP24XX
11 select OMAP_DM_TIMER
11 12
12comment "OMAP Board Type" 13comment "OMAP Board Type"
13 depends on ARCH_OMAP2 14 depends on ARCH_OMAP2
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 111eaa64258f..266d88e77bdc 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -3,12 +3,13 @@
3# 3#
4 4
5# Common support 5# Common support
6obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o serial.o 6obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o \
7 serial.o gpmc.o
7 8
8obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o 9obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o
9 10
10# Power Management 11# Power Management
11obj-$(CONFIG_PM) += pm.o sleep.o 12obj-$(CONFIG_PM) += pm.o pm-domain.o sleep.o
12 13
13# Specific board support 14# Specific board support
14obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o 15obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 72eb4bf571ac..6789dd4029a1 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -660,26 +660,35 @@ static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
660 660
661 /* Isolate control register */ 661 /* Isolate control register */
662 div_sel = (SRC_RATE_SEL_MASK & clk->flags); 662 div_sel = (SRC_RATE_SEL_MASK & clk->flags);
663 div_off = clk->src_offset; 663 div_off = clk->rate_offset;
664 664
665 validrate = omap2_clksel_round_rate(clk, rate, &new_div); 665 validrate = omap2_clksel_round_rate(clk, rate, &new_div);
666 if(validrate != rate) 666 if (validrate != rate)
667 return(ret); 667 return(ret);
668 668
669 field_val = omap2_get_clksel(&div_sel, &field_mask, clk); 669 field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
670 if (div_sel == 0) 670 if (div_sel == 0)
671 return ret; 671 return ret;
672 672
673 if(clk->flags & CM_SYSCLKOUT_SEL1){ 673 if (clk->flags & CM_SYSCLKOUT_SEL1) {
674 switch(new_div){ 674 switch (new_div) {
675 case 16: field_val = 4; break; 675 case 16:
676 case 8: field_val = 3; break; 676 field_val = 4;
677 case 4: field_val = 2; break; 677 break;
678 case 2: field_val = 1; break; 678 case 8:
679 case 1: field_val = 0; break; 679 field_val = 3;
680 break;
681 case 4:
682 field_val = 2;
683 break;
684 case 2:
685 field_val = 1;
686 break;
687 case 1:
688 field_val = 0;
689 break;
680 } 690 }
681 } 691 } else
682 else
683 field_val = new_div; 692 field_val = new_div;
684 693
685 reg = (void __iomem *)div_sel; 694 reg = (void __iomem *)div_sel;
@@ -744,7 +753,7 @@ static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset,
744 val = 0x2; 753 val = 0x2;
745 break; 754 break;
746 case CM_WKUP_SEL1: 755 case CM_WKUP_SEL1:
747 src_reg_addr = (u32)&CM_CLKSEL2_CORE; 756 src_reg_addr = (u32)&CM_CLKSEL_WKUP;
748 mask = 0x3; 757 mask = 0x3;
749 if (src_clk == &func_32k_ck) 758 if (src_clk == &func_32k_ck)
750 val = 0x0; 759 val = 0x0;
@@ -784,9 +793,9 @@ static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset,
784 val = 0; 793 val = 0;
785 if (src_clk == &sys_ck) 794 if (src_clk == &sys_ck)
786 val = 1; 795 val = 1;
787 if (src_clk == &func_54m_ck)
788 val = 2;
789 if (src_clk == &func_96m_ck) 796 if (src_clk == &func_96m_ck)
797 val = 2;
798 if (src_clk == &func_54m_ck)
790 val = 3; 799 val = 3;
791 break; 800 break;
792 } 801 }
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 6c78d471fab7..2781dfbc5164 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -1062,7 +1062,7 @@ static struct clk gpt2_ick = {
1062 .parent = &l4_ck, 1062 .parent = &l4_ck,
1063 .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, 1063 .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
1064 .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit4 */ 1064 .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit4 */
1065 .enable_bit = 0, 1065 .enable_bit = 4,
1066 .recalc = &omap2_followparent_recalc, 1066 .recalc = &omap2_followparent_recalc,
1067}; 1067};
1068 1068
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index fb7f91da1aad..5139677e4266 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -105,6 +105,51 @@ static inline void omap_init_sti(void)
105static inline void omap_init_sti(void) {} 105static inline void omap_init_sti(void) {}
106#endif 106#endif
107 107
108#if defined(CONFIG_SPI_OMAP24XX)
109
110#include <asm/arch/mcspi.h>
111
112#define OMAP2_MCSPI1_BASE 0x48098000
113#define OMAP2_MCSPI2_BASE 0x4809a000
114
115/* FIXME: use resources instead */
116
117static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
118 .base = io_p2v(OMAP2_MCSPI1_BASE),
119 .num_cs = 4,
120};
121
122struct platform_device omap2_mcspi1 = {
123 .name = "omap2_mcspi",
124 .id = 1,
125 .dev = {
126 .platform_data = &omap2_mcspi1_config,
127 },
128};
129
130static struct omap2_mcspi_platform_config omap2_mcspi2_config = {
131 .base = io_p2v(OMAP2_MCSPI2_BASE),
132 .num_cs = 2,
133};
134
135struct platform_device omap2_mcspi2 = {
136 .name = "omap2_mcspi",
137 .id = 2,
138 .dev = {
139 .platform_data = &omap2_mcspi2_config,
140 },
141};
142
143static void omap_init_mcspi(void)
144{
145 platform_device_register(&omap2_mcspi1);
146 platform_device_register(&omap2_mcspi2);
147}
148
149#else
150static inline void omap_init_mcspi(void) {}
151#endif
152
108/*-------------------------------------------------------------------------*/ 153/*-------------------------------------------------------------------------*/
109 154
110static int __init omap2_init_devices(void) 155static int __init omap2_init_devices(void)
@@ -113,6 +158,7 @@ static int __init omap2_init_devices(void)
113 * in alphabetical order so they're easier to sort through. 158 * in alphabetical order so they're easier to sort through.
114 */ 159 */
115 omap_init_i2c(); 160 omap_init_i2c();
161 omap_init_mcspi();
116 omap_init_sti(); 162 omap_init_sti();
117 163
118 return 0; 164 return 0;
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
new file mode 100644
index 000000000000..c7a48f921fef
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -0,0 +1,209 @@
1/*
2 * GPMC support functions
3 *
4 * Copyright (C) 2005-2006 Nokia Corporation
5 *
6 * Author: Juha Yrjola
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/err.h>
15#include <linux/clk.h>
16
17#include <asm/io.h>
18#include <asm/arch/gpmc.h>
19
20#undef DEBUG
21
22#define GPMC_BASE 0x6800a000
23#define GPMC_REVISION 0x00
24#define GPMC_SYSCONFIG 0x10
25#define GPMC_SYSSTATUS 0x14
26#define GPMC_IRQSTATUS 0x18
27#define GPMC_IRQENABLE 0x1c
28#define GPMC_TIMEOUT_CONTROL 0x40
29#define GPMC_ERR_ADDRESS 0x44
30#define GPMC_ERR_TYPE 0x48
31#define GPMC_CONFIG 0x50
32#define GPMC_STATUS 0x54
33#define GPMC_PREFETCH_CONFIG1 0x1e0
34#define GPMC_PREFETCH_CONFIG2 0x1e4
35#define GPMC_PREFETCH_CONTROL 0x1e8
36#define GPMC_PREFETCH_STATUS 0x1f0
37#define GPMC_ECC_CONFIG 0x1f4
38#define GPMC_ECC_CONTROL 0x1f8
39#define GPMC_ECC_SIZE_CONFIG 0x1fc
40
41#define GPMC_CS0 0x60
42#define GPMC_CS_SIZE 0x30
43
44static void __iomem *gpmc_base =
45 (void __iomem *) IO_ADDRESS(GPMC_BASE);
46static void __iomem *gpmc_cs_base =
47 (void __iomem *) IO_ADDRESS(GPMC_BASE) + GPMC_CS0;
48
49static struct clk *gpmc_l3_clk;
50
51static void gpmc_write_reg(int idx, u32 val)
52{
53 __raw_writel(val, gpmc_base + idx);
54}
55
56static u32 gpmc_read_reg(int idx)
57{
58 return __raw_readl(gpmc_base + idx);
59}
60
61void gpmc_cs_write_reg(int cs, int idx, u32 val)
62{
63 void __iomem *reg_addr;
64
65 reg_addr = gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx;
66 __raw_writel(val, reg_addr);
67}
68
69u32 gpmc_cs_read_reg(int cs, int idx)
70{
71 return __raw_readl(gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx);
72}
73
74/* TODO: Add support for gpmc_fck to clock framework and use it */
75static unsigned long gpmc_get_fclk_period(void)
76{
77 /* In picoseconds */
78 return 1000000000 / ((clk_get_rate(gpmc_l3_clk)) / 1000);
79}
80
81unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
82{
83 unsigned long tick_ps;
84
85 /* Calculate in picosecs to yield more exact results */
86 tick_ps = gpmc_get_fclk_period();
87
88 return (time_ns * 1000 + tick_ps - 1) / tick_ps;
89}
90
91#ifdef DEBUG
92static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
93 int time, const char *name)
94#else
95static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
96 int time)
97#endif
98{
99 u32 l;
100 int ticks, mask, nr_bits;
101
102 if (time == 0)
103 ticks = 0;
104 else
105 ticks = gpmc_ns_to_ticks(time);
106 nr_bits = end_bit - st_bit + 1;
107 if (ticks >= 1 << nr_bits)
108 return -1;
109
110 mask = (1 << nr_bits) - 1;
111 l = gpmc_cs_read_reg(cs, reg);
112#ifdef DEBUG
113 printk(KERN_INFO "GPMC CS%d: %-10s: %d ticks, %3lu ns (was %i ticks)\n",
114 cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
115 (l >> st_bit) & mask);
116#endif
117 l &= ~(mask << st_bit);
118 l |= ticks << st_bit;
119 gpmc_cs_write_reg(cs, reg, l);
120
121 return 0;
122}
123
124#ifdef DEBUG
125#define GPMC_SET_ONE(reg, st, end, field) \
126 if (set_gpmc_timing_reg(cs, (reg), (st), (end), \
127 t->field, #field) < 0) \
128 return -1
129#else
130#define GPMC_SET_ONE(reg, st, end, field) \
131 if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \
132 return -1
133#endif
134
135int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
136{
137 int div;
138 u32 l;
139
140 l = sync_clk * 1000 + (gpmc_get_fclk_period() - 1);
141 div = l / gpmc_get_fclk_period();
142 if (div > 4)
143 return -1;
144 if (div < 0)
145 div = 1;
146
147 return div;
148}
149
150int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
151{
152 int div;
153 u32 l;
154
155 div = gpmc_cs_calc_divider(cs, t->sync_clk);
156 if (div < 0)
157 return -1;
158
159 GPMC_SET_ONE(GPMC_CS_CONFIG2, 0, 3, cs_on);
160 GPMC_SET_ONE(GPMC_CS_CONFIG2, 8, 12, cs_rd_off);
161 GPMC_SET_ONE(GPMC_CS_CONFIG2, 16, 20, cs_wr_off);
162
163 GPMC_SET_ONE(GPMC_CS_CONFIG3, 0, 3, adv_on);
164 GPMC_SET_ONE(GPMC_CS_CONFIG3, 8, 12, adv_rd_off);
165 GPMC_SET_ONE(GPMC_CS_CONFIG3, 16, 20, adv_wr_off);
166
167 GPMC_SET_ONE(GPMC_CS_CONFIG4, 0, 3, oe_on);
168 GPMC_SET_ONE(GPMC_CS_CONFIG4, 8, 12, oe_off);
169 GPMC_SET_ONE(GPMC_CS_CONFIG4, 16, 19, we_on);
170 GPMC_SET_ONE(GPMC_CS_CONFIG4, 24, 28, we_off);
171
172 GPMC_SET_ONE(GPMC_CS_CONFIG5, 0, 4, rd_cycle);
173 GPMC_SET_ONE(GPMC_CS_CONFIG5, 8, 12, wr_cycle);
174 GPMC_SET_ONE(GPMC_CS_CONFIG5, 16, 20, access);
175
176 GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
177
178#ifdef DEBUG
179 printk(KERN_INFO "GPMC CS%d CLK period is %lu (div %d)\n",
180 cs, gpmc_get_fclk_period(), div);
181#endif
182
183 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
184 l &= ~0x03;
185 l |= (div - 1);
186
187 return 0;
188}
189
190unsigned long gpmc_cs_get_base_addr(int cs)
191{
192 return (gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7) & 0x1f) << 24;
193}
194
195void __init gpmc_init(void)
196{
197 u32 l;
198
199 gpmc_l3_clk = clk_get(NULL, "core_l3_ck");
200 BUG_ON(IS_ERR(gpmc_l3_clk));
201
202 l = gpmc_read_reg(GPMC_REVISION);
203 printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
204 /* Set smart idle mode and automatic L3 clock gating */
205 l = gpmc_read_reg(GPMC_SYSCONFIG);
206 l &= 0x03 << 3;
207 l |= (0x02 << 3) | (1 << 0);
208 gpmc_write_reg(GPMC_SYSCONFIG, l);
209}
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 7d5711611f2f..68456b79a0a8 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -27,6 +27,7 @@
27extern void omap_sram_init(void); 27extern void omap_sram_init(void);
28extern int omap2_clk_init(void); 28extern int omap2_clk_init(void);
29extern void omap2_check_revision(void); 29extern void omap2_check_revision(void);
30extern void gpmc_init(void);
30 31
31/* 32/*
32 * The machine specific code may provide the extra mapping besides the 33 * The machine specific code may provide the extra mapping besides the
@@ -67,4 +68,5 @@ void __init omap2_init_common_hw(void)
67{ 68{
68 omap2_mux_init(); 69 omap2_mux_init();
69 omap2_clk_init(); 70 omap2_clk_init();
71 gpmc_init();
70} 72}
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 1197dc38c20a..c2c482cd1cb7 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -53,6 +53,12 @@ MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1)
53/* 24xx clocks */ 53/* 24xx clocks */
54MUX_CFG_24XX("W14_24XX_SYS_CLKOUT", 0x137, 0, 1, 1, 1) 54MUX_CFG_24XX("W14_24XX_SYS_CLKOUT", 0x137, 0, 1, 1, 1)
55 55
56/* 24xx GPMC wait pin monitoring */
57MUX_CFG_24XX("L3_GPMC_WAIT0", 0x09a, 0, 1, 1, 1)
58MUX_CFG_24XX("N7_GPMC_WAIT1", 0x09b, 0, 1, 1, 1)
59MUX_CFG_24XX("M1_GPMC_WAIT2", 0x09c, 0, 1, 1, 1)
60MUX_CFG_24XX("P1_GPMC_WAIT3", 0x09d, 0, 1, 1, 1)
61
56/* 24xx McBSP */ 62/* 24xx McBSP */
57MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX", 0x124, 1, 1, 0, 1) 63MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX", 0x124, 1, 1, 0, 1)
58MUX_CFG_24XX("R14_24XX_MCBSP2_FSX", 0x125, 1, 1, 0, 1) 64MUX_CFG_24XX("R14_24XX_MCBSP2_FSX", 0x125, 1, 1, 0, 1)
@@ -60,18 +66,38 @@ MUX_CFG_24XX("W15_24XX_MCBSP2_DR", 0x126, 1, 1, 0, 1)
60MUX_CFG_24XX("V15_24XX_MCBSP2_DX", 0x127, 1, 1, 0, 1) 66MUX_CFG_24XX("V15_24XX_MCBSP2_DX", 0x127, 1, 1, 0, 1)
61 67
62/* 24xx GPIO */ 68/* 24xx GPIO */
63MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1) 69MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1)
64MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1) 70MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1)
65MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1) 71MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1)
66MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1) 72MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1)
67MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1) 73MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1)
68MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1) 74MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1)
69MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1) 75MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1)
70MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1) 76MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1)
71MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1) 77MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1)
72MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1) 78MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1)
73MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1) 79MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1)
74 80
81/* 242x DBG GPIO */
82MUX_CFG_24XX("V4_242X_GPIO49", 0xd3, 3, 0, 0, 1)
83MUX_CFG_24XX("W2_242X_GPIO50", 0xd4, 3, 0, 0, 1)
84MUX_CFG_24XX("U4_242X_GPIO51", 0xd5, 3, 0, 0, 1)
85MUX_CFG_24XX("V3_242X_GPIO52", 0xd6, 3, 0, 0, 1)
86MUX_CFG_24XX("V2_242X_GPIO53", 0xd7, 3, 0, 0, 1)
87MUX_CFG_24XX("V6_242X_GPIO53", 0xcf, 3, 0, 0, 1)
88MUX_CFG_24XX("T4_242X_GPIO54", 0xd8, 3, 0, 0, 1)
89MUX_CFG_24XX("Y4_242X_GPIO54", 0xd0, 3, 0, 0, 1)
90MUX_CFG_24XX("T3_242X_GPIO55", 0xd9, 3, 0, 0, 1)
91MUX_CFG_24XX("U2_242X_GPIO56", 0xda, 3, 0, 0, 1)
92
93/* 24xx external DMA requests */
94MUX_CFG_24XX("AA10_242X_DMAREQ0", 0x0e5, 2, 0, 0, 1)
95MUX_CFG_24XX("AA6_242X_DMAREQ1", 0x0e6, 2, 0, 0, 1)
96MUX_CFG_24XX("E4_242X_DMAREQ2", 0x074, 2, 0, 0, 1)
97MUX_CFG_24XX("G4_242X_DMAREQ3", 0x073, 2, 0, 0, 1)
98MUX_CFG_24XX("D3_242X_DMAREQ4", 0x072, 2, 0, 0, 1)
99MUX_CFG_24XX("E3_242X_DMAREQ5", 0x071, 2, 0, 0, 1)
100
75/* TSC IRQ */ 101/* TSC IRQ */
76MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1) 102MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1)
77 103
diff --git a/arch/arm/mach-omap2/pm-domain.c b/arch/arm/mach-omap2/pm-domain.c
new file mode 100644
index 000000000000..5e20e740cde5
--- /dev/null
+++ b/arch/arm/mach-omap2/pm-domain.c
@@ -0,0 +1,300 @@
1/*
2 * linux/arch/arm/mach-omap2/pm-domain.c
3 *
4 * Power domain functions for OMAP2
5 *
6 * Copyright (C) 2006 Nokia Corporation
7 * Tony Lindgren <tony@atomide.com>
8 *
9 * Some code based on earlier OMAP2 sample PM code
10 * Copyright (C) 2005 Texas Instruments, Inc.
11 * Richard Woodruff <r-woodruff2@ti.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17
18#include <linux/config.h>
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/clk.h>
22
23#include <asm/io.h>
24
25#include "prcm-regs.h"
26
27/* Power domain offsets */
28#define PM_MPU_OFFSET 0x100
29#define PM_CORE_OFFSET 0x200
30#define PM_GFX_OFFSET 0x300
31#define PM_WKUP_OFFSET 0x400 /* Autoidle only */
32#define PM_PLL_OFFSET 0x500 /* Autoidle only */
33#define PM_DSP_OFFSET 0x800
34#define PM_MDM_OFFSET 0xc00
35
36/* Power domain wake-up dependency control register */
37#define PM_WKDEP_OFFSET 0xc8
38#define EN_MDM (1 << 5)
39#define EN_WKUP (1 << 4)
40#define EN_GFX (1 << 3)
41#define EN_DSP (1 << 2)
42#define EN_MPU (1 << 1)
43#define EN_CORE (1 << 0)
44
45/* Core power domain state transition control register */
46#define PM_PWSTCTRL_OFFSET 0xe0
47#define FORCESTATE (1 << 18) /* Only for DSP & GFX */
48#define MEM4RETSTATE (1 << 6)
49#define MEM3RETSTATE (1 << 5)
50#define MEM2RETSTATE (1 << 4)
51#define MEM1RETSTATE (1 << 3)
52#define LOGICRETSTATE (1 << 2) /* Logic is retained */
53#define POWERSTATE_OFF 0x3
54#define POWERSTATE_RETENTION 0x1
55#define POWERSTATE_ON 0x0
56
57/* Power domain state register */
58#define PM_PWSTST_OFFSET 0xe4
59
60/* Hardware supervised state transition control register */
61#define CM_CLKSTCTRL_OFFSET 0x48
62#define AUTOSTAT_MPU (1 << 0) /* MPU */
63#define AUTOSTAT_DSS (1 << 2) /* Core */
64#define AUTOSTAT_L4 (1 << 1) /* Core */
65#define AUTOSTAT_L3 (1 << 0) /* Core */
66#define AUTOSTAT_GFX (1 << 0) /* GFX */
67#define AUTOSTAT_IVA (1 << 8) /* 2420 IVA in DSP domain */
68#define AUTOSTAT_DSP (1 << 0) /* DSP */
69#define AUTOSTAT_MDM (1 << 0) /* MDM */
70
71/* Automatic control of interface clock idling */
72#define CM_AUTOIDLE1_OFFSET 0x30
73#define CM_AUTOIDLE2_OFFSET 0x34 /* Core only */
74#define CM_AUTOIDLE3_OFFSET 0x38 /* Core only */
75#define CM_AUTOIDLE4_OFFSET 0x3c /* Core only */
76#define AUTO_54M(x) (((x) & 0x3) << 6)
77#define AUTO_96M(x) (((x) & 0x3) << 2)
78#define AUTO_DPLL(x) (((x) & 0x3) << 0)
79#define AUTO_STOPPED 0x3
80#define AUTO_BYPASS_FAST 0x2 /* DPLL only */
81#define AUTO_BYPASS_LOW_POWER 0x1 /* DPLL only */
82#define AUTO_DISABLED 0x0
83
84/* Voltage control PRCM_VOLTCTRL bits */
85#define AUTO_EXTVOLT (1 << 15)
86#define FORCE_EXTVOLT (1 << 14)
87#define SETOFF_LEVEL(x) (((x) & 0x3) << 12)
88#define MEMRETCTRL (1 << 8)
89#define SETRET_LEVEL(x) (((x) & 0x3) << 6)
90#define VOLT_LEVEL(x) (((x) & 0x3) << 0)
91
92#define OMAP24XX_PRCM_VBASE IO_ADDRESS(OMAP24XX_PRCM_BASE)
93#define prcm_readl(r) __raw_readl(OMAP24XX_PRCM_VBASE + (r))
94#define prcm_writel(v, r) __raw_writel((v), OMAP24XX_PRCM_VBASE + (r))
95
96static u32 pmdomain_get_wakeup_dependencies(int domain_offset)
97{
98 return prcm_readl(domain_offset + PM_WKDEP_OFFSET);
99}
100
101static void pmdomain_set_wakeup_dependencies(u32 state, int domain_offset)
102{
103 prcm_writel(state, domain_offset + PM_WKDEP_OFFSET);
104}
105
106static u32 pmdomain_get_powerstate(int domain_offset)
107{
108 return prcm_readl(domain_offset + PM_PWSTCTRL_OFFSET);
109}
110
111static void pmdomain_set_powerstate(u32 state, int domain_offset)
112{
113 prcm_writel(state, domain_offset + PM_PWSTCTRL_OFFSET);
114}
115
116static u32 pmdomain_get_clock_autocontrol(int domain_offset)
117{
118 return prcm_readl(domain_offset + CM_CLKSTCTRL_OFFSET);
119}
120
121static void pmdomain_set_clock_autocontrol(u32 state, int domain_offset)
122{
123 prcm_writel(state, domain_offset + CM_CLKSTCTRL_OFFSET);
124}
125
126static u32 pmdomain_get_clock_autoidle1(int domain_offset)
127{
128 return prcm_readl(domain_offset + CM_AUTOIDLE1_OFFSET);
129}
130
131/* Core domain only */
132static u32 pmdomain_get_clock_autoidle2(int domain_offset)
133{
134 return prcm_readl(domain_offset + CM_AUTOIDLE2_OFFSET);
135}
136
137/* Core domain only */
138static u32 pmdomain_get_clock_autoidle3(int domain_offset)
139{
140 return prcm_readl(domain_offset + CM_AUTOIDLE3_OFFSET);
141}
142
143/* Core domain only */
144static u32 pmdomain_get_clock_autoidle4(int domain_offset)
145{
146 return prcm_readl(domain_offset + CM_AUTOIDLE4_OFFSET);
147}
148
149static void pmdomain_set_clock_autoidle1(u32 state, int domain_offset)
150{
151 prcm_writel(state, CM_AUTOIDLE1_OFFSET + domain_offset);
152}
153
154/* Core domain only */
155static void pmdomain_set_clock_autoidle2(u32 state, int domain_offset)
156{
157 prcm_writel(state, CM_AUTOIDLE2_OFFSET + domain_offset);
158}
159
160/* Core domain only */
161static void pmdomain_set_clock_autoidle3(u32 state, int domain_offset)
162{
163 prcm_writel(state, CM_AUTOIDLE3_OFFSET + domain_offset);
164}
165
166/* Core domain only */
167static void pmdomain_set_clock_autoidle4(u32 state, int domain_offset)
168{
169 prcm_writel(state, CM_AUTOIDLE4_OFFSET + domain_offset);
170}
171
172/*
173 * Configures power management domains to idle clocks automatically.
174 */
175void pmdomain_set_autoidle(void)
176{
177 u32 val;
178
179 /* Set PLL auto stop for 54M, 96M & DPLL */
180 pmdomain_set_clock_autoidle1(AUTO_54M(AUTO_STOPPED) |
181 AUTO_96M(AUTO_STOPPED) |
182 AUTO_DPLL(AUTO_STOPPED), PM_PLL_OFFSET);
183
184 /* External clock input control
185 * REVISIT: Should this be in clock framework?
186 */
187 PRCM_CLKSRC_CTRL |= (0x3 << 3);
188
189 /* Configure number of 32KHz clock cycles for sys_clk */
190 PRCM_CLKSSETUP = 0x00ff;
191
192 /* Configure automatic voltage transition */
193 PRCM_VOLTSETUP = 0;
194 val = PRCM_VOLTCTRL;
195 val &= ~(SETOFF_LEVEL(0x3) | VOLT_LEVEL(0x3));
196 val |= SETOFF_LEVEL(1) | VOLT_LEVEL(1) | AUTO_EXTVOLT;
197 PRCM_VOLTCTRL = val;
198
199 /* Disable emulation tools functional clock */
200 PRCM_CLKEMUL_CTRL = 0x0;
201
202 /* Set core memory retention state */
203 val = pmdomain_get_powerstate(PM_CORE_OFFSET);
204 if (cpu_is_omap2420()) {
205 val &= ~(0x7 << 3);
206 val |= (MEM3RETSTATE | MEM2RETSTATE | MEM1RETSTATE);
207 } else {
208 val &= ~(0xf << 3);
209 val |= (MEM4RETSTATE | MEM3RETSTATE | MEM2RETSTATE |
210 MEM1RETSTATE);
211 }
212 pmdomain_set_powerstate(val, PM_CORE_OFFSET);
213
214 /* OCP interface smart idle. REVISIT: Enable autoidle bit0 ? */
215 val = SMS_SYSCONFIG;
216 val &= ~(0x3 << 3);
217 val |= (0x2 << 3) | (1 << 0);
218 SMS_SYSCONFIG |= val;
219
220 val = SDRC_SYSCONFIG;
221 val &= ~(0x3 << 3);
222 val |= (0x2 << 3);
223 SDRC_SYSCONFIG = val;
224
225 /* Configure L3 interface for smart idle.
226 * REVISIT: Enable autoidle bit0 ?
227 */
228 val = GPMC_SYSCONFIG;
229 val &= ~(0x3 << 3);
230 val |= (0x2 << 3) | (1 << 0);
231 GPMC_SYSCONFIG = val;
232
233 pmdomain_set_powerstate(LOGICRETSTATE | POWERSTATE_RETENTION,
234 PM_MPU_OFFSET);
235 pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_CORE_OFFSET);
236 if (!cpu_is_omap2420())
237 pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_MDM_OFFSET);
238
239 /* Assume suspend function has saved the state for DSP and GFX */
240 pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_DSP_OFFSET);
241 pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_GFX_OFFSET);
242
243#if 0
244 /* REVISIT: Internal USB needs special handling */
245 force_standby_usb();
246 if (cpu_is_omap2430())
247 force_hsmmc();
248 sdram_self_refresh_on_idle_req(1);
249#endif
250
251 /* Enable clock auto control for all domains.
252 * Note that CORE domain includes also DSS, L4 & L3.
253 */
254 pmdomain_set_clock_autocontrol(AUTOSTAT_MPU, PM_MPU_OFFSET);
255 pmdomain_set_clock_autocontrol(AUTOSTAT_GFX, PM_GFX_OFFSET);
256 pmdomain_set_clock_autocontrol(AUTOSTAT_DSS | AUTOSTAT_L4 | AUTOSTAT_L3,
257 PM_CORE_OFFSET);
258 if (cpu_is_omap2420())
259 pmdomain_set_clock_autocontrol(AUTOSTAT_IVA | AUTOSTAT_DSP,
260 PM_DSP_OFFSET);
261 else {
262 pmdomain_set_clock_autocontrol(AUTOSTAT_DSP, PM_DSP_OFFSET);
263 pmdomain_set_clock_autocontrol(AUTOSTAT_MDM, PM_MDM_OFFSET);
264 }
265
266 /* Enable clock autoidle for all domains */
267 pmdomain_set_clock_autoidle1(0x2, PM_DSP_OFFSET);
268 if (cpu_is_omap2420()) {
269 pmdomain_set_clock_autoidle1(0xfffffff9, PM_CORE_OFFSET);
270 pmdomain_set_clock_autoidle2(0x7, PM_CORE_OFFSET);
271 pmdomain_set_clock_autoidle1(0x3f, PM_WKUP_OFFSET);
272 } else {
273 pmdomain_set_clock_autoidle1(0xeafffff1, PM_CORE_OFFSET);
274 pmdomain_set_clock_autoidle2(0xfff, PM_CORE_OFFSET);
275 pmdomain_set_clock_autoidle1(0x7f, PM_WKUP_OFFSET);
276 pmdomain_set_clock_autoidle1(0x3, PM_MDM_OFFSET);
277 }
278 pmdomain_set_clock_autoidle3(0x7, PM_CORE_OFFSET);
279 pmdomain_set_clock_autoidle4(0x1f, PM_CORE_OFFSET);
280}
281
282/*
283 * Initializes power domains by removing wake-up dependencies and powering
284 * down DSP and GFX. Gets called from PM init. Note that DSP and IVA code
285 * must re-enable DSP and GFX when used.
286 */
287void __init pmdomain_init(void)
288{
289 /* Remove all domain wakeup dependencies */
290 pmdomain_set_wakeup_dependencies(EN_WKUP | EN_CORE, PM_MPU_OFFSET);
291 pmdomain_set_wakeup_dependencies(0, PM_DSP_OFFSET);
292 pmdomain_set_wakeup_dependencies(0, PM_GFX_OFFSET);
293 pmdomain_set_wakeup_dependencies(EN_WKUP | EN_MPU, PM_CORE_OFFSET);
294 if (cpu_is_omap2430())
295 pmdomain_set_wakeup_dependencies(0, PM_MDM_OFFSET);
296
297 /* Power down DSP and GFX */
298 pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_DSP_OFFSET);
299 pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_GFX_OFFSET);
300}
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 562168fa2b16..d7eee99b7e3f 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -23,6 +23,7 @@
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/sysfs.h> 24#include <linux/sysfs.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/delay.h>
26 27
27#include <asm/io.h> 28#include <asm/io.h>
28#include <asm/irq.h> 29#include <asm/irq.h>
@@ -36,11 +37,18 @@
36#include <asm/arch/sram.h> 37#include <asm/arch/sram.h>
37#include <asm/arch/pm.h> 38#include <asm/arch/pm.h>
38 39
40#include "prcm-regs.h"
41
39static struct clk *vclk; 42static struct clk *vclk;
40static void (*omap2_sram_idle)(void); 43static void (*omap2_sram_idle)(void);
41static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); 44static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
42static void (*saved_idle)(void); 45static void (*saved_idle)(void);
43 46
47extern void __init pmdomain_init(void);
48extern void pmdomain_set_autoidle(void);
49
50static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE];
51
44void omap2_pm_idle(void) 52void omap2_pm_idle(void)
45{ 53{
46 local_irq_disable(); 54 local_irq_disable();
@@ -87,23 +95,272 @@ static int omap2_pm_prepare(suspend_state_t state)
87 return error; 95 return error;
88} 96}
89 97
98#define INT0_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) | \
99 OMAP_IRQ_BIT(INT_24XX_GPIO_BANK2) | \
100 OMAP_IRQ_BIT(INT_24XX_GPIO_BANK3))
101
102#define INT1_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4))
103
104#define INT2_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_UART1_IRQ) | \
105 OMAP_IRQ_BIT(INT_24XX_UART2_IRQ) | \
106 OMAP_IRQ_BIT(INT_24XX_UART3_IRQ))
107
108#define preg(reg) printk("%s\t(0x%p):\t0x%08x\n", #reg, &reg, reg);
109
110static void omap2_pm_debug(char * desc)
111{
112 printk("%s:\n", desc);
113
114 preg(CM_CLKSTCTRL_MPU);
115 preg(CM_CLKSTCTRL_CORE);
116 preg(CM_CLKSTCTRL_GFX);
117 preg(CM_CLKSTCTRL_DSP);
118 preg(CM_CLKSTCTRL_MDM);
119
120 preg(PM_PWSTCTRL_MPU);
121 preg(PM_PWSTCTRL_CORE);
122 preg(PM_PWSTCTRL_GFX);
123 preg(PM_PWSTCTRL_DSP);
124 preg(PM_PWSTCTRL_MDM);
125
126 preg(PM_PWSTST_MPU);
127 preg(PM_PWSTST_CORE);
128 preg(PM_PWSTST_GFX);
129 preg(PM_PWSTST_DSP);
130 preg(PM_PWSTST_MDM);
131
132 preg(CM_AUTOIDLE1_CORE);
133 preg(CM_AUTOIDLE2_CORE);
134 preg(CM_AUTOIDLE3_CORE);
135 preg(CM_AUTOIDLE4_CORE);
136 preg(CM_AUTOIDLE_WKUP);
137 preg(CM_AUTOIDLE_PLL);
138 preg(CM_AUTOIDLE_DSP);
139 preg(CM_AUTOIDLE_MDM);
140
141 preg(CM_ICLKEN1_CORE);
142 preg(CM_ICLKEN2_CORE);
143 preg(CM_ICLKEN3_CORE);
144 preg(CM_ICLKEN4_CORE);
145 preg(CM_ICLKEN_GFX);
146 preg(CM_ICLKEN_WKUP);
147 preg(CM_ICLKEN_DSP);
148 preg(CM_ICLKEN_MDM);
149
150 preg(CM_IDLEST1_CORE);
151 preg(CM_IDLEST2_CORE);
152 preg(CM_IDLEST3_CORE);
153 preg(CM_IDLEST4_CORE);
154 preg(CM_IDLEST_GFX);
155 preg(CM_IDLEST_WKUP);
156 preg(CM_IDLEST_CKGEN);
157 preg(CM_IDLEST_DSP);
158 preg(CM_IDLEST_MDM);
159
160 preg(RM_RSTST_MPU);
161 preg(RM_RSTST_GFX);
162 preg(RM_RSTST_WKUP);
163 preg(RM_RSTST_DSP);
164 preg(RM_RSTST_MDM);
165
166 preg(PM_WKDEP_MPU);
167 preg(PM_WKDEP_CORE);
168 preg(PM_WKDEP_GFX);
169 preg(PM_WKDEP_DSP);
170 preg(PM_WKDEP_MDM);
171
172 preg(CM_FCLKEN_WKUP);
173 preg(CM_ICLKEN_WKUP);
174 preg(CM_IDLEST_WKUP);
175 preg(CM_AUTOIDLE_WKUP);
176 preg(CM_CLKSEL_WKUP);
177
178 preg(PM_WKEN_WKUP);
179 preg(PM_WKST_WKUP);
180}
181
182static inline void omap2_pm_save_registers(void)
183{
184 /* Save interrupt registers */
185 OMAP24XX_SAVE(INTC_MIR0);
186 OMAP24XX_SAVE(INTC_MIR1);
187 OMAP24XX_SAVE(INTC_MIR2);
188
189 /* Save power control registers */
190 OMAP24XX_SAVE(CM_CLKSTCTRL_MPU);
191 OMAP24XX_SAVE(CM_CLKSTCTRL_CORE);
192 OMAP24XX_SAVE(CM_CLKSTCTRL_GFX);
193 OMAP24XX_SAVE(CM_CLKSTCTRL_DSP);
194 OMAP24XX_SAVE(CM_CLKSTCTRL_MDM);
195
196 /* Save power state registers */
197 OMAP24XX_SAVE(PM_PWSTCTRL_MPU);
198 OMAP24XX_SAVE(PM_PWSTCTRL_CORE);
199 OMAP24XX_SAVE(PM_PWSTCTRL_GFX);
200 OMAP24XX_SAVE(PM_PWSTCTRL_DSP);
201 OMAP24XX_SAVE(PM_PWSTCTRL_MDM);
202
203 /* Save autoidle registers */
204 OMAP24XX_SAVE(CM_AUTOIDLE1_CORE);
205 OMAP24XX_SAVE(CM_AUTOIDLE2_CORE);
206 OMAP24XX_SAVE(CM_AUTOIDLE3_CORE);
207 OMAP24XX_SAVE(CM_AUTOIDLE4_CORE);
208 OMAP24XX_SAVE(CM_AUTOIDLE_WKUP);
209 OMAP24XX_SAVE(CM_AUTOIDLE_PLL);
210 OMAP24XX_SAVE(CM_AUTOIDLE_DSP);
211 OMAP24XX_SAVE(CM_AUTOIDLE_MDM);
212
213 /* Save idle state registers */
214 OMAP24XX_SAVE(CM_IDLEST1_CORE);
215 OMAP24XX_SAVE(CM_IDLEST2_CORE);
216 OMAP24XX_SAVE(CM_IDLEST3_CORE);
217 OMAP24XX_SAVE(CM_IDLEST4_CORE);
218 OMAP24XX_SAVE(CM_IDLEST_GFX);
219 OMAP24XX_SAVE(CM_IDLEST_WKUP);
220 OMAP24XX_SAVE(CM_IDLEST_CKGEN);
221 OMAP24XX_SAVE(CM_IDLEST_DSP);
222 OMAP24XX_SAVE(CM_IDLEST_MDM);
223
224 /* Save clock registers */
225 OMAP24XX_SAVE(CM_FCLKEN1_CORE);
226 OMAP24XX_SAVE(CM_FCLKEN2_CORE);
227 OMAP24XX_SAVE(CM_ICLKEN1_CORE);
228 OMAP24XX_SAVE(CM_ICLKEN2_CORE);
229 OMAP24XX_SAVE(CM_ICLKEN3_CORE);
230 OMAP24XX_SAVE(CM_ICLKEN4_CORE);
231}
232
233static inline void omap2_pm_restore_registers(void)
234{
235 /* Restore clock state registers */
236 OMAP24XX_RESTORE(CM_CLKSTCTRL_MPU);
237 OMAP24XX_RESTORE(CM_CLKSTCTRL_CORE);
238 OMAP24XX_RESTORE(CM_CLKSTCTRL_GFX);
239 OMAP24XX_RESTORE(CM_CLKSTCTRL_DSP);
240 OMAP24XX_RESTORE(CM_CLKSTCTRL_MDM);
241
242 /* Restore power state registers */
243 OMAP24XX_RESTORE(PM_PWSTCTRL_MPU);
244 OMAP24XX_RESTORE(PM_PWSTCTRL_CORE);
245 OMAP24XX_RESTORE(PM_PWSTCTRL_GFX);
246 OMAP24XX_RESTORE(PM_PWSTCTRL_DSP);
247 OMAP24XX_RESTORE(PM_PWSTCTRL_MDM);
248
249 /* Restore idle state registers */
250 OMAP24XX_RESTORE(CM_IDLEST1_CORE);
251 OMAP24XX_RESTORE(CM_IDLEST2_CORE);
252 OMAP24XX_RESTORE(CM_IDLEST3_CORE);
253 OMAP24XX_RESTORE(CM_IDLEST4_CORE);
254 OMAP24XX_RESTORE(CM_IDLEST_GFX);
255 OMAP24XX_RESTORE(CM_IDLEST_WKUP);
256 OMAP24XX_RESTORE(CM_IDLEST_CKGEN);
257 OMAP24XX_RESTORE(CM_IDLEST_DSP);
258 OMAP24XX_RESTORE(CM_IDLEST_MDM);
259
260 /* Restore autoidle registers */
261 OMAP24XX_RESTORE(CM_AUTOIDLE1_CORE);
262 OMAP24XX_RESTORE(CM_AUTOIDLE2_CORE);
263 OMAP24XX_RESTORE(CM_AUTOIDLE3_CORE);
264 OMAP24XX_RESTORE(CM_AUTOIDLE4_CORE);
265 OMAP24XX_RESTORE(CM_AUTOIDLE_WKUP);
266 OMAP24XX_RESTORE(CM_AUTOIDLE_PLL);
267 OMAP24XX_RESTORE(CM_AUTOIDLE_DSP);
268 OMAP24XX_RESTORE(CM_AUTOIDLE_MDM);
269
270 /* Restore clock registers */
271 OMAP24XX_RESTORE(CM_FCLKEN1_CORE);
272 OMAP24XX_RESTORE(CM_FCLKEN2_CORE);
273 OMAP24XX_RESTORE(CM_ICLKEN1_CORE);
274 OMAP24XX_RESTORE(CM_ICLKEN2_CORE);
275 OMAP24XX_RESTORE(CM_ICLKEN3_CORE);
276 OMAP24XX_RESTORE(CM_ICLKEN4_CORE);
277
278 /* REVISIT: Clear interrupts here */
279
280 /* Restore interrupt registers */
281 OMAP24XX_RESTORE(INTC_MIR0);
282 OMAP24XX_RESTORE(INTC_MIR1);
283 OMAP24XX_RESTORE(INTC_MIR2);
284}
285
286static int omap2_pm_suspend(void)
287{
288 int processor_type = 0;
289
290 /* REVISIT: 0x21 or 0x26? */
291 if (cpu_is_omap2420())
292 processor_type = 0x21;
293
294 if (!processor_type)
295 return -ENOTSUPP;
296
297 local_irq_disable();
298 local_fiq_disable();
299
300 omap2_pm_save_registers();
301
302 /* Disable interrupts except for the wake events */
303 INTC_MIR_SET0 = 0xffffffff & ~INT0_WAKE_MASK;
304 INTC_MIR_SET1 = 0xffffffff & ~INT1_WAKE_MASK;
305 INTC_MIR_SET2 = 0xffffffff & ~INT2_WAKE_MASK;
306
307 pmdomain_set_autoidle();
308
309 /* Clear old wake-up events */
310 PM_WKST1_CORE = 0;
311 PM_WKST2_CORE = 0;
312 PM_WKST_WKUP = 0;
313
314 /* Enable wake-up events */
315 PM_WKEN1_CORE = (1 << 22) | (1 << 21); /* UART1 & 2 */
316 PM_WKEN2_CORE = (1 << 2); /* UART3 */
317 PM_WKEN_WKUP = (1 << 2) | (1 << 0); /* GPIO & GPT1 */
318
319 /* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled
320 * in the SRAM suspend code */
321 CM_FCLKEN1_CORE = 0;
322 CM_FCLKEN2_CORE = 0;
323 CM_ICLKEN1_CORE = 0;
324 CM_ICLKEN3_CORE = 0;
325 CM_ICLKEN4_CORE = 0;
326
327 omap2_pm_debug("Status before suspend");
328
329 /* Must wait for serial buffers to clear */
330 mdelay(200);
331
332 /* Jump to SRAM suspend code
333 * REVISIT: When is this SDRC_DLLB_CTRL?
334 */
335 omap2_sram_suspend(SDRC_DLLA_CTRL, processor_type);
336
337 /* Back from sleep */
338 omap2_pm_restore_registers();
339
340 local_fiq_enable();
341 local_irq_enable();
342
343 return 0;
344}
345
90static int omap2_pm_enter(suspend_state_t state) 346static int omap2_pm_enter(suspend_state_t state)
91{ 347{
348 int ret = 0;
349
92 switch (state) 350 switch (state)
93 { 351 {
94 case PM_SUSPEND_STANDBY: 352 case PM_SUSPEND_STANDBY:
95 case PM_SUSPEND_MEM: 353 case PM_SUSPEND_MEM:
96 /* FIXME: Add suspend */ 354 ret = omap2_pm_suspend();
97 break; 355 break;
98
99 case PM_SUSPEND_DISK: 356 case PM_SUSPEND_DISK:
100 return -ENOTSUPP; 357 ret = -ENOTSUPP;
101 358 break;
102 default: 359 default:
103 return -EINVAL; 360 ret = -EINVAL;
104 } 361 }
105 362
106 return 0; 363 return ret;
107} 364}
108 365
109static int omap2_pm_finish(suspend_state_t state) 366static int omap2_pm_finish(suspend_state_t state)
@@ -143,6 +400,8 @@ int __init omap2_pm_init(void)
143 pm_set_ops(&omap_pm_ops); 400 pm_set_ops(&omap_pm_ops);
144 pm_idle = omap2_pm_idle; 401 pm_idle = omap2_pm_idle;
145 402
403 pmdomain_init();
404
146 return 0; 405 return 0;
147} 406}
148 407
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 1d2f5ac2f69b..cf78e6c5a277 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -6,6 +6,7 @@
6 * Copyright (C) 2005 Nokia Corporation 6 * Copyright (C) 2005 Nokia Corporation
7 * Author: Paul Mundt <paul.mundt@nokia.com> 7 * Author: Paul Mundt <paul.mundt@nokia.com>
8 * Juha Yrjölä <juha.yrjola@nokia.com> 8 * Juha Yrjölä <juha.yrjola@nokia.com>
9 * OMAP Dual-mode timer framework support by Timo Teras
9 * 10 *
10 * Some parts based off of TI's 24xx code: 11 * Some parts based off of TI's 24xx code:
11 * 12 *
@@ -22,54 +23,18 @@
22#include <linux/interrupt.h> 23#include <linux/interrupt.h>
23#include <linux/err.h> 24#include <linux/err.h>
24#include <linux/clk.h> 25#include <linux/clk.h>
26#include <linux/delay.h>
25 27
26#include <asm/mach/time.h> 28#include <asm/mach/time.h>
27#include <asm/delay.h> 29#include <asm/arch/dmtimer.h>
28#include <asm/io.h>
29 30
30#define OMAP2_GP_TIMER1_BASE 0x48028000 31static struct omap_dm_timer *gptimer;
31#define OMAP2_GP_TIMER2_BASE 0x4802a000
32#define OMAP2_GP_TIMER3_BASE 0x48078000
33#define OMAP2_GP_TIMER4_BASE 0x4807a000
34 32
35#define GP_TIMER_TIDR 0x00 33static inline void omap2_gp_timer_start(unsigned long load_val)
36#define GP_TIMER_TISR 0x18
37#define GP_TIMER_TIER 0x1c
38#define GP_TIMER_TCLR 0x24
39#define GP_TIMER_TCRR 0x28
40#define GP_TIMER_TLDR 0x2c
41#define GP_TIMER_TSICR 0x40
42
43#define OS_TIMER_NR 1 /* GP timer 2 */
44
45static unsigned long timer_base[] = {
46 IO_ADDRESS(OMAP2_GP_TIMER1_BASE),
47 IO_ADDRESS(OMAP2_GP_TIMER2_BASE),
48 IO_ADDRESS(OMAP2_GP_TIMER3_BASE),
49 IO_ADDRESS(OMAP2_GP_TIMER4_BASE),
50};
51
52static inline unsigned int timer_read_reg(int nr, unsigned int reg)
53{
54 return __raw_readl(timer_base[nr] + reg);
55}
56
57static inline void timer_write_reg(int nr, unsigned int reg, unsigned int val)
58{
59 __raw_writel(val, timer_base[nr] + reg);
60}
61
62/* Note that we always enable the clock prescale divider bit */
63static inline void omap2_gp_timer_start(int nr, unsigned long load_val)
64{ 34{
65 unsigned int tmp; 35 omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val);
66 36 omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
67 tmp = 0xffffffff - load_val; 37 omap_dm_timer_start(gptimer);
68
69 timer_write_reg(nr, GP_TIMER_TLDR, tmp);
70 timer_write_reg(nr, GP_TIMER_TCRR, tmp);
71 timer_write_reg(nr, GP_TIMER_TIER, 1 << 1);
72 timer_write_reg(nr, GP_TIMER_TCLR, (1 << 5) | (1 << 1) | 1);
73} 38}
74 39
75static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id, 40static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id,
@@ -77,7 +42,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id,
77{ 42{
78 write_seqlock(&xtime_lock); 43 write_seqlock(&xtime_lock);
79 44
80 timer_write_reg(OS_TIMER_NR, GP_TIMER_TISR, 1 << 1); 45 omap_dm_timer_write_status(gptimer, OMAP_TIMER_INT_OVERFLOW);
81 timer_tick(regs); 46 timer_tick(regs);
82 47
83 write_sequnlock(&xtime_lock); 48 write_sequnlock(&xtime_lock);
@@ -87,41 +52,26 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id,
87 52
88static struct irqaction omap2_gp_timer_irq = { 53static struct irqaction omap2_gp_timer_irq = {
89 .name = "gp timer", 54 .name = "gp timer",
90 .flags = SA_INTERRUPT, 55 .flags = SA_INTERRUPT | SA_TIMER,
91 .handler = omap2_gp_timer_interrupt, 56 .handler = omap2_gp_timer_interrupt,
92}; 57};
93 58
94static void __init omap2_gp_timer_init(void) 59static void __init omap2_gp_timer_init(void)
95{ 60{
96 struct clk * sys_ck; 61 u32 tick_period;
97 u32 tick_period = 120000;
98 u32 l;
99 62
100 /* Reset clock and prescale value */ 63 omap_dm_timer_init();
101 timer_write_reg(OS_TIMER_NR, GP_TIMER_TCLR, 0); 64 gptimer = omap_dm_timer_request_specific(1);
65 BUG_ON(gptimer == NULL);
102 66
103 sys_ck = clk_get(NULL, "sys_ck"); 67 omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK);
104 if (IS_ERR(sys_ck)) 68 tick_period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / 100;
105 printk(KERN_ERR "Could not get sys_ck\n");
106 else {
107 clk_enable(sys_ck);
108 tick_period = clk_get_rate(sys_ck) / 100;
109 clk_put(sys_ck);
110 }
111
112 tick_period /= 2; /* Minimum prescale divider is 2 */
113 tick_period -= 1; 69 tick_period -= 1;
114 70
115 l = timer_read_reg(OS_TIMER_NR, GP_TIMER_TIDR); 71 setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
116 printk(KERN_INFO "OMAP2 GP timer (HW version %d.%d)\n", 72 omap2_gp_timer_start(tick_period);
117 (l >> 4) & 0x0f, l & 0x0f);
118
119 setup_irq(38, &omap2_gp_timer_irq);
120
121 omap2_gp_timer_start(OS_TIMER_NR, tick_period);
122} 73}
123 74
124struct sys_timer omap_timer = { 75struct sys_timer omap_timer = {
125 .init = omap2_gp_timer_init, 76 .init = omap2_gp_timer_init,
126}; 77};
127
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index ec49495e651e..ec752e16d618 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -91,7 +91,7 @@ config OMAP_32K_TIMER_HZ
91 91
92config OMAP_DM_TIMER 92config OMAP_DM_TIMER
93 bool "Use dual-mode timer" 93 bool "Use dual-mode timer"
94 depends on ARCH_OMAP16XX 94 depends on ARCH_OMAP16XX || ARCH_OMAP24XX
95 help 95 help
96 Select this option if you want to use OMAP Dual-Mode timers. 96 Select this option if you want to use OMAP Dual-Mode timers.
97 97
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 32ec04c58bcd..dcd9d81201fa 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -28,9 +28,9 @@
28 28
29#include <asm/arch/clock.h> 29#include <asm/arch/clock.h>
30 30
31LIST_HEAD(clocks); 31static LIST_HEAD(clocks);
32static DEFINE_MUTEX(clocks_mutex); 32static DEFINE_MUTEX(clocks_mutex);
33DEFINE_SPINLOCK(clockfw_lock); 33static DEFINE_SPINLOCK(clockfw_lock);
34 34
35static struct clk_functions *arch_clock; 35static struct clk_functions *arch_clock;
36 36
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 98edc9fdd6d1..a0c71dca2373 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -25,6 +25,14 @@
25#include <asm/io.h> 25#include <asm/io.h>
26#include <asm/system.h> 26#include <asm/system.h>
27 27
28#define VERY_HI_RATE 900000000
29
30#ifdef CONFIG_ARCH_OMAP1
31#define MPU_CLK "mpu"
32#else
33#define MPU_CLK "virt_prcm_set"
34#endif
35
28/* TODO: Add support for SDRAM timing changes */ 36/* TODO: Add support for SDRAM timing changes */
29 37
30int omap_verify_speed(struct cpufreq_policy *policy) 38int omap_verify_speed(struct cpufreq_policy *policy)
@@ -36,7 +44,7 @@ int omap_verify_speed(struct cpufreq_policy *policy)
36 44
37 cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, 45 cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
38 policy->cpuinfo.max_freq); 46 policy->cpuinfo.max_freq);
39 mpu_clk = clk_get(NULL, "mpu"); 47 mpu_clk = clk_get(NULL, MPU_CLK);
40 if (IS_ERR(mpu_clk)) 48 if (IS_ERR(mpu_clk))
41 return PTR_ERR(mpu_clk); 49 return PTR_ERR(mpu_clk);
42 policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; 50 policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
@@ -56,7 +64,7 @@ unsigned int omap_getspeed(unsigned int cpu)
56 if (cpu) 64 if (cpu)
57 return 0; 65 return 0;
58 66
59 mpu_clk = clk_get(NULL, "mpu"); 67 mpu_clk = clk_get(NULL, MPU_CLK);
60 if (IS_ERR(mpu_clk)) 68 if (IS_ERR(mpu_clk))
61 return 0; 69 return 0;
62 rate = clk_get_rate(mpu_clk) / 1000; 70 rate = clk_get_rate(mpu_clk) / 1000;
@@ -73,7 +81,7 @@ static int omap_target(struct cpufreq_policy *policy,
73 struct cpufreq_freqs freqs; 81 struct cpufreq_freqs freqs;
74 int ret = 0; 82 int ret = 0;
75 83
76 mpu_clk = clk_get(NULL, "mpu"); 84 mpu_clk = clk_get(NULL, MPU_CLK);
77 if (IS_ERR(mpu_clk)) 85 if (IS_ERR(mpu_clk))
78 return PTR_ERR(mpu_clk); 86 return PTR_ERR(mpu_clk);
79 87
@@ -93,7 +101,7 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy)
93{ 101{
94 struct clk * mpu_clk; 102 struct clk * mpu_clk;
95 103
96 mpu_clk = clk_get(NULL, "mpu"); 104 mpu_clk = clk_get(NULL, MPU_CLK);
97 if (IS_ERR(mpu_clk)) 105 if (IS_ERR(mpu_clk))
98 return PTR_ERR(mpu_clk); 106 return PTR_ERR(mpu_clk);
99 107
@@ -102,7 +110,7 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy)
102 policy->cur = policy->min = policy->max = omap_getspeed(0); 110 policy->cur = policy->min = policy->max = omap_getspeed(0);
103 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 111 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
104 policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; 112 policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
105 policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, 216000000) / 1000; 113 policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000;
106 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 114 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
107 clk_put(mpu_clk); 115 clk_put(mpu_clk);
108 116
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 5d5d6eb222dd..ee15b4089127 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -105,7 +105,7 @@ static void omap_init_kp(void)
105 omap_cfg_reg(E20_1610_KBR3); 105 omap_cfg_reg(E20_1610_KBR3);
106 omap_cfg_reg(E19_1610_KBR4); 106 omap_cfg_reg(E19_1610_KBR4);
107 omap_cfg_reg(N19_1610_KBR5); 107 omap_cfg_reg(N19_1610_KBR5);
108 } else if (machine_is_omap_perseus2()) { 108 } else if (machine_is_omap_perseus2() || machine_is_omap_fsample()) {
109 omap_cfg_reg(E2_730_KBR0); 109 omap_cfg_reg(E2_730_KBR0);
110 omap_cfg_reg(J7_730_KBR1); 110 omap_cfg_reg(J7_730_KBR1);
111 omap_cfg_reg(E1_730_KBR2); 111 omap_cfg_reg(E1_730_KBR2);
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 5dac4230360d..c5d0214ef191 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -43,6 +43,7 @@
43 43
44#define OMAP_DMA_ACTIVE 0x01 44#define OMAP_DMA_ACTIVE 0x01
45#define OMAP_DMA_CCR_EN (1 << 7) 45#define OMAP_DMA_CCR_EN (1 << 7)
46#define OMAP2_DMA_CSR_CLEAR_MASK 0xffe
46 47
47#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) 48#define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec)
48 49
@@ -166,18 +167,24 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
166 if (cpu_is_omap24xx() && dma_trigger) { 167 if (cpu_is_omap24xx() && dma_trigger) {
167 u32 val = OMAP_DMA_CCR_REG(lch); 168 u32 val = OMAP_DMA_CCR_REG(lch);
168 169
170 val &= ~(3 << 19);
169 if (dma_trigger > 63) 171 if (dma_trigger > 63)
170 val |= 1 << 20; 172 val |= 1 << 20;
171 if (dma_trigger > 31) 173 if (dma_trigger > 31)
172 val |= 1 << 19; 174 val |= 1 << 19;
173 175
176 val &= ~(0x1f);
174 val |= (dma_trigger & 0x1f); 177 val |= (dma_trigger & 0x1f);
175 178
176 if (sync_mode & OMAP_DMA_SYNC_FRAME) 179 if (sync_mode & OMAP_DMA_SYNC_FRAME)
177 val |= 1 << 5; 180 val |= 1 << 5;
181 else
182 val &= ~(1 << 5);
178 183
179 if (sync_mode & OMAP_DMA_SYNC_BLOCK) 184 if (sync_mode & OMAP_DMA_SYNC_BLOCK)
180 val |= 1 << 18; 185 val |= 1 << 18;
186 else
187 val &= ~(1 << 18);
181 188
182 if (src_or_dst_synch) 189 if (src_or_dst_synch)
183 val |= 1 << 24; /* source synch */ 190 val |= 1 << 24; /* source synch */
@@ -286,22 +293,39 @@ void omap_set_dma_src_data_pack(int lch, int enable)
286 293
287void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) 294void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
288{ 295{
296 unsigned int burst = 0;
289 OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 7); 297 OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 7);
290 298
291 switch (burst_mode) { 299 switch (burst_mode) {
292 case OMAP_DMA_DATA_BURST_DIS: 300 case OMAP_DMA_DATA_BURST_DIS:
293 break; 301 break;
294 case OMAP_DMA_DATA_BURST_4: 302 case OMAP_DMA_DATA_BURST_4:
295 OMAP_DMA_CSDP_REG(lch) |= (0x02 << 7); 303 if (cpu_is_omap24xx())
304 burst = 0x1;
305 else
306 burst = 0x2;
296 break; 307 break;
297 case OMAP_DMA_DATA_BURST_8: 308 case OMAP_DMA_DATA_BURST_8:
298 /* not supported by current hardware 309 if (cpu_is_omap24xx()) {
310 burst = 0x2;
311 break;
312 }
313 /* not supported by current hardware on OMAP1
299 * w |= (0x03 << 7); 314 * w |= (0x03 << 7);
300 * fall through 315 * fall through
301 */ 316 */
317 case OMAP_DMA_DATA_BURST_16:
318 if (cpu_is_omap24xx()) {
319 burst = 0x3;
320 break;
321 }
322 /* OMAP1 don't support burst 16
323 * fall through
324 */
302 default: 325 default:
303 BUG(); 326 BUG();
304 } 327 }
328 OMAP_DMA_CSDP_REG(lch) |= (burst << 7);
305} 329}
306 330
307/* Note that dest_port is only for OMAP1 */ 331/* Note that dest_port is only for OMAP1 */
@@ -348,30 +372,49 @@ void omap_set_dma_dest_data_pack(int lch, int enable)
348 372
349void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) 373void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
350{ 374{
375 unsigned int burst = 0;
351 OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 14); 376 OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 14);
352 377
353 switch (burst_mode) { 378 switch (burst_mode) {
354 case OMAP_DMA_DATA_BURST_DIS: 379 case OMAP_DMA_DATA_BURST_DIS:
355 break; 380 break;
356 case OMAP_DMA_DATA_BURST_4: 381 case OMAP_DMA_DATA_BURST_4:
357 OMAP_DMA_CSDP_REG(lch) |= (0x02 << 14); 382 if (cpu_is_omap24xx())
383 burst = 0x1;
384 else
385 burst = 0x2;
358 break; 386 break;
359 case OMAP_DMA_DATA_BURST_8: 387 case OMAP_DMA_DATA_BURST_8:
360 OMAP_DMA_CSDP_REG(lch) |= (0x03 << 14); 388 if (cpu_is_omap24xx())
389 burst = 0x2;
390 else
391 burst = 0x3;
361 break; 392 break;
393 case OMAP_DMA_DATA_BURST_16:
394 if (cpu_is_omap24xx()) {
395 burst = 0x3;
396 break;
397 }
398 /* OMAP1 don't support burst 16
399 * fall through
400 */
362 default: 401 default:
363 printk(KERN_ERR "Invalid DMA burst mode\n"); 402 printk(KERN_ERR "Invalid DMA burst mode\n");
364 BUG(); 403 BUG();
365 return; 404 return;
366 } 405 }
406 OMAP_DMA_CSDP_REG(lch) |= (burst << 14);
367} 407}
368 408
369static inline void omap_enable_channel_irq(int lch) 409static inline void omap_enable_channel_irq(int lch)
370{ 410{
371 u32 status; 411 u32 status;
372 412
373 /* Read CSR to make sure it's cleared. */ 413 /* Clear CSR */
374 status = OMAP_DMA_CSR_REG(lch); 414 if (cpu_class_is_omap1())
415 status = OMAP_DMA_CSR_REG(lch);
416 else if (cpu_is_omap24xx())
417 OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK;
375 418
376 /* Enable some nice interrupts. */ 419 /* Enable some nice interrupts. */
377 OMAP_DMA_CICR_REG(lch) = dma_chan[lch].enabled_irqs; 420 OMAP_DMA_CICR_REG(lch) = dma_chan[lch].enabled_irqs;
@@ -470,11 +513,13 @@ int omap_request_dma(int dev_id, const char *dev_name,
470 chan->dev_name = dev_name; 513 chan->dev_name = dev_name;
471 chan->callback = callback; 514 chan->callback = callback;
472 chan->data = data; 515 chan->data = data;
473 chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | 516 chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
474 OMAP_DMA_BLOCK_IRQ;
475 517
476 if (cpu_is_omap24xx()) 518 if (cpu_class_is_omap1())
477 chan->enabled_irqs |= OMAP2_DMA_TRANS_ERR_IRQ; 519 chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
520 else if (cpu_is_omap24xx())
521 chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ |
522 OMAP2_DMA_TRANS_ERR_IRQ;
478 523
479 if (cpu_is_omap16xx()) { 524 if (cpu_is_omap16xx()) {
480 /* If the sync device is set, configure it dynamically. */ 525 /* If the sync device is set, configure it dynamically. */
@@ -494,7 +539,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
494 539
495 omap_enable_channel_irq(free_ch); 540 omap_enable_channel_irq(free_ch);
496 /* Clear the CSR register and IRQ status register */ 541 /* Clear the CSR register and IRQ status register */
497 OMAP_DMA_CSR_REG(free_ch) = 0x0; 542 OMAP_DMA_CSR_REG(free_ch) = OMAP2_DMA_CSR_CLEAR_MASK;
498 omap_writel(~0x0, OMAP_DMA4_IRQSTATUS_L0); 543 omap_writel(~0x0, OMAP_DMA4_IRQSTATUS_L0);
499 } 544 }
500 545
@@ -534,7 +579,7 @@ void omap_free_dma(int lch)
534 omap_writel(val, OMAP_DMA4_IRQENABLE_L0); 579 omap_writel(val, OMAP_DMA4_IRQENABLE_L0);
535 580
536 /* Clear the CSR register and IRQ status register */ 581 /* Clear the CSR register and IRQ status register */
537 OMAP_DMA_CSR_REG(lch) = 0x0; 582 OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK;
538 583
539 val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); 584 val = omap_readl(OMAP_DMA4_IRQSTATUS_L0);
540 val |= 1 << lch; 585 val |= 1 << lch;
@@ -798,7 +843,7 @@ static int omap1_dma_handle_ch(int ch)
798 "%d (CSR %04x)\n", ch, csr); 843 "%d (CSR %04x)\n", ch, csr);
799 return 0; 844 return 0;
800 } 845 }
801 if (unlikely(csr & OMAP_DMA_TOUT_IRQ)) 846 if (unlikely(csr & OMAP1_DMA_TOUT_IRQ))
802 printk(KERN_WARNING "DMA timeout with device %d\n", 847 printk(KERN_WARNING "DMA timeout with device %d\n",
803 dma_chan[ch].dev_id); 848 dma_chan[ch].dev_id);
804 if (unlikely(csr & OMAP_DMA_DROP_IRQ)) 849 if (unlikely(csr & OMAP_DMA_DROP_IRQ))
@@ -846,20 +891,21 @@ static int omap2_dma_handle_ch(int ch)
846 return 0; 891 return 0;
847 if (unlikely(dma_chan[ch].dev_id == -1)) 892 if (unlikely(dma_chan[ch].dev_id == -1))
848 return 0; 893 return 0;
849 /* REVISIT: According to 24xx TRM, there's no TOUT_IE */
850 if (unlikely(status & OMAP_DMA_TOUT_IRQ))
851 printk(KERN_INFO "DMA timeout with device %d\n",
852 dma_chan[ch].dev_id);
853 if (unlikely(status & OMAP_DMA_DROP_IRQ)) 894 if (unlikely(status & OMAP_DMA_DROP_IRQ))
854 printk(KERN_INFO 895 printk(KERN_INFO
855 "DMA synchronization event drop occurred with device " 896 "DMA synchronization event drop occurred with device "
856 "%d\n", dma_chan[ch].dev_id); 897 "%d\n", dma_chan[ch].dev_id);
857
858 if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) 898 if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ))
859 printk(KERN_INFO "DMA transaction error with device %d\n", 899 printk(KERN_INFO "DMA transaction error with device %d\n",
860 dma_chan[ch].dev_id); 900 dma_chan[ch].dev_id);
901 if (unlikely(status & OMAP2_DMA_SECURE_ERR_IRQ))
902 printk(KERN_INFO "DMA secure error with device %d\n",
903 dma_chan[ch].dev_id);
904 if (unlikely(status & OMAP2_DMA_MISALIGNED_ERR_IRQ))
905 printk(KERN_INFO "DMA misaligned error with device %d\n",
906 dma_chan[ch].dev_id);
861 907
862 OMAP_DMA_CSR_REG(ch) = 0x20; 908 OMAP_DMA_CSR_REG(ch) = OMAP2_DMA_CSR_CLEAR_MASK;
863 909
864 val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); 910 val = omap_readl(OMAP_DMA4_IRQSTATUS_L0);
865 /* ch in this function is from 0-31 while in register it is 1-32 */ 911 /* ch in this function is from 0-31 while in register it is 1-32 */
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index eba3cb52ad87..804a53534370 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -4,7 +4,8 @@
4 * OMAP Dual-Mode Timers 4 * OMAP Dual-Mode Timers
5 * 5 *
6 * Copyright (C) 2005 Nokia Corporation 6 * Copyright (C) 2005 Nokia Corporation
7 * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com> 7 * OMAP2 support by Juha Yrjola
8 * API improvements and OMAP2 clock framework support by Timo Teras
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the 11 * under the terms of the GNU General Public License as published by the
@@ -26,15 +27,17 @@
26 */ 27 */
27 28
28#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/spinlock.h>
31#include <linux/errno.h>
32#include <linux/list.h>
33#include <linux/clk.h>
34#include <linux/delay.h>
29#include <asm/hardware.h> 35#include <asm/hardware.h>
30#include <asm/arch/dmtimer.h> 36#include <asm/arch/dmtimer.h>
31#include <asm/io.h> 37#include <asm/io.h>
32#include <asm/arch/irqs.h> 38#include <asm/arch/irqs.h>
33#include <linux/spinlock.h>
34#include <linux/list.h>
35
36#define OMAP_TIMER_COUNT 8
37 39
40/* register offsets */
38#define OMAP_TIMER_ID_REG 0x00 41#define OMAP_TIMER_ID_REG 0x00
39#define OMAP_TIMER_OCP_CFG_REG 0x10 42#define OMAP_TIMER_OCP_CFG_REG 0x10
40#define OMAP_TIMER_SYS_STAT_REG 0x14 43#define OMAP_TIMER_SYS_STAT_REG 0x14
@@ -50,52 +53,196 @@
50#define OMAP_TIMER_CAPTURE_REG 0x3c 53#define OMAP_TIMER_CAPTURE_REG 0x3c
51#define OMAP_TIMER_IF_CTRL_REG 0x40 54#define OMAP_TIMER_IF_CTRL_REG 0x40
52 55
56/* timer control reg bits */
57#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
58#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
59#define OMAP_TIMER_CTRL_PT (1 << 12)
60#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8)
61#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8)
62#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8)
63#define OMAP_TIMER_CTRL_SCPWM (1 << 7)
64#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */
65#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */
66#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* how much to shift the prescaler value */
67#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */
68#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */
69
70struct omap_dm_timer {
71 unsigned long phys_base;
72 int irq;
73#ifdef CONFIG_ARCH_OMAP2
74 struct clk *iclk, *fclk;
75#endif
76 void __iomem *io_base;
77 unsigned reserved:1;
78};
53 79
54static struct dmtimer_info_struct { 80#ifdef CONFIG_ARCH_OMAP1
55 struct list_head unused_timers;
56 struct list_head reserved_timers;
57} dm_timer_info;
58 81
59static struct omap_dm_timer dm_timers[] = { 82static struct omap_dm_timer dm_timers[] = {
60 { .base=0xfffb1400, .irq=INT_1610_GPTIMER1 }, 83 { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
61 { .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 }, 84 { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
62 { .base=0xfffb2400, .irq=INT_1610_GPTIMER3 }, 85 { .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
63 { .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 }, 86 { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
64 { .base=0xfffb3400, .irq=INT_1610_GPTIMER5 }, 87 { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
65 { .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 }, 88 { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
66 { .base=0xfffb4400, .irq=INT_1610_GPTIMER7 }, 89 { .phys_base = 0xfffb4400, .irq = INT_1610_GPTIMER7 },
67 { .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 }, 90 { .phys_base = 0xfffb4c00, .irq = INT_1610_GPTIMER8 },
68 { .base=0x0 },
69}; 91};
70 92
93#elif defined(CONFIG_ARCH_OMAP2)
94
95static struct omap_dm_timer dm_timers[] = {
96 { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
97 { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
98 { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
99 { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
100 { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
101 { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
102 { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
103 { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
104 { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
105 { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
106 { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
107 { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
108};
109
110static const char *dm_source_names[] = {
111 "sys_ck",
112 "func_32k_ck",
113 "alt_ck"
114};
71 115
116static struct clk *dm_source_clocks[3];
117
118#else
119
120#error OMAP architecture not supported!
121
122#endif
123
124static const int dm_timer_count = ARRAY_SIZE(dm_timers);
72static spinlock_t dm_timer_lock; 125static spinlock_t dm_timer_lock;
73 126
127static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg)
128{
129 return readl(timer->io_base + reg);
130}
74 131
75inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value) 132static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value)
76{ 133{
77 omap_writel(value, timer->base + reg); 134 writel(value, timer->io_base + reg);
78 while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG)) 135 while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG))
79 ; 136 ;
80} 137}
81 138
82u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg) 139static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
83{ 140{
84 return omap_readl(timer->base + reg); 141 int c;
142
143 c = 0;
144 while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
145 c++;
146 if (c > 100000) {
147 printk(KERN_ERR "Timer failed to reset\n");
148 return;
149 }
150 }
85} 151}
86 152
87int omap_dm_timers_active(void) 153static void omap_dm_timer_reset(struct omap_dm_timer *timer)
154{
155 u32 l;
156
157 if (timer != &dm_timers[0]) {
158 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
159 omap_dm_timer_wait_for_reset(timer);
160 }
161 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK);
162
163 /* Set to smart-idle mode */
164 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
165 l |= 0x02 << 3;
166 omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
167}
168
169static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
170{
171#ifdef CONFIG_ARCH_OMAP2
172 clk_enable(timer->iclk);
173 clk_enable(timer->fclk);
174#endif
175 omap_dm_timer_reset(timer);
176}
177
178struct omap_dm_timer *omap_dm_timer_request(void)
179{
180 struct omap_dm_timer *timer = NULL;
181 unsigned long flags;
182 int i;
183
184 spin_lock_irqsave(&dm_timer_lock, flags);
185 for (i = 0; i < dm_timer_count; i++) {
186 if (dm_timers[i].reserved)
187 continue;
188
189 timer = &dm_timers[i];
190 timer->reserved = 1;
191 break;
192 }
193 spin_unlock_irqrestore(&dm_timer_lock, flags);
194
195 if (timer != NULL)
196 omap_dm_timer_prepare(timer);
197
198 return timer;
199}
200
201struct omap_dm_timer *omap_dm_timer_request_specific(int id)
88{ 202{
89 struct omap_dm_timer *timer; 203 struct omap_dm_timer *timer;
204 unsigned long flags;
90 205
91 for (timer = &dm_timers[0]; timer->base; ++timer) 206 spin_lock_irqsave(&dm_timer_lock, flags);
92 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & 207 if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
93 OMAP_TIMER_CTRL_ST) 208 spin_unlock_irqrestore(&dm_timer_lock, flags);
94 return 1; 209 printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
210 __FILE__, __LINE__, __FUNCTION__, id);
211 dump_stack();
212 return NULL;
213 }
95 214
96 return 0; 215 timer = &dm_timers[id-1];
216 timer->reserved = 1;
217 spin_unlock_irqrestore(&dm_timer_lock, flags);
218
219 omap_dm_timer_prepare(timer);
220
221 return timer;
97} 222}
98 223
224void omap_dm_timer_free(struct omap_dm_timer *timer)
225{
226 omap_dm_timer_reset(timer);
227#ifdef CONFIG_ARCH_OMAP2
228 clk_disable(timer->iclk);
229 clk_disable(timer->fclk);
230#endif
231 WARN_ON(!timer->reserved);
232 timer->reserved = 0;
233}
234
235int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
236{
237 return timer->irq;
238}
239
240#if defined(CONFIG_ARCH_OMAP1)
241
242struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
243{
244 BUG();
245}
99 246
100/** 247/**
101 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR 248 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
@@ -103,184 +250,229 @@ int omap_dm_timers_active(void)
103 */ 250 */
104__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) 251__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
105{ 252{
106 int n; 253 int i;
107 254
108 /* If ARMXOR cannot be idled this function call is unnecessary */ 255 /* If ARMXOR cannot be idled this function call is unnecessary */
109 if (!(inputmask & (1 << 1))) 256 if (!(inputmask & (1 << 1)))
110 return inputmask; 257 return inputmask;
111 258
112 /* If any active timer is using ARMXOR return modified mask */ 259 /* If any active timer is using ARMXOR return modified mask */
113 for (n = 0; dm_timers[n].base; ++n) 260 for (i = 0; i < dm_timer_count; i++) {
114 if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)& 261 u32 l;
115 OMAP_TIMER_CTRL_ST) { 262
116 if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0) 263 l = omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG);
264 if (l & OMAP_TIMER_CTRL_ST) {
265 if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
117 inputmask &= ~(1 << 1); 266 inputmask &= ~(1 << 1);
118 else 267 else
119 inputmask &= ~(1 << 2); 268 inputmask &= ~(1 << 2);
120 } 269 }
270 }
121 271
122 return inputmask; 272 return inputmask;
123} 273}
124 274
275#elif defined(CONFIG_ARCH_OMAP2)
125 276
126void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) 277struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
127{ 278{
128 int n = (timer - dm_timers) << 1; 279 return timer->fclk;
129 u32 l; 280}
130 281
131 l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n); 282__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
132 l |= source << n; 283{
133 omap_writel(l, MOD_CONF_CTRL_1); 284 BUG();
134} 285}
135 286
287#endif
136 288
137static void omap_dm_timer_reset(struct omap_dm_timer *timer) 289void omap_dm_timer_trigger(struct omap_dm_timer *timer)
138{ 290{
139 /* Reset and set posted mode */ 291 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
140 omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
141 omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02);
142
143 omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR);
144} 292}
145 293
294void omap_dm_timer_start(struct omap_dm_timer *timer)
295{
296 u32 l;
146 297
298 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
299 if (!(l & OMAP_TIMER_CTRL_ST)) {
300 l |= OMAP_TIMER_CTRL_ST;
301 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
302 }
303}
147 304
148struct omap_dm_timer * omap_dm_timer_request(void) 305void omap_dm_timer_stop(struct omap_dm_timer *timer)
149{ 306{
150 struct omap_dm_timer *timer = NULL; 307 u32 l;
151 unsigned long flags;
152 308
153 spin_lock_irqsave(&dm_timer_lock, flags); 309 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
154 if (!list_empty(&dm_timer_info.unused_timers)) { 310 if (l & OMAP_TIMER_CTRL_ST) {
155 timer = (struct omap_dm_timer *) 311 l &= ~0x1;
156 dm_timer_info.unused_timers.next; 312 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
157 list_move_tail((struct list_head *)timer,
158 &dm_timer_info.reserved_timers);
159 } 313 }
160 spin_unlock_irqrestore(&dm_timer_lock, flags);
161
162 return timer;
163} 314}
164 315
316#ifdef CONFIG_ARCH_OMAP1
165 317
166void omap_dm_timer_free(struct omap_dm_timer *timer) 318void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
167{ 319{
168 unsigned long flags; 320 int n = (timer - dm_timers) << 1;
169 321 u32 l;
170 omap_dm_timer_reset(timer);
171 322
172 spin_lock_irqsave(&dm_timer_lock, flags); 323 l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
173 list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers); 324 l |= source << n;
174 spin_unlock_irqrestore(&dm_timer_lock, flags); 325 omap_writel(l, MOD_CONF_CTRL_1);
175} 326}
176 327
177void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, 328#else
178 unsigned int value)
179{
180 omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
181}
182 329
183unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) 330void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
184{ 331{
185 return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); 332 if (source < 0 || source >= 3)
186} 333 return;
187 334
188void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) 335 clk_disable(timer->fclk);
189{ 336 clk_set_parent(timer->fclk, dm_source_clocks[source]);
190 omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value); 337 clk_enable(timer->fclk);
338
339 /* When the functional clock disappears, too quick writes seem to
340 * cause an abort. */
341 __delay(15000);
191} 342}
192 343
193void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer) 344#endif
345
346void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
347 unsigned int load)
194{ 348{
195 u32 l; 349 u32 l;
350
196 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 351 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
197 l |= OMAP_TIMER_CTRL_AR; 352 if (autoreload)
353 l |= OMAP_TIMER_CTRL_AR;
354 else
355 l &= ~OMAP_TIMER_CTRL_AR;
198 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 356 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
357 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
358 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
199} 359}
200 360
201void omap_dm_timer_trigger(struct omap_dm_timer *timer) 361void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
202{ 362 unsigned int match)
203 omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1);
204}
205
206void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value)
207{ 363{
208 u32 l; 364 u32 l;
209 365
210 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 366 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
211 l |= value & 0x3; 367 if (enable)
368 l |= OMAP_TIMER_CTRL_CE;
369 else
370 l &= ~OMAP_TIMER_CTRL_CE;
212 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 371 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
372 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
213} 373}
214 374
215void omap_dm_timer_start(struct omap_dm_timer *timer) 375
376void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
377 int toggle, int trigger)
216{ 378{
217 u32 l; 379 u32 l;
218 380
219 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 381 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
220 l |= OMAP_TIMER_CTRL_ST; 382 l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
383 OMAP_TIMER_CTRL_PT | (0x03 << 10));
384 if (def_on)
385 l |= OMAP_TIMER_CTRL_SCPWM;
386 if (toggle)
387 l |= OMAP_TIMER_CTRL_PT;
388 l |= trigger << 10;
221 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 389 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
222} 390}
223 391
224void omap_dm_timer_stop(struct omap_dm_timer *timer) 392void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
225{ 393{
226 u32 l; 394 u32 l;
227 395
228 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); 396 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
229 l &= ~0x1; 397 l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
398 if (prescaler >= 0x00 && prescaler <= 0x07) {
399 l |= OMAP_TIMER_CTRL_PRE;
400 l |= prescaler << 2;
401 }
230 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); 402 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
231} 403}
232 404
233unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) 405void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
406 unsigned int value)
234{ 407{
235 return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); 408 omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
236} 409}
237 410
238void omap_dm_timer_reset_counter(struct omap_dm_timer *timer) 411unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
239{ 412{
240 omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0); 413 return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
241} 414}
242 415
243void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load) 416void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
244{ 417{
245 omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); 418 omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
246} 419}
247 420
248void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match) 421unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
249{ 422{
250 omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); 423 return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
251} 424}
252 425
253void omap_dm_timer_enable_compare(struct omap_dm_timer *timer) 426void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
254{ 427{
255 u32 l; 428 return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
256
257 l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
258 l |= OMAP_TIMER_CTRL_CE;
259 omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
260} 429}
261 430
431int omap_dm_timers_active(void)
432{
433 int i;
434
435 for (i = 0; i < dm_timer_count; i++) {
436 struct omap_dm_timer *timer;
437
438 timer = &dm_timers[i];
439 if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
440 OMAP_TIMER_CTRL_ST)
441 return 1;
442 }
443 return 0;
444}
262 445
263static inline void __dm_timer_init(void) 446int omap_dm_timer_init(void)
264{ 447{
265 struct omap_dm_timer *timer; 448 struct omap_dm_timer *timer;
449 int i;
450
451 if (!(cpu_is_omap16xx() || cpu_is_omap24xx()))
452 return -ENODEV;
266 453
267 spin_lock_init(&dm_timer_lock); 454 spin_lock_init(&dm_timer_lock);
268 INIT_LIST_HEAD(&dm_timer_info.unused_timers); 455#ifdef CONFIG_ARCH_OMAP2
269 INIT_LIST_HEAD(&dm_timer_info.reserved_timers); 456 for (i = 0; i < ARRAY_SIZE(dm_source_names); i++) {
270 457 dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
271 timer = &dm_timers[0]; 458 BUG_ON(dm_source_clocks[i] == NULL);
272 while (timer->base) { 459 }
273 list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers); 460#endif
274 omap_dm_timer_reset(timer); 461
275 timer++; 462 for (i = 0; i < dm_timer_count; i++) {
463#ifdef CONFIG_ARCH_OMAP2
464 char clk_name[16];
465#endif
466
467 timer = &dm_timers[i];
468 timer->io_base = (void __iomem *) io_p2v(timer->phys_base);
469#ifdef CONFIG_ARCH_OMAP2
470 sprintf(clk_name, "gpt%d_ick", i + 1);
471 timer->iclk = clk_get(NULL, clk_name);
472 sprintf(clk_name, "gpt%d_fck", i + 1);
473 timer->fclk = clk_get(NULL, clk_name);
474#endif
276 } 475 }
277}
278 476
279static int __init omap_dm_timer_init(void)
280{
281 if (cpu_is_omap16xx())
282 __dm_timer_init();
283 return 0; 477 return 0;
284} 478}
285
286arch_initcall(omap_dm_timer_init);
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index d3c8ea7eecfd..e75a2ca70ba1 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -537,6 +537,49 @@ static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
537 _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio)); 537 _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
538} 538}
539 539
540static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
541{
542 void __iomem *reg = bank->base;
543 int inv = 0;
544 u32 l;
545 u32 mask;
546
547 switch (bank->method) {
548 case METHOD_MPUIO:
549 reg += OMAP_MPUIO_GPIO_MASKIT;
550 mask = 0xffff;
551 inv = 1;
552 break;
553 case METHOD_GPIO_1510:
554 reg += OMAP1510_GPIO_INT_MASK;
555 mask = 0xffff;
556 inv = 1;
557 break;
558 case METHOD_GPIO_1610:
559 reg += OMAP1610_GPIO_IRQENABLE1;
560 mask = 0xffff;
561 break;
562 case METHOD_GPIO_730:
563 reg += OMAP730_GPIO_INT_MASK;
564 mask = 0xffffffff;
565 inv = 1;
566 break;
567 case METHOD_GPIO_24XX:
568 reg += OMAP24XX_GPIO_IRQENABLE1;
569 mask = 0xffffffff;
570 break;
571 default:
572 BUG();
573 return 0;
574 }
575
576 l = __raw_readl(reg);
577 if (inv)
578 l = ~l;
579 l &= mask;
580 return l;
581}
582
540static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable) 583static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
541{ 584{
542 void __iomem *reg = bank->base; 585 void __iomem *reg = bank->base;
@@ -736,6 +779,8 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
736 u32 isr; 779 u32 isr;
737 unsigned int gpio_irq; 780 unsigned int gpio_irq;
738 struct gpio_bank *bank; 781 struct gpio_bank *bank;
782 u32 retrigger = 0;
783 int unmasked = 0;
739 784
740 desc->chip->ack(irq); 785 desc->chip->ack(irq);
741 786
@@ -760,18 +805,22 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
760#endif 805#endif
761 while(1) { 806 while(1) {
762 u32 isr_saved, level_mask = 0; 807 u32 isr_saved, level_mask = 0;
808 u32 enabled;
763 809
764 isr_saved = isr = __raw_readl(isr_reg); 810 enabled = _get_gpio_irqbank_mask(bank);
811 isr_saved = isr = __raw_readl(isr_reg) & enabled;
765 812
766 if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO)) 813 if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
767 isr &= 0x0000ffff; 814 isr &= 0x0000ffff;
768 815
769 if (cpu_is_omap24xx()) 816 if (cpu_is_omap24xx()) {
770 level_mask = 817 level_mask =
771 __raw_readl(bank->base + 818 __raw_readl(bank->base +
772 OMAP24XX_GPIO_LEVELDETECT0) | 819 OMAP24XX_GPIO_LEVELDETECT0) |
773 __raw_readl(bank->base + 820 __raw_readl(bank->base +
774 OMAP24XX_GPIO_LEVELDETECT1); 821 OMAP24XX_GPIO_LEVELDETECT1);
822 level_mask &= enabled;
823 }
775 824
776 /* clear edge sensitive interrupts before handler(s) are 825 /* clear edge sensitive interrupts before handler(s) are
777 called so that we don't miss any interrupt occurred while 826 called so that we don't miss any interrupt occurred while
@@ -782,19 +831,54 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
782 831
783 /* if there is only edge sensitive GPIO pin interrupts 832 /* if there is only edge sensitive GPIO pin interrupts
784 configured, we could unmask GPIO bank interrupt immediately */ 833 configured, we could unmask GPIO bank interrupt immediately */
785 if (!level_mask) 834 if (!level_mask && !unmasked) {
835 unmasked = 1;
786 desc->chip->unmask(irq); 836 desc->chip->unmask(irq);
837 }
787 838
839 isr |= retrigger;
840 retrigger = 0;
788 if (!isr) 841 if (!isr)
789 break; 842 break;
790 843
791 gpio_irq = bank->virtual_irq_start; 844 gpio_irq = bank->virtual_irq_start;
792 for (; isr != 0; isr >>= 1, gpio_irq++) { 845 for (; isr != 0; isr >>= 1, gpio_irq++) {
793 struct irqdesc *d; 846 struct irqdesc *d;
847 int irq_mask;
794 if (!(isr & 1)) 848 if (!(isr & 1))
795 continue; 849 continue;
796 d = irq_desc + gpio_irq; 850 d = irq_desc + gpio_irq;
851 /* Don't run the handler if it's already running
852 * or was disabled lazely.
853 */
854 if (unlikely((d->disable_depth || d->running))) {
855 irq_mask = 1 <<
856 (gpio_irq - bank->virtual_irq_start);
857 /* The unmasking will be done by
858 * enable_irq in case it is disabled or
859 * after returning from the handler if
860 * it's already running.
861 */
862 _enable_gpio_irqbank(bank, irq_mask, 0);
863 if (!d->disable_depth) {
864 /* Level triggered interrupts
865 * won't ever be reentered
866 */
867 BUG_ON(level_mask & irq_mask);
868 d->pending = 1;
869 }
870 continue;
871 }
872 d->running = 1;
797 desc_handle_irq(gpio_irq, d, regs); 873 desc_handle_irq(gpio_irq, d, regs);
874 d->running = 0;
875 if (unlikely(d->pending && !d->disable_depth)) {
876 irq_mask = 1 <<
877 (gpio_irq - bank->virtual_irq_start);
878 d->pending = 0;
879 _enable_gpio_irqbank(bank, irq_mask, 1);
880 retrigger |= irq_mask;
881 }
798 } 882 }
799 883
800 if (cpu_is_omap24xx()) { 884 if (cpu_is_omap24xx()) {
@@ -804,13 +888,14 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
804 _enable_gpio_irqbank(bank, isr_saved & level_mask, 1); 888 _enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
805 } 889 }
806 890
807 /* if bank has any level sensitive GPIO pin interrupt
808 configured, we must unmask the bank interrupt only after
809 handler(s) are executed in order to avoid spurious bank
810 interrupt */
811 if (level_mask)
812 desc->chip->unmask(irq);
813 } 891 }
892 /* if bank has any level sensitive GPIO pin interrupt
893 configured, we must unmask the bank interrupt only after
894 handler(s) are executed in order to avoid spurious bank
895 interrupt */
896 if (!unmasked)
897 desc->chip->unmask(irq);
898
814} 899}
815 900
816static void gpio_ack_irq(unsigned int irq) 901static void gpio_ack_irq(unsigned int irq)
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index b7bf09b1b412..aebd06faf2cf 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -158,14 +158,12 @@ static struct map_desc omap_sram_io_desc[] __initdata = {
158 { /* .length gets filled in at runtime */ 158 { /* .length gets filled in at runtime */
159 .virtual = OMAP1_SRAM_VA, 159 .virtual = OMAP1_SRAM_VA,
160 .pfn = __phys_to_pfn(OMAP1_SRAM_PA), 160 .pfn = __phys_to_pfn(OMAP1_SRAM_PA),
161 .type = MT_DEVICE 161 .type = MT_MEMORY
162 } 162 }
163}; 163};
164 164
165/* 165/*
166 * In order to use last 2kB of SRAM on 1611b, we must round the size 166 * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
167 * up to multiple of PAGE_SIZE. We cannot use ioremap for SRAM, as
168 * clock init needs SRAM early.
169 */ 167 */
170void __init omap_map_sram(void) 168void __init omap_map_sram(void)
171{ 169{
@@ -185,8 +183,7 @@ void __init omap_map_sram(void)
185 omap_sram_io_desc[0].pfn = __phys_to_pfn(base); 183 omap_sram_io_desc[0].pfn = __phys_to_pfn(base);
186 } 184 }
187 185
188 omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; 186 omap_sram_io_desc[0].length = 1024 * 1024; /* Use section desc */
189 omap_sram_io_desc[0].length *= PAGE_SIZE;
190 iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); 187 iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc));
191 188
192 printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", 189 printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n",
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
index 3461a6c9665c..f028e182215a 100644
--- a/arch/arm/plat-omap/timer32k.c
+++ b/arch/arm/plat-omap/timer32k.c
@@ -7,6 +7,7 @@
7 * Partial timer rewrite and additional dynamic tick timer support by 7 * Partial timer rewrite and additional dynamic tick timer support by
8 * Tony Lindgen <tony@atomide.com> and 8 * Tony Lindgen <tony@atomide.com> and
9 * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> 9 * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
10 * OMAP Dual-mode timer framework support by Timo Teras
10 * 11 *
11 * MPU timer code based on the older MPU timer code for OMAP 12 * MPU timer code based on the older MPU timer code for OMAP
12 * Copyright (C) 2000 RidgeRun, Inc. 13 * Copyright (C) 2000 RidgeRun, Inc.
@@ -79,18 +80,6 @@ struct sys_timer omap_timer;
79#define OMAP1_32K_TIMER_TVR 0x00 80#define OMAP1_32K_TIMER_TVR 0x00
80#define OMAP1_32K_TIMER_TCR 0x04 81#define OMAP1_32K_TIMER_TCR 0x04
81 82
82/* 24xx specific defines */
83#define OMAP2_GP_TIMER_BASE 0x48028000
84#define CM_CLKSEL_WKUP 0x48008440
85#define GP_TIMER_TIDR 0x00
86#define GP_TIMER_TISR 0x18
87#define GP_TIMER_TIER 0x1c
88#define GP_TIMER_TCLR 0x24
89#define GP_TIMER_TCRR 0x28
90#define GP_TIMER_TLDR 0x2c
91#define GP_TIMER_TTGR 0x30
92#define GP_TIMER_TSICR 0x40
93
94#define OMAP_32K_TICKS_PER_HZ (32768 / HZ) 83#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
95 84
96/* 85/*
@@ -102,54 +91,64 @@ struct sys_timer omap_timer;
102#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ 91#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
103 (((nr_jiffies) * (clock_rate)) / HZ) 92 (((nr_jiffies) * (clock_rate)) / HZ)
104 93
94#if defined(CONFIG_ARCH_OMAP1)
95
105static inline void omap_32k_timer_write(int val, int reg) 96static inline void omap_32k_timer_write(int val, int reg)
106{ 97{
107 if (cpu_class_is_omap1()) 98 omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
108 omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
109
110 if (cpu_is_omap24xx())
111 omap_writel(val, OMAP2_GP_TIMER_BASE + reg);
112} 99}
113 100
114static inline unsigned long omap_32k_timer_read(int reg) 101static inline unsigned long omap_32k_timer_read(int reg)
115{ 102{
116 if (cpu_class_is_omap1()) 103 return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
117 return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff; 104}
118 105
119 if (cpu_is_omap24xx()) 106static inline void omap_32k_timer_start(unsigned long load_val)
120 return omap_readl(OMAP2_GP_TIMER_BASE + reg); 107{
108 omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
109 omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
121} 110}
122 111
123/* 112static inline void omap_32k_timer_stop(void)
124 * The 32KHz synchronized timer is an additional timer on 16xx.
125 * It is always running.
126 */
127static inline unsigned long omap_32k_sync_timer_read(void)
128{ 113{
129 return omap_readl(TIMER_32K_SYNCHRONIZED); 114 omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
130} 115}
131 116
117#define omap_32k_timer_ack_irq()
118
119#elif defined(CONFIG_ARCH_OMAP2)
120
121#include <asm/arch/dmtimer.h>
122
123static struct omap_dm_timer *gptimer;
124
132static inline void omap_32k_timer_start(unsigned long load_val) 125static inline void omap_32k_timer_start(unsigned long load_val)
133{ 126{
134 if (cpu_class_is_omap1()) { 127 omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val);
135 omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR); 128 omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
136 omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR); 129 omap_dm_timer_start(gptimer);
137 }
138
139 if (cpu_is_omap24xx()) {
140 omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR);
141 omap_32k_timer_write((1 << 1), GP_TIMER_TIER);
142 omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR);
143 }
144} 130}
145 131
146static inline void omap_32k_timer_stop(void) 132static inline void omap_32k_timer_stop(void)
147{ 133{
148 if (cpu_class_is_omap1()) 134 omap_dm_timer_stop(gptimer);
149 omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR); 135}
150 136
151 if (cpu_is_omap24xx()) 137static inline void omap_32k_timer_ack_irq(void)
152 omap_32k_timer_write(0x0, GP_TIMER_TCLR); 138{
139 u32 status = omap_dm_timer_read_status(gptimer);
140 omap_dm_timer_write_status(gptimer, status);
141}
142
143#endif
144
145/*
146 * The 32KHz synchronized timer is an additional timer on 16xx.
147 * It is always running.
148 */
149static inline unsigned long omap_32k_sync_timer_read(void)
150{
151 return omap_readl(TIMER_32K_SYNCHRONIZED);
153} 152}
154 153
155/* 154/*
@@ -203,11 +202,7 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
203 202
204 write_seqlock_irqsave(&xtime_lock, flags); 203 write_seqlock_irqsave(&xtime_lock, flags);
205 204
206 if (cpu_is_omap24xx()) { 205 omap_32k_timer_ack_irq();
207 u32 status = omap_32k_timer_read(GP_TIMER_TISR);
208 omap_32k_timer_write(status, GP_TIMER_TISR);
209 }
210
211 now = omap_32k_sync_timer_read(); 206 now = omap_32k_sync_timer_read();
212 207
213 while ((signed long)(now - omap_32k_last_tick) 208 while ((signed long)(now - omap_32k_last_tick)
@@ -269,9 +264,6 @@ static struct irqaction omap_32k_timer_irq = {
269 .handler = omap_32k_timer_interrupt, 264 .handler = omap_32k_timer_interrupt,
270}; 265};
271 266
272static struct clk * gpt1_ick;
273static struct clk * gpt1_fck;
274
275static __init void omap_init_32k_timer(void) 267static __init void omap_init_32k_timer(void)
276{ 268{
277#ifdef CONFIG_NO_IDLE_HZ 269#ifdef CONFIG_NO_IDLE_HZ
@@ -280,31 +272,19 @@ static __init void omap_init_32k_timer(void)
280 272
281 if (cpu_class_is_omap1()) 273 if (cpu_class_is_omap1())
282 setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); 274 setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
283 if (cpu_is_omap24xx())
284 setup_irq(37, &omap_32k_timer_irq);
285 omap_timer.offset = omap_32k_timer_gettimeoffset; 275 omap_timer.offset = omap_32k_timer_gettimeoffset;
286 omap_32k_last_tick = omap_32k_sync_timer_read(); 276 omap_32k_last_tick = omap_32k_sync_timer_read();
287 277
288 /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */ 278 /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */
289 if (cpu_is_omap24xx()) { 279 if (cpu_is_omap24xx()) {
290 omap_32k_timer_write(0, GP_TIMER_TCLR); 280 gptimer = omap_dm_timer_request_specific(1);
291 omap_writel(0, CM_CLKSEL_WKUP); /* 32KHz clock source */ 281 BUG_ON(gptimer == NULL);
292 282
293 gpt1_ick = clk_get(NULL, "gpt1_ick"); 283 omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ);
294 if (IS_ERR(gpt1_ick)) 284 setup_irq(omap_dm_timer_get_irq(gptimer), &omap_32k_timer_irq);
295 printk(KERN_ERR "Could not get gpt1_ick\n"); 285 omap_dm_timer_set_int_enable(gptimer,
296 else 286 OMAP_TIMER_INT_CAPTURE | OMAP_TIMER_INT_OVERFLOW |
297 clk_enable(gpt1_ick); 287 OMAP_TIMER_INT_MATCH);
298
299 gpt1_fck = clk_get(NULL, "gpt1_fck");
300 if (IS_ERR(gpt1_fck))
301 printk(KERN_ERR "Could not get gpt1_fck\n");
302 else
303 clk_enable(gpt1_fck);
304
305 mdelay(100); /* Wait for clocks to stabilize */
306
307 omap_32k_timer_write(0x7, GP_TIMER_TISR);
308 } 288 }
309 289
310 omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); 290 omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
@@ -317,6 +297,9 @@ static __init void omap_init_32k_timer(void)
317 */ 297 */
318static void __init omap_timer_init(void) 298static void __init omap_timer_init(void)
319{ 299{
300#ifdef CONFIG_OMAP_DM_TIMER
301 omap_dm_timer_init();
302#endif
320 omap_init_32k_timer(); 303 omap_init_32k_timer();
321} 304}
322 305