Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | // SPDX-License-Identifier: GPL-2.0 // // Copyright (c) 2003-2004 Simtec Electronics // Ben Dooks <ben@simtec.co.uk> // http://armlinux.simtec.co.uk/ // // S3C24XX - IRQ PM code #include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/syscore_ops.h> #include <linux/io.h> #include "cpu.h" #include "pm.h" #include "map-base.h" #include "map-s3c.h" #include "regs-irq.h" #include "regs-gpio.h" #include "pm-core.h" #include <asm/irq.h> int s3c_irq_wake(struct irq_data *data, unsigned int state) { unsigned long irqbit = 1 << data->hwirq; if (!(s3c_irqwake_intallow & irqbit)) return -ENOENT; pr_info("wake %s for hwirq %lu\n", state ? "enabled" : "disabled", data->hwirq); if (!state) s3c_irqwake_intmask |= irqbit; else s3c_irqwake_intmask &= ~irqbit; return 0; } static struct sleep_save irq_save[] = { SAVE_ITEM(S3C2410_INTMSK), SAVE_ITEM(S3C2410_INTSUBMSK), }; /* the extint values move between the s3c2410/s3c2440 and the s3c2412 * so we use an array to hold them, and to calculate the address of * the register at run-time */ static unsigned long save_extint[3]; static unsigned long save_eintflt[4]; static unsigned long save_eintmask; static int s3c24xx_irq_suspend(void) { unsigned int i; for (i = 0; i < ARRAY_SIZE(save_extint); i++) save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4)); for (i = 0; i < ARRAY_SIZE(save_eintflt); i++) save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4)); s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); save_eintmask = __raw_readl(S3C24XX_EINTMASK); return 0; } static void s3c24xx_irq_resume(void) { unsigned int i; for (i = 0; i < ARRAY_SIZE(save_extint); i++) __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4)); for (i = 0; i < ARRAY_SIZE(save_eintflt); i++) __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4)); s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); __raw_writel(save_eintmask, S3C24XX_EINTMASK); } struct syscore_ops s3c24xx_irq_syscore_ops = { .suspend = s3c24xx_irq_suspend, .resume = s3c24xx_irq_resume, }; #ifdef CONFIG_CPU_S3C2416 static struct sleep_save s3c2416_irq_save[] = { SAVE_ITEM(S3C2416_INTMSK2), }; static int s3c2416_irq_suspend(void) { s3c_pm_do_save(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save)); return 0; } static void s3c2416_irq_resume(void) { s3c_pm_do_restore(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save)); } struct syscore_ops s3c2416_irq_syscore_ops = { .suspend = s3c2416_irq_suspend, .resume = s3c2416_irq_resume, }; #endif |