2 * Driver code for Tegra's Legacy Interrupt Controller
4 * Author: Marc Zyngier <marc.zyngier@arm.com>
6 * Heavily based on the original arch/arm/mach-tegra/irq.c code:
7 * Copyright (C) 2011 Google, Inc.
10 * Colin Cross <ccross@android.com>
12 * Copyright (C) 2010,2013, NVIDIA Corporation
14 * This software is licensed under the terms of the GNU General Public
15 * License version 2, as published by the Free Software Foundation, and
16 * may be copied, distributed, and modified under those terms.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
26 #include <linux/irq.h>
27 #include <linux/irqdomain.h>
28 #include <linux/of_address.h>
29 #include <linux/slab.h>
30 #include <linux/syscore_ops.h>
32 #include <dt-bindings/interrupt-controller/arm-gic.h>
36 #define ICTLR_CPU_IEP_VFIQ 0x08
37 #define ICTLR_CPU_IEP_FIR 0x14
38 #define ICTLR_CPU_IEP_FIR_SET 0x18
39 #define ICTLR_CPU_IEP_FIR_CLR 0x1c
41 #define ICTLR_CPU_IER 0x20
42 #define ICTLR_CPU_IER_SET 0x24
43 #define ICTLR_CPU_IER_CLR 0x28
44 #define ICTLR_CPU_IEP_CLASS 0x2C
46 #define ICTLR_COP_IER 0x30
47 #define ICTLR_COP_IER_SET 0x34
48 #define ICTLR_COP_IER_CLR 0x38
49 #define ICTLR_COP_IEP_CLASS 0x3c
51 #define TEGRA_MAX_NUM_ICTLRS 6
53 static unsigned int num_ictlrs
;
55 struct tegra_ictlr_soc
{
56 unsigned int num_ictlrs
;
59 static const struct tegra_ictlr_soc tegra20_ictlr_soc
= {
63 static const struct tegra_ictlr_soc tegra30_ictlr_soc
= {
67 static const struct tegra_ictlr_soc tegra210_ictlr_soc
= {
71 static const struct of_device_id ictlr_matches
[] = {
72 { .compatible
= "nvidia,tegra210-ictlr", .data
= &tegra210_ictlr_soc
},
73 { .compatible
= "nvidia,tegra30-ictlr", .data
= &tegra30_ictlr_soc
},
74 { .compatible
= "nvidia,tegra20-ictlr", .data
= &tegra20_ictlr_soc
},
78 struct tegra_ictlr_info
{
79 void __iomem
*base
[TEGRA_MAX_NUM_ICTLRS
];
80 #ifdef CONFIG_PM_SLEEP
81 u32 cop_ier
[TEGRA_MAX_NUM_ICTLRS
];
82 u32 cop_iep
[TEGRA_MAX_NUM_ICTLRS
];
83 u32 cpu_ier
[TEGRA_MAX_NUM_ICTLRS
];
84 u32 cpu_iep
[TEGRA_MAX_NUM_ICTLRS
];
86 u32 ictlr_wake_mask
[TEGRA_MAX_NUM_ICTLRS
];
90 static struct tegra_ictlr_info
*lic
;
92 static inline void tegra_ictlr_write_mask(struct irq_data
*d
, unsigned long reg
)
94 void __iomem
*base
= d
->chip_data
;
97 mask
= BIT(d
->hwirq
% 32);
98 writel_relaxed(mask
, base
+ reg
);
101 static void tegra_mask(struct irq_data
*d
)
103 tegra_ictlr_write_mask(d
, ICTLR_CPU_IER_CLR
);
104 irq_chip_mask_parent(d
);
107 static void tegra_unmask(struct irq_data
*d
)
109 tegra_ictlr_write_mask(d
, ICTLR_CPU_IER_SET
);
110 irq_chip_unmask_parent(d
);
113 static void tegra_eoi(struct irq_data
*d
)
115 tegra_ictlr_write_mask(d
, ICTLR_CPU_IEP_FIR_CLR
);
116 irq_chip_eoi_parent(d
);
119 static int tegra_retrigger(struct irq_data
*d
)
121 tegra_ictlr_write_mask(d
, ICTLR_CPU_IEP_FIR_SET
);
122 return irq_chip_retrigger_hierarchy(d
);
125 #ifdef CONFIG_PM_SLEEP
126 static int tegra_set_wake(struct irq_data
*d
, unsigned int enable
)
132 mask
= BIT(irq
% 32);
134 lic
->ictlr_wake_mask
[index
] |= mask
;
136 lic
->ictlr_wake_mask
[index
] &= ~mask
;
139 * Do *not* call into the parent, as the GIC doesn't have any
140 * wake-up facility...
145 static int tegra_ictlr_suspend(void)
150 local_irq_save(flags
);
151 for (i
= 0; i
< num_ictlrs
; i
++) {
152 void __iomem
*ictlr
= lic
->base
[i
];
154 /* Save interrupt state */
155 lic
->cpu_ier
[i
] = readl_relaxed(ictlr
+ ICTLR_CPU_IER
);
156 lic
->cpu_iep
[i
] = readl_relaxed(ictlr
+ ICTLR_CPU_IEP_CLASS
);
157 lic
->cop_ier
[i
] = readl_relaxed(ictlr
+ ICTLR_COP_IER
);
158 lic
->cop_iep
[i
] = readl_relaxed(ictlr
+ ICTLR_COP_IEP_CLASS
);
160 /* Disable COP interrupts */
161 writel_relaxed(~0ul, ictlr
+ ICTLR_COP_IER_CLR
);
163 /* Disable CPU interrupts */
164 writel_relaxed(~0ul, ictlr
+ ICTLR_CPU_IER_CLR
);
166 /* Enable the wakeup sources of ictlr */
167 writel_relaxed(lic
->ictlr_wake_mask
[i
], ictlr
+ ICTLR_CPU_IER_SET
);
169 local_irq_restore(flags
);
174 static void tegra_ictlr_resume(void)
179 local_irq_save(flags
);
180 for (i
= 0; i
< num_ictlrs
; i
++) {
181 void __iomem
*ictlr
= lic
->base
[i
];
183 writel_relaxed(lic
->cpu_iep
[i
],
184 ictlr
+ ICTLR_CPU_IEP_CLASS
);
185 writel_relaxed(~0ul, ictlr
+ ICTLR_CPU_IER_CLR
);
186 writel_relaxed(lic
->cpu_ier
[i
],
187 ictlr
+ ICTLR_CPU_IER_SET
);
188 writel_relaxed(lic
->cop_iep
[i
],
189 ictlr
+ ICTLR_COP_IEP_CLASS
);
190 writel_relaxed(~0ul, ictlr
+ ICTLR_COP_IER_CLR
);
191 writel_relaxed(lic
->cop_ier
[i
],
192 ictlr
+ ICTLR_COP_IER_SET
);
194 local_irq_restore(flags
);
197 static struct syscore_ops tegra_ictlr_syscore_ops
= {
198 .suspend
= tegra_ictlr_suspend
,
199 .resume
= tegra_ictlr_resume
,
202 static void tegra_ictlr_syscore_init(void)
204 register_syscore_ops(&tegra_ictlr_syscore_ops
);
207 #define tegra_set_wake NULL
208 static inline void tegra_ictlr_syscore_init(void) {}
211 static struct irq_chip tegra_ictlr_chip
= {
213 .irq_eoi
= tegra_eoi
,
214 .irq_mask
= tegra_mask
,
215 .irq_unmask
= tegra_unmask
,
216 .irq_retrigger
= tegra_retrigger
,
217 .irq_set_wake
= tegra_set_wake
,
218 .flags
= IRQCHIP_MASK_ON_SUSPEND
,
220 .irq_set_affinity
= irq_chip_set_affinity_parent
,
224 static int tegra_ictlr_domain_xlate(struct irq_domain
*domain
,
225 struct device_node
*controller
,
227 unsigned int intsize
,
228 unsigned long *out_hwirq
,
229 unsigned int *out_type
)
231 if (domain
->of_node
!= controller
)
232 return -EINVAL
; /* Shouldn't happen, really... */
234 return -EINVAL
; /* Not GIC compliant */
235 if (intspec
[0] != GIC_SPI
)
236 return -EINVAL
; /* No PPI should point to this domain */
238 *out_hwirq
= intspec
[1];
239 *out_type
= intspec
[2];
243 static int tegra_ictlr_domain_alloc(struct irq_domain
*domain
,
245 unsigned int nr_irqs
, void *data
)
247 struct of_phandle_args
*args
= data
;
248 struct of_phandle_args parent_args
;
249 struct tegra_ictlr_info
*info
= domain
->host_data
;
250 irq_hw_number_t hwirq
;
253 if (args
->args_count
!= 3)
254 return -EINVAL
; /* Not GIC compliant */
255 if (args
->args
[0] != GIC_SPI
)
256 return -EINVAL
; /* No PPI should point to this domain */
258 hwirq
= args
->args
[1];
259 if (hwirq
>= (num_ictlrs
* 32))
262 for (i
= 0; i
< nr_irqs
; i
++) {
263 int ictlr
= (hwirq
+ i
) / 32;
265 irq_domain_set_hwirq_and_chip(domain
, virq
+ i
, hwirq
+ i
,
271 parent_args
.np
= domain
->parent
->of_node
;
272 return irq_domain_alloc_irqs_parent(domain
, virq
, nr_irqs
, &parent_args
);
275 static void tegra_ictlr_domain_free(struct irq_domain
*domain
,
277 unsigned int nr_irqs
)
281 for (i
= 0; i
< nr_irqs
; i
++) {
282 struct irq_data
*d
= irq_domain_get_irq_data(domain
, virq
+ i
);
283 irq_domain_reset_irq_data(d
);
287 static const struct irq_domain_ops tegra_ictlr_domain_ops
= {
288 .xlate
= tegra_ictlr_domain_xlate
,
289 .alloc
= tegra_ictlr_domain_alloc
,
290 .free
= tegra_ictlr_domain_free
,
293 static int __init
tegra_ictlr_init(struct device_node
*node
,
294 struct device_node
*parent
)
296 struct irq_domain
*parent_domain
, *domain
;
297 const struct of_device_id
*match
;
298 const struct tegra_ictlr_soc
*soc
;
303 pr_err("%s: no parent, giving up\n", node
->full_name
);
307 parent_domain
= irq_find_host(parent
);
308 if (!parent_domain
) {
309 pr_err("%s: unable to obtain parent domain\n", node
->full_name
);
313 match
= of_match_node(ictlr_matches
, node
);
314 if (!match
) /* Should never happen... */
319 lic
= kzalloc(sizeof(*lic
), GFP_KERNEL
);
323 for (i
= 0; i
< TEGRA_MAX_NUM_ICTLRS
; i
++) {
326 base
= of_iomap(node
, i
);
332 /* Disable all interrupts */
333 writel_relaxed(~0UL, base
+ ICTLR_CPU_IER_CLR
);
334 /* All interrupts target IRQ */
335 writel_relaxed(0, base
+ ICTLR_CPU_IEP_CLASS
);
341 pr_err("%s: no valid regions, giving up\n", node
->full_name
);
346 WARN(num_ictlrs
!= soc
->num_ictlrs
,
347 "%s: Found %u interrupt controllers in DT; expected %u.\n",
348 node
->full_name
, num_ictlrs
, soc
->num_ictlrs
);
351 domain
= irq_domain_add_hierarchy(parent_domain
, 0, num_ictlrs
* 32,
352 node
, &tegra_ictlr_domain_ops
,
355 pr_err("%s: failed to allocated domain\n", node
->full_name
);
360 tegra_ictlr_syscore_init();
362 pr_info("%s: %d interrupts forwarded to %s\n",
363 node
->full_name
, num_ictlrs
* 32, parent
->full_name
);
368 for (i
= 0; i
< num_ictlrs
; i
++)
369 iounmap(lic
->base
[i
]);
375 IRQCHIP_DECLARE(tegra20_ictlr
, "nvidia,tegra20-ictlr", tegra_ictlr_init
);
376 IRQCHIP_DECLARE(tegra30_ictlr
, "nvidia,tegra30-ictlr", tegra_ictlr_init
);
377 IRQCHIP_DECLARE(tegra210_ictlr
, "nvidia,tegra210-ictlr", tegra_ictlr_init
);