2007-02-11 20:31:01 +03:00
/* linux/arch/arm/plat-s3c24xx/pm.c
*
2009-11-14 01:54:14 +03:00
* Copyright ( c ) 2004 - 2006 Simtec Electronics
2007-02-11 20:31:01 +03:00
* Ben Dooks < ben @ simtec . co . uk >
*
* S3C24XX Power Manager ( Suspend - To - RAM ) support
*
* See Documentation / arm / Samsung - S3C24XX / Suspend . txt for more information
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
* Parts based on arch / arm / mach - pxa / pm . c
*
* Thanks to Dimitry Andric for debugging
*/
# include <linux/init.h>
# include <linux/suspend.h>
# include <linux/errno.h>
# include <linux/time.h>
2009-05-14 01:52:24 +04:00
# include <linux/gpio.h>
2007-02-11 20:31:01 +03:00
# include <linux/interrupt.h>
# include <linux/serial_core.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2007-02-11 20:31:01 +03:00
2008-10-08 01:26:09 +04:00
# include <plat/regs-serial.h>
2008-08-05 19:14:15 +04:00
# include <mach/regs-clock.h>
# include <mach/regs-gpio.h>
# include <mach/regs-mem.h>
# include <mach/regs-irq.h>
2007-02-11 20:31:01 +03:00
# include <asm/mach/time.h>
2010-05-04 09:38:49 +04:00
# include <plat/gpio-cfg.h>
2008-10-08 01:26:09 +04:00
# include <plat/pm.h>
2007-02-11 20:31:01 +03:00
# define PFX "s3c24xx-pm: "
static struct sleep_save core_save [ ] = {
SAVE_ITEM ( S3C2410_LOCKTIME ) ,
SAVE_ITEM ( S3C2410_CLKCON ) ,
/* we restore the timings here, with the proviso that the board
* brings the system up in an slower , or equal frequency setting
* to the original system .
*
* if we cannot guarantee this , then things are going to go very
* wrong here , as we modify the refresh and both pll settings .
*/
SAVE_ITEM ( S3C2410_BWSCON ) ,
SAVE_ITEM ( S3C2410_BANKCON0 ) ,
SAVE_ITEM ( S3C2410_BANKCON1 ) ,
SAVE_ITEM ( S3C2410_BANKCON2 ) ,
SAVE_ITEM ( S3C2410_BANKCON3 ) ,
SAVE_ITEM ( S3C2410_BANKCON4 ) ,
SAVE_ITEM ( S3C2410_BANKCON5 ) ,
2008-10-21 17:06:38 +04:00
# ifndef CONFIG_CPU_FREQ
2007-02-11 20:31:01 +03:00
SAVE_ITEM ( S3C2410_CLKDIVN ) ,
SAVE_ITEM ( S3C2410_MPLLCON ) ,
2008-10-21 17:06:38 +04:00
SAVE_ITEM ( S3C2410_REFRESH ) ,
# endif
2007-02-11 20:31:01 +03:00
SAVE_ITEM ( S3C2410_UPLLCON ) ,
SAVE_ITEM ( S3C2410_CLKSLOW ) ,
} ;
2008-01-28 15:01:24 +03:00
static struct sleep_save misc_save [ ] = {
2007-02-11 20:31:01 +03:00
SAVE_ITEM ( S3C2410_DCLKCON ) ,
} ;
2008-12-12 03:24:07 +03:00
/* s3c_pm_check_resume_pin
2007-02-11 20:31:01 +03:00
*
* check to see if the pin is configured correctly for sleep mode , and
* make any necessary adjustments if it is not
*/
2008-12-12 03:24:07 +03:00
static void s3c_pm_check_resume_pin ( unsigned int pin , unsigned int irqoffs )
2007-02-11 20:31:01 +03:00
{
unsigned long irqstate ;
unsigned long pinstate ;
2010-05-04 12:14:10 +04:00
int irq = gpio_to_irq ( pin ) ;
2007-02-11 20:31:01 +03:00
if ( irqoffs < 4 )
irqstate = s3c_irqwake_intmask & ( 1L < < irqoffs ) ;
else
irqstate = s3c_irqwake_eintmask & ( 1L < < irqoffs ) ;
2010-05-06 05:50:42 +04:00
pinstate = s3c_gpio_getcfg ( pin ) ;
2007-02-11 20:31:01 +03:00
if ( ! irqstate ) {
if ( pinstate = = S3C2410_GPIO_IRQ )
2010-05-06 05:50:42 +04:00
S3C_PMDBG ( " Leaving IRQ %d (pin %d) as is \n " , irq , pin ) ;
2007-02-11 20:31:01 +03:00
} else {
if ( pinstate = = S3C2410_GPIO_IRQ ) {
2008-12-12 03:24:06 +03:00
S3C_PMDBG ( " Disabling IRQ %d (pin %d) \n " , irq , pin ) ;
2010-05-04 09:38:49 +04:00
s3c_gpio_cfgpin ( pin , S3C2410_GPIO_INPUT ) ;
2007-02-11 20:31:01 +03:00
}
}
}
2008-12-12 03:24:08 +03:00
/* s3c_pm_configure_extint
2007-02-11 20:31:01 +03:00
*
* configure all external interrupt pins
*/
2008-12-12 03:24:08 +03:00
void s3c_pm_configure_extint ( void )
2007-02-11 20:31:01 +03:00
{
int pin ;
/* for each of the external interrupts (EINT0..EINT15) we
* need to check wether it is an external interrupt source ,
* and then configure it as an input if it is not
*/
2009-05-18 01:32:23 +04:00
for ( pin = S3C2410_GPF ( 0 ) ; pin < = S3C2410_GPF ( 7 ) ; pin + + ) {
s3c_pm_check_resume_pin ( pin , pin - S3C2410_GPF ( 0 ) ) ;
2007-02-11 20:31:01 +03:00
}
2009-05-18 01:32:23 +04:00
for ( pin = S3C2410_GPG ( 0 ) ; pin < = S3C2410_GPG ( 7 ) ; pin + + ) {
s3c_pm_check_resume_pin ( pin , ( pin - S3C2410_GPG ( 0 ) ) + 8 ) ;
2007-02-11 20:31:01 +03:00
}
}
2008-01-28 15:01:24 +03:00
2008-12-12 03:24:08 +03:00
void s3c_pm_restore_core ( void )
2007-02-11 20:31:01 +03:00
{
2008-12-12 03:24:06 +03:00
s3c_pm_do_restore_core ( core_save , ARRAY_SIZE ( core_save ) ) ;
s3c_pm_do_restore ( misc_save , ARRAY_SIZE ( misc_save ) ) ;
2007-02-11 20:31:01 +03:00
}
2008-12-12 03:24:08 +03:00
void s3c_pm_save_core ( void )
2007-02-11 20:31:01 +03:00
{
2008-12-12 03:24:08 +03:00
s3c_pm_do_save ( misc_save , ARRAY_SIZE ( misc_save ) ) ;
s3c_pm_do_save ( core_save , ARRAY_SIZE ( core_save ) ) ;
2007-02-11 20:31:01 +03:00
}
2008-12-12 03:24:08 +03:00