aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/pxa3xx.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-01-28 08:21:38 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-28 08:21:38 -0500
commit0ff66f0c7a5f1f4f5a0d91341b6f71fd2a49f0fa (patch)
tree7c4d74a76bf4f49e87d769c236fdd2db77fb241d /arch/arm/mach-pxa/pxa3xx.c
parentc00d4ffdbace1bdc9fdd888e4ba6d207ffa3b679 (diff)
parent4e4fc05a2b6e7bd2e0facd96e0c18dceb34d9349 (diff)
Merge branch 'pxa-plat' into devel
* pxa-plat: (53 commits) [ARM] 4762/1: Basic support for Toradex Colibri module [ARM] pxa: fix mci_init functions returning -1 [ARM] 4737/1: Refactor corgi_lcd to improve readability + bugfix [ARM] 4747/1: pcm027: support for pcm990 baseboard for phyCORE-PXA270 [ARM] 4746/1: pcm027: network support for phyCORE-PXA270 [ARM] 4745/1: pcm027: default configuration [ARM] 4744/1: pcm027: add support for phyCORE-PXA270 CPU module [NET] smc91x: Make smc91x use IRQ resource trigger flags [ARM] pxa: add default config for littleton [ARM] pxa: add basic support for Littleton (PXA3xx Form Factor Platform) [ARM] 4664/1: Add basic support for HTC Magician PDA phones [ARM] 4649/1: Base support for pxa-based Toshiba e-series PDAs. [ARM] pxa: skip registers saving/restoring if entering standby mode [ARM] pxa: fix PXA27x resume [ARM] pxa: Avoid fiddling with CKEN register on suspend [ARM] pxa: Add PXA3 standby code hooked into the IRQ wake scheme [ARM] pxa: Add zylonite MFP wakeup configurations [ARM] pxa: program MFPs for low power mode when suspending [ARM] pxa: make MFP configuration processor independent [ARM] pxa: remove un-used pxa3xx_mfp_set_xxx() functions ... Conflicts: arch/arm/mach-pxa/ssp.c Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-pxa/pxa3xx.c')
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c241
1 files changed, 237 insertions, 4 deletions
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 37e93f9ba8fc..5cbf057a1b32 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -19,6 +19,7 @@
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <linux/io.h>
22 23
23#include <asm/hardware.h> 24#include <asm/hardware.h>
24#include <asm/arch/pxa3xx-regs.h> 25#include <asm/arch/pxa3xx-regs.h>
@@ -189,8 +190,237 @@ static struct clk pxa3xx_clks[] = {
189 190
190 PXA3xx_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev), 191 PXA3xx_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev),
191 PXA3xx_CKEN("UDCCLK", UDC, 48000000, 5, &pxa_device_udc.dev), 192 PXA3xx_CKEN("UDCCLK", UDC, 48000000, 5, &pxa_device_udc.dev),
193 PXA3xx_CKEN("USBCLK", USBH, 48000000, 0, &pxa27x_device_ohci.dev),
194
195 PXA3xx_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
196 PXA3xx_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
197 PXA3xx_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
198 PXA3xx_CKEN("SSPCLK", SSP4, 13000000, 0, &pxa3xx_device_ssp4.dev),
199
200 PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev),
201 PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev),
202 PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
203};
204
205#ifdef CONFIG_PM
206#define SLEEP_SAVE_SIZE 4
207
208#define ISRAM_START 0x5c000000
209#define ISRAM_SIZE SZ_256K
210
211static void __iomem *sram;
212static unsigned long wakeup_src;
213
214static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
215{
216 pr_debug("PM: CKENA=%08x CKENB=%08x\n", CKENA, CKENB);
217
218 if (CKENA & (1 << CKEN_USBH)) {
219 printk(KERN_ERR "PM: USB host clock not stopped?\n");
220 CKENA &= ~(1 << CKEN_USBH);
221 }
222// CKENA |= 1 << (CKEN_ISC & 31);
223
224 /*
225 * Low power modes require the HSIO2 clock to be enabled.
226 */
227 CKENB |= 1 << (CKEN_HSIO2 & 31);
228}
229
230static void pxa3xx_cpu_pm_restore(unsigned long *sleep_save)
231{
232 CKENB &= ~(1 << (CKEN_HSIO2 & 31));
233}
234
235/*
236 * Enter a standby mode (S0D1C2 or S0D2C2). Upon wakeup, the dynamic
237 * memory controller has to be reinitialised, so we place some code
238 * in the SRAM to perform this function.
239 *
240 * We disable FIQs across the standby - otherwise, we might receive a
241 * FIQ while the SDRAM is unavailable.
242 */
243static void pxa3xx_cpu_standby(unsigned int pwrmode)
244{
245 extern const char pm_enter_standby_start[], pm_enter_standby_end[];
246 void (*fn)(unsigned int) = (void __force *)(sram + 0x8000);
247
248 memcpy_toio(sram + 0x8000, pm_enter_standby_start,
249 pm_enter_standby_end - pm_enter_standby_start);
250
251 AD2D0SR = ~0;
252 AD2D1SR = ~0;
253 AD2D0ER = wakeup_src;
254 AD2D1ER = 0;
255 ASCR = ASCR;
256 ARSR = ARSR;
257
258 local_fiq_disable();
259 fn(pwrmode);
260 local_fiq_enable();
261
262 AD2D0ER = 0;
263 AD2D1ER = 0;
264
265 printk("PM: AD2D0SR=%08x ASCR=%08x\n", AD2D0SR, ASCR);
266}
267
268static void pxa3xx_cpu_pm_enter(suspend_state_t state)
269{
270 /*
271 * Don't sleep if no wakeup sources are defined
272 */
273 if (wakeup_src == 0)
274 return;
275
276 switch (state) {
277 case PM_SUSPEND_STANDBY:
278 pxa3xx_cpu_standby(PXA3xx_PM_S0D2C2);
279 break;
280
281 case PM_SUSPEND_MEM:
282 break;
283 }
284}
285
286static int pxa3xx_cpu_pm_valid(suspend_state_t state)
287{
288 return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
289}
290
291static struct pxa_cpu_pm_fns pxa3xx_cpu_pm_fns = {
292 .save_size = SLEEP_SAVE_SIZE,
293 .save = pxa3xx_cpu_pm_save,
294 .restore = pxa3xx_cpu_pm_restore,
295 .valid = pxa3xx_cpu_pm_valid,
296 .enter = pxa3xx_cpu_pm_enter,
192}; 297};
193 298
299static void __init pxa3xx_init_pm(void)
300{
301 sram = ioremap(ISRAM_START, ISRAM_SIZE);
302 if (!sram) {
303 printk(KERN_ERR "Unable to map ISRAM: disabling standby/suspend\n");
304 return;
305 }
306
307 /*
308 * Since we copy wakeup code into the SRAM, we need to ensure
309 * that it is preserved over the low power modes. Note: bit 8
310 * is undocumented in the developer manual, but must be set.
311 */
312 AD1R |= ADXR_L2 | ADXR_R0;
313 AD2R |= ADXR_L2 | ADXR_R0;
314 AD3R |= ADXR_L2 | ADXR_R0;
315
316 /*
317 * Clear the resume enable registers.
318 */
319 AD1D0ER = 0;
320 AD2D0ER = 0;
321 AD2D1ER = 0;
322 AD3ER = 0;
323
324 pxa_cpu_pm_fns = &pxa3xx_cpu_pm_fns;
325}
326
327static int pxa3xx_set_wake(unsigned int irq, unsigned int on)
328{
329 unsigned long flags, mask = 0;
330
331 switch (irq) {
332 case IRQ_SSP3:
333 mask = ADXER_MFP_WSSP3;
334 break;
335 case IRQ_MSL:
336 mask = ADXER_WMSL0;
337 break;
338 case IRQ_USBH2:
339 case IRQ_USBH1:
340 mask = ADXER_WUSBH;
341 break;
342 case IRQ_KEYPAD:
343 mask = ADXER_WKP;
344 break;
345 case IRQ_AC97:
346 mask = ADXER_MFP_WAC97;
347 break;
348 case IRQ_USIM:
349 mask = ADXER_WUSIM0;
350 break;
351 case IRQ_SSP2:
352 mask = ADXER_MFP_WSSP2;
353 break;
354 case IRQ_I2C:
355 mask = ADXER_MFP_WI2C;
356 break;
357 case IRQ_STUART:
358 mask = ADXER_MFP_WUART3;
359 break;
360 case IRQ_BTUART:
361 mask = ADXER_MFP_WUART2;
362 break;
363 case IRQ_FFUART:
364 mask = ADXER_MFP_WUART1;
365 break;
366 case IRQ_MMC:
367 mask = ADXER_MFP_WMMC1;
368 break;
369 case IRQ_SSP:
370 mask = ADXER_MFP_WSSP1;
371 break;
372 case IRQ_RTCAlrm:
373 mask = ADXER_WRTC;
374 break;
375 case IRQ_SSP4:
376 mask = ADXER_MFP_WSSP4;
377 break;
378 case IRQ_TSI:
379 mask = ADXER_WTSI;
380 break;
381 case IRQ_USIM2:
382 mask = ADXER_WUSIM1;
383 break;
384 case IRQ_MMC2:
385 mask = ADXER_MFP_WMMC2;
386 break;
387 case IRQ_NAND:
388 mask = ADXER_MFP_WFLASH;
389 break;
390 case IRQ_USB2:
391 mask = ADXER_WUSB2;
392 break;
393 case IRQ_WAKEUP0:
394 mask = ADXER_WEXTWAKE0;
395 break;
396 case IRQ_WAKEUP1:
397 mask = ADXER_WEXTWAKE1;
398 break;
399 case IRQ_MMC3:
400 mask = ADXER_MFP_GEN12;
401 break;
402 }
403
404 local_irq_save(flags);
405 if (on)
406 wakeup_src |= mask;
407 else
408 wakeup_src &= ~mask;
409 local_irq_restore(flags);
410
411 return 0;
412}
413
414static void pxa3xx_init_irq_pm(void)
415{
416 pxa_init_irq_set_wake(pxa3xx_set_wake);
417}
418
419#else
420static inline void pxa3xx_init_pm(void) {}
421static inline void pxa3xx_init_irq_pm(void) {}
422#endif
423
194void __init pxa3xx_init_irq(void) 424void __init pxa3xx_init_irq(void)
195{ 425{
196 /* enable CP6 access */ 426 /* enable CP6 access */
@@ -202,6 +432,7 @@ void __init pxa3xx_init_irq(void)
202 pxa_init_irq_low(); 432 pxa_init_irq_low();
203 pxa_init_irq_high(); 433 pxa_init_irq_high();
204 pxa_init_irq_gpio(128); 434 pxa_init_irq_gpio(128);
435 pxa3xx_init_irq_pm();
205} 436}
206 437
207/* 438/*
@@ -209,16 +440,16 @@ void __init pxa3xx_init_irq(void)
209 */ 440 */
210 441
211static struct platform_device *devices[] __initdata = { 442static struct platform_device *devices[] __initdata = {
212 &pxa_device_mci,
213 &pxa_device_udc, 443 &pxa_device_udc,
214 &pxa_device_fb,
215 &pxa_device_ffuart, 444 &pxa_device_ffuart,
216 &pxa_device_btuart, 445 &pxa_device_btuart,
217 &pxa_device_stuart, 446 &pxa_device_stuart,
218 &pxa_device_i2c,
219 &pxa_device_i2s, 447 &pxa_device_i2s,
220 &pxa_device_ficp,
221 &pxa_device_rtc, 448 &pxa_device_rtc,
449 &pxa27x_device_ssp1,
450 &pxa27x_device_ssp2,
451 &pxa27x_device_ssp3,
452 &pxa3xx_device_ssp4,
222}; 453};
223 454
224static int __init pxa3xx_init(void) 455static int __init pxa3xx_init(void)
@@ -231,6 +462,8 @@ static int __init pxa3xx_init(void)
231 if ((ret = pxa_init_dma(32))) 462 if ((ret = pxa_init_dma(32)))
232 return ret; 463 return ret;
233 464
465 pxa3xx_init_pm();
466
234 return platform_add_devices(devices, ARRAY_SIZE(devices)); 467 return platform_add_devices(devices, ARRAY_SIZE(devices));
235 } 468 }
236 return 0; 469 return 0;