Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright 2008 Openmoko, Inc.
0004 // Copyright 2008 Simtec Electronics
0005 //      Ben Dooks <ben@simtec.co.uk>
0006 //      http://armlinux.simtec.co.uk/
0007 //
0008 // S3C64XX - Interrupt handling Power Management
0009 
0010 /*
0011  * NOTE: Code in this file is not used when booting with Device Tree support.
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 /* We handled all the IRQ types in this code, to save having to make several
0030  * small files to handle each different type separately. Having the EINT_GRP
0031  * code here shouldn't be as much bloat as the IRQ table space needed when
0032  * they are enabled. The added benefit is we ensure that these registers are
0033  * in the same state as we suspended.
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     /* Appropriate drivers (pinctrl, uart) handle this when using DT. */
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);