Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // Copyright (c) 2004-2006 Simtec Electronics
0004 //  Ben Dooks <ben@simtec.co.uk>
0005 //
0006 // S3C24XX Power Manager (Suspend-To-RAM) support
0007 //
0008 // See Documentation/arm/samsung-s3c24xx/suspend.rst for more information
0009 //
0010 // Parts based on arch/arm/mach-pxa/pm.c
0011 //
0012 // Thanks to Dimitry Andric for debugging
0013 
0014 #include <linux/init.h>
0015 #include <linux/suspend.h>
0016 #include <linux/errno.h>
0017 #include <linux/time.h>
0018 #include <linux/gpio.h>
0019 #include <linux/interrupt.h>
0020 #include <linux/serial_core.h>
0021 #include <linux/serial_s3c.h>
0022 #include <linux/io.h>
0023 
0024 #include "regs-clock.h"
0025 #include "regs-gpio.h"
0026 #include "regs-irq.h"
0027 #include "gpio-samsung.h"
0028 
0029 #include <asm/mach/time.h>
0030 
0031 #include "gpio-cfg.h"
0032 #include "pm.h"
0033 
0034 #include "regs-mem-s3c24xx.h"
0035 
0036 #define PFX "s3c24xx-pm: "
0037 
0038 #ifdef CONFIG_PM_SLEEP
0039 static struct sleep_save core_save[] = {
0040     /* we restore the timings here, with the proviso that the board
0041      * brings the system up in an slower, or equal frequency setting
0042      * to the original system.
0043      *
0044      * if we cannot guarantee this, then things are going to go very
0045      * wrong here, as we modify the refresh and both pll settings.
0046      */
0047 
0048     SAVE_ITEM(S3C2410_BWSCON),
0049     SAVE_ITEM(S3C2410_BANKCON0),
0050     SAVE_ITEM(S3C2410_BANKCON1),
0051     SAVE_ITEM(S3C2410_BANKCON2),
0052     SAVE_ITEM(S3C2410_BANKCON3),
0053     SAVE_ITEM(S3C2410_BANKCON4),
0054     SAVE_ITEM(S3C2410_BANKCON5),
0055 };
0056 #endif
0057 
0058 /* s3c_pm_check_resume_pin
0059  *
0060  * check to see if the pin is configured correctly for sleep mode, and
0061  * make any necessary adjustments if it is not
0062 */
0063 
0064 static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
0065 {
0066     unsigned long irqstate;
0067     unsigned long pinstate;
0068     int irq = gpio_to_irq(pin);
0069 
0070     if (irqoffs < 4)
0071         irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
0072     else
0073         irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
0074 
0075     pinstate = s3c_gpio_getcfg(pin);
0076 
0077     if (!irqstate) {
0078         if (pinstate == S3C2410_GPIO_IRQ)
0079             S3C_PMDBG("Leaving IRQ %d (pin %d) as is\n", irq, pin);
0080     } else {
0081         if (pinstate == S3C2410_GPIO_IRQ) {
0082             S3C_PMDBG("Disabling IRQ %d (pin %d)\n", irq, pin);
0083             s3c_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
0084         }
0085     }
0086 }
0087 
0088 /* s3c_pm_configure_extint
0089  *
0090  * configure all external interrupt pins
0091 */
0092 
0093 void s3c_pm_configure_extint(void)
0094 {
0095     int pin;
0096 
0097     /* for each of the external interrupts (EINT0..EINT15) we
0098      * need to check whether it is an external interrupt source,
0099      * and then configure it as an input if it is not
0100     */
0101 
0102     for (pin = S3C2410_GPF(0); pin <= S3C2410_GPF(7); pin++) {
0103         s3c_pm_check_resume_pin(pin, pin - S3C2410_GPF(0));
0104     }
0105 
0106     for (pin = S3C2410_GPG(0); pin <= S3C2410_GPG(7); pin++) {
0107         s3c_pm_check_resume_pin(pin, (pin - S3C2410_GPG(0))+8);
0108     }
0109 }
0110 
0111 #ifdef CONFIG_PM_SLEEP
0112 void s3c_pm_restore_core(void)
0113 {
0114     s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
0115 }
0116 
0117 void s3c_pm_save_core(void)
0118 {
0119     s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
0120 }
0121 #endif