xref: /linux/arch/arm/mach-s3c/irq-pm-s3c64xx.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
171b9114dSArnd Bergmann // SPDX-License-Identifier: GPL-2.0
271b9114dSArnd Bergmann //
371b9114dSArnd Bergmann // Copyright 2008 Openmoko, Inc.
471b9114dSArnd Bergmann // Copyright 2008 Simtec Electronics
571b9114dSArnd Bergmann //      Ben Dooks <ben@simtec.co.uk>
671b9114dSArnd Bergmann //      http://armlinux.simtec.co.uk/
771b9114dSArnd Bergmann //
871b9114dSArnd Bergmann // S3C64XX - Interrupt handling Power Management
971b9114dSArnd Bergmann 
1071b9114dSArnd Bergmann /*
1171b9114dSArnd Bergmann  * NOTE: Code in this file is not used when booting with Device Tree support.
1271b9114dSArnd Bergmann  */
1371b9114dSArnd Bergmann 
1471b9114dSArnd Bergmann #include <linux/kernel.h>
1571b9114dSArnd Bergmann #include <linux/syscore_ops.h>
1671b9114dSArnd Bergmann #include <linux/interrupt.h>
1771b9114dSArnd Bergmann #include <linux/serial_core.h>
1871b9114dSArnd Bergmann #include <linux/serial_s3c.h>
1971b9114dSArnd Bergmann #include <linux/irq.h>
2071b9114dSArnd Bergmann #include <linux/io.h>
2171b9114dSArnd Bergmann #include <linux/of.h>
2271b9114dSArnd Bergmann 
23*c6ff132dSArnd Bergmann #include "map.h"
2471b9114dSArnd Bergmann 
25*c6ff132dSArnd Bergmann #include "regs-gpio.h"
26*c6ff132dSArnd Bergmann #include "cpu.h"
27*c6ff132dSArnd Bergmann #include "pm.h"
2871b9114dSArnd Bergmann 
2971b9114dSArnd Bergmann /* We handled all the IRQ types in this code, to save having to make several
3071b9114dSArnd Bergmann  * small files to handle each different type separately. Having the EINT_GRP
3171b9114dSArnd Bergmann  * code here shouldn't be as much bloat as the IRQ table space needed when
3271b9114dSArnd Bergmann  * they are enabled. The added benefit is we ensure that these registers are
3371b9114dSArnd Bergmann  * in the same state as we suspended.
3471b9114dSArnd Bergmann  */
3571b9114dSArnd Bergmann 
3671b9114dSArnd Bergmann static struct sleep_save irq_save[] = {
3771b9114dSArnd Bergmann 	SAVE_ITEM(S3C64XX_PRIORITY),
3871b9114dSArnd Bergmann 	SAVE_ITEM(S3C64XX_EINT0CON0),
3971b9114dSArnd Bergmann 	SAVE_ITEM(S3C64XX_EINT0CON1),
4071b9114dSArnd Bergmann 	SAVE_ITEM(S3C64XX_EINT0FLTCON0),
4171b9114dSArnd Bergmann 	SAVE_ITEM(S3C64XX_EINT0FLTCON1),
4271b9114dSArnd Bergmann 	SAVE_ITEM(S3C64XX_EINT0FLTCON2),
4371b9114dSArnd Bergmann 	SAVE_ITEM(S3C64XX_EINT0FLTCON3),
4471b9114dSArnd Bergmann 	SAVE_ITEM(S3C64XX_EINT0MASK),
4571b9114dSArnd Bergmann };
4671b9114dSArnd Bergmann 
4771b9114dSArnd Bergmann static struct irq_grp_save {
4871b9114dSArnd Bergmann 	u32	fltcon;
4971b9114dSArnd Bergmann 	u32	con;
5071b9114dSArnd Bergmann 	u32	mask;
5171b9114dSArnd Bergmann } eint_grp_save[5];
5271b9114dSArnd Bergmann 
5371b9114dSArnd Bergmann #ifndef CONFIG_SERIAL_SAMSUNG_UARTS
5471b9114dSArnd Bergmann #define SERIAL_SAMSUNG_UARTS 0
5571b9114dSArnd Bergmann #else
5671b9114dSArnd Bergmann #define	SERIAL_SAMSUNG_UARTS CONFIG_SERIAL_SAMSUNG_UARTS
5771b9114dSArnd Bergmann #endif
5871b9114dSArnd Bergmann 
5971b9114dSArnd Bergmann static u32 irq_uart_mask[SERIAL_SAMSUNG_UARTS];
6071b9114dSArnd Bergmann 
s3c64xx_irq_pm_suspend(void)6171b9114dSArnd Bergmann static int s3c64xx_irq_pm_suspend(void)
6271b9114dSArnd Bergmann {
6371b9114dSArnd Bergmann 	struct irq_grp_save *grp = eint_grp_save;
6471b9114dSArnd Bergmann 	int i;
6571b9114dSArnd Bergmann 
6671b9114dSArnd Bergmann 	S3C_PMDBG("%s: suspending IRQs\n", __func__);
6771b9114dSArnd Bergmann 
6871b9114dSArnd Bergmann 	s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
6971b9114dSArnd Bergmann 
7071b9114dSArnd Bergmann 	for (i = 0; i < SERIAL_SAMSUNG_UARTS; i++)
7171b9114dSArnd Bergmann 		irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
7271b9114dSArnd Bergmann 
7371b9114dSArnd Bergmann 	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
7471b9114dSArnd Bergmann 		grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4));
7571b9114dSArnd Bergmann 		grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4));
7671b9114dSArnd Bergmann 		grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4));
7771b9114dSArnd Bergmann 	}
7871b9114dSArnd Bergmann 
7971b9114dSArnd Bergmann 	return 0;
8071b9114dSArnd Bergmann }
8171b9114dSArnd Bergmann 
s3c64xx_irq_pm_resume(void)8271b9114dSArnd Bergmann static void s3c64xx_irq_pm_resume(void)
8371b9114dSArnd Bergmann {
8471b9114dSArnd Bergmann 	struct irq_grp_save *grp = eint_grp_save;
8571b9114dSArnd Bergmann 	int i;
8671b9114dSArnd Bergmann 
8771b9114dSArnd Bergmann 	S3C_PMDBG("%s: resuming IRQs\n", __func__);
8871b9114dSArnd Bergmann 
8971b9114dSArnd Bergmann 	s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
9071b9114dSArnd Bergmann 
9171b9114dSArnd Bergmann 	for (i = 0; i < SERIAL_SAMSUNG_UARTS; i++)
9271b9114dSArnd Bergmann 		__raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
9371b9114dSArnd Bergmann 
9471b9114dSArnd Bergmann 	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
9571b9114dSArnd Bergmann 		__raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4));
9671b9114dSArnd Bergmann 		__raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4));
9771b9114dSArnd Bergmann 		__raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
9871b9114dSArnd Bergmann 	}
9971b9114dSArnd Bergmann 
10071b9114dSArnd Bergmann 	S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
10171b9114dSArnd Bergmann }
10271b9114dSArnd Bergmann 
10371b9114dSArnd Bergmann static struct syscore_ops s3c64xx_irq_syscore_ops = {
10471b9114dSArnd Bergmann 	.suspend = s3c64xx_irq_pm_suspend,
10571b9114dSArnd Bergmann 	.resume	 = s3c64xx_irq_pm_resume,
10671b9114dSArnd Bergmann };
10771b9114dSArnd Bergmann 
s3c64xx_syscore_init(void)10871b9114dSArnd Bergmann static __init int s3c64xx_syscore_init(void)
10971b9114dSArnd Bergmann {
11071b9114dSArnd Bergmann 	/* Appropriate drivers (pinctrl, uart) handle this when using DT. */
11171b9114dSArnd Bergmann 	if (of_have_populated_dt() || !soc_is_s3c64xx())
11271b9114dSArnd Bergmann 		return 0;
11371b9114dSArnd Bergmann 
11471b9114dSArnd Bergmann 	register_syscore_ops(&s3c64xx_irq_syscore_ops);
11571b9114dSArnd Bergmann 
11671b9114dSArnd Bergmann 	return 0;
11771b9114dSArnd Bergmann }
11871b9114dSArnd Bergmann 
11971b9114dSArnd Bergmann core_initcall(s3c64xx_syscore_init);
120