1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2011 Google, Inc. |
4 | * |
5 | * Author: |
6 | * Colin Cross <ccross@android.com> |
7 | * |
8 | * Copyright (C) 2010,2013, NVIDIA Corporation |
9 | */ |
10 | |
11 | #include <linux/cpu_pm.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/io.h> |
14 | #include <linux/irqchip/arm-gic.h> |
15 | #include <linux/irq.h> |
16 | #include <linux/kernel.h> |
17 | #include <linux/of_address.h> |
18 | #include <linux/of.h> |
19 | #include <linux/syscore_ops.h> |
20 | |
21 | #include <soc/tegra/irq.h> |
22 | |
23 | #include "board.h" |
24 | #include "iomap.h" |
25 | |
26 | #define SGI_MASK 0xFFFF |
27 | |
28 | #ifdef CONFIG_PM_SLEEP |
29 | static void __iomem *tegra_gic_cpu_base; |
30 | #endif |
31 | |
32 | bool tegra_pending_sgi(void) |
33 | { |
34 | u32 pending_set; |
35 | void __iomem *distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE); |
36 | |
37 | pending_set = readl_relaxed(distbase + GIC_DIST_PENDING_SET); |
38 | |
39 | if (pending_set & SGI_MASK) |
40 | return true; |
41 | |
42 | return false; |
43 | } |
44 | |
45 | #ifdef CONFIG_PM_SLEEP |
46 | static int tegra_gic_notifier(struct notifier_block *self, |
47 | unsigned long cmd, void *v) |
48 | { |
49 | switch (cmd) { |
50 | case CPU_PM_ENTER: |
51 | writel_relaxed(0x1E0, tegra_gic_cpu_base + GIC_CPU_CTRL); |
52 | break; |
53 | } |
54 | |
55 | return NOTIFY_OK; |
56 | } |
57 | |
58 | static struct notifier_block tegra_gic_notifier_block = { |
59 | .notifier_call = tegra_gic_notifier, |
60 | }; |
61 | |
62 | static const struct of_device_id tegra114_dt_gic_match[] __initconst = { |
63 | { .compatible = "arm,cortex-a15-gic" }, |
64 | { } |
65 | }; |
66 | |
67 | static void __init tegra114_gic_cpu_pm_registration(void) |
68 | { |
69 | struct device_node *dn; |
70 | |
71 | dn = of_find_matching_node(NULL, matches: tegra114_dt_gic_match); |
72 | if (!dn) |
73 | return; |
74 | |
75 | tegra_gic_cpu_base = of_iomap(node: dn, index: 1); |
76 | |
77 | cpu_pm_register_notifier(nb: &tegra_gic_notifier_block); |
78 | } |
79 | #else |
80 | static void __init tegra114_gic_cpu_pm_registration(void) { } |
81 | #endif |
82 | |
83 | static const struct of_device_id tegra_ictlr_match[] __initconst = { |
84 | { .compatible = "nvidia,tegra20-ictlr" }, |
85 | { .compatible = "nvidia,tegra30-ictlr" }, |
86 | { } |
87 | }; |
88 | |
89 | void __init tegra_init_irq(void) |
90 | { |
91 | if (WARN_ON(!of_find_matching_node(NULL, tegra_ictlr_match))) |
92 | pr_warn("Outdated DT detected, suspend/resume will NOT work\n" ); |
93 | |
94 | tegra114_gic_cpu_pm_registration(); |
95 | } |
96 | |