| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * SA1100 Power Management Routines | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * History: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 2001-02-06:	Cliff Brake         Initial code | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 2001-02-25:	Sukjae Cho <sjcho@east.isi.edu> & | 
					
						
							|  |  |  |  * 		Chester Kuo <chester@linux.org.tw> | 
					
						
							|  |  |  |  * 			Save more value for the resume function! Support | 
					
						
							|  |  |  |  * 			Bitsy/Assabet/Freebird board | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2009-09-14 03:25:28 -04:00
										 |  |  |  * 2001-08-29:	Nicolas Pitre <nico@fluxnic.net> | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * 			Cleaned up, pushed platform dependent stuff | 
					
						
							|  |  |  |  * 			in the platform specific files. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 2002-05-27:	Nicolas Pitre	Killed sleep.h and the kmalloced save array. | 
					
						
							|  |  |  |  * 				Storage is local on the stack now. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/suspend.h>
 | 
					
						
							|  |  |  | #include <linux/errno.h>
 | 
					
						
							|  |  |  | #include <linux/time.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-05 16:14:15 +01:00
										 |  |  | #include <mach/hardware.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <asm/memory.h>
 | 
					
						
							| 
									
										
										
										
											2011-06-22 17:41:48 +01:00
										 |  |  | #include <asm/suspend.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <asm/system.h>
 | 
					
						
							|  |  |  | #include <asm/mach/time.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-02 09:54:01 +01:00
										 |  |  | extern int sa1100_finish_suspend(unsigned long); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
 | 
					
						
							|  |  |  | #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * List of global SA11x0 peripheral registers to preserve. | 
					
						
							|  |  |  |  * More ones like CP and general purpose register values are preserved | 
					
						
							|  |  |  |  * on the stack and then the stack pointer is stored last in sleep.S. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-05-02 21:17:06 +01:00
										 |  |  | enum {	SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SLEEP_SAVE_Ser1SDCR0, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-02 21:17:06 +01:00
										 |  |  | 	SLEEP_SAVE_COUNT | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int sa11x0_pm_enter(suspend_state_t state) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-02 21:17:06 +01:00
										 |  |  | 	unsigned long gpio, sleep_save[SLEEP_SAVE_COUNT]; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	gpio = GPLR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* save vital registers */ | 
					
						
							|  |  |  | 	SAVE(GPDR); | 
					
						
							|  |  |  | 	SAVE(GAFR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SAVE(PPDR); | 
					
						
							|  |  |  | 	SAVE(PPSR); | 
					
						
							|  |  |  | 	SAVE(PPAR); | 
					
						
							|  |  |  | 	SAVE(PSDR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SAVE(Ser1SDCR0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Clear previous reset status */ | 
					
						
							|  |  |  | 	RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* set resume return address */ | 
					
						
							| 
									
										
										
										
											2011-02-06 17:41:40 +00:00
										 |  |  | 	PSPR = virt_to_phys(cpu_resume); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* go zzz */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:41:48 +01:00
										 |  |  | 	cpu_suspend(0, sa1100_finish_suspend); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Ensure not to come back here if it wasn't intended | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	PSPR = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Ensure interrupt sources are disabled; we will re-init | 
					
						
							|  |  |  | 	 * the interrupt subsystem via the device manager. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	ICLR = 0; | 
					
						
							|  |  |  | 	ICCR = 1; | 
					
						
							|  |  |  | 	ICMR = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* restore registers */ | 
					
						
							|  |  |  | 	RESTORE(GPDR); | 
					
						
							|  |  |  | 	RESTORE(GAFR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	RESTORE(PPDR); | 
					
						
							|  |  |  | 	RESTORE(PPSR); | 
					
						
							|  |  |  | 	RESTORE(PPAR); | 
					
						
							|  |  |  | 	RESTORE(PSDR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	RESTORE(Ser1SDCR0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPSR = gpio; | 
					
						
							|  |  |  | 	GPCR = ~gpio; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Clear the peripheral sleep-hold bit. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	PSSR = PSSR_PH; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-16 14:14:02 +01:00
										 |  |  | static const struct platform_suspend_ops sa11x0_pm_ops = { | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	.enter		= sa11x0_pm_enter, | 
					
						
							| 
									
										
										
										
											2007-10-18 03:04:40 -07:00
										 |  |  | 	.valid		= suspend_valid_only_mem, | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int __init sa11x0_pm_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-18 03:04:40 -07:00
										 |  |  | 	suspend_set_ops(&sa11x0_pm_ops); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | late_initcall(sa11x0_pm_init); |