Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright (c) 2003-2004 Simtec Electronics
0004 //  Ben Dooks <ben@simtec.co.uk>
0005 //  http://armlinux.simtec.co.uk/
0006 //
0007 // S3C24XX - IRQ PM code
0008 
0009 #include <linux/init.h>
0010 #include <linux/module.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/irq.h>
0013 #include <linux/syscore_ops.h>
0014 #include <linux/io.h>
0015 
0016 #include "cpu.h"
0017 #include "pm.h"
0018 #include "map-base.h"
0019 #include "map-s3c.h"
0020 
0021 #include "regs-irq.h"
0022 #include "regs-gpio.h"
0023 #include "pm-core.h"
0024 
0025 #include <asm/irq.h>
0026 
0027 int s3c_irq_wake(struct irq_data *data, unsigned int state)
0028 {
0029     unsigned long irqbit = 1 << data->hwirq;
0030 
0031     if (!(s3c_irqwake_intallow & irqbit))
0032         return -ENOENT;
0033 
0034     pr_info("wake %s for hwirq %lu\n",
0035         state ? "enabled" : "disabled", data->hwirq);
0036 
0037     if (!state)
0038         s3c_irqwake_intmask |= irqbit;
0039     else
0040         s3c_irqwake_intmask &= ~irqbit;
0041 
0042     return 0;
0043 }
0044 
0045 static struct sleep_save irq_save[] = {
0046     SAVE_ITEM(S3C2410_INTMSK),
0047     SAVE_ITEM(S3C2410_INTSUBMSK),
0048 };
0049 
0050 /* the extint values move between the s3c2410/s3c2440 and the s3c2412
0051  * so we use an array to hold them, and to calculate the address of
0052  * the register at run-time
0053 */
0054 
0055 static unsigned long save_extint[3];
0056 static unsigned long save_eintflt[4];
0057 static unsigned long save_eintmask;
0058 
0059 static int s3c24xx_irq_suspend(void)
0060 {
0061     unsigned int i;
0062 
0063     for (i = 0; i < ARRAY_SIZE(save_extint); i++)
0064         save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
0065 
0066     for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
0067         save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
0068 
0069     s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
0070     save_eintmask = __raw_readl(S3C24XX_EINTMASK);
0071 
0072     return 0;
0073 }
0074 
0075 static void s3c24xx_irq_resume(void)
0076 {
0077     unsigned int i;
0078 
0079     for (i = 0; i < ARRAY_SIZE(save_extint); i++)
0080         __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
0081 
0082     for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
0083         __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
0084 
0085     s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
0086     __raw_writel(save_eintmask, S3C24XX_EINTMASK);
0087 }
0088 
0089 struct syscore_ops s3c24xx_irq_syscore_ops = {
0090     .suspend    = s3c24xx_irq_suspend,
0091     .resume     = s3c24xx_irq_resume,
0092 };
0093 
0094 #ifdef CONFIG_CPU_S3C2416
0095 static struct sleep_save s3c2416_irq_save[] = {
0096     SAVE_ITEM(S3C2416_INTMSK2),
0097 };
0098 
0099 static int s3c2416_irq_suspend(void)
0100 {
0101     s3c_pm_do_save(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save));
0102 
0103     return 0;
0104 }
0105 
0106 static void s3c2416_irq_resume(void)
0107 {
0108     s3c_pm_do_restore(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save));
0109 }
0110 
0111 struct syscore_ops s3c2416_irq_syscore_ops = {
0112     .suspend    = s3c2416_irq_suspend,
0113     .resume     = s3c2416_irq_resume,
0114 };
0115 #endif