Krzysztof Kozlowski | 28a196f | 2017-12-25 20:54:33 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | // |
| 3 | // Copyright 2008 Openmoko, Inc. |
| 4 | // Copyright 2008 Simtec Electronics |
| 5 | // Ben Dooks <ben@simtec.co.uk> |
| 6 | // http://armlinux.simtec.co.uk/ |
| 7 | // |
| 8 | // S3C64XX - Interrupt handling Power Management |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 9 | |
Tomasz Figa | c836c90 | 2013-08-26 02:37:34 +0900 | [diff] [blame] | 10 | /* |
| 11 | * NOTE: Code in this file is not used when booting with Device Tree support. |
| 12 | */ |
| 13 | |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 14 | #include <linux/kernel.h> |
Rafael J. Wysocki | bb072c3 | 2011-04-22 22:03:21 +0200 | [diff] [blame] | 15 | #include <linux/syscore_ops.h> |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 16 | #include <linux/interrupt.h> |
| 17 | #include <linux/serial_core.h> |
Tushar Behera | 334a1c7 | 2014-02-14 10:32:45 +0900 | [diff] [blame] | 18 | #include <linux/serial_s3c.h> |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 19 | #include <linux/irq.h> |
| 20 | #include <linux/io.h> |
Tomasz Figa | c836c90 | 2013-08-26 02:37:34 +0900 | [diff] [blame] | 21 | #include <linux/of.h> |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 22 | |
Arnd Bergmann | c6ff132 | 2019-09-02 18:37:30 +0200 | [diff] [blame] | 23 | #include "map.h" |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 24 | |
Arnd Bergmann | c6ff132 | 2019-09-02 18:37:30 +0200 | [diff] [blame] | 25 | #include "regs-gpio.h" |
| 26 | #include "cpu.h" |
| 27 | #include "pm.h" |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 28 | |
| 29 | /* We handled all the IRQ types in this code, to save having to make several |
| 30 | * small files to handle each different type separately. Having the EINT_GRP |
| 31 | * code here shouldn't be as much bloat as the IRQ table space needed when |
| 32 | * they are enabled. The added benefit is we ensure that these registers are |
| 33 | * in the same state as we suspended. |
| 34 | */ |
| 35 | |
| 36 | static struct sleep_save irq_save[] = { |
| 37 | SAVE_ITEM(S3C64XX_PRIORITY), |
| 38 | SAVE_ITEM(S3C64XX_EINT0CON0), |
| 39 | SAVE_ITEM(S3C64XX_EINT0CON1), |
| 40 | SAVE_ITEM(S3C64XX_EINT0FLTCON0), |
| 41 | SAVE_ITEM(S3C64XX_EINT0FLTCON1), |
| 42 | SAVE_ITEM(S3C64XX_EINT0FLTCON2), |
| 43 | SAVE_ITEM(S3C64XX_EINT0FLTCON3), |
| 44 | SAVE_ITEM(S3C64XX_EINT0MASK), |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 45 | }; |
| 46 | |
| 47 | static struct irq_grp_save { |
| 48 | u32 fltcon; |
| 49 | u32 con; |
| 50 | u32 mask; |
| 51 | } eint_grp_save[5]; |
| 52 | |
Arnd Bergmann | 0443a65 | 2014-02-26 17:55:35 +0100 | [diff] [blame] | 53 | #ifndef CONFIG_SERIAL_SAMSUNG_UARTS |
| 54 | #define SERIAL_SAMSUNG_UARTS 0 |
| 55 | #else |
| 56 | #define SERIAL_SAMSUNG_UARTS CONFIG_SERIAL_SAMSUNG_UARTS |
| 57 | #endif |
| 58 | |
| 59 | static u32 irq_uart_mask[SERIAL_SAMSUNG_UARTS]; |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 60 | |
Rafael J. Wysocki | bb072c3 | 2011-04-22 22:03:21 +0200 | [diff] [blame] | 61 | static int s3c64xx_irq_pm_suspend(void) |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 62 | { |
| 63 | struct irq_grp_save *grp = eint_grp_save; |
| 64 | int i; |
| 65 | |
| 66 | S3C_PMDBG("%s: suspending IRQs\n", __func__); |
| 67 | |
| 68 | s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); |
| 69 | |
Arnd Bergmann | 0443a65 | 2014-02-26 17:55:35 +0100 | [diff] [blame] | 70 | for (i = 0; i < SERIAL_SAMSUNG_UARTS; i++) |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 71 | irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM); |
| 72 | |
| 73 | for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) { |
| 74 | grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4)); |
| 75 | grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4)); |
| 76 | grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4)); |
| 77 | } |
| 78 | |
| 79 | return 0; |
| 80 | } |
| 81 | |
Rafael J. Wysocki | bb072c3 | 2011-04-22 22:03:21 +0200 | [diff] [blame] | 82 | static void s3c64xx_irq_pm_resume(void) |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 83 | { |
| 84 | struct irq_grp_save *grp = eint_grp_save; |
| 85 | int i; |
| 86 | |
| 87 | S3C_PMDBG("%s: resuming IRQs\n", __func__); |
| 88 | |
| 89 | s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); |
| 90 | |
Arnd Bergmann | 0443a65 | 2014-02-26 17:55:35 +0100 | [diff] [blame] | 91 | for (i = 0; i < SERIAL_SAMSUNG_UARTS; i++) |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 92 | __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM); |
| 93 | |
| 94 | for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) { |
| 95 | __raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4)); |
| 96 | __raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4)); |
| 97 | __raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4)); |
| 98 | } |
| 99 | |
| 100 | S3C_PMDBG("%s: IRQ configuration restored\n", __func__); |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 101 | } |
| 102 | |
Kukjin Kim | 5086c6c | 2012-01-21 11:32:42 +0900 | [diff] [blame] | 103 | static struct syscore_ops s3c64xx_irq_syscore_ops = { |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 104 | .suspend = s3c64xx_irq_pm_suspend, |
| 105 | .resume = s3c64xx_irq_pm_resume, |
| 106 | }; |
| 107 | |
Rafael J. Wysocki | bb072c3 | 2011-04-22 22:03:21 +0200 | [diff] [blame] | 108 | static __init int s3c64xx_syscore_init(void) |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 109 | { |
Tomasz Figa | c836c90 | 2013-08-26 02:37:34 +0900 | [diff] [blame] | 110 | /* Appropriate drivers (pinctrl, uart) handle this when using DT. */ |
Arnd Bergmann | a0e157a | 2015-02-27 20:31:51 +0100 | [diff] [blame] | 111 | if (of_have_populated_dt() || !soc_is_s3c64xx()) |
Tomasz Figa | c836c90 | 2013-08-26 02:37:34 +0900 | [diff] [blame] | 112 | return 0; |
| 113 | |
Rafael J. Wysocki | bb072c3 | 2011-04-22 22:03:21 +0200 | [diff] [blame] | 114 | register_syscore_ops(&s3c64xx_irq_syscore_ops); |
| 115 | |
| 116 | return 0; |
Ben Dooks | 966bcc1 | 2008-12-12 00:24:32 +0000 | [diff] [blame] | 117 | } |
| 118 | |
Rafael J. Wysocki | bb072c3 | 2011-04-22 22:03:21 +0200 | [diff] [blame] | 119 | core_initcall(s3c64xx_syscore_init); |