aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/arm/mach-pxa
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/arm/mach-pxa')
-rw-r--r--arch/arm/mach-pxa/Kconfig77
-rw-r--r--arch/arm/mach-pxa/Makefile26
-rw-r--r--arch/arm/mach-pxa/Makefile.boot2
-rw-r--r--arch/arm/mach-pxa/corgi.c320
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c248
-rw-r--r--arch/arm/mach-pxa/dma.c133
-rw-r--r--arch/arm/mach-pxa/generic.c237
-rw-r--r--arch/arm/mach-pxa/generic.h24
-rw-r--r--arch/arm/mach-pxa/idp.c190
-rw-r--r--arch/arm/mach-pxa/irq.c313
-rw-r--r--arch/arm/mach-pxa/leds-idp.c117
-rw-r--r--arch/arm/mach-pxa/leds-lubbock.c126
-rw-r--r--arch/arm/mach-pxa/leds-mainstone.c121
-rw-r--r--arch/arm/mach-pxa/leds.c32
-rw-r--r--arch/arm/mach-pxa/leds.h12
-rw-r--r--arch/arm/mach-pxa/lubbock.c247
-rw-r--r--arch/arm/mach-pxa/mainstone.c316
-rw-r--r--arch/arm/mach-pxa/pm.c227
-rw-r--r--arch/arm/mach-pxa/poodle.c189
-rw-r--r--arch/arm/mach-pxa/pxa25x.c104
-rw-r--r--arch/arm/mach-pxa/pxa27x.c163
-rw-r--r--arch/arm/mach-pxa/sleep.S194
-rw-r--r--arch/arm/mach-pxa/ssp.c363
-rw-r--r--arch/arm/mach-pxa/time.c164
24 files changed, 3945 insertions, 0 deletions
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
new file mode 100644
index 000000000000..405a55f2287c
--- /dev/null
+++ b/arch/arm/mach-pxa/Kconfig
@@ -0,0 +1,77 @@
1if ARCH_PXA
2
3menu "Intel PXA2xx Implementations"
4
5choice
6 prompt "Select target board"
7
8config ARCH_LUBBOCK
9 bool "Intel DBPXA250 Development Platform"
10 select PXA25x
11 select SA1111
12
13config MACH_MAINSTONE
14 bool "Intel HCDDBBVA0 Development Platform"
15 select PXA27x
16 select IWMMXT
17
18config ARCH_PXA_IDP
19 bool "Accelent Xscale IDP"
20 select PXA25x
21
22config PXA_SHARPSL
23 bool "SHARP SL-5600 and SL-C7xx Models"
24 select PXA25x
25 select SHARP_SCOOP
26 select SHARP_PARAM
27 help
28 Say Y here if you intend to run this kernel on a
29 Sharp SL-5600 (Poodle), Sharp SL-C700 (Corgi),
30 SL-C750 (Shepherd) or a Sharp SL-C760 (Husky)
31 handheld computer.
32
33endchoice
34
35endmenu
36
37config MACH_POODLE
38 bool "Enable Sharp SL-5600 (Poodle) Support"
39 depends PXA_SHARPSL
40 select SHARP_LOCOMO
41
42config MACH_CORGI
43 bool "Enable Sharp SL-C700 (Corgi) Support"
44 depends PXA_SHARPSL
45 select PXA_SHARP_C7xx
46
47config MACH_SHEPHERD
48 bool "Enable Sharp SL-C750 (Shepherd) Support"
49 depends PXA_SHARPSL
50 select PXA_SHARP_C7xx
51
52config MACH_HUSKY
53 bool "Enable Sharp SL-C760 (Husky) Support"
54 depends PXA_SHARPSL
55 select PXA_SHARP_C7xx
56
57config PXA25x
58 bool
59 help
60 Select code specific to PXA21x/25x/26x variants
61
62config PXA27x
63 bool
64 help
65 Select code specific to PXA27x variants
66
67config IWMMXT
68 bool
69 help
70 Enable support for iWMMXt
71
72config PXA_SHARP_C7xx
73 bool
74 help
75 Enable support for all Sharp C7xx models
76
77endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
new file mode 100644
index 000000000000..c4e6d2523585
--- /dev/null
+++ b/arch/arm/mach-pxa/Makefile
@@ -0,0 +1,26 @@
1#
2# Makefile for the linux kernel.
3#
4
5# Common support (must be linked before board specific support)
6obj-y += generic.o irq.o dma.o time.o
7obj-$(CONFIG_PXA25x) += pxa25x.o
8obj-$(CONFIG_PXA27x) += pxa27x.o
9
10# Specific board support
11obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
12obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
13obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
14obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o ssp.o
15obj-$(CONFIG_MACH_POODLE) += poodle.o
16
17# Support for blinky lights
18led-y := leds.o
19led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
20led-$(CONFIG_MACH_MAINSTONE) += leds-mainstone.o
21led-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
22
23obj-$(CONFIG_LEDS) += $(led-y)
24
25# Misc features
26obj-$(CONFIG_PM) += pm.o sleep.o
diff --git a/arch/arm/mach-pxa/Makefile.boot b/arch/arm/mach-pxa/Makefile.boot
new file mode 100644
index 000000000000..1ead67178eca
--- /dev/null
+++ b/arch/arm/mach-pxa/Makefile.boot
@@ -0,0 +1,2 @@
1 zreladdr-y := 0xa0008000
2
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
new file mode 100644
index 000000000000..f691cf77d390
--- /dev/null
+++ b/arch/arm/mach-pxa/corgi.c
@@ -0,0 +1,320 @@
1/*
2 * Support for Sharp SL-C7xx PDAs
3 * Models: SL-C700 (Corgi), SL-C750 (Shepherd), SL-C760 (Husky)
4 *
5 * Copyright (c) 2004-2005 Richard Purdie
6 *
7 * Based on Sharp's 2.4 kernel patches/lubbock.c
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
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/device.h>
18#include <linux/major.h>
19#include <linux/fs.h>
20#include <linux/interrupt.h>
21#include <linux/mmc/host.h>
22
23#include <asm/setup.h>
24#include <asm/memory.h>
25#include <asm/mach-types.h>
26#include <asm/hardware.h>
27#include <asm/irq.h>
28#include <asm/io.h>
29
30#include <asm/mach/arch.h>
31#include <asm/mach/map.h>
32#include <asm/mach/irq.h>
33
34#include <asm/arch/pxa-regs.h>
35#include <asm/arch/irq.h>
36#include <asm/arch/mmc.h>
37#include <asm/arch/udc.h>
38#include <asm/arch/corgi.h>
39
40#include <asm/mach/sharpsl_param.h>
41#include <asm/hardware/scoop.h>
42#include <video/w100fb.h>
43
44#include "generic.h"
45
46
47/*
48 * Corgi SCOOP Device
49 */
50static struct resource corgi_scoop_resources[] = {
51 [0] = {
52 .start = 0x10800000,
53 .end = 0x10800fff,
54 .flags = IORESOURCE_MEM,
55 },
56};
57
58static struct scoop_config corgi_scoop_setup = {
59 .io_dir = CORGI_SCOOP_IO_DIR,
60 .io_out = CORGI_SCOOP_IO_OUT,
61};
62
63struct platform_device corgiscoop_device = {
64 .name = "sharp-scoop",
65 .id = -1,
66 .dev = {
67 .platform_data = &corgi_scoop_setup,
68 },
69 .num_resources = ARRAY_SIZE(corgi_scoop_resources),
70 .resource = corgi_scoop_resources,
71};
72
73
74/*
75 * Corgi SSP Device
76 *
77 * Set the parent as the scoop device because a lot of SSP devices
78 * also use scoop functions and this makes the power up/down order
79 * work correctly.
80 */
81static struct platform_device corgissp_device = {
82 .name = "corgi-ssp",
83 .dev = {
84 .parent = &corgiscoop_device.dev,
85 },
86 .id = -1,
87};
88
89
90/*
91 * Corgi w100 Frame Buffer Device
92 */
93static struct w100fb_mach_info corgi_fb_info = {
94 .w100fb_ssp_send = corgi_ssp_lcdtg_send,
95 .comadj = -1,
96 .phadadj = -1,
97};
98
99static struct resource corgi_fb_resources[] = {
100 [0] = {
101 .start = 0x08000000,
102 .end = 0x08ffffff,
103 .flags = IORESOURCE_MEM,
104 },
105};
106
107static struct platform_device corgifb_device = {
108 .name = "w100fb",
109 .id = -1,
110 .dev = {
111 .platform_data = &corgi_fb_info,
112 .parent = &corgissp_device.dev,
113 },
114 .num_resources = ARRAY_SIZE(corgi_fb_resources),
115 .resource = corgi_fb_resources,
116};
117
118
119/*
120 * Corgi Backlight Device
121 */
122static struct platform_device corgibl_device = {
123 .name = "corgi-bl",
124 .dev = {
125 .parent = &corgifb_device.dev,
126 },
127 .id = -1,
128};
129
130
131/*
132 * MMC/SD Device
133 *
134 * The card detect interrupt isn't debounced so we delay it by HZ/4
135 * to give the card a chance to fully insert/eject.
136 */
137static struct mmc_detect {
138 struct timer_list detect_timer;
139 void *devid;
140} mmc_detect;
141
142static void mmc_detect_callback(unsigned long data)
143{
144 mmc_detect_change(mmc_detect.devid);
145}
146
147static irqreturn_t corgi_mmc_detect_int(int irq, void *devid, struct pt_regs *regs)
148{
149 mmc_detect.devid=devid;
150 mod_timer(&mmc_detect.detect_timer, jiffies + HZ/4);
151 return IRQ_HANDLED;
152}
153
154static int corgi_mci_init(struct device *dev, irqreturn_t (*unused_detect_int)(int, void *, struct pt_regs *), void *data)
155{
156 int err;
157
158 /* setup GPIO for PXA25x MMC controller */
159 pxa_gpio_mode(GPIO6_MMCCLK_MD);
160 pxa_gpio_mode(GPIO8_MMCCS0_MD);
161 pxa_gpio_mode(CORGI_GPIO_nSD_DETECT | GPIO_IN);
162 pxa_gpio_mode(CORGI_GPIO_SD_PWR | GPIO_OUT);
163
164 init_timer(&mmc_detect.detect_timer);
165 mmc_detect.detect_timer.function = mmc_detect_callback;
166 mmc_detect.detect_timer.data = (unsigned long) &mmc_detect;
167
168 err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_mmc_detect_int, SA_INTERRUPT,
169 "MMC card detect", data);
170 if (err) {
171 printk(KERN_ERR "corgi_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
172 return -1;
173 }
174
175 set_irq_type(CORGI_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE);
176
177 return 0;
178}
179
180static void corgi_mci_setpower(struct device *dev, unsigned int vdd)
181{
182 struct pxamci_platform_data* p_d = dev->platform_data;
183
184 if (( 1 << vdd) & p_d->ocr_mask) {
185 printk(KERN_DEBUG "%s: on\n", __FUNCTION__);
186 GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR);
187 } else {
188 printk(KERN_DEBUG "%s: off\n", __FUNCTION__);
189 GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR);
190 }
191}
192
193static void corgi_mci_exit(struct device *dev, void *data)
194{
195 free_irq(CORGI_IRQ_GPIO_nSD_DETECT, data);
196 del_timer(&mmc_detect.detect_timer);
197}
198
199static struct pxamci_platform_data corgi_mci_platform_data = {
200 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
201 .init = corgi_mci_init,
202 .setpower = corgi_mci_setpower,
203 .exit = corgi_mci_exit,
204};
205
206
207/*
208 * USB Device Controller
209 */
210static void corgi_udc_command(int cmd)
211{
212 switch(cmd) {
213 case PXA2XX_UDC_CMD_CONNECT:
214 GPSR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
215 break;
216 case PXA2XX_UDC_CMD_DISCONNECT:
217 GPCR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
218 break;
219 }
220}
221
222static struct pxa2xx_udc_mach_info udc_info __initdata = {
223 /* no connect GPIO; corgi can't tell connection status */
224 .udc_command = corgi_udc_command,
225};
226
227
228static struct platform_device *devices[] __initdata = {
229 &corgiscoop_device,
230 &corgissp_device,
231 &corgifb_device,
232 &corgibl_device,
233};
234
235static void __init corgi_init(void)
236{
237 corgi_fb_info.comadj=sharpsl_param.comadj;
238 corgi_fb_info.phadadj=sharpsl_param.phadadj;
239
240 pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
241 pxa_set_udc_info(&udc_info);
242 pxa_set_mci_info(&corgi_mci_platform_data);
243
244 platform_add_devices(devices, ARRAY_SIZE(devices));
245}
246
247static void __init fixup_corgi(struct machine_desc *desc,
248 struct tag *tags, char **cmdline, struct meminfo *mi)
249{
250 sharpsl_save_param();
251 mi->nr_banks=1;
252 mi->bank[0].start = 0xa0000000;
253 mi->bank[0].node = 0;
254 if (machine_is_corgi())
255 mi->bank[0].size = (32*1024*1024);
256 else
257 mi->bank[0].size = (64*1024*1024);
258}
259
260static void __init corgi_init_irq(void)
261{
262 pxa_init_irq();
263}
264
265static struct map_desc corgi_io_desc[] __initdata = {
266/* virtual physical length */
267/* { 0xf1000000, 0x08000000, 0x01000000, MT_DEVICE },*/ /* LCDC (readable for Qt driver) */
268/* { 0xef700000, 0x10800000, 0x00001000, MT_DEVICE },*/ /* SCOOP */
269 { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */
270};
271
272static void __init corgi_map_io(void)
273{
274 pxa_map_io();
275 iotable_init(corgi_io_desc,ARRAY_SIZE(corgi_io_desc));
276
277 /* setup sleep mode values */
278 PWER = 0x00000002;
279 PFER = 0x00000000;
280 PRER = 0x00000002;
281 PGSR0 = 0x0158C000;
282 PGSR1 = 0x00FF0080;
283 PGSR2 = 0x0001C004;
284 /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
285 PCFR |= PCFR_OPDE;
286}
287
288#ifdef CONFIG_MACH_CORGI
289MACHINE_START(CORGI, "SHARP Corgi")
290 BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
291 FIXUP(fixup_corgi)
292 MAPIO(corgi_map_io)
293 INITIRQ(corgi_init_irq)
294 .init_machine = corgi_init,
295 .timer = &pxa_timer,
296MACHINE_END
297#endif
298
299#ifdef CONFIG_MACH_SHEPHERD
300MACHINE_START(SHEPHERD, "SHARP Shepherd")
301 BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
302 FIXUP(fixup_corgi)
303 MAPIO(corgi_map_io)
304 INITIRQ(corgi_init_irq)
305 .init_machine = corgi_init,
306 .timer = &pxa_timer,
307MACHINE_END
308#endif
309
310#ifdef CONFIG_MACH_HUSKY
311MACHINE_START(HUSKY, "SHARP Husky")
312 BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
313 FIXUP(fixup_corgi)
314 MAPIO(corgi_map_io)
315 INITIRQ(corgi_init_irq)
316 .init_machine = corgi_init,
317 .timer = &pxa_timer,
318MACHINE_END
319#endif
320
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
new file mode 100644
index 000000000000..8ccffba0018f
--- /dev/null
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -0,0 +1,248 @@
1/*
2 * SSP control code for Sharp Corgi devices
3 *
4 * Copyright (c) 2004 Richard Purdie
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/slab.h>
17#include <linux/delay.h>
18#include <linux/device.h>
19#include <asm/hardware.h>
20
21#include <asm/arch/ssp.h>
22#include <asm/arch/corgi.h>
23#include <asm/arch/pxa-regs.h>
24
25static spinlock_t corgi_ssp_lock = SPIN_LOCK_UNLOCKED;
26static struct ssp_dev corgi_ssp_dev;
27static struct ssp_state corgi_ssp_state;
28
29/*
30 * There are three devices connected to the SSP interface:
31 * 1. A touchscreen controller (TI ADS7846 compatible)
32 * 2. An LCD contoller (with some Backlight functionality)
33 * 3. A battery moinitoring IC (Maxim MAX1111)
34 *
35 * Each device uses a different speed/mode of communication.
36 *
37 * The touchscreen is very sensitive and the most frequently used
38 * so the port is left configured for this.
39 *
40 * Devices are selected using Chip Selects on GPIOs.
41 */
42
43/*
44 * ADS7846 Routines
45 */
46unsigned long corgi_ssp_ads7846_putget(ulong data)
47{
48 unsigned long ret,flag;
49
50 spin_lock_irqsave(&corgi_ssp_lock, flag);
51 GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
52
53 ssp_write_word(&corgi_ssp_dev,data);
54 ret = ssp_read_word(&corgi_ssp_dev);
55
56 GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
57 spin_unlock_irqrestore(&corgi_ssp_lock, flag);
58
59 return ret;
60}
61
62/*
63 * NOTE: These functions should always be called in interrupt context
64 * and use the _lock and _unlock functions. They are very time sensitive.
65 */
66void corgi_ssp_ads7846_lock(void)
67{
68 spin_lock(&corgi_ssp_lock);
69 GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
70}
71
72void corgi_ssp_ads7846_unlock(void)
73{
74 GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS);
75 spin_unlock(&corgi_ssp_lock);
76}
77
78void corgi_ssp_ads7846_put(ulong data)
79{
80 ssp_write_word(&corgi_ssp_dev,data);
81}
82
83unsigned long corgi_ssp_ads7846_get(void)
84{
85 return ssp_read_word(&corgi_ssp_dev);
86}
87
88EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
89EXPORT_SYMBOL(corgi_ssp_ads7846_lock);
90EXPORT_SYMBOL(corgi_ssp_ads7846_unlock);
91EXPORT_SYMBOL(corgi_ssp_ads7846_put);
92EXPORT_SYMBOL(corgi_ssp_ads7846_get);
93
94
95/*
96 * LCD/Backlight Routines
97 */
98unsigned long corgi_ssp_dac_put(ulong data)
99{
100 unsigned long flag;
101
102 spin_lock_irqsave(&corgi_ssp_lock, flag);
103 GPCR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
104
105 ssp_disable(&corgi_ssp_dev);
106 ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPH, 0, SSCR0_SerClkDiv(76));
107 ssp_enable(&corgi_ssp_dev);
108
109 ssp_write_word(&corgi_ssp_dev,data);
110 /* Read null data back from device to prevent SSP overflow */
111 ssp_read_word(&corgi_ssp_dev);
112
113 ssp_disable(&corgi_ssp_dev);
114 ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
115 ssp_enable(&corgi_ssp_dev);
116 GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS);
117 spin_unlock_irqrestore(&corgi_ssp_lock, flag);
118
119 return 0;
120}
121
122void corgi_ssp_lcdtg_send(u8 adrs, u8 data)
123{
124 corgi_ssp_dac_put(((adrs & 0x07) << 5) | (data & 0x1f));
125}
126
127void corgi_ssp_blduty_set(int duty)
128{
129 corgi_ssp_lcdtg_send(0x02,duty);
130}
131
132EXPORT_SYMBOL(corgi_ssp_lcdtg_send);
133EXPORT_SYMBOL(corgi_ssp_blduty_set);
134
135/*
136 * Max1111 Routines
137 */
138int corgi_ssp_max1111_get(ulong data)
139{
140 unsigned long flag;
141 int voltage,voltage1,voltage2;
142
143 spin_lock_irqsave(&corgi_ssp_lock, flag);
144 GPCR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
145 ssp_disable(&corgi_ssp_dev);
146 ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(8));
147 ssp_enable(&corgi_ssp_dev);
148
149 udelay(1);
150
151 /* TB1/RB1 */
152 ssp_write_word(&corgi_ssp_dev,data);
153 ssp_read_word(&corgi_ssp_dev); /* null read */
154
155 /* TB12/RB2 */
156 ssp_write_word(&corgi_ssp_dev,0);
157 voltage1=ssp_read_word(&corgi_ssp_dev);
158
159 /* TB13/RB3*/
160 ssp_write_word(&corgi_ssp_dev,0);
161 voltage2=ssp_read_word(&corgi_ssp_dev);
162
163 ssp_disable(&corgi_ssp_dev);
164 ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
165 ssp_enable(&corgi_ssp_dev);
166 GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS);
167 spin_unlock_irqrestore(&corgi_ssp_lock, flag);
168
169 if (voltage1 & 0xc0 || voltage2 & 0x3f)
170 voltage = -1;
171 else
172 voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03);
173
174 return voltage;
175}
176
177EXPORT_SYMBOL(corgi_ssp_max1111_get);
178
179/*
180 * Support Routines
181 */
182int __init corgi_ssp_probe(struct device *dev)
183{
184 int ret;
185
186 /* Chip Select - Disable All */
187 GPDR0 |= GPIO_bit(CORGI_GPIO_LCDCON_CS); /* output */
188 GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
189 GPDR0 |= GPIO_bit(CORGI_GPIO_MAX1111_CS); /* output */
190 GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
191 GPDR0 |= GPIO_bit(CORGI_GPIO_ADS7846_CS); /* output */
192 GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
193
194 ret=ssp_init(&corgi_ssp_dev,1);
195
196 if (ret)
197 printk(KERN_ERR "Unable to register SSP handler!\n");
198 else {
199 ssp_disable(&corgi_ssp_dev);
200 ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2));
201 ssp_enable(&corgi_ssp_dev);
202 }
203
204 return ret;
205}
206
207static int corgi_ssp_remove(struct device *dev)
208{
209 ssp_exit(&corgi_ssp_dev);
210 return 0;
211}
212
213static int corgi_ssp_suspend(struct device *dev, pm_message_t state, u32 level)
214{
215 if (level == SUSPEND_POWER_DOWN) {
216 ssp_flush(&corgi_ssp_dev);
217 ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
218 }
219 return 0;
220}
221
222static int corgi_ssp_resume(struct device *dev, u32 level)
223{
224 if (level == RESUME_POWER_ON) {
225 GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */
226 GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/
227 GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/
228 ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
229 ssp_enable(&corgi_ssp_dev);
230 }
231 return 0;
232}
233
234static struct device_driver corgissp_driver = {
235 .name = "corgi-ssp",
236 .bus = &platform_bus_type,
237 .probe = corgi_ssp_probe,
238 .remove = corgi_ssp_remove,
239 .suspend = corgi_ssp_suspend,
240 .resume = corgi_ssp_resume,
241};
242
243int __init corgi_ssp_init(void)
244{
245 return driver_register(&corgissp_driver);
246}
247
248arch_initcall(corgi_ssp_init);
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
new file mode 100644
index 000000000000..458112b21e25
--- /dev/null
+++ b/arch/arm/mach-pxa/dma.c
@@ -0,0 +1,133 @@
1/*
2 * linux/arch/arm/mach-pxa/dma.c
3 *
4 * PXA DMA registration and IRQ dispatching
5 *
6 * Author: Nicolas Pitre
7 * Created: Nov 15, 2001
8 * Copyright: MontaVista Software Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/interrupt.h>
19#include <linux/errno.h>
20
21#include <asm/system.h>
22#include <asm/irq.h>
23#include <asm/hardware.h>
24#include <asm/dma.h>
25
26#include <asm/arch/pxa-regs.h>
27
28static struct dma_channel {
29 char *name;
30 void (*irq_handler)(int, void *, struct pt_regs *);
31 void *data;
32} dma_channels[PXA_DMA_CHANNELS];
33
34
35int pxa_request_dma (char *name, pxa_dma_prio prio,
36 void (*irq_handler)(int, void *, struct pt_regs *),
37 void *data)
38{
39 unsigned long flags;
40 int i, found = 0;
41
42 /* basic sanity checks */
43 if (!name || !irq_handler)
44 return -EINVAL;
45
46 local_irq_save(flags);
47
48 /* try grabbing a DMA channel with the requested priority */
49 for (i = prio; i < prio + PXA_DMA_NBCH(prio); i++) {
50 if (!dma_channels[i].name) {
51 found = 1;
52 break;
53 }
54 }
55
56 if (!found) {
57 /* requested prio group is full, try hier priorities */
58 for (i = prio-1; i >= 0; i--) {
59 if (!dma_channels[i].name) {
60 found = 1;
61 break;
62 }
63 }
64 }
65
66 if (found) {
67 DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
68 dma_channels[i].name = name;
69 dma_channels[i].irq_handler = irq_handler;
70 dma_channels[i].data = data;
71 } else {
72 printk (KERN_WARNING "No more available DMA channels for %s\n", name);
73 i = -ENODEV;
74 }
75
76 local_irq_restore(flags);
77 return i;
78}
79
80void pxa_free_dma (int dma_ch)
81{
82 unsigned long flags;
83
84 if (!dma_channels[dma_ch].name) {
85 printk (KERN_CRIT
86 "%s: trying to free channel %d which is already freed\n",
87 __FUNCTION__, dma_ch);
88 return;
89 }
90
91 local_irq_save(flags);
92 DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
93 dma_channels[dma_ch].name = NULL;
94 local_irq_restore(flags);
95}
96
97static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
98{
99 int i, dint = DINT;
100
101 for (i = 0; i < PXA_DMA_CHANNELS; i++) {
102 if (dint & (1 << i)) {
103 struct dma_channel *channel = &dma_channels[i];
104 if (channel->name && channel->irq_handler) {
105 channel->irq_handler(i, channel->data, regs);
106 } else {
107 /*
108 * IRQ for an unregistered DMA channel:
109 * let's clear the interrupts and disable it.
110 */
111 printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);
112 DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
113 }
114 }
115 }
116 return IRQ_HANDLED;
117}
118
119static int __init pxa_dma_init (void)
120{
121 int ret;
122
123 ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
124 if (ret)
125 printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n");
126 return ret;
127}
128
129arch_initcall(pxa_dma_init);
130
131EXPORT_SYMBOL(pxa_request_dma);
132EXPORT_SYMBOL(pxa_free_dma);
133
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
new file mode 100644
index 000000000000..b1575b8dc1cd
--- /dev/null
+++ b/arch/arm/mach-pxa/generic.c
@@ -0,0 +1,237 @@
1/*
2 * linux/arch/arm/mach-pxa/generic.c
3 *
4 * Author: Nicolas Pitre
5 * Created: Jun 15, 2001
6 * Copyright: MontaVista Software Inc.
7 *
8 * Code common to all PXA machines.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * Since this file should be linked before any other machine specific file,
15 * the __initcall() here will be executed first. This serves as default
16 * initialization stuff for PXA machines which can be overridden later if
17 * need be.
18 */
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/delay.h>
23#include <linux/device.h>
24#include <linux/ioport.h>
25#include <linux/pm.h>
26
27#include <asm/hardware.h>
28#include <asm/irq.h>
29#include <asm/system.h>
30#include <asm/pgtable.h>
31#include <asm/mach/map.h>
32
33#include <asm/arch/pxa-regs.h>
34#include <asm/arch/udc.h>
35#include <asm/arch/pxafb.h>
36#include <asm/arch/mmc.h>
37
38#include "generic.h"
39
40/*
41 * Handy function to set GPIO alternate functions
42 */
43
44void pxa_gpio_mode(int gpio_mode)
45{
46 unsigned long flags;
47 int gpio = gpio_mode & GPIO_MD_MASK_NR;
48 int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
49 int gafr;
50
51 local_irq_save(flags);
52 if (gpio_mode & GPIO_DFLT_LOW)
53 GPCR(gpio) = GPIO_bit(gpio);
54 else if (gpio_mode & GPIO_DFLT_HIGH)
55 GPSR(gpio) = GPIO_bit(gpio);
56 if (gpio_mode & GPIO_MD_MASK_DIR)
57 GPDR(gpio) |= GPIO_bit(gpio);
58 else
59 GPDR(gpio) &= ~GPIO_bit(gpio);
60 gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
61 GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2));
62 local_irq_restore(flags);
63}
64
65EXPORT_SYMBOL(pxa_gpio_mode);
66
67/*
68 * Routine to safely enable or disable a clock in the CKEN
69 */
70void pxa_set_cken(int clock, int enable)
71{
72 unsigned long flags;
73 local_irq_save(flags);
74
75 if (enable)
76 CKEN |= clock;
77 else
78 CKEN &= ~clock;
79
80 local_irq_restore(flags);
81}
82
83EXPORT_SYMBOL(pxa_set_cken);
84
85/*
86 * Intel PXA2xx internal register mapping.
87 *
88 * Note 1: not all PXA2xx variants implement all those addresses.
89 *
90 * Note 2: virtual 0xfffe0000-0xffffffff is reserved for the vector table
91 * and cache flush area.
92 */
93static struct map_desc standard_io_desc[] __initdata = {
94 /* virtual physical length type */
95 { 0xf2000000, 0x40000000, 0x02000000, MT_DEVICE }, /* Devs */
96 { 0xf4000000, 0x44000000, 0x00100000, MT_DEVICE }, /* LCD */
97 { 0xf6000000, 0x48000000, 0x00100000, MT_DEVICE }, /* Mem Ctl */
98 { 0xf8000000, 0x4c000000, 0x00100000, MT_DEVICE }, /* USB host */
99 { 0xfa000000, 0x50000000, 0x00100000, MT_DEVICE }, /* Camera */
100 { 0xfe000000, 0x58000000, 0x00100000, MT_DEVICE }, /* IMem ctl */
101 { 0xff000000, 0x00000000, 0x00100000, MT_DEVICE } /* UNCACHED_PHYS_0 */
102};
103
104void __init pxa_map_io(void)
105{
106 iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
107 get_clk_frequency_khz(1);
108}
109
110
111static struct resource pxamci_resources[] = {
112 [0] = {
113 .start = 0x41100000,
114 .end = 0x41100fff,
115 .flags = IORESOURCE_MEM,
116 },
117 [1] = {
118 .start = IRQ_MMC,
119 .end = IRQ_MMC,
120 .flags = IORESOURCE_IRQ,
121 },
122};
123
124static u64 pxamci_dmamask = 0xffffffffUL;
125
126static struct platform_device pxamci_device = {
127 .name = "pxa2xx-mci",
128 .id = -1,
129 .dev = {
130 .dma_mask = &pxamci_dmamask,
131 .coherent_dma_mask = 0xffffffff,
132 },
133 .num_resources = ARRAY_SIZE(pxamci_resources),
134 .resource = pxamci_resources,
135};
136
137void __init pxa_set_mci_info(struct pxamci_platform_data *info)
138{
139 pxamci_device.dev.platform_data = info;
140}
141
142
143static struct pxa2xx_udc_mach_info pxa_udc_info;
144
145void __init pxa_set_udc_info(struct pxa2xx_udc_mach_info *info)
146{
147 memcpy(&pxa_udc_info, info, sizeof *info);
148}
149
150static struct resource pxa2xx_udc_resources[] = {
151 [0] = {
152 .start = 0x40600000,
153 .end = 0x4060ffff,
154 .flags = IORESOURCE_MEM,
155 },
156 [1] = {
157 .start = IRQ_USB,
158 .end = IRQ_USB,
159 .flags = IORESOURCE_IRQ,
160 },
161};
162
163static u64 udc_dma_mask = ~(u32)0;
164
165static struct platform_device udc_device = {
166 .name = "pxa2xx-udc",
167 .id = -1,
168 .resource = pxa2xx_udc_resources,
169 .num_resources = ARRAY_SIZE(pxa2xx_udc_resources),
170 .dev = {
171 .platform_data = &pxa_udc_info,
172 .dma_mask = &udc_dma_mask,
173 }
174};
175
176static struct pxafb_mach_info pxa_fb_info;
177
178void __init set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info)
179{
180 memcpy(&pxa_fb_info,hard_pxa_fb_info,sizeof(struct pxafb_mach_info));
181}
182
183static struct resource pxafb_resources[] = {
184 [0] = {
185 .start = 0x44000000,
186 .end = 0x4400ffff,
187 .flags = IORESOURCE_MEM,
188 },
189 [1] = {
190 .start = IRQ_LCD,
191 .end = IRQ_LCD,
192 .flags = IORESOURCE_IRQ,
193 },
194};
195
196static u64 fb_dma_mask = ~(u64)0;
197
198static struct platform_device pxafb_device = {
199 .name = "pxa2xx-fb",
200 .id = -1,
201 .dev = {
202 .platform_data = &pxa_fb_info,
203 .dma_mask = &fb_dma_mask,
204 .coherent_dma_mask = 0xffffffff,
205 },
206 .num_resources = ARRAY_SIZE(pxafb_resources),
207 .resource = pxafb_resources,
208};
209
210static struct platform_device ffuart_device = {
211 .name = "pxa2xx-uart",
212 .id = 0,
213};
214static struct platform_device btuart_device = {
215 .name = "pxa2xx-uart",
216 .id = 1,
217};
218static struct platform_device stuart_device = {
219 .name = "pxa2xx-uart",
220 .id = 2,
221};
222
223static struct platform_device *devices[] __initdata = {
224 &pxamci_device,
225 &udc_device,
226 &pxafb_device,
227 &ffuart_device,
228 &btuart_device,
229 &stuart_device,
230};
231
232static int __init pxa_init(void)
233{
234 return platform_add_devices(devices, ARRAY_SIZE(devices));
235}
236
237subsys_initcall(pxa_init);
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
new file mode 100644
index 000000000000..e54a8dd63c17
--- /dev/null
+++ b/arch/arm/mach-pxa/generic.h
@@ -0,0 +1,24 @@
1/*
2 * linux/arch/arm/mach-pxa/generic.h
3 *
4 * Author: Nicolas Pitre
5 * Copyright: MontaVista Software Inc.
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
12struct sys_timer;
13
14extern struct sys_timer pxa_timer;
15extern void __init pxa_map_io(void);
16extern void __init pxa_init_irq(void);
17
18extern unsigned int get_clk_frequency_khz(int info);
19
20#define SET_BANK(__nr,__start,__size) \
21 mi->bank[__nr].start = (__start), \
22 mi->bank[__nr].size = (__size), \
23 mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
24
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
new file mode 100644
index 000000000000..c5a66bf4d3d5
--- /dev/null
+++ b/arch/arm/mach-pxa/idp.c
@@ -0,0 +1,190 @@
1/*
2 * linux/arch/arm/mach-pxa/idp.c
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
9 *
10 * 2001-09-13: Cliff Brake <cbrake@accelent.com>
11 * Initial code
12 *
13 * 2005-02-15: Cliff Brake <cliff.brake@gmail.com>
14 * <http://www.vibren.com> <http://bec-systems.com>
15 * Updated for 2.6 kernel
16 *
17 */
18
19#include <linux/init.h>
20#include <linux/interrupt.h>
21#include <linux/device.h>
22#include <linux/fb.h>
23
24#include <asm/setup.h>
25#include <asm/memory.h>
26#include <asm/mach-types.h>
27#include <asm/hardware.h>
28#include <asm/irq.h>
29
30#include <asm/mach/arch.h>
31#include <asm/mach/map.h>
32
33#include <asm/arch/pxa-regs.h>
34#include <asm/arch/idp.h>
35#include <asm/arch/pxafb.h>
36#include <asm/arch/bitfield.h>
37#include <asm/arch/mmc.h>
38
39#include "generic.h"
40
41/* TODO:
42 * - add pxa2xx_audio_ops_t device structure
43 * - Ethernet interrupt
44 */
45
46static struct resource smc91x_resources[] = {
47 [0] = {
48 .start = (IDP_ETH_PHYS + 0x300),
49 .end = (IDP_ETH_PHYS + 0xfffff),
50 .flags = IORESOURCE_MEM,
51 },
52 [1] = {
53 .start = IRQ_GPIO(4),
54 .end = IRQ_GPIO(4),
55 .flags = IORESOURCE_IRQ,
56 }
57};
58
59static struct platform_device smc91x_device = {
60 .name = "smc91x",
61 .id = 0,
62 .num_resources = ARRAY_SIZE(smc91x_resources),
63 .resource = smc91x_resources,
64};
65
66static void idp_backlight_power(int on)
67{
68 if (on) {
69 IDP_CPLD_LCD |= (1<<1);
70 } else {
71 IDP_CPLD_LCD &= ~(1<<1);
72 }
73}
74
75static void idp_vlcd(int on)
76{
77 if (on) {
78 IDP_CPLD_LCD |= (1<<2);
79 } else {
80 IDP_CPLD_LCD &= ~(1<<2);
81 }
82}
83
84static void idp_lcd_power(int on)
85{
86 if (on) {
87 IDP_CPLD_LCD |= (1<<0);
88 } else {
89 IDP_CPLD_LCD &= ~(1<<0);
90 }
91
92 /* call idp_vlcd for now as core driver does not support
93 * both power and vlcd hooks. Note, this is not technically
94 * the correct sequence, but seems to work. Disclaimer:
95 * this may eventually damage the display.
96 */
97
98 idp_vlcd(on);
99}
100
101static struct pxafb_mach_info sharp_lm8v31 __initdata = {
102 .pixclock = 270000,
103 .xres = 640,
104 .yres = 480,
105 .bpp = 16,
106 .hsync_len = 1,
107 .left_margin = 3,
108 .right_margin = 3,
109 .vsync_len = 1,
110 .upper_margin = 0,
111 .lower_margin = 0,
112 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
113 .cmap_greyscale = 0,
114 .cmap_inverse = 0,
115 .cmap_static = 0,
116 .lccr0 = LCCR0_SDS,
117 .lccr3 = LCCR3_PCP | LCCR3_Acb(255),
118 .pxafb_backlight_power = &idp_backlight_power,
119 .pxafb_lcd_power = &idp_lcd_power
120};
121
122static int idp_mci_init(struct device *dev, irqreturn_t (*idp_detect_int)(int, void *, struct pt_regs *), void *data)
123{
124 /* setup GPIO for PXA25x MMC controller */
125 pxa_gpio_mode(GPIO6_MMCCLK_MD);
126 pxa_gpio_mode(GPIO8_MMCCS0_MD);
127
128 return 0;
129}
130
131static struct pxamci_platform_data idp_mci_platform_data = {
132 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
133 .init = idp_mci_init,
134};
135
136static void __init idp_init(void)
137{
138 printk("idp_init()\n");
139
140 platform_device_register(&smc91x_device);
141 //platform_device_register(&mst_audio_device);
142 set_pxa_fb_info(&sharp_lm8v31);
143 pxa_set_mci_info(&idp_mci_platform_data);
144}
145
146static void __init idp_init_irq(void)
147{
148
149 pxa_init_irq();
150
151 set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
152}
153
154static struct map_desc idp_io_desc[] __initdata = {
155 /* virtual physical length type */
156
157 { IDP_COREVOLT_VIRT,
158 IDP_COREVOLT_PHYS,
159 IDP_COREVOLT_SIZE,
160 MT_DEVICE },
161 { IDP_CPLD_VIRT,
162 IDP_CPLD_PHYS,
163 IDP_CPLD_SIZE,
164 MT_DEVICE }
165};
166
167static void __init idp_map_io(void)
168{
169 pxa_map_io();
170 iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
171
172 // serial ports 2 & 3
173 pxa_gpio_mode(GPIO42_BTRXD_MD);
174 pxa_gpio_mode(GPIO43_BTTXD_MD);
175 pxa_gpio_mode(GPIO44_BTCTS_MD);
176 pxa_gpio_mode(GPIO45_BTRTS_MD);
177 pxa_gpio_mode(GPIO46_STRXD_MD);
178 pxa_gpio_mode(GPIO47_STTXD_MD);
179
180}
181
182
183MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
184 MAINTAINER("Vibren Technologies")
185 BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
186 MAPIO(idp_map_io)
187 INITIRQ(idp_init_irq)
188 .timer = &pxa_timer,
189 INIT_MACHINE(idp_init)
190MACHINE_END
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
new file mode 100644
index 000000000000..f3cac43124a5
--- /dev/null
+++ b/arch/arm/mach-pxa/irq.c
@@ -0,0 +1,313 @@
1/*
2 * linux/arch/arm/mach-pxa/irq.c
3 *
4 * Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc.
5 *
6 * Author: Nicolas Pitre
7 * Created: Jun 15, 2001
8 * Copyright: MontaVista Software Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/interrupt.h>
18#include <linux/ptrace.h>
19
20#include <asm/hardware.h>
21#include <asm/irq.h>
22#include <asm/mach/irq.h>
23#include <asm/arch/pxa-regs.h>
24
25#include "generic.h"
26
27
28/*
29 * This is for peripheral IRQs internal to the PXA chip.
30 */
31
32static void pxa_mask_low_irq(unsigned int irq)
33{
34 ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
35}
36
37static void pxa_unmask_low_irq(unsigned int irq)
38{
39 ICMR |= (1 << (irq + PXA_IRQ_SKIP));
40}
41
42static struct irqchip pxa_internal_chip_low = {
43 .ack = pxa_mask_low_irq,
44 .mask = pxa_mask_low_irq,
45 .unmask = pxa_unmask_low_irq,
46};
47
48#if PXA_INTERNAL_IRQS > 32
49
50/*
51 * This is for the second set of internal IRQs as found on the PXA27x.
52 */
53
54static void pxa_mask_high_irq(unsigned int irq)
55{
56 ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
57}
58
59static void pxa_unmask_high_irq(unsigned int irq)
60{
61 ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
62}
63
64static struct irqchip pxa_internal_chip_high = {
65 .ack = pxa_mask_high_irq,
66 .mask = pxa_mask_high_irq,
67 .unmask = pxa_unmask_high_irq,
68};
69
70#endif
71
72/*
73 * PXA GPIO edge detection for IRQs:
74 * IRQs are generated on Falling-Edge, Rising-Edge, or both.
75 * Use this instead of directly setting GRER/GFER.
76 */
77
78static long GPIO_IRQ_rising_edge[4];
79static long GPIO_IRQ_falling_edge[4];
80static long GPIO_IRQ_mask[4];
81
82static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
83{
84 int gpio, idx;
85
86 gpio = IRQ_TO_GPIO(irq);
87 idx = gpio >> 5;
88
89 if (type == IRQT_PROBE) {
90 /* Don't mess with enabled GPIOs using preconfigured edges or
91 GPIOs set to alternate function during probe */
92 if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx]) &
93 GPIO_bit(gpio))
94 return 0;
95 if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2)))
96 return 0;
97 type = __IRQT_RISEDGE | __IRQT_FALEDGE;
98 }
99
100 /* printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio); */
101
102 pxa_gpio_mode(gpio | GPIO_IN);
103
104 if (type & __IRQT_RISEDGE) {
105 /* printk("rising "); */
106 __set_bit (gpio, GPIO_IRQ_rising_edge);
107 } else
108 __clear_bit (gpio, GPIO_IRQ_rising_edge);
109
110 if (type & __IRQT_FALEDGE) {
111 /* printk("falling "); */
112 __set_bit (gpio, GPIO_IRQ_falling_edge);
113 } else
114 __clear_bit (gpio, GPIO_IRQ_falling_edge);
115
116 /* printk("edges\n"); */
117
118 GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
119 GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
120 return 0;
121}
122
123/*
124 * GPIO IRQs must be acknowledged. This is for GPIO 0 and 1.
125 */
126
127static void pxa_ack_low_gpio(unsigned int irq)
128{
129 GEDR0 = (1 << (irq - IRQ_GPIO0));
130}
131
132static struct irqchip pxa_low_gpio_chip = {
133 .ack = pxa_ack_low_gpio,
134 .mask = pxa_mask_low_irq,
135 .unmask = pxa_unmask_low_irq,
136 .type = pxa_gpio_irq_type,
137};
138
139/*
140 * Demux handler for GPIO>=2 edge detect interrupts
141 */
142
143static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
144 struct pt_regs *regs)
145{
146 unsigned int mask;
147 int loop;
148
149 do {
150 loop = 0;
151
152 mask = GEDR0 & ~3;
153 if (mask) {
154 GEDR0 = mask;
155 irq = IRQ_GPIO(2);
156 desc = irq_desc + irq;
157 mask >>= 2;
158 do {
159 if (mask & 1)
160 desc->handle(irq, desc, regs);
161 irq++;
162 desc++;
163 mask >>= 1;
164 } while (mask);
165 loop = 1;
166 }
167
168 mask = GEDR1;
169 if (mask) {
170 GEDR1 = mask;
171 irq = IRQ_GPIO(32);
172 desc = irq_desc + irq;
173 do {
174 if (mask & 1)
175 desc->handle(irq, desc, regs);
176 irq++;
177 desc++;
178 mask >>= 1;
179 } while (mask);
180 loop = 1;
181 }
182
183 mask = GEDR2;
184 if (mask) {
185 GEDR2 = mask;
186 irq = IRQ_GPIO(64);
187 desc = irq_desc + irq;
188 do {
189 if (mask & 1)
190 desc->handle(irq, desc, regs);
191 irq++;
192 desc++;
193 mask >>= 1;
194 } while (mask);
195 loop = 1;
196 }
197
198#if PXA_LAST_GPIO >= 96
199 mask = GEDR3;
200 if (mask) {
201 GEDR3 = mask;
202 irq = IRQ_GPIO(96);
203 desc = irq_desc + irq;
204 do {
205 if (mask & 1)
206 desc->handle(irq, desc, regs);
207 irq++;
208 desc++;
209 mask >>= 1;
210 } while (mask);
211 loop = 1;
212 }
213#endif
214 } while (loop);
215}
216
217static void pxa_ack_muxed_gpio(unsigned int irq)
218{
219 int gpio = irq - IRQ_GPIO(2) + 2;
220 GEDR(gpio) = GPIO_bit(gpio);
221}
222
223static void pxa_mask_muxed_gpio(unsigned int irq)
224{
225 int gpio = irq - IRQ_GPIO(2) + 2;
226 __clear_bit(gpio, GPIO_IRQ_mask);
227 GRER(gpio) &= ~GPIO_bit(gpio);
228 GFER(gpio) &= ~GPIO_bit(gpio);
229}
230
231static void pxa_unmask_muxed_gpio(unsigned int irq)
232{
233 int gpio = irq - IRQ_GPIO(2) + 2;
234 int idx = gpio >> 5;
235 __set_bit(gpio, GPIO_IRQ_mask);
236 GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
237 GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
238}
239
240static struct irqchip pxa_muxed_gpio_chip = {
241 .ack = pxa_ack_muxed_gpio,
242 .mask = pxa_mask_muxed_gpio,
243 .unmask = pxa_unmask_muxed_gpio,
244 .type = pxa_gpio_irq_type,
245};
246
247
248void __init pxa_init_irq(void)
249{
250 int irq;
251
252 /* disable all IRQs */
253 ICMR = 0;
254
255 /* all IRQs are IRQ, not FIQ */
256 ICLR = 0;
257
258 /* clear all GPIO edge detects */
259 GFER0 = 0;
260 GFER1 = 0;
261 GFER2 = 0;
262 GRER0 = 0;
263 GRER1 = 0;
264 GRER2 = 0;
265 GEDR0 = GEDR0;
266 GEDR1 = GEDR1;
267 GEDR2 = GEDR2;
268
269#ifdef CONFIG_PXA27x
270 /* And similarly for the extra regs on the PXA27x */
271 ICMR2 = 0;
272 ICLR2 = 0;
273 GFER3 = 0;
274 GRER3 = 0;
275 GEDR3 = GEDR3;
276#endif
277
278 /* only unmasked interrupts kick us out of idle */
279 ICCR = 1;
280
281 /* GPIO 0 and 1 must have their mask bit always set */
282 GPIO_IRQ_mask[0] = 3;
283
284 for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
285 set_irq_chip(irq, &pxa_internal_chip_low);
286 set_irq_handler(irq, do_level_IRQ);
287 set_irq_flags(irq, IRQF_VALID);
288 }
289
290#if PXA_INTERNAL_IRQS > 32
291 for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
292 set_irq_chip(irq, &pxa_internal_chip_high);
293 set_irq_handler(irq, do_level_IRQ);
294 set_irq_flags(irq, IRQF_VALID);
295 }
296#endif
297
298 for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
299 set_irq_chip(irq, &pxa_low_gpio_chip);
300 set_irq_handler(irq, do_edge_IRQ);
301 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
302 }
303
304 for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
305 set_irq_chip(irq, &pxa_muxed_gpio_chip);
306 set_irq_handler(irq, do_edge_IRQ);
307 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
308 }
309
310 /* Install handler for GPIO>=2 edge detect interrupts */
311 set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
312 set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
313}
diff --git a/arch/arm/mach-pxa/leds-idp.c b/arch/arm/mach-pxa/leds-idp.c
new file mode 100644
index 000000000000..5eba6ea0b0f7
--- /dev/null
+++ b/arch/arm/mach-pxa/leds-idp.c
@@ -0,0 +1,117 @@
1/*
2 * linux/arch/arm/mach-pxa/leds-idp.c
3 *
4 * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
5 *
6 * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
7 *
8 * Original (leds-footbridge.c) by Russell King
9 *
10 * Macros for actual LED manipulation should be in machine specific
11 * files in this 'mach' directory.
12 */
13
14
15#include <linux/config.h>
16#include <linux/init.h>
17
18#include <asm/hardware.h>
19#include <asm/leds.h>
20#include <asm/system.h>
21
22#include <asm/arch/pxa-regs.h>
23#include <asm/arch/idp.h>
24
25#include "leds.h"
26
27#define LED_STATE_ENABLED 1
28#define LED_STATE_CLAIMED 2
29
30static unsigned int led_state;
31static unsigned int hw_led_state;
32
33void idp_leds_event(led_event_t evt)
34{
35 unsigned long flags;
36
37 local_irq_save(flags);
38
39 switch (evt) {
40 case led_start:
41 hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
42 led_state = LED_STATE_ENABLED;
43 break;
44
45 case led_stop:
46 led_state &= ~LED_STATE_ENABLED;
47 break;
48
49 case led_claim:
50 led_state |= LED_STATE_CLAIMED;
51 hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
52 break;
53
54 case led_release:
55 led_state &= ~LED_STATE_CLAIMED;
56 hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
57 break;
58
59#ifdef CONFIG_LEDS_TIMER
60 case led_timer:
61 if (!(led_state & LED_STATE_CLAIMED))
62 hw_led_state ^= IDP_HB_LED;
63 break;
64#endif
65
66#ifdef CONFIG_LEDS_CPU
67 case led_idle_start:
68 if (!(led_state & LED_STATE_CLAIMED))
69 hw_led_state &= ~IDP_BUSY_LED;
70 break;
71
72 case led_idle_end:
73 if (!(led_state & LED_STATE_CLAIMED))
74 hw_led_state |= IDP_BUSY_LED;
75 break;
76#endif
77
78 case led_halted:
79 break;
80
81 case led_green_on:
82 if (led_state & LED_STATE_CLAIMED)
83 hw_led_state |= IDP_HB_LED;
84 break;
85
86 case led_green_off:
87 if (led_state & LED_STATE_CLAIMED)
88 hw_led_state &= ~IDP_HB_LED;
89 break;
90
91 case led_amber_on:
92 break;
93
94 case led_amber_off:
95 break;
96
97 case led_red_on:
98 if (led_state & LED_STATE_CLAIMED)
99 hw_led_state |= IDP_BUSY_LED;
100 break;
101
102 case led_red_off:
103 if (led_state & LED_STATE_CLAIMED)
104 hw_led_state &= ~IDP_BUSY_LED;
105 break;
106
107 default:
108 break;
109 }
110
111 if (led_state & LED_STATE_ENABLED)
112 IDP_CPLD_LED_CONTROL = ( (IDP_CPLD_LED_CONTROL | IDP_LEDS_MASK) & ~hw_led_state);
113 else
114 IDP_CPLD_LED_CONTROL |= IDP_LEDS_MASK;
115
116 local_irq_restore(flags);
117}
diff --git a/arch/arm/mach-pxa/leds-lubbock.c b/arch/arm/mach-pxa/leds-lubbock.c
new file mode 100644
index 000000000000..05cf56059a0f
--- /dev/null
+++ b/arch/arm/mach-pxa/leds-lubbock.c
@@ -0,0 +1,126 @@
1/*
2 * linux/arch/arm/mach-pxa/leds-lubbock.c
3 *
4 * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
5 *
6 * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
7 *
8 * Original (leds-footbridge.c) by Russell King
9 *
10 * Major surgery on April 2004 by Nicolas Pitre for less global
11 * namespace collision. Mostly adapted the Mainstone version.
12 */
13
14#include <linux/config.h>
15#include <linux/init.h>
16
17#include <asm/hardware.h>
18#include <asm/leds.h>
19#include <asm/system.h>
20#include <asm/arch/pxa-regs.h>
21#include <asm/arch/lubbock.h>
22
23#include "leds.h"
24
25/*
26 * 8 discrete leds available for general use:
27 *
28 * Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays
29 * so be sure to not monkey with them here.
30 */
31
32#define D28 (1 << 0)
33#define D27 (1 << 1)
34#define D26 (1 << 2)
35#define D25 (1 << 3)
36#define D24 (1 << 4)
37#define D23 (1 << 5)
38#define D22 (1 << 6)
39#define D21 (1 << 7)
40
41#define LED_STATE_ENABLED 1
42#define LED_STATE_CLAIMED 2
43
44static unsigned int led_state;
45static unsigned int hw_led_state;
46
47void lubbock_leds_event(led_event_t evt)
48{
49 unsigned long flags;
50
51 local_irq_save(flags);
52
53 switch (evt) {
54 case led_start:
55 hw_led_state = 0;
56 led_state = LED_STATE_ENABLED;
57 break;
58
59 case led_stop:
60 led_state &= ~LED_STATE_ENABLED;
61 break;
62
63 case led_claim:
64 led_state |= LED_STATE_CLAIMED;
65 hw_led_state = 0;
66 break;
67
68 case led_release:
69 led_state &= ~LED_STATE_CLAIMED;
70 hw_led_state = 0;
71 break;
72
73#ifdef CONFIG_LEDS_TIMER
74 case led_timer:
75 hw_led_state ^= D26;
76 break;
77#endif
78
79#ifdef CONFIG_LEDS_CPU
80 case led_idle_start:
81 hw_led_state &= ~D27;
82 break;
83
84 case led_idle_end:
85 hw_led_state |= D27;
86 break;
87#endif
88
89 case led_halted:
90 break;
91
92 case led_green_on:
93 hw_led_state |= D21;
94 break;
95
96 case led_green_off:
97 hw_led_state &= ~D21;
98 break;
99
100 case led_amber_on:
101 hw_led_state |= D22;
102 break;
103
104 case led_amber_off:
105 hw_led_state &= ~D22;
106 break;
107
108 case led_red_on:
109 hw_led_state |= D23;
110 break;
111
112 case led_red_off:
113 hw_led_state &= ~D23;
114 break;
115
116 default:
117 break;
118 }
119
120 if (led_state & LED_STATE_ENABLED)
121 LUB_DISC_BLNK_LED = (LUB_DISC_BLNK_LED | 0xff) & ~hw_led_state;
122 else
123 LUB_DISC_BLNK_LED |= 0xff;
124
125 local_irq_restore(flags);
126}
diff --git a/arch/arm/mach-pxa/leds-mainstone.c b/arch/arm/mach-pxa/leds-mainstone.c
new file mode 100644
index 000000000000..bbd3f87a9fc2
--- /dev/null
+++ b/arch/arm/mach-pxa/leds-mainstone.c
@@ -0,0 +1,121 @@
1/*
2 * linux/arch/arm/mach-pxa/leds-mainstone.c
3 *
4 * Author: Nicolas Pitre
5 * Created: Nov 05, 2002
6 * Copyright: MontaVista Software Inc.
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
13#include <linux/config.h>
14#include <linux/init.h>
15
16#include <asm/hardware.h>
17#include <asm/leds.h>
18#include <asm/system.h>
19
20#include <asm/arch/pxa-regs.h>
21#include <asm/arch/mainstone.h>
22
23#include "leds.h"
24
25
26/* 8 discrete leds available for general use: */
27#define D28 (1 << 0)
28#define D27 (1 << 1)
29#define D26 (1 << 2)
30#define D25 (1 << 3)
31#define D24 (1 << 4)
32#define D23 (1 << 5)
33#define D22 (1 << 6)
34#define D21 (1 << 7)
35
36#define LED_STATE_ENABLED 1
37#define LED_STATE_CLAIMED 2
38
39static unsigned int led_state;
40static unsigned int hw_led_state;
41
42void mainstone_leds_event(led_event_t evt)
43{
44 unsigned long flags;
45
46 local_irq_save(flags);
47
48 switch (evt) {
49 case led_start:
50 hw_led_state = 0;
51 led_state = LED_STATE_ENABLED;
52 break;
53
54 case led_stop:
55 led_state &= ~LED_STATE_ENABLED;
56 break;
57
58 case led_claim:
59 led_state |= LED_STATE_CLAIMED;
60 hw_led_state = 0;
61 break;
62
63 case led_release:
64 led_state &= ~LED_STATE_CLAIMED;
65 hw_led_state = 0;
66 break;
67
68#ifdef CONFIG_LEDS_TIMER
69 case led_timer:
70 hw_led_state ^= D26;
71 break;
72#endif
73
74#ifdef CONFIG_LEDS_CPU
75 case led_idle_start:
76 hw_led_state &= ~D27;
77 break;
78
79 case led_idle_end:
80 hw_led_state |= D27;
81 break;
82#endif
83
84 case led_halted:
85 break;
86
87 case led_green_on:
88 hw_led_state |= D21;;
89 break;
90
91 case led_green_off:
92 hw_led_state &= ~D21;
93 break;
94
95 case led_amber_on:
96 hw_led_state |= D22;;
97 break;
98
99 case led_amber_off:
100 hw_led_state &= ~D22;
101 break;
102
103 case led_red_on:
104 hw_led_state |= D23;;
105 break;
106
107 case led_red_off:
108 hw_led_state &= ~D23;
109 break;
110
111 default:
112 break;
113 }
114
115 if (led_state & LED_STATE_ENABLED)
116 MST_LEDCTRL = (MST_LEDCTRL | 0xff) & ~hw_led_state;
117 else
118 MST_LEDCTRL |= 0xff;
119
120 local_irq_restore(flags);
121}
diff --git a/arch/arm/mach-pxa/leds.c b/arch/arm/mach-pxa/leds.c
new file mode 100644
index 000000000000..bbe4d5f6afaa
--- /dev/null
+++ b/arch/arm/mach-pxa/leds.c
@@ -0,0 +1,32 @@
1/*
2 * linux/arch/arm/mach-pxa/leds.c
3 *
4 * xscale LEDs dispatcher
5 *
6 * Copyright (C) 2001 Nicolas Pitre
7 *
8 * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
9 */
10#include <linux/compiler.h>
11#include <linux/init.h>
12
13#include <asm/leds.h>
14#include <asm/mach-types.h>
15
16#include "leds.h"
17
18static int __init
19pxa_leds_init(void)
20{
21 if (machine_is_lubbock())
22 leds_event = lubbock_leds_event;
23 if (machine_is_mainstone())
24 leds_event = mainstone_leds_event;
25 if (machine_is_pxa_idp())
26 leds_event = idp_leds_event;
27
28 leds_event(led_start);
29 return 0;
30}
31
32core_initcall(pxa_leds_init);
diff --git a/arch/arm/mach-pxa/leds.h b/arch/arm/mach-pxa/leds.h
new file mode 100644
index 000000000000..d98f6e93c12b
--- /dev/null
+++ b/arch/arm/mach-pxa/leds.h
@@ -0,0 +1,12 @@
1/*
2 * include/asm-arm/arch-pxa/leds.h
3 *
4 * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
5 *
6 * blinky lights for various PXA-based systems:
7 *
8 */
9
10extern void idp_leds_event(led_event_t evt);
11extern void lubbock_leds_event(led_event_t evt);
12extern void mainstone_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
new file mode 100644
index 000000000000..dd012d6e2f5c
--- /dev/null
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -0,0 +1,247 @@
1/*
2 * linux/arch/arm/mach-pxa/lubbock.c
3 *
4 * Support for the Intel DBPXA250 Development Platform.
5 *
6 * Author: Nicolas Pitre
7 * Created: Jun 15, 2001
8 * Copyright: MontaVista Software Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/device.h>
18#include <linux/major.h>
19#include <linux/fb.h>
20#include <linux/interrupt.h>
21
22#include <asm/setup.h>
23#include <asm/memory.h>
24#include <asm/mach-types.h>
25#include <asm/hardware.h>
26#include <asm/irq.h>
27
28#include <asm/mach/arch.h>
29#include <asm/mach/map.h>
30#include <asm/mach/irq.h>
31
32#include <asm/hardware/sa1111.h>
33
34#include <asm/arch/pxa-regs.h>
35#include <asm/arch/lubbock.h>
36#include <asm/arch/udc.h>
37#include <asm/arch/pxafb.h>
38#include <asm/arch/mmc.h>
39
40#include "generic.h"
41
42
43#define LUB_MISC_WR __LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
44
45void lubbock_set_misc_wr(unsigned int mask, unsigned int set)
46{
47 unsigned long flags;
48
49 local_irq_save(flags);
50 LUB_MISC_WR = (LUB_MISC_WR & ~mask) | (set & mask);
51 local_irq_restore(flags);
52}
53EXPORT_SYMBOL(lubbock_set_misc_wr);
54
55static unsigned long lubbock_irq_enabled;
56
57static void lubbock_mask_irq(unsigned int irq)
58{
59 int lubbock_irq = (irq - LUBBOCK_IRQ(0));
60 LUB_IRQ_MASK_EN = (lubbock_irq_enabled &= ~(1 << lubbock_irq));
61}
62
63static void lubbock_unmask_irq(unsigned int irq)
64{
65 int lubbock_irq = (irq - LUBBOCK_IRQ(0));
66 /* the irq can be acknowledged only if deasserted, so it's done here */
67 LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
68 LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq));
69}
70
71static struct irqchip lubbock_irq_chip = {
72 .ack = lubbock_mask_irq,
73 .mask = lubbock_mask_irq,
74 .unmask = lubbock_unmask_irq,
75};
76
77static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
78 struct pt_regs *regs)
79{
80 unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
81 do {
82 GEDR(0) = GPIO_bit(0); /* clear our parent irq */
83 if (likely(pending)) {
84 irq = LUBBOCK_IRQ(0) + __ffs(pending);
85 desc = irq_desc + irq;
86 desc->handle(irq, desc, regs);
87 }
88 pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
89 } while (pending);
90}
91
92static void __init lubbock_init_irq(void)
93{
94 int irq;
95
96 pxa_init_irq();
97
98 /* setup extra lubbock irqs */
99 for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
100 set_irq_chip(irq, &lubbock_irq_chip);
101 set_irq_handler(irq, do_level_IRQ);
102 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
103 }
104
105 set_irq_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
106 set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
107}
108
109static int lubbock_udc_is_connected(void)
110{
111 return (LUB_MISC_RD & (1 << 9)) == 0;
112}
113
114static struct pxa2xx_udc_mach_info udc_info __initdata = {
115 .udc_is_connected = lubbock_udc_is_connected,
116 // no D+ pullup; lubbock can't connect/disconnect in software
117};
118
119static struct resource sa1111_resources[] = {
120 [0] = {
121 .start = 0x10000000,
122 .end = 0x10001fff,
123 .flags = IORESOURCE_MEM,
124 },
125 [1] = {
126 .start = LUBBOCK_SA1111_IRQ,
127 .end = LUBBOCK_SA1111_IRQ,
128 .flags = IORESOURCE_IRQ,
129 },
130};
131
132static struct platform_device sa1111_device = {
133 .name = "sa1111",
134 .id = -1,
135 .num_resources = ARRAY_SIZE(sa1111_resources),
136 .resource = sa1111_resources,
137};
138
139static struct resource smc91x_resources[] = {
140 [0] = {
141 .name = "smc91x-regs",
142 .start = 0x0c000000,
143 .end = 0x0c0fffff,
144 .flags = IORESOURCE_MEM,
145 },
146 [1] = {
147 .start = LUBBOCK_ETH_IRQ,
148 .end = LUBBOCK_ETH_IRQ,
149 .flags = IORESOURCE_IRQ,
150 },
151 [2] = {
152 .name = "smc91x-attrib",
153 .start = 0x0e000000,
154 .end = 0x0e0fffff,
155 .flags = IORESOURCE_MEM,
156 },
157};
158
159static struct platform_device smc91x_device = {
160 .name = "smc91x",
161 .id = -1,
162 .num_resources = ARRAY_SIZE(smc91x_resources),
163 .resource = smc91x_resources,
164};
165
166static struct platform_device *devices[] __initdata = {
167 &sa1111_device,
168 &smc91x_device,
169};
170
171static struct pxafb_mach_info sharp_lm8v31 __initdata = {
172 .pixclock = 270000,
173 .xres = 640,
174 .yres = 480,
175 .bpp = 16,
176 .hsync_len = 1,
177 .left_margin = 3,
178 .right_margin = 3,
179 .vsync_len = 1,
180 .upper_margin = 0,
181 .lower_margin = 0,
182 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
183 .cmap_greyscale = 0,
184 .cmap_inverse = 0,
185 .cmap_static = 0,
186 .lccr0 = LCCR0_SDS,
187 .lccr3 = LCCR3_PCP | LCCR3_Acb(255),
188};
189
190static int lubbock_mci_init(struct device *dev, irqreturn_t (*lubbock_detect_int)(int, void *, struct pt_regs *), void *data)
191{
192 /* setup GPIO for PXA25x MMC controller */
193 pxa_gpio_mode(GPIO6_MMCCLK_MD);
194 pxa_gpio_mode(GPIO8_MMCCS0_MD);
195
196 return 0;
197}
198
199static struct pxamci_platform_data lubbock_mci_platform_data = {
200 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
201 .init = lubbock_mci_init,
202};
203
204static void __init lubbock_init(void)
205{
206 pxa_set_udc_info(&udc_info);
207 set_pxa_fb_info(&sharp_lm8v31);
208 pxa_set_mci_info(&lubbock_mci_platform_data);
209 (void) platform_add_devices(devices, ARRAY_SIZE(devices));
210}
211
212static struct map_desc lubbock_io_desc[] __initdata = {
213 { LUBBOCK_FPGA_VIRT, LUBBOCK_FPGA_PHYS, 0x00100000, MT_DEVICE }, /* CPLD */
214};
215
216static void __init lubbock_map_io(void)
217{
218 pxa_map_io();
219 iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc));
220
221 /* This enables the BTUART */
222 pxa_gpio_mode(GPIO42_BTRXD_MD);
223 pxa_gpio_mode(GPIO43_BTTXD_MD);
224 pxa_gpio_mode(GPIO44_BTCTS_MD);
225 pxa_gpio_mode(GPIO45_BTRTS_MD);
226
227 /* This is for the SMC chip select */
228 pxa_gpio_mode(GPIO79_nCS_3_MD);
229
230 /* setup sleep mode values */
231 PWER = 0x00000002;
232 PFER = 0x00000000;
233 PRER = 0x00000002;
234 PGSR0 = 0x00008000;
235 PGSR1 = 0x003F0202;
236 PGSR2 = 0x0001C000;
237 PCFR |= PCFR_OPDE;
238}
239
240MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
241 MAINTAINER("MontaVista Software Inc.")
242 BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
243 MAPIO(lubbock_map_io)
244 INITIRQ(lubbock_init_irq)
245 .timer = &pxa_timer,
246 INIT_MACHINE(lubbock_init)
247MACHINE_END
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
new file mode 100644
index 000000000000..3f952237ae3d
--- /dev/null
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -0,0 +1,316 @@
1/*
2 * linux/arch/arm/mach-pxa/mainstone.c
3 *
4 * Support for the Intel HCDDBBVA0 Development Platform.
5 * (go figure how they came up with such name...)
6 *
7 * Author: Nicolas Pitre
8 * Created: Nov 05, 2002
9 * Copyright: MontaVista Software Inc.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/init.h>
17#include <linux/device.h>
18#include <linux/interrupt.h>
19#include <linux/sched.h>
20#include <linux/bitops.h>
21#include <linux/fb.h>
22
23#include <asm/types.h>
24#include <asm/setup.h>
25#include <asm/memory.h>
26#include <asm/mach-types.h>
27#include <asm/hardware.h>
28#include <asm/irq.h>
29
30#include <asm/mach/arch.h>
31#include <asm/mach/map.h>
32#include <asm/mach/irq.h>
33
34#include <asm/arch/pxa-regs.h>
35#include <asm/arch/mainstone.h>
36#include <asm/arch/audio.h>
37#include <asm/arch/pxafb.h>
38#include <asm/arch/mmc.h>
39
40#include "generic.h"
41
42
43static unsigned long mainstone_irq_enabled;
44
45static void mainstone_mask_irq(unsigned int irq)
46{
47 int mainstone_irq = (irq - MAINSTONE_IRQ(0));
48 MST_INTMSKENA = (mainstone_irq_enabled &= ~(1 << mainstone_irq));
49}
50
51static void mainstone_unmask_irq(unsigned int irq)
52{
53 int mainstone_irq = (irq - MAINSTONE_IRQ(0));
54 /* the irq can be acknowledged only if deasserted, so it's done here */
55 MST_INTSETCLR &= ~(1 << mainstone_irq);
56 MST_INTMSKENA = (mainstone_irq_enabled |= (1 << mainstone_irq));
57}
58
59static struct irqchip mainstone_irq_chip = {
60 .ack = mainstone_mask_irq,
61 .mask = mainstone_mask_irq,
62 .unmask = mainstone_unmask_irq,
63};
64
65
66static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
67 struct pt_regs *regs)
68{
69 unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled;
70 do {
71 GEDR(0) = GPIO_bit(0); /* clear useless edge notification */
72 if (likely(pending)) {
73 irq = MAINSTONE_IRQ(0) + __ffs(pending);
74 desc = irq_desc + irq;
75 desc->handle(irq, desc, regs);
76 }
77 pending = MST_INTSETCLR & mainstone_irq_enabled;
78 } while (pending);
79}
80
81static void __init mainstone_init_irq(void)
82{
83 int irq;
84
85 pxa_init_irq();
86
87 /* setup extra Mainstone irqs */
88 for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
89 set_irq_chip(irq, &mainstone_irq_chip);
90 set_irq_handler(irq, do_level_IRQ);
91 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
92 }
93 set_irq_flags(MAINSTONE_IRQ(8), 0);
94 set_irq_flags(MAINSTONE_IRQ(12), 0);
95
96 MST_INTMSKENA = 0;
97 MST_INTSETCLR = 0;
98
99 set_irq_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
100 set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
101}
102
103
104static struct resource smc91x_resources[] = {
105 [0] = {
106 .start = (MST_ETH_PHYS + 0x300),
107 .end = (MST_ETH_PHYS + 0xfffff),
108 .flags = IORESOURCE_MEM,
109 },
110 [1] = {
111 .start = MAINSTONE_IRQ(3),
112 .end = MAINSTONE_IRQ(3),
113 .flags = IORESOURCE_IRQ,
114 }
115};
116
117static struct platform_device smc91x_device = {
118 .name = "smc91x",
119 .id = 0,
120 .num_resources = ARRAY_SIZE(smc91x_resources),
121 .resource = smc91x_resources,
122};
123
124static int mst_audio_startup(snd_pcm_substream_t *substream, void *priv)
125{
126 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
127 MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF;
128 return 0;
129}
130
131static void mst_audio_shutdown(snd_pcm_substream_t *substream, void *priv)
132{
133 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
134 MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
135}
136
137static long mst_audio_suspend_mask;
138
139static void mst_audio_suspend(void *priv)
140{
141 mst_audio_suspend_mask = MST_MSCWR2;
142 MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
143}
144
145static void mst_audio_resume(void *priv)
146{
147 MST_MSCWR2 &= mst_audio_suspend_mask | ~MST_MSCWR2_AC97_SPKROFF;
148}
149
150static pxa2xx_audio_ops_t mst_audio_ops = {
151 .startup = mst_audio_startup,
152 .shutdown = mst_audio_shutdown,
153 .suspend = mst_audio_suspend,
154 .resume = mst_audio_resume,
155};
156
157static struct platform_device mst_audio_device = {
158 .name = "pxa2xx-ac97",
159 .id = -1,
160 .dev = { .platform_data = &mst_audio_ops },
161};
162
163static void mainstone_backlight_power(int on)
164{
165 if (on) {
166 pxa_gpio_mode(GPIO16_PWM0_MD);
167 pxa_set_cken(CKEN0_PWM0, 1);
168 PWM_CTRL0 = 0;
169 PWM_PWDUTY0 = 0x3ff;
170 PWM_PERVAL0 = 0x3ff;
171 } else {
172 PWM_CTRL0 = 0;
173 PWM_PWDUTY0 = 0x0;
174 PWM_PERVAL0 = 0x3FF;
175 pxa_set_cken(CKEN0_PWM0, 0);
176 }
177}
178
179static struct pxafb_mach_info toshiba_ltm04c380k __initdata = {
180 .pixclock = 50000,
181 .xres = 640,
182 .yres = 480,
183 .bpp = 16,
184 .hsync_len = 1,
185 .left_margin = 0x9f,
186 .right_margin = 1,
187 .vsync_len = 44,
188 .upper_margin = 0,
189 .lower_margin = 0,
190 .sync = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
191 .lccr0 = LCCR0_Act,
192 .lccr3 = LCCR3_PCP,
193 .pxafb_backlight_power = mainstone_backlight_power,
194};
195
196static struct pxafb_mach_info toshiba_ltm035a776c __initdata = {
197 .pixclock = 110000,
198 .xres = 240,
199 .yres = 320,
200 .bpp = 16,
201 .hsync_len = 4,
202 .left_margin = 8,
203 .right_margin = 20,
204 .vsync_len = 3,
205 .upper_margin = 1,
206 .lower_margin = 10,
207 .sync = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
208 .lccr0 = LCCR0_Act,
209 .lccr3 = LCCR3_PCP,
210 .pxafb_backlight_power = mainstone_backlight_power,
211};
212
213static int mainstone_mci_init(struct device *dev, irqreturn_t (*mstone_detect_int)(int, void *, struct pt_regs *), void *data)
214{
215 int err;
216
217 /*
218 * setup GPIO for PXA27x MMC controller
219 */
220 pxa_gpio_mode(GPIO32_MMCCLK_MD);
221 pxa_gpio_mode(GPIO112_MMCCMD_MD);
222 pxa_gpio_mode(GPIO92_MMCDAT0_MD);
223 pxa_gpio_mode(GPIO109_MMCDAT1_MD);
224 pxa_gpio_mode(GPIO110_MMCDAT2_MD);
225 pxa_gpio_mode(GPIO111_MMCDAT3_MD);
226
227 /* make sure SD/Memory Stick multiplexer's signals
228 * are routed to MMC controller
229 */
230 MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL;
231
232 err = request_irq(MAINSTONE_MMC_IRQ, mstone_detect_int, SA_INTERRUPT,
233 "MMC card detect", data);
234 if (err) {
235 printk(KERN_ERR "mainstone_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
236 return -1;
237 }
238
239 return 0;
240}
241
242static void mainstone_mci_setpower(struct device *dev, unsigned int vdd)
243{
244 struct pxamci_platform_data* p_d = dev->platform_data;
245
246 if (( 1 << vdd) & p_d->ocr_mask) {
247 printk(KERN_DEBUG "%s: on\n", __FUNCTION__);
248 MST_MSCWR1 |= MST_MSCWR1_MMC_ON;
249 MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL;
250 } else {
251 printk(KERN_DEBUG "%s: off\n", __FUNCTION__);
252 MST_MSCWR1 &= ~MST_MSCWR1_MMC_ON;
253 }
254}
255
256static void mainstone_mci_exit(struct device *dev, void *data)
257{
258 free_irq(MAINSTONE_MMC_IRQ, data);
259}
260
261static struct pxamci_platform_data mainstone_mci_platform_data = {
262 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
263 .init = mainstone_mci_init,
264 .setpower = mainstone_mci_setpower,
265 .exit = mainstone_mci_exit,
266};
267
268static void __init mainstone_init(void)
269{
270 /*
271 * On Mainstone, we route AC97_SYSCLK via GPIO45 to
272 * the audio daughter card
273 */
274 pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD);
275
276 platform_device_register(&smc91x_device);
277 platform_device_register(&mst_audio_device);
278
279 /* reading Mainstone's "Virtual Configuration Register"
280 might be handy to select LCD type here */
281 if (0)
282 set_pxa_fb_info(&toshiba_ltm04c380k);
283 else
284 set_pxa_fb_info(&toshiba_ltm035a776c);
285
286 pxa_set_mci_info(&mainstone_mci_platform_data);
287}
288
289
290static struct map_desc mainstone_io_desc[] __initdata = {
291 { MST_FPGA_VIRT, MST_FPGA_PHYS, 0x00100000, MT_DEVICE }, /* CPLD */
292};
293
294static void __init mainstone_map_io(void)
295{
296 pxa_map_io();
297 iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
298
299 /* initialize sleep mode regs (wake-up sources, etc) */
300 PGSR0 = 0x00008800;
301 PGSR1 = 0x00000002;
302 PGSR2 = 0x0001FC00;
303 PGSR3 = 0x00001F81;
304 PWER = 0xC0000002;
305 PRER = 0x00000002;
306 PFER = 0x00000002;
307}
308
309MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
310 MAINTAINER("MontaVista Software Inc.")
311 BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
312 MAPIO(mainstone_map_io)
313 INITIRQ(mainstone_init_irq)
314 .timer = &pxa_timer,
315 INIT_MACHINE(mainstone_init)
316MACHINE_END
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
new file mode 100644
index 000000000000..82a4bf34c251
--- /dev/null
+++ b/arch/arm/mach-pxa/pm.c
@@ -0,0 +1,227 @@
1/*
2 * PXA250/210 Power Management Routines
3 *
4 * Original code for the SA11x0:
5 * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
6 *
7 * Modified for the PXA250 by Nicolas Pitre:
8 * Copyright (c) 2002 Monta Vista Software, Inc.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License.
12 */
13#include <linux/config.h>
14#include <linux/init.h>
15#include <linux/suspend.h>
16#include <linux/errno.h>
17#include <linux/time.h>
18
19#include <asm/hardware.h>
20#include <asm/memory.h>
21#include <asm/system.h>
22#include <asm/arch/pxa-regs.h>
23#include <asm/arch/lubbock.h>
24#include <asm/mach/time.h>
25
26
27/*
28 * Debug macros
29 */
30#undef DEBUG
31
32extern void pxa_cpu_suspend(void);
33extern void pxa_cpu_resume(void);
34
35#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
36#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
37
38#define RESTORE_GPLEVEL(n) do { \
39 GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
40 GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
41} while (0)
42
43/*
44 * List of global PXA peripheral registers to preserve.
45 * More ones like CP and general purpose register values are preserved
46 * with the stack pointer in sleep.S.
47 */
48enum { SLEEP_SAVE_START = 0,
49
50 SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
51 SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
52 SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
53 SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
54 SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
55
56 SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
57 SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
58 SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
59 SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U,
60
61 SLEEP_SAVE_PSTR,
62
63 SLEEP_SAVE_ICMR,
64 SLEEP_SAVE_CKEN,
65
66 SLEEP_SAVE_CKSUM,
67
68 SLEEP_SAVE_SIZE
69};
70
71
72static int pxa_pm_enter(suspend_state_t state)
73{
74 unsigned long sleep_save[SLEEP_SAVE_SIZE];
75 unsigned long checksum = 0;
76 struct timespec delta, rtc;
77 int i;
78
79 if (state != PM_SUSPEND_MEM)
80 return -EINVAL;
81
82#ifdef CONFIG_IWMMXT
83 /* force any iWMMXt context to ram **/
84 iwmmxt_task_disable(NULL);
85#endif
86
87 /* preserve current time */
88 rtc.tv_sec = RCNR;
89 rtc.tv_nsec = 0;
90 save_time_delta(&delta, &rtc);
91
92 SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
93 SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
94 SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
95 SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
96 SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
97
98 SAVE(GAFR0_L); SAVE(GAFR0_U);
99 SAVE(GAFR1_L); SAVE(GAFR1_U);
100 SAVE(GAFR2_L); SAVE(GAFR2_U);
101
102#ifdef CONFIG_PXA27x
103 SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
104 SAVE(GAFR3_L); SAVE(GAFR3_U);
105#endif
106
107 SAVE(ICMR);
108 ICMR = 0;
109
110 SAVE(CKEN);
111 CKEN = 0;
112
113 SAVE(PSTR);
114
115 /* Note: wake up source are set up in each machine specific files */
116
117 /* clear GPIO transition detect bits */
118 GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2;
119#ifdef CONFIG_PXA27x
120 GEDR3 = GEDR3;
121#endif
122
123 /* Clear sleep reset status */
124 RCSR = RCSR_SMR;
125
126 /* set resume return address */
127 PSPR = virt_to_phys(pxa_cpu_resume);
128
129 /* before sleeping, calculate and save a checksum */
130 for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
131 checksum += sleep_save[i];
132 sleep_save[SLEEP_SAVE_CKSUM] = checksum;
133
134 /* *** go zzz *** */
135 pxa_cpu_suspend();
136
137 /* after sleeping, validate the checksum */
138 checksum = 0;
139 for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
140 checksum += sleep_save[i];
141
142 /* if invalid, display message and wait for a hardware reset */
143 if (checksum != sleep_save[SLEEP_SAVE_CKSUM]) {
144#ifdef CONFIG_ARCH_LUBBOCK
145 LUB_HEXLED = 0xbadbadc5;
146#endif
147 while (1)
148 pxa_cpu_suspend();
149 }
150
151 /* ensure not to come back here if it wasn't intended */
152 PSPR = 0;
153
154 /* restore registers */
155 RESTORE(GAFR0_L); RESTORE(GAFR0_U);
156 RESTORE(GAFR1_L); RESTORE(GAFR1_U);
157 RESTORE(GAFR2_L); RESTORE(GAFR2_U);
158 RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
159 RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
160 RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
161 RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
162 RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
163
164#ifdef CONFIG_PXA27x
165 RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
166 RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
167#endif
168
169 PSSR = PSSR_RDH | PSSR_PH;
170
171 RESTORE(CKEN);
172
173 ICLR = 0;
174 ICCR = 1;
175 RESTORE(ICMR);
176
177 RESTORE(PSTR);
178
179 /* restore current time */
180 rtc.tv_sec = RCNR;
181 restore_time_delta(&delta, &rtc);
182
183#ifdef DEBUG
184 printk(KERN_DEBUG "*** made it back from resume\n");
185#endif
186
187 return 0;
188}
189
190unsigned long sleep_phys_sp(void *sp)
191{
192 return virt_to_phys(sp);
193}
194
195/*
196 * Called after processes are frozen, but before we shut down devices.
197 */
198static int pxa_pm_prepare(suspend_state_t state)
199{
200 return 0;
201}
202
203/*
204 * Called after devices are re-setup, but before processes are thawed.
205 */
206static int pxa_pm_finish(suspend_state_t state)
207{
208 return 0;
209}
210
211/*
212 * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
213 */
214static struct pm_ops pxa_pm_ops = {
215 .pm_disk_mode = PM_DISK_FIRMWARE,
216 .prepare = pxa_pm_prepare,
217 .enter = pxa_pm_enter,
218 .finish = pxa_pm_finish,
219};
220
221static int __init pxa_pm_init(void)
222{
223 pm_set_ops(&pxa_pm_ops);
224 return 0;
225}
226
227late_initcall(pxa_pm_init);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
new file mode 100644
index 000000000000..b6c746ea3830
--- /dev/null
+++ b/arch/arm/mach-pxa/poodle.c
@@ -0,0 +1,189 @@
1/*
2 * linux/arch/arm/mach-pxa/poodle.c
3 *
4 * Support for the SHARP Poodle Board.
5 *
6 * Based on:
7 * linux/arch/arm/mach-pxa/lubbock.c Author: Nicolas Pitre
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 * Change Log
14 * 12-Dec-2002 Sharp Corporation for Poodle
15 * John Lenz <lenz@cs.wisc.edu> updates to 2.6
16 */
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/device.h>
20#include <linux/fb.h>
21
22#include <asm/hardware.h>
23#include <asm/mach-types.h>
24#include <asm/irq.h>
25#include <asm/setup.h>
26
27#include <asm/mach/arch.h>
28#include <asm/mach/map.h>
29#include <asm/mach/irq.h>
30
31#include <asm/arch/pxa-regs.h>
32#include <asm/arch/irq.h>
33#include <asm/arch/poodle.h>
34#include <asm/arch/pxafb.h>
35
36#include <asm/hardware/scoop.h>
37#include <asm/hardware/locomo.h>
38#include <asm/mach/sharpsl_param.h>
39
40#include "generic.h"
41
42static struct resource poodle_scoop_resources[] = {
43 [0] = {
44 .start = 0x10800000,
45 .end = 0x10800fff,
46 .flags = IORESOURCE_MEM,
47 },
48};
49
50static struct scoop_config poodle_scoop_setup = {
51 .io_dir = POODLE_SCOOP_IO_DIR,
52 .io_out = POODLE_SCOOP_IO_OUT,
53};
54
55struct platform_device poodle_scoop_device = {
56 .name = "sharp-scoop",
57 .id = -1,
58 .dev = {
59 .platform_data = &poodle_scoop_setup,
60 },
61 .num_resources = ARRAY_SIZE(poodle_scoop_resources),
62 .resource = poodle_scoop_resources,
63};
64
65
66/* LoCoMo device */
67static struct resource locomo_resources[] = {
68 [0] = {
69 .start = 0x10000000,
70 .end = 0x10001fff,
71 .flags = IORESOURCE_MEM,
72 },
73 [1] = {
74 .start = IRQ_GPIO(10),
75 .end = IRQ_GPIO(10),
76 .flags = IORESOURCE_IRQ,
77 },
78};
79
80static struct platform_device locomo_device = {
81 .name = "locomo",
82 .id = 0,
83 .num_resources = ARRAY_SIZE(locomo_resources),
84 .resource = locomo_resources,
85};
86
87/* PXAFB device */
88static struct pxafb_mach_info poodle_fb_info __initdata = {
89 .pixclock = 144700,
90
91 .xres = 320,
92 .yres = 240,
93 .bpp = 16,
94
95 .hsync_len = 7,
96 .left_margin = 11,
97 .right_margin = 30,
98
99 .vsync_len = 2,
100 .upper_margin = 2,
101 .lower_margin = 0,
102 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
103
104 .lccr0 = LCCR0_Act | LCCR0_Sngl | LCCR0_Color,
105 .lccr3 = 0,
106
107 .pxafb_backlight_power = NULL,
108 .pxafb_lcd_power = NULL,
109};
110
111static struct platform_device *devices[] __initdata = {
112 &locomo_device,
113 &poodle_scoop_device,
114};
115
116static void __init poodle_init(void)
117{
118 int ret = 0;
119
120 /* cpu initialize */
121 /* Pgsr Register */
122 PGSR0 = 0x0146dd80;
123 PGSR1 = 0x03bf0890;
124 PGSR2 = 0x0001c000;
125
126 /* Alternate Register */
127 GAFR0_L = 0x01001000;
128 GAFR0_U = 0x591a8010;
129 GAFR1_L = 0x900a8451;
130 GAFR1_U = 0xaaa5aaaa;
131 GAFR2_L = 0x8aaaaaaa;
132 GAFR2_U = 0x00000002;
133
134 /* Direction Register */
135 GPDR0 = 0xd3f0904c;
136 GPDR1 = 0xfcffb7d3;
137 GPDR2 = 0x0001ffff;
138
139 /* Output Register */
140 GPCR0 = 0x00000000;
141 GPCR1 = 0x00000000;
142 GPCR2 = 0x00000000;
143
144 GPSR0 = 0x00400000;
145 GPSR1 = 0x00000000;
146 GPSR2 = 0x00000000;
147
148 set_pxa_fb_info(&poodle_fb_info);
149
150 ret = platform_add_devices(devices, ARRAY_SIZE(devices));
151 if (ret) {
152 printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
153 }
154}
155
156static void __init fixup_poodle(struct machine_desc *desc,
157 struct tag *tags, char **cmdline, struct meminfo *mi)
158{
159 sharpsl_save_param();
160}
161
162static struct map_desc poodle_io_desc[] __initdata = {
163 /* virtual physical length */
164 { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */
165};
166
167static void __init poodle_map_io(void)
168{
169 pxa_map_io();
170 iotable_init(poodle_io_desc, ARRAY_SIZE(poodle_io_desc));
171
172 /* setup sleep mode values */
173 PWER = 0x00000002;
174 PFER = 0x00000000;
175 PRER = 0x00000002;
176 PGSR0 = 0x00008000;
177 PGSR1 = 0x003F0202;
178 PGSR2 = 0x0001C000;
179 PCFR |= PCFR_OPDE;
180}
181
182MACHINE_START(POODLE, "SHARP Poodle")
183 BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
184 FIXUP(fixup_poodle)
185 MAPIO(poodle_map_io)
186 INITIRQ(pxa_init_irq)
187 .timer = &pxa_timer,
188 .init_machine = poodle_init,
189MACHINE_END
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
new file mode 100644
index 000000000000..e887b7175ef3
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -0,0 +1,104 @@
1/*
2 * linux/arch/arm/mach-pxa/pxa25x.c
3 *
4 * Author: Nicolas Pitre
5 * Created: Jun 15, 2001
6 * Copyright: MontaVista Software Inc.
7 *
8 * Code specific to PXA21x/25x/26x variants.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * Since this file should be linked before any other machine specific file,
15 * the __initcall() here will be executed first. This serves as default
16 * initialization stuff for PXA machines which can be overridden later if
17 * need be.
18 */
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/pm.h>
23
24#include <asm/hardware.h>
25#include <asm/arch/pxa-regs.h>
26
27#include "generic.h"
28
29/*
30 * Various clock factors driven by the CCCR register.
31 */
32
33/* Crystal Frequency to Memory Frequency Multiplier (L) */
34static unsigned char L_clk_mult[32] = { 0, 27, 32, 36, 40, 45, 0, };
35
36/* Memory Frequency to Run Mode Frequency Multiplier (M) */
37static unsigned char M_clk_mult[4] = { 0, 1, 2, 4 };
38
39/* Run Mode Frequency to Turbo Mode Frequency Multiplier (N) */
40/* Note: we store the value N * 2 here. */
41static unsigned char N2_clk_mult[8] = { 0, 0, 2, 3, 4, 0, 6, 0 };
42
43/* Crystal clock */
44#define BASE_CLK 3686400
45
46/*
47 * Get the clock frequency as reflected by CCCR and the turbo flag.
48 * We assume these values have been applied via a fcs.
49 * If info is not 0 we also display the current settings.
50 */
51unsigned int get_clk_frequency_khz(int info)
52{
53 unsigned long cccr, turbo;
54 unsigned int l, L, m, M, n2, N;
55
56 cccr = CCCR;
57 asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (turbo) );
58
59 l = L_clk_mult[(cccr >> 0) & 0x1f];
60 m = M_clk_mult[(cccr >> 5) & 0x03];
61 n2 = N2_clk_mult[(cccr >> 7) & 0x07];
62
63 L = l * BASE_CLK;
64 M = m * L;
65 N = n2 * M / 2;
66
67 if(info)
68 {
69 L += 5000;
70 printk( KERN_INFO "Memory clock: %d.%02dMHz (*%d)\n",
71 L / 1000000, (L % 1000000) / 10000, l );
72 M += 5000;
73 printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n",
74 M / 1000000, (M % 1000000) / 10000, m );
75 N += 5000;
76 printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n",
77 N / 1000000, (N % 1000000) / 10000, n2 / 2, (n2 % 2) * 5,
78 (turbo & 1) ? "" : "in" );
79 }
80
81 return (turbo & 1) ? (N/1000) : (M/1000);
82}
83
84EXPORT_SYMBOL(get_clk_frequency_khz);
85
86/*
87 * Return the current memory clock frequency in units of 10kHz
88 */
89unsigned int get_memclk_frequency_10khz(void)
90{
91 return L_clk_mult[(CCCR >> 0) & 0x1f] * BASE_CLK / 10000;
92}
93
94EXPORT_SYMBOL(get_memclk_frequency_10khz);
95
96/*
97 * Return the current LCD clock frequency in units of 10kHz
98 */
99unsigned int get_lcdclk_frequency_10khz(void)
100{
101 return get_memclk_frequency_10khz();
102}
103
104EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
new file mode 100644
index 000000000000..7e863afefb53
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -0,0 +1,163 @@
1/*
2 * linux/arch/arm/mach-pxa/pxa27x.c
3 *
4 * Author: Nicolas Pitre
5 * Created: Nov 05, 2002
6 * Copyright: MontaVista Software Inc.
7 *
8 * Code specific to PXA27x aka Bulverde.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/config.h>
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/pm.h>
19#include <linux/device.h>
20
21#include <asm/hardware.h>
22#include <asm/irq.h>
23#include <asm/arch/pxa-regs.h>
24
25#include "generic.h"
26
27/* Crystal clock: 13MHz */
28#define BASE_CLK 13000000
29
30/*
31 * Get the clock frequency as reflected by CCSR and the turbo flag.
32 * We assume these values have been applied via a fcs.
33 * If info is not 0 we also display the current settings.
34 */
35unsigned int get_clk_frequency_khz( int info)
36{
37 unsigned long ccsr, clkcfg;
38 unsigned int l, L, m, M, n2, N, S;
39 int cccr_a, t, ht, b;
40
41 ccsr = CCSR;
42 cccr_a = CCCR & (1 << 25);
43
44 /* Read clkcfg register: it has turbo, b, half-turbo (and f) */
45 asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg) );
46 t = clkcfg & (1 << 1);
47 ht = clkcfg & (1 << 2);
48 b = clkcfg & (1 << 3);
49
50 l = ccsr & 0x1f;
51 n2 = (ccsr>>7) & 0xf;
52 m = (l <= 10) ? 1 : (l <= 20) ? 2 : 4;
53
54 L = l * BASE_CLK;
55 N = (L * n2) / 2;
56 M = (!cccr_a) ? (L/m) : ((b) ? L : (L/2));
57 S = (b) ? L : (L/2);
58
59 if (info) {
60 printk( KERN_INFO "Run Mode clock: %d.%02dMHz (*%d)\n",
61 L / 1000000, (L % 1000000) / 10000, l );
62 printk( KERN_INFO "Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive)\n",
63 N / 1000000, (N % 1000000)/10000, n2 / 2, (n2 % 2)*5,
64 (t) ? "" : "in" );
65 printk( KERN_INFO "Memory clock: %d.%02dMHz (/%d)\n",
66 M / 1000000, (M % 1000000) / 10000, m );
67 printk( KERN_INFO "System bus clock: %d.%02dMHz \n",
68 S / 1000000, (S % 1000000) / 10000 );
69 }
70
71 return (t) ? (N/1000) : (L/1000);
72}
73
74/*
75 * Return the current mem clock frequency in units of 10kHz as
76 * reflected by CCCR[A], B, and L
77 */
78unsigned int get_memclk_frequency_10khz(void)
79{
80 unsigned long ccsr, clkcfg;
81 unsigned int l, L, m, M;
82 int cccr_a, b;
83
84 ccsr = CCSR;
85 cccr_a = CCCR & (1 << 25);
86
87 /* Read clkcfg register: it has turbo, b, half-turbo (and f) */
88 asm( "mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg) );
89 b = clkcfg & (1 << 3);
90
91 l = ccsr & 0x1f;
92 m = (l <= 10) ? 1 : (l <= 20) ? 2 : 4;
93
94 L = l * BASE_CLK;
95 M = (!cccr_a) ? (L/m) : ((b) ? L : (L/2));
96
97 return (M / 10000);
98}
99
100/*
101 * Return the current LCD clock frequency in units of 10kHz as
102 */
103unsigned int get_lcdclk_frequency_10khz(void)
104{
105 unsigned long ccsr;
106 unsigned int l, L, k, K;
107
108 ccsr = CCSR;
109
110 l = ccsr & 0x1f;
111 k = (l <= 7) ? 1 : (l <= 16) ? 2 : 4;
112
113 L = l * BASE_CLK;
114 K = L / k;
115
116 return (K / 10000);
117}
118
119EXPORT_SYMBOL(get_clk_frequency_khz);
120EXPORT_SYMBOL(get_memclk_frequency_10khz);
121EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
122
123
124/*
125 * device registration specific to PXA27x.
126 */
127
128static u64 pxa27x_dmamask = 0xffffffffUL;
129
130static struct resource pxa27x_ohci_resources[] = {
131 [0] = {
132 .start = 0x4C000000,
133 .end = 0x4C00ff6f,
134 .flags = IORESOURCE_MEM,
135 },
136 [1] = {
137 .start = IRQ_USBH1,
138 .end = IRQ_USBH1,
139 .flags = IORESOURCE_IRQ,
140 },
141};
142
143static struct platform_device ohci_device = {
144 .name = "pxa27x-ohci",
145 .id = -1,
146 .dev = {
147 .dma_mask = &pxa27x_dmamask,
148 .coherent_dma_mask = 0xffffffff,
149 },
150 .num_resources = ARRAY_SIZE(pxa27x_ohci_resources),
151 .resource = pxa27x_ohci_resources,
152};
153
154static struct platform_device *devices[] __initdata = {
155 &ohci_device,
156};
157
158static int __init pxa27x_init(void)
159{
160 return platform_add_devices(devices, ARRAY_SIZE(devices));
161}
162
163subsys_initcall(pxa27x_init);
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
new file mode 100644
index 000000000000..16cad2c2497c
--- /dev/null
+++ b/arch/arm/mach-pxa/sleep.S
@@ -0,0 +1,194 @@
1/*
2 * Low-level PXA250/210 sleep/wakeUp support
3 *
4 * Initial SA1110 code:
5 * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
6 *
7 * Adapted for PXA by Nicolas Pitre:
8 * Copyright (c) 2002 Monta Vista Software, Inc.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License.
12 */
13
14#include <linux/config.h>
15#include <linux/linkage.h>
16#include <asm/assembler.h>
17#include <asm/hardware.h>
18
19#include <asm/arch/pxa-regs.h>
20
21 .text
22
23/*
24 * pxa_cpu_suspend()
25 *
26 * Forces CPU into sleep state
27 */
28
29ENTRY(pxa_cpu_suspend)
30
31 mra r2, r3, acc0
32 stmfd sp!, {r2 - r12, lr} @ save registers on stack
33
34 @ get coprocessor registers
35 mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode
36 mrc p15, 0, r4, c15, c1, 0 @ CP access reg
37 mrc p15, 0, r5, c13, c0, 0 @ PID
38 mrc p15, 0, r6, c3, c0, 0 @ domain ID
39 mrc p15, 0, r7, c2, c0, 0 @ translation table base addr
40 mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg
41 mrc p15, 0, r9, c1, c0, 0 @ control reg
42
43 bic r3, r3, #2 @ clear frequency change bit
44
45 @ store them plus current virtual stack ptr on stack
46 mov r10, sp
47 stmfd sp!, {r3 - r10}
48
49 @ preserve phys address of stack
50 mov r0, sp
51 bl sleep_phys_sp
52 ldr r1, =sleep_save_sp
53 str r0, [r1]
54
55 @ clean data cache
56 bl xscale_flush_kern_cache_all
57
58 @ Put the processor to sleep
59 @ (also workaround for sighting 28071)
60
61 @ prepare value for sleep mode
62 mov r1, #3 @ sleep mode
63
64 @ prepare to put SDRAM into self-refresh manually
65 ldr r4, =MDREFR
66 ldr r5, [r4]
67 orr r5, r5, #MDREFR_SLFRSH
68
69 @ prepare pointer to physical address 0 (virtual mapping in generic.c)
70 mov r2, #UNCACHED_PHYS_0
71
72 @ Intel PXA255 Specification Update notes problems
73 @ about suspending with PXBus operating above 133MHz
74 @ (see Errata 31, GPIO output signals, ... unpredictable in sleep
75 @
76 @ We keep the change-down close to the actual suspend on SDRAM
77 @ as possible to eliminate messing about with the refresh clock
78 @ as the system will restore with the original speed settings
79 @
80 @ Ben Dooks, 13-Sep-2004
81
82 ldr r6, =CCCR
83 ldr r8, [r6] @ keep original value for resume
84
85 @ ensure x1 for run and turbo mode with memory clock
86 bic r7, r8, #CCCR_M_MASK | CCCR_N_MASK
87 orr r7, r7, #(1<<5) | (2<<7)
88
89 @ check that the memory frequency is within limits
90 and r14, r7, #CCCR_L_MASK
91 teq r14, #1
92 bicne r7, r7, #CCCR_L_MASK
93 orrne r7, r7, #1 @@ 99.53MHz
94
95 @ get ready for the change
96
97 @ note, turbo is not preserved over sleep so there is no
98 @ point in preserving it here. we save it on the stack with the
99 @ other CP registers instead.
100 mov r0, #0
101 mcr p14, 0, r0, c6, c0, 0
102 orr r0, r0, #2 @ initiate change bit
103
104 @ align execution to a cache line
105 b 1f
106
107 .ltorg
108 .align 5
1091:
110
111 @ All needed values are now in registers.
112 @ These last instructions should be in cache
113
114 @ initiate the frequency change...
115 str r7, [r6]
116 mcr p14, 0, r0, c6, c0, 0
117
118 @ restore the original cpu speed value for resume
119 str r8, [r6]
120
121 @ put SDRAM into self-refresh
122 str r5, [r4]
123
124 @ force address lines low by reading at physical address 0
125 ldr r3, [r2]
126
127 @ enter sleep mode
128 mcr p14, 0, r1, c7, c0, 0
129
13020: b 20b @ loop waiting for sleep
131
132/*
133 * cpu_pxa_resume()
134 *
135 * entry point from bootloader into kernel during resume
136 *
137 * Note: Yes, part of the following code is located into the .data section.
138 * This is to allow sleep_save_sp to be accessed with a relative load
139 * while we can't rely on any MMU translation. We could have put
140 * sleep_save_sp in the .text section as well, but some setups might
141 * insist on it to be truly read-only.
142 */
143
144 .data
145 .align 5
146ENTRY(pxa_cpu_resume)
147 mov r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC @ set SVC, irqs off
148 msr cpsr_c, r0
149
150 ldr r0, sleep_save_sp @ stack phys addr
151 ldr r2, =resume_after_mmu @ its absolute virtual address
152 ldmfd r0, {r3 - r9, sp} @ CP regs + virt stack ptr
153
154 mov r1, #0
155 mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
156 mcr p15, 0, r1, c7, c7, 0 @ invalidate I & D caches, BTB
157
158#ifdef CONFIG_XSCALE_CACHE_ERRATA
159 bic r9, r9, #0x0004 @ see cpu_xscale_proc_init
160#endif
161
162 mcr p14, 0, r3, c6, c0, 0 @ clock configuration, turbo mode.
163 mcr p15, 0, r4, c15, c1, 0 @ CP access reg
164 mcr p15, 0, r5, c13, c0, 0 @ PID
165 mcr p15, 0, r6, c3, c0, 0 @ domain ID
166 mcr p15, 0, r7, c2, c0, 0 @ translation table base addr
167 mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg
168 b resume_turn_on_mmu @ cache align execution
169
170 .align 5
171resume_turn_on_mmu:
172 mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, caches, etc.
173
174 @ Let us ensure we jump to resume_after_mmu only when the mcr above
175 @ actually took effect. They call it the "cpwait" operation.
176 mrc p15, 0, r1, c2, c0, 0 @ queue a dependency on CP15
177 sub pc, r2, r1, lsr #32 @ jump to virtual addr
178 nop
179 nop
180 nop
181
182sleep_save_sp:
183 .word 0 @ preserve stack phys ptr here
184
185 .text
186resume_after_mmu:
187#ifdef CONFIG_XSCALE_CACHE_ERRATA
188 bl cpu_xscale_proc_init
189#endif
190 ldmfd sp!, {r2, r3}
191 mar acc0, r2, r3
192 ldmfd sp!, {r4 - r12, pc} @ return to caller
193
194
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
new file mode 100644
index 000000000000..4d826c021315
--- /dev/null
+++ b/arch/arm/mach-pxa/ssp.c
@@ -0,0 +1,363 @@
1/*
2 * linux/arch/arm/mach-pxa/ssp.c
3 *
4 * based on linux/arch/arm/mach-sa1100/ssp.c by Russell King
5 *
6 * Copyright (C) 2003 Russell King.
7 * Copyright (C) 2003 Wolfson Microelectronics PLC
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 * PXA2xx SSP driver. This provides the generic core for simple
14 * IO-based SSP applications and allows easy port setup for DMA access.
15 *
16 * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
17 *
18 * Revision history:
19 * 22nd Aug 2003 Initial version.
20 * 20th Dec 2004 Added ssp_config for changing port config without
21 * closing the port.
22 */
23
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/sched.h>
27#include <linux/slab.h>
28#include <linux/errno.h>
29#include <linux/interrupt.h>
30#include <linux/ioport.h>
31#include <linux/init.h>
32#include <asm/io.h>
33#include <asm/irq.h>
34#include <asm/hardware.h>
35#include <asm/arch/ssp.h>
36#include <asm/arch/pxa-regs.h>
37
38#define PXA_SSP_PORTS 3
39
40static DECLARE_MUTEX(sem);
41static int use_count[PXA_SSP_PORTS] = {0, 0, 0};
42
43static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
44{
45 struct ssp_dev *dev = (struct ssp_dev*) dev_id;
46 unsigned int status = SSSR_P(dev->port);
47
48 SSSR_P(dev->port) = status; /* clear status bits */
49
50 if (status & SSSR_ROR)
51 printk(KERN_WARNING "SSP(%d): receiver overrun\n", dev->port);
52
53 if (status & SSSR_TUR)
54 printk(KERN_WARNING "SSP(%d): transmitter underrun\n", dev->port);
55
56 if (status & SSSR_BCE)
57 printk(KERN_WARNING "SSP(%d): bit count error\n", dev->port);
58
59 return IRQ_HANDLED;
60}
61
62/**
63 * ssp_write_word - write a word to the SSP port
64 * @data: 32-bit, MSB justified data to write.
65 *
66 * Wait for a free entry in the SSP transmit FIFO, and write a data
67 * word to the SSP port.
68 *
69 * The caller is expected to perform the necessary locking.
70 *
71 * Returns:
72 * %-ETIMEDOUT timeout occurred (for future)
73 * 0 success
74 */
75int ssp_write_word(struct ssp_dev *dev, u32 data)
76{
77 while (!(SSSR_P(dev->port) & SSSR_TNF))
78 cpu_relax();
79
80 SSDR_P(dev->port) = data;
81
82 return 0;
83}
84
85/**
86 * ssp_read_word - read a word from the SSP port
87 *
88 * Wait for a data word in the SSP receive FIFO, and return the
89 * received data. Data is LSB justified.
90 *
91 * Note: Currently, if data is not expected to be received, this
92 * function will wait for ever.
93 *
94 * The caller is expected to perform the necessary locking.
95 *
96 * Returns:
97 * %-ETIMEDOUT timeout occurred (for future)
98 * 32-bit data success
99 */
100int ssp_read_word(struct ssp_dev *dev)
101{
102 while (!(SSSR_P(dev->port) & SSSR_RNE))
103 cpu_relax();
104
105 return SSDR_P(dev->port);
106}
107
108/**
109 * ssp_flush - flush the transmit and receive FIFOs
110 *
111 * Wait for the SSP to idle, and ensure that the receive FIFO
112 * is empty.
113 *
114 * The caller is expected to perform the necessary locking.
115 */
116void ssp_flush(struct ssp_dev *dev)
117{
118 do {
119 while (SSSR_P(dev->port) & SSSR_RNE) {
120 (void) SSDR_P(dev->port);
121 }
122 } while (SSSR_P(dev->port) & SSSR_BSY);
123}
124
125/**
126 * ssp_enable - enable the SSP port
127 *
128 * Turn on the SSP port.
129 */
130void ssp_enable(struct ssp_dev *dev)
131{
132 SSCR0_P(dev->port) |= SSCR0_SSE;
133}
134
135/**
136 * ssp_disable - shut down the SSP port
137 *
138 * Turn off the SSP port, optionally powering it down.
139 */
140void ssp_disable(struct ssp_dev *dev)
141{
142 SSCR0_P(dev->port) &= ~SSCR0_SSE;
143}
144
145/**
146 * ssp_save_state - save the SSP configuration
147 * @ssp: pointer to structure to save SSP configuration
148 *
149 * Save the configured SSP state for suspend.
150 */
151void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp)
152{
153 ssp->cr0 = SSCR0_P(dev->port);
154 ssp->cr1 = SSCR1_P(dev->port);
155 ssp->to = SSTO_P(dev->port);
156 ssp->psp = SSPSP_P(dev->port);
157
158 SSCR0_P(dev->port) &= ~SSCR0_SSE;
159}
160
161/**
162 * ssp_restore_state - restore a previously saved SSP configuration
163 * @ssp: pointer to configuration saved by ssp_save_state
164 *
165 * Restore the SSP configuration saved previously by ssp_save_state.
166 */
167void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp)
168{
169 SSSR_P(dev->port) = SSSR_ROR | SSSR_TUR | SSSR_BCE;
170
171 SSCR0_P(dev->port) = ssp->cr0 & ~SSCR0_SSE;
172 SSCR1_P(dev->port) = ssp->cr1;
173 SSTO_P(dev->port) = ssp->to;
174 SSPSP_P(dev->port) = ssp->psp;
175
176 SSCR0_P(dev->port) = ssp->cr0;
177}
178
179/**
180 * ssp_config - configure SSP port settings
181 * @mode: port operating mode
182 * @flags: port config flags
183 * @psp_flags: port PSP config flags
184 * @speed: port speed
185 *
186 * Port MUST be disabled by ssp_disable before making any config changes.
187 */
188int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed)
189{
190 dev->mode = mode;
191 dev->flags = flags;
192 dev->psp_flags = psp_flags;
193 dev->speed = speed;
194
195 /* set up port type, speed, port settings */
196 SSCR0_P(dev->port) = (dev->speed | dev->mode);
197 SSCR1_P(dev->port) = dev->flags;
198 SSPSP_P(dev->port) = dev->psp_flags;
199
200 return 0;
201}
202
203/**
204 * ssp_init - setup the SSP port
205 *
206 * initialise and claim resources for the SSP port.
207 *
208 * Returns:
209 * %-ENODEV if the SSP port is unavailable
210 * %-EBUSY if the resources are already in use
211 * %0 on success
212 */
213int ssp_init(struct ssp_dev *dev, u32 port)
214{
215 int ret, irq;
216
217 if (port > PXA_SSP_PORTS || port == 0)
218 return -ENODEV;
219
220 down(&sem);
221 if (use_count[port - 1]) {
222 up(&sem);
223 return -EBUSY;
224 }
225 use_count[port - 1]++;
226
227 if (!request_mem_region(__PREG(SSCR0_P(port)), 0x2c, "SSP")) {
228 use_count[port - 1]--;
229 up(&sem);
230 return -EBUSY;
231 }
232
233 switch (port) {
234 case 1:
235 irq = IRQ_SSP;
236 break;
237#if defined (CONFIG_PXA27x)
238 case 2:
239 irq = IRQ_SSP2;
240 break;
241 case 3:
242 irq = IRQ_SSP3;
243 break;
244#else
245 case 2:
246 irq = IRQ_NSSP;
247 break;
248 case 3:
249 irq = IRQ_ASSP;
250 break;
251#endif
252 default:
253 return -ENODEV;
254 }
255
256 dev->port = port;
257
258 ret = request_irq(irq, ssp_interrupt, 0, "SSP", dev);
259 if (ret)
260 goto out_region;
261
262 /* turn on SSP port clock */
263 switch (dev->port) {
264#if defined (CONFIG_PXA27x)
265 case 1:
266 pxa_set_cken(CKEN23_SSP1, 1);
267 break;
268 case 2:
269 pxa_set_cken(CKEN3_SSP2, 1);
270 break;
271 case 3:
272 pxa_set_cken(CKEN4_SSP3, 1);
273 break;
274#else
275 case 1:
276 pxa_set_cken(CKEN3_SSP, 1);
277 break;
278 case 2:
279 pxa_set_cken(CKEN9_NSSP, 1);
280 break;
281 case 3:
282 pxa_set_cken(CKEN10_ASSP, 1);
283 break;
284#endif
285 }
286
287 up(&sem);
288 return 0;
289
290out_region:
291 release_mem_region(__PREG(SSCR0_P(port)), 0x2c);
292 use_count[port - 1]--;
293 up(&sem);
294 return ret;
295}
296
297/**
298 * ssp_exit - undo the effects of ssp_init
299 *
300 * release and free resources for the SSP port.
301 */
302void ssp_exit(struct ssp_dev *dev)
303{
304 int irq;
305
306 down(&sem);
307 SSCR0_P(dev->port) &= ~SSCR0_SSE;
308
309 /* find irq, save power and turn off SSP port clock */
310 switch (dev->port) {
311#if defined (CONFIG_PXA27x)
312 case 1:
313 irq = IRQ_SSP;
314 pxa_set_cken(CKEN23_SSP1, 0);
315 break;
316 case 2:
317 irq = IRQ_SSP2;
318 pxa_set_cken(CKEN3_SSP2, 0);
319 break;
320 case 3:
321 irq = IRQ_SSP3;
322 pxa_set_cken(CKEN4_SSP3, 0);
323 break;
324#else
325 case 1:
326 irq = IRQ_SSP;
327 pxa_set_cken(CKEN3_SSP, 0);
328 break;
329 case 2:
330 irq = IRQ_NSSP;
331 pxa_set_cken(CKEN9_NSSP, 0);
332 break;
333 case 3:
334 irq = IRQ_ASSP;
335 pxa_set_cken(CKEN10_ASSP, 0);
336 break;
337#endif
338 default:
339 printk(KERN_WARNING "SSP: tried to close invalid port\n");
340 return;
341 }
342
343 free_irq(irq, dev);
344 release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c);
345 use_count[dev->port - 1]--;
346 up(&sem);
347}
348
349EXPORT_SYMBOL(ssp_write_word);
350EXPORT_SYMBOL(ssp_read_word);
351EXPORT_SYMBOL(ssp_flush);
352EXPORT_SYMBOL(ssp_enable);
353EXPORT_SYMBOL(ssp_disable);
354EXPORT_SYMBOL(ssp_save_state);
355EXPORT_SYMBOL(ssp_restore_state);
356EXPORT_SYMBOL(ssp_init);
357EXPORT_SYMBOL(ssp_exit);
358EXPORT_SYMBOL(ssp_config);
359
360MODULE_DESCRIPTION("PXA SSP driver");
361MODULE_AUTHOR("Liam Girdwood");
362MODULE_LICENSE("GPL");
363
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
new file mode 100644
index 000000000000..473fb6173f72
--- /dev/null
+++ b/arch/arm/mach-pxa/time.c
@@ -0,0 +1,164 @@
1/*
2 * arch/arm/mach-pxa/time.c
3 *
4 * Author: Nicolas Pitre
5 * Created: Jun 15, 2001
6 * Copyright: MontaVista Software Inc.
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
13#include <linux/config.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/interrupt.h>
18#include <linux/time.h>
19#include <linux/signal.h>
20#include <linux/errno.h>
21#include <linux/sched.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>
29#include <asm/mach/time.h>
30#include <asm/arch/pxa-regs.h>
31
32
33static inline unsigned long pxa_get_rtc_time(void)
34{
35 return RCNR;
36}
37
38static int pxa_set_rtc(void)
39{
40 unsigned long current_time = xtime.tv_sec;
41
42 if (RTSR & RTSR_ALE) {
43 /* make sure not to forward the clock over an alarm */
44 unsigned long alarm = RTAR;
45 if (current_time >= alarm && alarm >= RCNR)
46 return -ERESTARTSYS;
47 }
48 RCNR = current_time;
49 return 0;
50}
51
52/* IRQs are disabled before entering here from do_gettimeofday() */
53static unsigned long pxa_gettimeoffset (void)
54{
55 long ticks_to_match, elapsed, usec;
56
57 /* Get ticks before next timer match */
58 ticks_to_match = OSMR0 - OSCR;
59
60 /* We need elapsed ticks since last match */
61 elapsed = LATCH - ticks_to_match;
62
63 /* don't get fooled by the workaround in pxa_timer_interrupt() */
64 if (elapsed <= 0)
65 return 0;
66
67 /* Now convert them to usec */
68 usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
69
70 return usec;
71}
72
73static irqreturn_t
74pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
75{
76 int next_match;
77
78 write_seqlock(&xtime_lock);
79
80 /* Loop until we get ahead of the free running timer.
81 * This ensures an exact clock tick count and time accuracy.
82 * IRQs are disabled inside the loop to ensure coherence between
83 * lost_ticks (updated in do_timer()) and the match reg value, so we
84 * can use do_gettimeofday() from interrupt handlers.
85 *
86 * HACK ALERT: it seems that the PXA timer regs aren't updated right
87 * away in all cases when a write occurs. We therefore compare with
88 * 8 instead of 0 in the while() condition below to avoid missing a
89 * match if OSCR has already reached the next OSMR value.
90 * Experience has shown that up to 6 ticks are needed to work around
91 * this problem, but let's use 8 to be conservative. Note that this
92 * affect things only when the timer IRQ has been delayed by nearly
93 * exactly one tick period which should be a pretty rare event.
94 */
95 do {
96 timer_tick(regs);
97 OSSR = OSSR_M0; /* Clear match on timer 0 */
98 next_match = (OSMR0 += LATCH);
99 } while( (signed long)(next_match - OSCR) <= 8 );
100
101 write_sequnlock(&xtime_lock);
102
103 return IRQ_HANDLED;
104}
105
106static struct irqaction pxa_timer_irq = {
107 .name = "PXA Timer Tick",
108 .flags = SA_INTERRUPT,
109 .handler = pxa_timer_interrupt
110};
111
112static void __init pxa_timer_init(void)
113{
114 struct timespec tv;
115
116 set_rtc = pxa_set_rtc;
117
118 tv.tv_nsec = 0;
119 tv.tv_sec = pxa_get_rtc_time();
120 do_settimeofday(&tv);
121
122 OSMR0 = 0; /* set initial match at 0 */
123 OSSR = 0xf; /* clear status on all timers */
124 setup_irq(IRQ_OST0, &pxa_timer_irq);
125 OIER |= OIER_E0; /* enable match on timer 0 to cause interrupts */
126 OSCR = 0; /* initialize free-running timer, force first match */
127}
128
129#ifdef CONFIG_PM
130static unsigned long osmr[4], oier;
131
132static void pxa_timer_suspend(void)
133{
134 osmr[0] = OSMR0;
135 osmr[1] = OSMR1;
136 osmr[2] = OSMR2;
137 osmr[3] = OSMR3;
138 oier = OIER;
139}
140
141static void pxa_timer_resume(void)
142{
143 OSMR0 = osmr[0];
144 OSMR1 = osmr[1];
145 OSMR2 = osmr[2];
146 OSMR3 = osmr[3];
147 OIER = oier;
148
149 /*
150 * OSMR0 is the system timer: make sure OSCR is sufficiently behind
151 */
152 OSCR = OSMR0 - LATCH;
153}
154#else
155#define pxa_timer_suspend NULL
156#define pxa_timer_resume NULL
157#endif
158
159struct sys_timer pxa_timer = {
160 .init = pxa_timer_init,
161 .suspend = pxa_timer_suspend,
162 .resume = pxa_timer_resume,
163 .offset = pxa_gettimeoffset,
164};