aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-pxa')
-rw-r--r--arch/arm/mach-pxa/Kconfig4
-rw-r--r--arch/arm/mach-pxa/Makefile1
-rw-r--r--arch/arm/mach-pxa/devices.h22
-rw-r--r--arch/arm/mach-pxa/em-x270.c354
-rw-r--r--arch/arm/mach-pxa/generic.c32
-rw-r--r--arch/arm/mach-pxa/pm.c169
-rw-r--r--arch/arm/mach-pxa/pxa25x.c109
-rw-r--r--arch/arm/mach-pxa/pxa27x.c151
-rw-r--r--arch/arm/mach-pxa/sleep.S112
-rw-r--r--arch/arm/mach-pxa/time.c258
10 files changed, 848 insertions, 364 deletions
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 5c0a10041cd1..5ebec6d88b51 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -37,6 +37,10 @@ config MACH_TRIZEPS4
37 bool "Keith und Koep Trizeps4 DIMM-Module" 37 bool "Keith und Koep Trizeps4 DIMM-Module"
38 select PXA27x 38 select PXA27x
39 39
40config MACH_EM_X270
41 bool "CompuLab EM-x270 platform"
42 select PXA27x
43
40endchoice 44endchoice
41 45
42if PXA_SHARPSL 46if PXA_SHARPSL
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 9093eb1c94eb..7d6ab5c59ab9 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o sp
18obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o 18obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o
19obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o 19obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o
20obj-$(CONFIG_MACH_TOSA) += tosa.o 20obj-$(CONFIG_MACH_TOSA) += tosa.o
21obj-$(CONFIG_MACH_EM_X270) += em-x270.o
21 22
22# Support for blinky lights 23# Support for blinky lights
23led-y := leds.o 24led-y := leds.o
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 9a6faff8e5a7..636fdb1c049c 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -1,11 +1,11 @@
1extern struct platform_device pxamci_device; 1extern struct platform_device pxa_device_mci;
2extern struct platform_device pxaudc_device; 2extern struct platform_device pxa_device_udc;
3extern struct platform_device pxafb_device; 3extern struct platform_device pxa_device_fb;
4extern struct platform_device ffuart_device; 4extern struct platform_device pxa_device_ffuart;
5extern struct platform_device btuart_device; 5extern struct platform_device pxa_device_btuart;
6extern struct platform_device stuart_device; 6extern struct platform_device pxa_device_stuart;
7extern struct platform_device hwuart_device; 7extern struct platform_device pxa_device_hwuart;
8extern struct platform_device pxai2c_device; 8extern struct platform_device pxa_device_i2c;
9extern struct platform_device pxai2s_device; 9extern struct platform_device pxa_device_i2s;
10extern struct platform_device pxaficp_device; 10extern struct platform_device pxa_device_ficp;
11extern struct platform_device pxartc_device; 11extern struct platform_device pxa_device_rtc;
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
new file mode 100644
index 000000000000..3d0ad5065ee5
--- /dev/null
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -0,0 +1,354 @@
1/*
2 * Support for CompuLab EM-x270 platform
3 *
4 * Copyright (C) 2007 CompuLab, Ltd.
5 * Author: Mike Rapoport <mike@compulab.co.il>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/irq.h>
13#include <linux/platform_device.h>
14
15#include <linux/dm9000.h>
16#include <linux/rtc-v3020.h>
17
18#include <linux/mtd/nand.h>
19#include <linux/mtd/partitions.h>
20
21#include <asm/mach-types.h>
22
23#include <asm/mach/arch.h>
24
25#include <asm/arch/pxa-regs.h>
26#include <asm/arch/pxafb.h>
27#include <asm/arch/ohci.h>
28#include <asm/arch/mmc.h>
29#include <asm/arch/bitfield.h>
30
31#include "generic.h"
32
33/* GPIO IRQ usage */
34#define EM_X270_MMC_PD (105)
35#define EM_X270_ETHIRQ IRQ_GPIO(41)
36#define EM_X270_MMC_IRQ IRQ_GPIO(13)
37
38static struct resource em_x270_dm9k_resource[] = {
39 [0] = {
40 .start = PXA_CS2_PHYS,
41 .end = PXA_CS2_PHYS + 3,
42 .flags = IORESOURCE_MEM,
43 },
44 [1] = {
45 .start = PXA_CS2_PHYS + 8,
46 .end = PXA_CS2_PHYS + 8 + 0x3f,
47 .flags = IORESOURCE_MEM,
48 },
49 [2] = {
50 .start = EM_X270_ETHIRQ,
51 .end = EM_X270_ETHIRQ,
52 .flags = IORESOURCE_IRQ,
53 }
54};
55
56/* for the moment we limit ourselves to 32bit IO until some
57 * better IO routines can be written and tested
58 */
59static struct dm9000_plat_data em_x270_dm9k_platdata = {
60 .flags = DM9000_PLATF_32BITONLY,
61};
62
63/* Ethernet device */
64static struct platform_device em_x270_dm9k = {
65 .name = "dm9000",
66 .id = 0,
67 .num_resources = ARRAY_SIZE(em_x270_dm9k_resource),
68 .resource = em_x270_dm9k_resource,
69 .dev = {
70 .platform_data = &em_x270_dm9k_platdata,
71 }
72};
73
74/* audio device */
75static struct platform_device em_x270_audio = {
76 .name = "pxa2xx-ac97",
77 .id = -1,
78};
79
80/* WM9712 touchscreen controller. Hopefully the driver will make it to
81 * the mainstream sometime */
82static struct platform_device em_x270_ts = {
83 .name = "wm97xx-ts",
84 .id = -1,
85};
86
87/* RTC */
88static struct resource em_x270_v3020_resource[] = {
89 [0] = {
90 .start = PXA_CS4_PHYS,
91 .end = PXA_CS4_PHYS + 3,
92 .flags = IORESOURCE_MEM,
93 },
94};
95
96static struct v3020_platform_data em_x270_v3020_platdata = {
97 .leftshift = 0,
98};
99
100static struct platform_device em_x270_rtc = {
101 .name = "v3020",
102 .num_resources = ARRAY_SIZE(em_x270_v3020_resource),
103 .resource = em_x270_v3020_resource,
104 .id = -1,
105 .dev = {
106 .platform_data = &em_x270_v3020_platdata,
107 }
108};
109
110/* NAND flash */
111#define GPIO_NAND_CS (11)
112#define GPIO_NAND_RB (56)
113
114static inline void nand_cs_on(void)
115{
116 GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
117}
118
119static void nand_cs_off(void)
120{
121 dsb();
122
123 GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
124}
125
126/* hardware specific access to control-lines */
127static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat,
128 unsigned int ctrl)
129{
130 struct nand_chip *this = mtd->priv;
131 unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
132
133 dsb();
134
135 if (ctrl & NAND_CTRL_CHANGE) {
136 if (ctrl & NAND_ALE)
137 nandaddr |= (1 << 3);
138 else
139 nandaddr &= ~(1 << 3);
140 if (ctrl & NAND_CLE)
141 nandaddr |= (1 << 2);
142 else
143 nandaddr &= ~(1 << 2);
144 if (ctrl & NAND_NCE)
145 nand_cs_on();
146 else
147 nand_cs_off();
148 }
149
150 dsb();
151 this->IO_ADDR_W = (void __iomem *)nandaddr;
152 if (dat != NAND_CMD_NONE)
153 writel(dat, this->IO_ADDR_W);
154
155 dsb();
156}
157
158/* read device ready pin */
159static int em_x270_nand_device_ready(struct mtd_info *mtd)
160{
161 dsb();
162
163 return GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB);
164}
165
166static struct mtd_partition em_x270_partition_info[] = {
167 [0] = {
168 .name = "em_x270-0",
169 .offset = 0,
170 .size = SZ_4M,
171 },
172 [1] = {
173 .name = "em_x270-1",
174 .offset = MTDPART_OFS_APPEND,
175 .size = MTDPART_SIZ_FULL
176 },
177};
178
179static const char *em_x270_part_probes[] = { "cmdlinepart", NULL };
180
181struct platform_nand_data em_x270_nand_platdata = {
182 .chip = {
183 .nr_chips = 1,
184 .chip_offset = 0,
185 .nr_partitions = ARRAY_SIZE(em_x270_partition_info),
186 .partitions = em_x270_partition_info,
187 .chip_delay = 20,
188 .part_probe_types = em_x270_part_probes,
189 },
190 .ctrl = {
191 .hwcontrol = 0,
192 .dev_ready = em_x270_nand_device_ready,
193 .select_chip = 0,
194 .cmd_ctrl = em_x270_nand_cmd_ctl,
195 },
196};
197
198static struct resource em_x270_nand_resource[] = {
199 [0] = {
200 .start = PXA_CS1_PHYS,
201 .end = PXA_CS1_PHYS + 12,
202 .flags = IORESOURCE_MEM,
203 },
204};
205
206static struct platform_device em_x270_nand = {
207 .name = "gen_nand",
208 .num_resources = ARRAY_SIZE(em_x270_nand_resource),
209 .resource = em_x270_nand_resource,
210 .id = -1,
211 .dev = {
212 .platform_data = &em_x270_nand_platdata,
213 }
214};
215
216/* platform devices */
217static struct platform_device *platform_devices[] __initdata = {
218 &em_x270_dm9k,
219 &em_x270_audio,
220 &em_x270_ts,
221 &em_x270_rtc,
222 &em_x270_nand,
223};
224
225
226/* PXA27x OHCI controller setup */
227static int em_x270_ohci_init(struct device *dev)
228{
229 /* Set the Power Control Polarity Low */
230 UHCHR = (UHCHR | UHCHR_PCPL) &
231 ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE);
232
233 /* enable port 2 transiever */
234 UP2OCR = UP2OCR_HXS | UP2OCR_HXOE;
235
236 return 0;
237}
238
239static struct pxaohci_platform_data em_x270_ohci_platform_data = {
240 .port_mode = PMM_PERPORT_MODE,
241 .init = em_x270_ohci_init,
242};
243
244
245static int em_x270_mci_init(struct device *dev,
246 irq_handler_t em_x270_detect_int,
247 void *data)
248{
249 int err;
250
251 /* setup GPIO for PXA27x MMC controller */
252 pxa_gpio_mode(GPIO32_MMCCLK_MD);
253 pxa_gpio_mode(GPIO112_MMCCMD_MD);
254 pxa_gpio_mode(GPIO92_MMCDAT0_MD);
255 pxa_gpio_mode(GPIO109_MMCDAT1_MD);
256 pxa_gpio_mode(GPIO110_MMCDAT2_MD);
257 pxa_gpio_mode(GPIO111_MMCDAT3_MD);
258
259 /* EM-X270 uses GPIO13 as SD power enable */
260 pxa_gpio_mode(EM_X270_MMC_PD | GPIO_OUT);
261
262 err = request_irq(EM_X270_MMC_IRQ, em_x270_detect_int,
263 IRQF_DISABLED | IRQF_TRIGGER_FALLING,
264 "MMC card detect", data);
265 if (err) {
266 printk(KERN_ERR "%s: can't request MMC card detect IRQ: %d\n",
267 __FUNCTION__, err);
268 return err;
269 }
270
271 return 0;
272}
273
274static void em_x270_mci_setpower(struct device *dev, unsigned int vdd)
275{
276 /*
277 FIXME: current hardware implementation does not allow to
278 enable/disable MMC power. This will be fixed in next HW releases,
279 and we'll need to add implmentation here.
280 */
281 return;
282}
283
284static void em_x270_mci_exit(struct device *dev, void *data)
285{
286 free_irq(EM_X270_MMC_IRQ, data);
287}
288
289static struct pxamci_platform_data em_x270_mci_platform_data = {
290 .ocr_mask = MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31,
291 .init = em_x270_mci_init,
292 .setpower = em_x270_mci_setpower,
293 .exit = em_x270_mci_exit,
294};
295
296/* LCD 480x640 */
297static struct pxafb_mode_info em_x270_lcd_mode = {
298 .pixclock = 50000,
299 .bpp = 16,
300 .xres = 480,
301 .yres = 640,
302 .hsync_len = 8,
303 .vsync_len = 2,
304 .left_margin = 8,
305 .upper_margin = 0,
306 .right_margin = 24,
307 .lower_margin = 4,
308 .cmap_greyscale = 0,
309};
310
311static struct pxafb_mach_info em_x270_lcd = {
312 .modes = &em_x270_lcd_mode,
313 .num_modes = 1,
314 .cmap_inverse = 0,
315 .cmap_static = 0,
316 .lccr0 = LCCR0_PAS,
317 .lccr3 = LCCR3_PixClkDiv(0x01) | LCCR3_Acb(0xff),
318};
319
320static void __init em_x270_init(void)
321{
322 /* setup LCD */
323 set_pxa_fb_info(&em_x270_lcd);
324
325 /* register EM-X270 platform devices */
326 platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
327
328 /* set MCI and OHCI platform parameters */
329 pxa_set_mci_info(&em_x270_mci_platform_data);
330 pxa_set_ohci_info(&em_x270_ohci_platform_data);
331
332 /* setup STUART GPIOs */
333 pxa_gpio_mode(GPIO46_STRXD_MD);
334 pxa_gpio_mode(GPIO47_STTXD_MD);
335
336 /* setup BTUART GPIOs */
337 pxa_gpio_mode(GPIO42_BTRXD_MD);
338 pxa_gpio_mode(GPIO43_BTTXD_MD);
339 pxa_gpio_mode(GPIO44_BTCTS_MD);
340 pxa_gpio_mode(GPIO45_BTRTS_MD);
341
342 /* Setup interrupt for dm9000 */
343 set_irq_type(EM_X270_ETHIRQ, IRQT_RISING);
344}
345
346MACHINE_START(EM_X270, "Compulab EM-x270")
347 .boot_params = 0xa0000100,
348 .phys_io = 0x40000000,
349 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
350 .map_io = pxa_map_io,
351 .init_irq = pxa27x_init_irq,
352 .timer = &pxa_timer,
353 .init_machine = em_x270_init,
354MACHINE_END
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 296539b6359c..5510f6fdce55 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -243,7 +243,7 @@ static struct resource pxamci_resources[] = {
243 243
244static u64 pxamci_dmamask = 0xffffffffUL; 244static u64 pxamci_dmamask = 0xffffffffUL;
245 245
246struct platform_device pxamci_device = { 246struct platform_device pxa_device_mci = {
247 .name = "pxa2xx-mci", 247 .name = "pxa2xx-mci",
248 .id = -1, 248 .id = -1,
249 .dev = { 249 .dev = {
@@ -256,7 +256,7 @@ struct platform_device pxamci_device = {
256 256
257void __init pxa_set_mci_info(struct pxamci_platform_data *info) 257void __init pxa_set_mci_info(struct pxamci_platform_data *info)
258{ 258{
259 pxamci_device.dev.platform_data = info; 259 pxa_device_mci.dev.platform_data = info;
260} 260}
261 261
262 262
@@ -282,7 +282,7 @@ static struct resource pxa2xx_udc_resources[] = {
282 282
283static u64 udc_dma_mask = ~(u32)0; 283static u64 udc_dma_mask = ~(u32)0;
284 284
285struct platform_device pxaudc_device = { 285struct platform_device pxa_device_udc = {
286 .name = "pxa2xx-udc", 286 .name = "pxa2xx-udc",
287 .id = -1, 287 .id = -1,
288 .resource = pxa2xx_udc_resources, 288 .resource = pxa2xx_udc_resources,
@@ -308,7 +308,7 @@ static struct resource pxafb_resources[] = {
308 308
309static u64 fb_dma_mask = ~(u64)0; 309static u64 fb_dma_mask = ~(u64)0;
310 310
311struct platform_device pxafb_device = { 311struct platform_device pxa_device_fb = {
312 .name = "pxa2xx-fb", 312 .name = "pxa2xx-fb",
313 .id = -1, 313 .id = -1,
314 .dev = { 314 .dev = {
@@ -321,27 +321,27 @@ struct platform_device pxafb_device = {
321 321
322void __init set_pxa_fb_info(struct pxafb_mach_info *info) 322void __init set_pxa_fb_info(struct pxafb_mach_info *info)
323{ 323{
324 pxafb_device.dev.platform_data = info; 324 pxa_device_fb.dev.platform_data = info;
325} 325}
326 326
327void __init set_pxa_fb_parent(struct device *parent_dev) 327void __init set_pxa_fb_parent(struct device *parent_dev)
328{ 328{
329 pxafb_device.dev.parent = parent_dev; 329 pxa_device_fb.dev.parent = parent_dev;
330} 330}
331 331
332struct platform_device ffuart_device = { 332struct platform_device pxa_device_ffuart= {
333 .name = "pxa2xx-uart", 333 .name = "pxa2xx-uart",
334 .id = 0, 334 .id = 0,
335}; 335};
336struct platform_device btuart_device = { 336struct platform_device pxa_device_btuart = {
337 .name = "pxa2xx-uart", 337 .name = "pxa2xx-uart",
338 .id = 1, 338 .id = 1,
339}; 339};
340struct platform_device stuart_device = { 340struct platform_device pxa_device_stuart = {
341 .name = "pxa2xx-uart", 341 .name = "pxa2xx-uart",
342 .id = 2, 342 .id = 2,
343}; 343};
344struct platform_device hwuart_device = { 344struct platform_device pxa_device_hwuart = {
345 .name = "pxa2xx-uart", 345 .name = "pxa2xx-uart",
346 .id = 3, 346 .id = 3,
347}; 347};
@@ -358,7 +358,7 @@ static struct resource pxai2c_resources[] = {
358 }, 358 },
359}; 359};
360 360
361struct platform_device pxai2c_device = { 361struct platform_device pxa_device_i2c = {
362 .name = "pxa2xx-i2c", 362 .name = "pxa2xx-i2c",
363 .id = 0, 363 .id = 0,
364 .resource = pxai2c_resources, 364 .resource = pxai2c_resources,
@@ -367,7 +367,7 @@ struct platform_device pxai2c_device = {
367 367
368void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info) 368void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
369{ 369{
370 pxai2c_device.dev.platform_data = info; 370 pxa_device_i2c.dev.platform_data = info;
371} 371}
372 372
373static struct resource pxai2s_resources[] = { 373static struct resource pxai2s_resources[] = {
@@ -382,7 +382,7 @@ static struct resource pxai2s_resources[] = {
382 }, 382 },
383}; 383};
384 384
385struct platform_device pxai2s_device = { 385struct platform_device pxa_device_i2s = {
386 .name = "pxa2xx-i2s", 386 .name = "pxa2xx-i2s",
387 .id = -1, 387 .id = -1,
388 .resource = pxai2s_resources, 388 .resource = pxai2s_resources,
@@ -391,7 +391,7 @@ struct platform_device pxai2s_device = {
391 391
392static u64 pxaficp_dmamask = ~(u32)0; 392static u64 pxaficp_dmamask = ~(u32)0;
393 393
394struct platform_device pxaficp_device = { 394struct platform_device pxa_device_ficp = {
395 .name = "pxa2xx-ir", 395 .name = "pxa2xx-ir",
396 .id = -1, 396 .id = -1,
397 .dev = { 397 .dev = {
@@ -402,10 +402,10 @@ struct platform_device pxaficp_device = {
402 402
403void __init pxa_set_ficp_info(struct pxaficp_platform_data *info) 403void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
404{ 404{
405 pxaficp_device.dev.platform_data = info; 405 pxa_device_ficp.dev.platform_data = info;
406} 406}
407 407
408struct platform_device pxartc_device = { 408struct platform_device pxa_device_rtc = {
409 .name = "sa1100-rtc", 409 .name = "sa1100-rtc",
410 .id = -1, 410 .id = -1,
411}; 411};
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index e66dbc26add1..b59a81a8e7d3 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -24,61 +24,13 @@
24#include <asm/arch/lubbock.h> 24#include <asm/arch/lubbock.h>
25#include <asm/mach/time.h> 25#include <asm/mach/time.h>
26 26
27 27struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
28/* 28static unsigned long *sleep_save;
29 * Debug macros
30 */
31#undef DEBUG
32
33#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
34#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
35
36#define RESTORE_GPLEVEL(n) do { \
37 GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
38 GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
39} while (0)
40
41/*
42 * List of global PXA peripheral registers to preserve.
43 * More ones like CP and general purpose register values are preserved
44 * with the stack pointer in sleep.S.
45 */
46enum { SLEEP_SAVE_START = 0,
47
48 SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
49 SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
50 SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
51 SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
52 SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
53
54 SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
55 SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
56 SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
57 SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U,
58
59 SLEEP_SAVE_PSTR,
60
61 SLEEP_SAVE_ICMR,
62 SLEEP_SAVE_CKEN,
63
64#ifdef CONFIG_PXA27x
65 SLEEP_SAVE_MDREFR,
66 SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
67 SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
68#endif
69
70 SLEEP_SAVE_CKSUM,
71
72 SLEEP_SAVE_SIZE
73};
74
75 29
76int pxa_pm_enter(suspend_state_t state) 30int pxa_pm_enter(suspend_state_t state)
77{ 31{
78 unsigned long sleep_save[SLEEP_SAVE_SIZE]; 32 unsigned long sleep_save_checksum = 0, checksum = 0;
79 unsigned long checksum = 0;
80 int i; 33 int i;
81 extern void pxa_cpu_pm_enter(suspend_state_t state);
82 34
83#ifdef CONFIG_IWMMXT 35#ifdef CONFIG_IWMMXT
84 /* force any iWMMXt context to ram **/ 36 /* force any iWMMXt context to ram **/
@@ -86,100 +38,35 @@ int pxa_pm_enter(suspend_state_t state)
86 iwmmxt_task_disable(NULL); 38 iwmmxt_task_disable(NULL);
87#endif 39#endif
88 40
89 SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); 41 pxa_cpu_pm_fns->save(sleep_save);
90 SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
91 SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
92 SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
93 SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
94
95 SAVE(GAFR0_L); SAVE(GAFR0_U);
96 SAVE(GAFR1_L); SAVE(GAFR1_U);
97 SAVE(GAFR2_L); SAVE(GAFR2_U);
98
99#ifdef CONFIG_PXA27x
100 SAVE(MDREFR);
101 SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
102 SAVE(GAFR3_L); SAVE(GAFR3_U);
103 SAVE(PWER); SAVE(PCFR); SAVE(PRER);
104 SAVE(PFER); SAVE(PKWR);
105#endif
106
107 SAVE(ICMR);
108 ICMR = 0;
109
110 SAVE(CKEN);
111 SAVE(PSTR);
112
113 /* Note: wake up source are set up in each machine specific files */
114
115 /* clear GPIO transition detect bits */
116 GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2;
117#ifdef CONFIG_PXA27x
118 GEDR3 = GEDR3;
119#endif
120 42
121 /* Clear sleep reset status */ 43 /* Clear sleep reset status */
122 RCSR = RCSR_SMR; 44 RCSR = RCSR_SMR;
123 45
124 /* before sleeping, calculate and save a checksum */ 46 /* before sleeping, calculate and save a checksum */
125 for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++) 47 for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++)
126 checksum += sleep_save[i]; 48 sleep_save_checksum += sleep_save[i];
127 sleep_save[SLEEP_SAVE_CKSUM] = checksum;
128 49
129 /* *** go zzz *** */ 50 /* *** go zzz *** */
130 pxa_cpu_pm_enter(state); 51 pxa_cpu_pm_fns->enter(state);
131
132 cpu_init(); 52 cpu_init();
133 53
134 /* after sleeping, validate the checksum */ 54 /* after sleeping, validate the checksum */
135 checksum = 0; 55 for (i = 0; i < pxa_cpu_pm_fns->save_size - 1; i++)
136 for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
137 checksum += sleep_save[i]; 56 checksum += sleep_save[i];
138 57
139 /* if invalid, display message and wait for a hardware reset */ 58 /* if invalid, display message and wait for a hardware reset */
140 if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) { 59 if (checksum != sleep_save_checksum) {
141#ifdef CONFIG_ARCH_LUBBOCK 60#ifdef CONFIG_ARCH_LUBBOCK
142 LUB_HEXLED = 0xbadbadc5; 61 LUB_HEXLED = 0xbadbadc5;
143#endif 62#endif
144 while (1) 63 while (1)
145 pxa_cpu_pm_enter(state); 64 pxa_cpu_pm_fns->enter(state);
146 } 65 }
147 66
148 /* ensure not to come back here if it wasn't intended */ 67 pxa_cpu_pm_fns->restore(sleep_save);
149 PSPR = 0;
150
151 /* restore registers */
152 RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
153 RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
154 RESTORE(GAFR0_L); RESTORE(GAFR0_U);
155 RESTORE(GAFR1_L); RESTORE(GAFR1_U);
156 RESTORE(GAFR2_L); RESTORE(GAFR2_U);
157 RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
158 RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
159 RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
160
161#ifdef CONFIG_PXA27x
162 RESTORE(MDREFR);
163 RESTORE_GPLEVEL(3); RESTORE(GPDR3);
164 RESTORE(GAFR3_L); RESTORE(GAFR3_U);
165 RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
166 RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
167 RESTORE(PFER); RESTORE(PKWR);
168#endif
169
170 PSSR = PSSR_RDH | PSSR_PH;
171
172 RESTORE(CKEN);
173
174 ICLR = 0;
175 ICCR = 1;
176 RESTORE(ICMR);
177 68
178 RESTORE(PSTR); 69 pr_debug("*** made it back from resume\n");
179
180#ifdef DEBUG
181 printk(KERN_DEBUG "*** made it back from resume\n");
182#endif
183 70
184 return 0; 71 return 0;
185} 72}
@@ -190,3 +77,35 @@ unsigned long sleep_phys_sp(void *sp)
190{ 77{
191 return virt_to_phys(sp); 78 return virt_to_phys(sp);
192} 79}
80
81static int pxa_pm_valid(suspend_state_t state)
82{
83 if (pxa_cpu_pm_fns)
84 return pxa_cpu_pm_fns->valid(state);
85
86 return -EINVAL;
87}
88
89static struct pm_ops pxa_pm_ops = {
90 .valid = pxa_pm_valid,
91 .enter = pxa_pm_enter,
92};
93
94static int __init pxa_pm_init(void)
95{
96 if (!pxa_cpu_pm_fns) {
97 printk(KERN_ERR "no valid pxa_cpu_pm_fns defined\n");
98 return -EINVAL;
99 }
100
101 sleep_save = kmalloc(pxa_cpu_pm_fns->save_size, GFP_KERNEL);
102 if (!sleep_save) {
103 printk(KERN_ERR "failed to alloc memory for pm save\n");
104 return -ENOMEM;
105 }
106
107 pm_set_ops(&pxa_pm_ops);
108 return 0;
109}
110
111device_initcall(pxa_pm_init);
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index f36ca448338e..6dfcca72e90f 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -110,26 +110,99 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
110 110
111#ifdef CONFIG_PM 111#ifdef CONFIG_PM
112 112
113void pxa_cpu_pm_enter(suspend_state_t state) 113#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
114#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
115
116#define RESTORE_GPLEVEL(n) do { \
117 GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
118 GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
119} while (0)
120
121/*
122 * List of global PXA peripheral registers to preserve.
123 * More ones like CP and general purpose register values are preserved
124 * with the stack pointer in sleep.S.
125 */
126enum { SLEEP_SAVE_START = 0,
127
128 SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
129 SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
130 SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
131 SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
132 SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
133
134 SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
135 SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
136 SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
137
138 SLEEP_SAVE_PSTR,
139
140 SLEEP_SAVE_ICMR,
141 SLEEP_SAVE_CKEN,
142
143 SLEEP_SAVE_SIZE
144};
145
146
147static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
148{
149 SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
150 SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
151 SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
152 SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
153 SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
154
155 SAVE(GAFR0_L); SAVE(GAFR0_U);
156 SAVE(GAFR1_L); SAVE(GAFR1_U);
157 SAVE(GAFR2_L); SAVE(GAFR2_U);
158
159 SAVE(ICMR);
160 SAVE(CKEN);
161 SAVE(PSTR);
162}
163
164static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
114{ 165{
115 extern void pxa_cpu_suspend(unsigned int); 166 /* restore registers */
116 extern void pxa_cpu_resume(void); 167 RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
168 RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
169 RESTORE(GAFR0_L); RESTORE(GAFR0_U);
170 RESTORE(GAFR1_L); RESTORE(GAFR1_U);
171 RESTORE(GAFR2_L); RESTORE(GAFR2_U);
172 RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
173 RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
174 RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
175
176 RESTORE(CKEN);
177 RESTORE(ICMR);
178 RESTORE(PSTR);
179}
117 180
181static void pxa25x_cpu_pm_enter(suspend_state_t state)
182{
118 CKEN = 0; 183 CKEN = 0;
119 184
120 switch (state) { 185 switch (state) {
121 case PM_SUSPEND_MEM: 186 case PM_SUSPEND_MEM:
122 /* set resume return address */ 187 /* set resume return address */
123 PSPR = virt_to_phys(pxa_cpu_resume); 188 PSPR = virt_to_phys(pxa_cpu_resume);
124 pxa_cpu_suspend(PWRMODE_SLEEP); 189 pxa25x_cpu_suspend(PWRMODE_SLEEP);
125 break; 190 break;
126 } 191 }
127} 192}
128 193
129static struct pm_ops pxa25x_pm_ops = { 194static struct pxa_cpu_pm_fns pxa25x_cpu_pm_fns = {
130 .enter = pxa_pm_enter, 195 .save_size = SLEEP_SAVE_SIZE,
131 .valid = pm_valid_only_mem, 196 .valid = pm_valid_only_mem,
197 .save = pxa25x_cpu_pm_save,
198 .restore = pxa25x_cpu_pm_restore,
199 .enter = pxa25x_cpu_pm_enter,
132}; 200};
201
202static void __init pxa25x_init_pm(void)
203{
204 pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns;
205}
133#endif 206#endif
134 207
135void __init pxa25x_init_irq(void) 208void __init pxa25x_init_irq(void)
@@ -139,16 +212,16 @@ void __init pxa25x_init_irq(void)
139} 212}
140 213
141static struct platform_device *pxa25x_devices[] __initdata = { 214static struct platform_device *pxa25x_devices[] __initdata = {
142 &pxamci_device, 215 &pxa_device_mci,
143 &pxaudc_device, 216 &pxa_device_udc,
144 &pxafb_device, 217 &pxa_device_fb,
145 &ffuart_device, 218 &pxa_device_ffuart,
146 &btuart_device, 219 &pxa_device_btuart,
147 &stuart_device, 220 &pxa_device_stuart,
148 &pxai2c_device, 221 &pxa_device_i2c,
149 &pxai2s_device, 222 &pxa_device_i2s,
150 &pxaficp_device, 223 &pxa_device_ficp,
151 &pxartc_device, 224 &pxa_device_rtc,
152}; 225};
153 226
154static int __init pxa25x_init(void) 227static int __init pxa25x_init(void)
@@ -159,14 +232,14 @@ static int __init pxa25x_init(void)
159 if ((ret = pxa_init_dma(16))) 232 if ((ret = pxa_init_dma(16)))
160 return ret; 233 return ret;
161#ifdef CONFIG_PM 234#ifdef CONFIG_PM
162 pm_set_ops(&pxa25x_pm_ops); 235 pxa25x_init_pm();
163#endif 236#endif
164 ret = platform_add_devices(pxa25x_devices, 237 ret = platform_add_devices(pxa25x_devices,
165 ARRAY_SIZE(pxa25x_devices)); 238 ARRAY_SIZE(pxa25x_devices));
166 } 239 }
167 /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */ 240 /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
168 if (cpu_is_pxa25x()) 241 if (cpu_is_pxa25x())
169 ret = platform_device_register(&hwuart_device); 242 ret = platform_device_register(&pxa_device_hwuart);
170 243
171 return ret; 244 return ret;
172} 245}
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index aa5bb02c897b..203371ab19db 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -126,14 +126,107 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
126 126
127#ifdef CONFIG_PM 127#ifdef CONFIG_PM
128 128
129void pxa_cpu_pm_enter(suspend_state_t state) 129#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
130#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
131
132#define RESTORE_GPLEVEL(n) do { \
133 GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
134 GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
135} while (0)
136
137/*
138 * List of global PXA peripheral registers to preserve.
139 * More ones like CP and general purpose register values are preserved
140 * with the stack pointer in sleep.S.
141 */
142enum { SLEEP_SAVE_START = 0,
143
144 SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
145 SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
146 SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
147 SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
148 SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
149
150 SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
151 SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
152 SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
153 SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U,
154
155 SLEEP_SAVE_PSTR,
156
157 SLEEP_SAVE_ICMR,
158 SLEEP_SAVE_CKEN,
159
160 SLEEP_SAVE_MDREFR,
161 SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
162 SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
163
164 SLEEP_SAVE_SIZE
165};
166
167void pxa27x_cpu_pm_save(unsigned long *sleep_save)
168{
169 SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPLR3);
170 SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GPDR3);
171 SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); SAVE(GRER3);
172 SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); SAVE(GFER3);
173 SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3);
174
175 SAVE(GAFR0_L); SAVE(GAFR0_U);
176 SAVE(GAFR1_L); SAVE(GAFR1_U);
177 SAVE(GAFR2_L); SAVE(GAFR2_U);
178 SAVE(GAFR3_L); SAVE(GAFR3_U);
179
180 SAVE(MDREFR);
181 SAVE(PWER); SAVE(PCFR); SAVE(PRER);
182 SAVE(PFER); SAVE(PKWR);
183
184 SAVE(ICMR); ICMR = 0;
185 SAVE(CKEN);
186 SAVE(PSTR);
187
188 /* Clear GPIO transition detect bits */
189 GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; GEDR3 = GEDR3;
190}
191
192void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
193{
194 /* ensure not to come back here if it wasn't intended */
195 PSPR = 0;
196
197 /* restore registers */
198 RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1);
199 RESTORE_GPLEVEL(2); RESTORE_GPLEVEL(3);
200 RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GPDR3);
201 RESTORE(GAFR0_L); RESTORE(GAFR0_U);
202 RESTORE(GAFR1_L); RESTORE(GAFR1_U);
203 RESTORE(GAFR2_L); RESTORE(GAFR2_U);
204 RESTORE(GAFR3_L); RESTORE(GAFR3_U);
205 RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); RESTORE(GRER3);
206 RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); RESTORE(GFER3);
207 RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3);
208
209 RESTORE(MDREFR);
210 RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
211 RESTORE(PFER); RESTORE(PKWR);
212
213 PSSR = PSSR_RDH | PSSR_PH;
214
215 RESTORE(CKEN);
216
217 ICLR = 0;
218 ICCR = 1;
219 RESTORE(ICMR);
220 RESTORE(PSTR);
221}
222
223void pxa27x_cpu_pm_enter(suspend_state_t state)
130{ 224{
131 extern void pxa_cpu_standby(void); 225 extern void pxa_cpu_standby(void);
132 extern void pxa_cpu_suspend(unsigned int);
133 extern void pxa_cpu_resume(void);
134 226
135 if (state == PM_SUSPEND_STANDBY) 227 if (state == PM_SUSPEND_STANDBY)
136 CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) | (1 << CKEN_LCD) | (1 << CKEN_PWM0); 228 CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) |
229 (1 << CKEN_LCD) | (1 << CKEN_PWM0);
137 else 230 else
138 CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER); 231 CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER);
139 232
@@ -150,20 +243,28 @@ void pxa_cpu_pm_enter(suspend_state_t state)
150 case PM_SUSPEND_MEM: 243 case PM_SUSPEND_MEM:
151 /* set resume return address */ 244 /* set resume return address */
152 PSPR = virt_to_phys(pxa_cpu_resume); 245 PSPR = virt_to_phys(pxa_cpu_resume);
153 pxa_cpu_suspend(PWRMODE_SLEEP); 246 pxa27x_cpu_suspend(PWRMODE_SLEEP);
154 break; 247 break;
155 } 248 }
156} 249}
157 250
158static int pxa27x_pm_valid(suspend_state_t state) 251static int pxa27x_cpu_pm_valid(suspend_state_t state)
159{ 252{
160 return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; 253 return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
161} 254}
162 255
163static struct pm_ops pxa27x_pm_ops = { 256static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = {
164 .enter = pxa_pm_enter, 257 .save_size = SLEEP_SAVE_SIZE,
165 .valid = pxa27x_pm_valid, 258 .save = pxa27x_cpu_pm_save,
259 .restore = pxa27x_cpu_pm_restore,
260 .valid = pxa27x_cpu_pm_valid,
261 .enter = pxa27x_cpu_pm_enter,
166}; 262};
263
264static void __init pxa27x_init_pm(void)
265{
266 pxa_cpu_pm_fns = &pxa27x_cpu_pm_fns;
267}
167#endif 268#endif
168 269
169/* 270/*
@@ -185,7 +286,7 @@ static struct resource pxa27x_ohci_resources[] = {
185 }, 286 },
186}; 287};
187 288
188static struct platform_device pxaohci_device = { 289static struct platform_device pxa27x_device_ohci = {
189 .name = "pxa27x-ohci", 290 .name = "pxa27x-ohci",
190 .id = -1, 291 .id = -1,
191 .dev = { 292 .dev = {
@@ -198,7 +299,7 @@ static struct platform_device pxaohci_device = {
198 299
199void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) 300void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
200{ 301{
201 pxaohci_device.dev.platform_data = info; 302 pxa27x_device_ohci.dev.platform_data = info;
202} 303}
203 304
204static struct resource i2c_power_resources[] = { 305static struct resource i2c_power_resources[] = {
@@ -213,7 +314,7 @@ static struct resource i2c_power_resources[] = {
213 }, 314 },
214}; 315};
215 316
216static struct platform_device pxai2c_power_device = { 317static struct platform_device pxa27x_device_i2c_power = {
217 .name = "pxa2xx-i2c", 318 .name = "pxa2xx-i2c",
218 .id = 1, 319 .id = 1,
219 .resource = i2c_power_resources, 320 .resource = i2c_power_resources,
@@ -221,18 +322,18 @@ static struct platform_device pxai2c_power_device = {
221}; 322};
222 323
223static struct platform_device *devices[] __initdata = { 324static struct platform_device *devices[] __initdata = {
224 &pxamci_device, 325 &pxa_device_mci,
225 &pxaudc_device, 326 &pxa_device_udc,
226 &pxafb_device, 327 &pxa_device_fb,
227 &ffuart_device, 328 &pxa_device_ffuart,
228 &btuart_device, 329 &pxa_device_btuart,
229 &stuart_device, 330 &pxa_device_stuart,
230 &pxai2c_device, 331 &pxa_device_i2c,
231 &pxai2c_power_device, 332 &pxa_device_i2s,
232 &pxai2s_device, 333 &pxa_device_ficp,
233 &pxaficp_device, 334 &pxa_device_rtc,
234 &pxartc_device, 335 &pxa27x_device_i2c_power,
235 &pxaohci_device, 336 &pxa27x_device_ohci,
236}; 337};
237 338
238void __init pxa27x_init_irq(void) 339void __init pxa27x_init_irq(void)
@@ -249,7 +350,7 @@ static int __init pxa27x_init(void)
249 if ((ret = pxa_init_dma(32))) 350 if ((ret = pxa_init_dma(32)))
250 return ret; 351 return ret;
251#ifdef CONFIG_PM 352#ifdef CONFIG_PM
252 pm_set_ops(&pxa27x_pm_ops); 353 pxa27x_init_pm();
253#endif 354#endif
254 ret = platform_add_devices(devices, ARRAY_SIZE(devices)); 355 ret = platform_add_devices(devices, ARRAY_SIZE(devices));
255 } 356 }
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 15874b360e51..aff71fec618a 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -17,28 +17,12 @@
17 17
18#include <asm/arch/pxa-regs.h> 18#include <asm/arch/pxa-regs.h>
19 19
20#ifdef CONFIG_PXA27x // workaround for Errata 50
21#define MDREFR_KDIV 0x200a4000 // all banks 20#define MDREFR_KDIV 0x200a4000 // all banks
22#define CCCR_SLEEP 0x00000107 // L=7 2N=2 A=0 PPDIS=0 CPDIS=0 21#define CCCR_SLEEP 0x00000107 // L=7 2N=2 A=0 PPDIS=0 CPDIS=0
23#endif
24 22
25 .text 23 .text
26 24
27/* 25pxa_cpu_save_cp:
28 * pxa_cpu_suspend()
29 *
30 * Forces CPU into sleep state.
31 *
32 * r0 = value for PWRMODE M field for desired sleep state
33 */
34
35ENTRY(pxa_cpu_suspend)
36
37#ifndef CONFIG_IWMMXT
38 mra r2, r3, acc0
39#endif
40 stmfd sp!, {r2 - r12, lr} @ save registers on stack
41
42 @ get coprocessor registers 26 @ get coprocessor registers
43 mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode 27 mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode
44 mrc p15, 0, r4, c15, c1, 0 @ CP access reg 28 mrc p15, 0, r4, c15, c1, 0 @ CP access reg
@@ -54,12 +38,36 @@ ENTRY(pxa_cpu_suspend)
54 mov r10, sp 38 mov r10, sp
55 stmfd sp!, {r3 - r10} 39 stmfd sp!, {r3 - r10}
56 40
57 mov r5, r0 @ save sleep mode 41 mov pc, lr
42
43pxa_cpu_save_sp:
58 @ preserve phys address of stack 44 @ preserve phys address of stack
59 mov r0, sp 45 mov r0, sp
46 mov r2, lr
60 bl sleep_phys_sp 47 bl sleep_phys_sp
61 ldr r1, =sleep_save_sp 48 ldr r1, =sleep_save_sp
62 str r0, [r1] 49 str r0, [r1]
50 mov pc, r2
51
52/*
53 * pxa27x_cpu_suspend()
54 *
55 * Forces CPU into sleep state.
56 *
57 * r0 = value for PWRMODE M field for desired sleep state
58 */
59
60ENTRY(pxa27x_cpu_suspend)
61
62#ifndef CONFIG_IWMMXT
63 mra r2, r3, acc0
64#endif
65 stmfd sp!, {r2 - r12, lr} @ save registers on stack
66
67 bl pxa_cpu_save_cp
68
69 mov r5, r0 @ save sleep mode
70 bl pxa_cpu_save_sp
63 71
64 @ clean data cache 72 @ clean data cache
65 bl xscale_flush_kern_cache_all 73 bl xscale_flush_kern_cache_all
@@ -80,13 +88,55 @@ ENTRY(pxa_cpu_suspend)
80 @ enable SDRAM self-refresh mode 88 @ enable SDRAM self-refresh mode
81 orr r5, r5, #MDREFR_SLFRSH 89 orr r5, r5, #MDREFR_SLFRSH
82 90
83#ifdef CONFIG_PXA27x
84 @ set SDCLKx divide-by-2 bits (this is part of a workaround for Errata 50) 91 @ set SDCLKx divide-by-2 bits (this is part of a workaround for Errata 50)
85 ldr r6, =MDREFR_KDIV 92 ldr r6, =MDREFR_KDIV
86 orr r5, r5, r6 93 orr r5, r5, r6
87#endif
88 94
89#ifdef CONFIG_PXA25x 95 @ Intel PXA270 Specification Update notes problems sleeping
96 @ with core operating above 91 MHz
97 @ (see Errata 50, ...processor does not exit from sleep...)
98
99 ldr r6, =CCCR
100 ldr r8, [r6] @ keep original value for resume
101
102 ldr r7, =CCCR_SLEEP @ prepare CCCR sleep value
103 mov r0, #0x2 @ prepare value for CLKCFG
104
105 @ align execution to a cache line
106 b pxa_cpu_do_suspend
107
108/*
109 * pxa27x_cpu_suspend()
110 *
111 * Forces CPU into sleep state.
112 *
113 * r0 = value for PWRMODE M field for desired sleep state
114 */
115
116ENTRY(pxa25x_cpu_suspend)
117 stmfd sp!, {r2 - r12, lr} @ save registers on stack
118
119 bl pxa_cpu_save_cp
120
121 mov r5, r0 @ save sleep mode
122 bl pxa_cpu_save_sp
123
124 @ clean data cache
125 bl xscale_flush_kern_cache_all
126
127 @ prepare value for sleep mode
128 mov r1, r5 @ sleep mode
129
130 @ prepare pointer to physical address 0 (virtual mapping in generic.c)
131 mov r2, #UNCACHED_PHYS_0
132
133 @ prepare SDRAM refresh settings
134 ldr r4, =MDREFR
135 ldr r5, [r4]
136
137 @ enable SDRAM self-refresh mode
138 orr r5, r5, #MDREFR_SLFRSH
139
90 @ Intel PXA255 Specification Update notes problems 140 @ Intel PXA255 Specification Update notes problems
91 @ about suspending with PXBus operating above 133MHz 141 @ about suspending with PXBus operating above 133MHz
92 @ (see Errata 31, GPIO output signals, ... unpredictable in sleep 142 @ (see Errata 31, GPIO output signals, ... unpredictable in sleep
@@ -118,30 +168,15 @@ ENTRY(pxa_cpu_suspend)
118 mov r0, #0 168 mov r0, #0
119 mcr p14, 0, r0, c6, c0, 0 169 mcr p14, 0, r0, c6, c0, 0
120 orr r0, r0, #2 @ initiate change bit 170 orr r0, r0, #2 @ initiate change bit
121#endif 171 b pxa_cpu_do_suspend
122#ifdef CONFIG_PXA27x
123 @ Intel PXA270 Specification Update notes problems sleeping
124 @ with core operating above 91 MHz
125 @ (see Errata 50, ...processor does not exit from sleep...)
126
127 ldr r6, =CCCR
128 ldr r8, [r6] @ keep original value for resume
129
130 ldr r7, =CCCR_SLEEP @ prepare CCCR sleep value
131 mov r0, #0x2 @ prepare value for CLKCFG
132#endif
133
134 @ align execution to a cache line
135 b 1f
136 172
137 .ltorg 173 .ltorg
138 .align 5 174 .align 5
1391: 175pxa_cpu_do_suspend:
140 176
141 @ All needed values are now in registers. 177 @ All needed values are now in registers.
142 @ These last instructions should be in cache 178 @ These last instructions should be in cache
143 179
144#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
145 @ initiate the frequency change... 180 @ initiate the frequency change...
146 str r7, [r6] 181 str r7, [r6]
147 mcr p14, 0, r0, c6, c0, 0 182 mcr p14, 0, r0, c6, c0, 0
@@ -155,7 +190,6 @@ ENTRY(pxa_cpu_suspend)
155 mov r0, #42 190 mov r0, #42
15610: subs r0, r0, #1 19110: subs r0, r0, #1
157 bne 10b 192 bne 10b
158#endif
159 193
160 @ Do not reorder... 194 @ Do not reorder...
161 @ Intel PXA270 Specification Update notes problems performing 195 @ Intel PXA270 Specification Update notes problems performing
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 6f91fd2d061a..98d27e646b09 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -1,9 +1,11 @@
1/* 1/*
2 * arch/arm/mach-pxa/time.c 2 * arch/arm/mach-pxa/time.c
3 * 3 *
4 * Author: Nicolas Pitre 4 * PXA clocksource, clockevents, and OST interrupt handlers.
5 * Created: Jun 15, 2001 5 * Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>.
6 * Copyright: MontaVista Software Inc. 6 *
7 * Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001
8 * by MontaVista Software, Inc. (Nico, your code rocks!)
7 * 9 *
8 * This program is free software; you can redistribute it and/or modify 10 * 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 11 * it under the terms of the GNU General Public License version 2 as
@@ -12,164 +14,160 @@
12 14
13#include <linux/kernel.h> 15#include <linux/kernel.h>
14#include <linux/init.h> 16#include <linux/init.h>
15#include <linux/delay.h>
16#include <linux/interrupt.h> 17#include <linux/interrupt.h>
17#include <linux/time.h> 18#include <linux/clockchips.h>
18#include <linux/signal.h> 19
19#include <linux/errno.h>
20#include <linux/sched.h>
21#include <linux/clocksource.h>
22
23#include <asm/system.h>
24#include <asm/hardware.h>
25#include <asm/io.h>
26#include <asm/leds.h>
27#include <asm/irq.h>
28#include <asm/mach/irq.h> 20#include <asm/mach/irq.h>
29#include <asm/mach/time.h> 21#include <asm/mach/time.h>
30#include <asm/arch/pxa-regs.h> 22#include <asm/arch/pxa-regs.h>
31 23
32
33static int pxa_set_rtc(void)
34{
35 unsigned long current_time = xtime.tv_sec;
36
37 if (RTSR & RTSR_ALE) {
38 /* make sure not to forward the clock over an alarm */
39 unsigned long alarm = RTAR;
40 if (current_time >= alarm && alarm >= RCNR)
41 return -ERESTARTSYS;
42 }
43 RCNR = current_time;
44 return 0;
45}
46
47#ifdef CONFIG_NO_IDLE_HZ
48static unsigned long initial_match;
49static int match_posponed;
50#endif
51
52static irqreturn_t 24static irqreturn_t
53pxa_timer_interrupt(int irq, void *dev_id) 25pxa_ost0_interrupt(int irq, void *dev_id)
54{ 26{
55 int next_match; 27 int next_match;
56 28 struct clock_event_device *c = dev_id;
57 write_seqlock(&xtime_lock); 29
58 30 if (c->mode == CLOCK_EVT_MODE_ONESHOT) {
59#ifdef CONFIG_NO_IDLE_HZ 31 /* Disarm the compare/match, signal the event. */
60 if (match_posponed) { 32 OIER &= ~OIER_E0;
61 match_posponed = 0; 33 c->event_handler(c);
62 OSMR0 = initial_match; 34 } else if (c->mode == CLOCK_EVT_MODE_PERIODIC) {
63 } 35 /* Call the event handler as many times as necessary
64#endif 36 * to recover missed events, if any (if we update
65 37 * OSMR0 and OSCR0 is still ahead of us, we've missed
66 /* Loop until we get ahead of the free running timer. 38 * the event). As we're dealing with that, re-arm the
67 * This ensures an exact clock tick count and time accuracy. 39 * compare/match for the next event.
68 * Since IRQs are disabled at this point, coherence between 40 *
69 * lost_ticks(updated in do_timer()) and the match reg value is 41 * HACK ALERT:
70 * ensured, hence we can use do_gettimeofday() from interrupt 42 *
71 * handlers. 43 * There's a latency between the instruction that
72 * 44 * writes to OSMR0 and the actual commit to the
73 * HACK ALERT: it seems that the PXA timer regs aren't updated right 45 * physical hardware, because the CPU doesn't (have
74 * away in all cases when a write occurs. We therefore compare with 46 * to) run at bus speed, there's a write buffer
75 * 8 instead of 0 in the while() condition below to avoid missing a 47 * between the CPU and the bus, etc. etc. So if the
76 * match if OSCR has already reached the next OSMR value. 48 * target OSCR0 is "very close", to the OSMR0 load
77 * Experience has shown that up to 6 ticks are needed to work around 49 * value, the update to OSMR0 might not get to the
78 * this problem, but let's use 8 to be conservative. Note that this 50 * hardware in time and we'll miss that interrupt.
79 * affect things only when the timer IRQ has been delayed by nearly 51 *
80 * exactly one tick period which should be a pretty rare event. 52 * To be safe, if the new OSMR0 is "very close" to the
53 * target OSCR0 value, we call the event_handler as
54 * though the event actually happened. According to
55 * Nico's comment in the previous version of this
56 * code, experience has shown that 6 OSCR ticks is
57 * "very close" but he went with 8. We will use 16,
58 * based on the results of testing on PXA270.
59 *
60 * To be doubly sure, we also tell clkevt via
61 * clockevents_register_device() not to ask for
62 * anything that might put us "very close".
81 */ 63 */
64#define MIN_OSCR_DELTA 16
82 do { 65 do {
83 timer_tick(); 66 OSSR = OSSR_M0;
84 OSSR = OSSR_M0; /* Clear match on timer 0 */
85 next_match = (OSMR0 += LATCH); 67 next_match = (OSMR0 += LATCH);
86 } while( (signed long)(next_match - OSCR) <= 8 ); 68 c->event_handler(c);
87 69 } while (((signed long)(next_match - OSCR) <= MIN_OSCR_DELTA)
88 write_sequnlock(&xtime_lock); 70 && (c->mode == CLOCK_EVT_MODE_PERIODIC));
71 }
89 72
90 return IRQ_HANDLED; 73 return IRQ_HANDLED;
91} 74}
92 75
93static struct irqaction pxa_timer_irq = { 76static int
94 .name = "PXA Timer Tick", 77pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
95 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 78{
96 .handler = pxa_timer_interrupt, 79 unsigned long irqflags;
80
81 raw_local_irq_save(irqflags);
82 OSMR0 = OSCR + delta;
83 OSSR = OSSR_M0;
84 OIER |= OIER_E0;
85 raw_local_irq_restore(irqflags);
86 return 0;
87}
88
89static void
90pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
91{
92 unsigned long irqflags;
93
94 switch (mode) {
95 case CLOCK_EVT_MODE_PERIODIC:
96 raw_local_irq_save(irqflags);
97 OSMR0 = OSCR + LATCH;
98 OSSR = OSSR_M0;
99 OIER |= OIER_E0;
100 raw_local_irq_restore(irqflags);
101 break;
102
103 case CLOCK_EVT_MODE_ONESHOT:
104 raw_local_irq_save(irqflags);
105 OIER &= ~OIER_E0;
106 raw_local_irq_restore(irqflags);
107 break;
108
109 case CLOCK_EVT_MODE_UNUSED:
110 case CLOCK_EVT_MODE_SHUTDOWN:
111 /* initializing, released, or preparing for suspend */
112 raw_local_irq_save(irqflags);
113 OIER &= ~OIER_E0;
114 raw_local_irq_restore(irqflags);
115 break;
116 }
117}
118
119static struct clock_event_device ckevt_pxa_osmr0 = {
120 .name = "osmr0",
121 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
122 .shift = 32,
123 .rating = 200,
124 .cpumask = CPU_MASK_CPU0,
125 .set_next_event = pxa_osmr0_set_next_event,
126 .set_mode = pxa_osmr0_set_mode,
97}; 127};
98 128
99static cycle_t pxa_get_cycles(void) 129static cycle_t pxa_read_oscr(void)
100{ 130{
101 return OSCR; 131 return OSCR;
102} 132}
103 133
104static struct clocksource clocksource_pxa = { 134static struct clocksource cksrc_pxa_oscr0 = {
105 .name = "pxa_timer", 135 .name = "oscr0",
106 .rating = 200, 136 .rating = 200,
107 .read = pxa_get_cycles, 137 .read = pxa_read_oscr,
108 .mask = CLOCKSOURCE_MASK(32), 138 .mask = CLOCKSOURCE_MASK(32),
109 .shift = 20, 139 .shift = 20,
110 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 140 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
111}; 141};
112 142
143static struct irqaction pxa_ost0_irq = {
144 .name = "ost0",
145 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
146 .handler = pxa_ost0_interrupt,
147 .dev_id = &ckevt_pxa_osmr0,
148};
149
113static void __init pxa_timer_init(void) 150static void __init pxa_timer_init(void)
114{ 151{
115 struct timespec tv; 152 OIER = 0;
116 unsigned long flags; 153 OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
117 154
118 set_rtc = pxa_set_rtc; 155 ckevt_pxa_osmr0.mult =
156 div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
157 ckevt_pxa_osmr0.max_delta_ns =
158 clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
159 ckevt_pxa_osmr0.min_delta_ns =
160 clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1;
119 161
120 OIER = 0; /* disable any timer interrupts */ 162 cksrc_pxa_oscr0.mult =
121 OSSR = 0xf; /* clear status on all timers */ 163 clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_pxa_oscr0.shift);
122 setup_irq(IRQ_OST0, &pxa_timer_irq);
123 local_irq_save(flags);
124 OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */
125 OSMR0 = OSCR + LATCH; /* set initial match */
126 local_irq_restore(flags);
127
128 /*
129 * OSCR runs continuously on PXA and is not written to,
130 * so we can use it as clock source directly.
131 */
132 clocksource_pxa.mult =
133 clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_pxa.shift);
134 clocksource_register(&clocksource_pxa);
135}
136
137#ifdef CONFIG_NO_IDLE_HZ
138static int pxa_dyn_tick_enable_disable(void)
139{
140 /* nothing to do */
141 return 0;
142}
143 164
144static void pxa_dyn_tick_reprogram(unsigned long ticks) 165 setup_irq(IRQ_OST0, &pxa_ost0_irq);
145{
146 if (ticks > 1) {
147 initial_match = OSMR0;
148 OSMR0 = initial_match + ticks * LATCH;
149 match_posponed = 1;
150 }
151}
152 166
153static irqreturn_t 167 clocksource_register(&cksrc_pxa_oscr0);
154pxa_dyn_tick_handler(int irq, void *dev_id) 168 clockevents_register_device(&ckevt_pxa_osmr0);
155{
156 if (match_posponed) {
157 match_posponed = 0;
158 OSMR0 = initial_match;
159 if ( (signed long)(initial_match - OSCR) <= 8 )
160 return pxa_timer_interrupt(irq, dev_id);
161 }
162 return IRQ_NONE;
163} 169}
164 170
165static struct dyn_tick_timer pxa_dyn_tick = {
166 .enable = pxa_dyn_tick_enable_disable,
167 .disable = pxa_dyn_tick_enable_disable,
168 .reprogram = pxa_dyn_tick_reprogram,
169 .handler = pxa_dyn_tick_handler,
170};
171#endif
172
173#ifdef CONFIG_PM 171#ifdef CONFIG_PM
174static unsigned long osmr[4], oier; 172static unsigned long osmr[4], oier;
175 173
@@ -191,7 +189,10 @@ static void pxa_timer_resume(void)
191 OIER = oier; 189 OIER = oier;
192 190
193 /* 191 /*
194 * OSMR0 is the system timer: make sure OSCR is sufficiently behind 192 * OSCR0 is the system timer, which has to increase
193 * monotonically until it rolls over in hardware. The value
194 * (OSMR0 - LATCH) is OSCR0 at the most recent system tick,
195 * which is a handy value to restore to OSCR0.
195 */ 196 */
196 OSCR = OSMR0 - LATCH; 197 OSCR = OSMR0 - LATCH;
197} 198}
@@ -204,7 +205,4 @@ struct sys_timer pxa_timer = {
204 .init = pxa_timer_init, 205 .init = pxa_timer_init,
205 .suspend = pxa_timer_suspend, 206 .suspend = pxa_timer_suspend,
206 .resume = pxa_timer_resume, 207 .resume = pxa_timer_resume,
207#ifdef CONFIG_NO_IDLE_HZ
208 .dyn_tick = &pxa_dyn_tick,
209#endif
210}; 208};