0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/kernel.h>
0015 #include <linux/syscore_ops.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/serial_core.h>
0018 #include <linux/serial_s3c.h>
0019 #include <linux/irq.h>
0020 #include <linux/io.h>
0021 #include <linux/of.h>
0022
0023 #include "map.h"
0024
0025 #include "regs-gpio.h"
0026 #include "cpu.h"
0027 #include "pm.h"
0028
0029
0030
0031
0032
0033
0034
0035
0036 static struct sleep_save irq_save[] = {
0037 SAVE_ITEM(S3C64XX_PRIORITY),
0038 SAVE_ITEM(S3C64XX_EINT0CON0),
0039 SAVE_ITEM(S3C64XX_EINT0CON1),
0040 SAVE_ITEM(S3C64XX_EINT0FLTCON0),
0041 SAVE_ITEM(S3C64XX_EINT0FLTCON1),
0042 SAVE_ITEM(S3C64XX_EINT0FLTCON2),
0043 SAVE_ITEM(S3C64XX_EINT0FLTCON3),
0044 SAVE_ITEM(S3C64XX_EINT0MASK),
0045 };
0046
0047 static struct irq_grp_save {
0048 u32 fltcon;
0049 u32 con;
0050 u32 mask;
0051 } eint_grp_save[5];
0052
0053 #ifndef CONFIG_SERIAL_SAMSUNG_UARTS
0054 #define SERIAL_SAMSUNG_UARTS 0
0055 #else
0056 #define SERIAL_SAMSUNG_UARTS CONFIG_SERIAL_SAMSUNG_UARTS
0057 #endif
0058
0059 static u32 irq_uart_mask[SERIAL_SAMSUNG_UARTS];
0060
0061 static int s3c64xx_irq_pm_suspend(void)
0062 {
0063 struct irq_grp_save *grp = eint_grp_save;
0064 int i;
0065
0066 S3C_PMDBG("%s: suspending IRQs\n", __func__);
0067
0068 s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
0069
0070 for (i = 0; i < SERIAL_SAMSUNG_UARTS; i++)
0071 irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
0072
0073 for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
0074 grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4));
0075 grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4));
0076 grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4));
0077 }
0078
0079 return 0;
0080 }
0081
0082 static void s3c64xx_irq_pm_resume(void)
0083 {
0084 struct irq_grp_save *grp = eint_grp_save;
0085 int i;
0086
0087 S3C_PMDBG("%s: resuming IRQs\n", __func__);
0088
0089 s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
0090
0091 for (i = 0; i < SERIAL_SAMSUNG_UARTS; i++)
0092 __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
0093
0094 for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
0095 __raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4));
0096 __raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4));
0097 __raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
0098 }
0099
0100 S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
0101 }
0102
0103 static struct syscore_ops s3c64xx_irq_syscore_ops = {
0104 .suspend = s3c64xx_irq_pm_suspend,
0105 .resume = s3c64xx_irq_pm_resume,
0106 };
0107
0108 static __init int s3c64xx_syscore_init(void)
0109 {
0110
0111 if (of_have_populated_dt() || !soc_is_s3c64xx())
0112 return 0;
0113
0114 register_syscore_ops(&s3c64xx_irq_syscore_ops);
0115
0116 return 0;
0117 }
0118
0119 core_initcall(s3c64xx_syscore_init);