Loading...
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Copyright (C) 2017 Imagination Technologies
4 * Author: Paul Burton <paul.burton@mips.com>
5 */
6
7#ifndef __MIPS_ASM_MIPS_CPS_H__
8# error Please include asm/mips-cps.h rather than asm/mips-gic.h
9#endif
10
11#ifndef __MIPS_ASM_MIPS_GIC_H__
12#define __MIPS_ASM_MIPS_GIC_H__
13
14#include <linux/bitops.h>
15
16/* The base address of the GIC registers */
17extern void __iomem *mips_gic_base;
18
19/* Offsets from the GIC base address to various control blocks */
20#define MIPS_GIC_SHARED_OFS 0x00000
21#define MIPS_GIC_SHARED_SZ 0x08000
22#define MIPS_GIC_LOCAL_OFS 0x08000
23#define MIPS_GIC_LOCAL_SZ 0x04000
24#define MIPS_GIC_REDIR_OFS 0x0c000
25#define MIPS_GIC_REDIR_SZ 0x04000
26#define MIPS_GIC_USER_OFS 0x10000
27#define MIPS_GIC_USER_SZ 0x10000
28
29/* For read-only shared registers */
30#define GIC_ACCESSOR_RO(sz, off, name) \
31 CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_SHARED_OFS + off, name)
32
33/* For read-write shared registers */
34#define GIC_ACCESSOR_RW(sz, off, name) \
35 CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_SHARED_OFS + off, name)
36
37/* For read-only local registers */
38#define GIC_VX_ACCESSOR_RO(sz, off, name) \
39 CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_##name) \
40 CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_##name)
41
42/* For read-write local registers */
43#define GIC_VX_ACCESSOR_RW(sz, off, name) \
44 CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_##name) \
45 CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_##name)
46
47/* For read-only shared per-interrupt registers */
48#define GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
49static inline void __iomem *addr_gic_##name(unsigned int intr) \
50{ \
51 return mips_gic_base + (off) + (intr * (stride)); \
52} \
53 \
54static inline unsigned int read_gic_##name(unsigned int intr) \
55{ \
56 BUILD_BUG_ON(sz != 32); \
57 return __raw_readl(addr_gic_##name(intr)); \
58}
59
60/* For read-write shared per-interrupt registers */
61#define GIC_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \
62 GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
63 \
64static inline void write_gic_##name(unsigned int intr, \
65 unsigned int val) \
66{ \
67 BUILD_BUG_ON(sz != 32); \
68 __raw_writel(val, addr_gic_##name(intr)); \
69}
70
71/* For read-only local per-interrupt registers */
72#define GIC_VX_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
73 GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off, \
74 stride, vl_##name) \
75 GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, \
76 stride, vo_##name)
77
78/* For read-write local per-interrupt registers */
79#define GIC_VX_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \
80 GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off, \
81 stride, vl_##name) \
82 GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, \
83 stride, vo_##name)
84
85/* For read-only shared bit-per-interrupt registers */
86#define GIC_ACCESSOR_RO_INTR_BIT(off, name) \
87static inline void __iomem *addr_gic_##name(void) \
88{ \
89 return mips_gic_base + (off); \
90} \
91 \
92static inline unsigned int read_gic_##name(unsigned int intr) \
93{ \
94 void __iomem *addr = addr_gic_##name(); \
95 unsigned int val; \
96 \
97 if (mips_cm_is64) { \
98 addr += (intr / 64) * sizeof(uint64_t); \
99 val = __raw_readq(addr) >> intr % 64; \
100 } else { \
101 addr += (intr / 32) * sizeof(uint32_t); \
102 val = __raw_readl(addr) >> intr % 32; \
103 } \
104 \
105 return val & 0x1; \
106}
107
108/* For read-write shared bit-per-interrupt registers */
109#define GIC_ACCESSOR_RW_INTR_BIT(off, name) \
110 GIC_ACCESSOR_RO_INTR_BIT(off, name) \
111 \
112static inline void write_gic_##name(unsigned int intr) \
113{ \
114 void __iomem *addr = addr_gic_##name(); \
115 \
116 if (mips_cm_is64) { \
117 addr += (intr / 64) * sizeof(uint64_t); \
118 __raw_writeq(BIT(intr % 64), addr); \
119 } else { \
120 addr += (intr / 32) * sizeof(uint32_t); \
121 __raw_writel(BIT(intr % 32), addr); \
122 } \
123} \
124 \
125static inline void change_gic_##name(unsigned int intr, \
126 unsigned int val) \
127{ \
128 void __iomem *addr = addr_gic_##name(); \
129 \
130 if (mips_cm_is64) { \
131 uint64_t _val; \
132 \
133 addr += (intr / 64) * sizeof(uint64_t); \
134 _val = __raw_readq(addr); \
135 _val &= ~BIT_ULL(intr % 64); \
136 _val |= (uint64_t)val << (intr % 64); \
137 __raw_writeq(_val, addr); \
138 } else { \
139 uint32_t _val; \
140 \
141 addr += (intr / 32) * sizeof(uint32_t); \
142 _val = __raw_readl(addr); \
143 _val &= ~BIT(intr % 32); \
144 _val |= val << (intr % 32); \
145 __raw_writel(_val, addr); \
146 } \
147}
148
149/* For read-only local bit-per-interrupt registers */
150#define GIC_VX_ACCESSOR_RO_INTR_BIT(sz, off, name) \
151 GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off, \
152 vl_##name) \
153 GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off, \
154 vo_##name)
155
156/* For read-write local bit-per-interrupt registers */
157#define GIC_VX_ACCESSOR_RW_INTR_BIT(sz, off, name) \
158 GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off, \
159 vl_##name) \
160 GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off, \
161 vo_##name)
162
163/* GIC_SH_CONFIG - Information about the GIC configuration */
164GIC_ACCESSOR_RW(32, 0x000, config)
165#define GIC_CONFIG_COUNTSTOP BIT(28)
166#define GIC_CONFIG_COUNTBITS GENMASK(27, 24)
167#define GIC_CONFIG_NUMINTERRUPTS GENMASK(23, 16)
168#define GIC_CONFIG_PVPS GENMASK(6, 0)
169
170/* GIC_SH_COUNTER - Shared global counter value */
171GIC_ACCESSOR_RW(64, 0x010, counter)
172GIC_ACCESSOR_RW(32, 0x010, counter_32l)
173GIC_ACCESSOR_RW(32, 0x014, counter_32h)
174
175/* GIC_SH_POL_* - Configures interrupt polarity */
176GIC_ACCESSOR_RW_INTR_BIT(0x100, pol)
177#define GIC_POL_ACTIVE_LOW 0 /* when level triggered */
178#define GIC_POL_ACTIVE_HIGH 1 /* when level triggered */
179#define GIC_POL_FALLING_EDGE 0 /* when single-edge triggered */
180#define GIC_POL_RISING_EDGE 1 /* when single-edge triggered */
181
182/* GIC_SH_TRIG_* - Configures interrupts to be edge or level triggered */
183GIC_ACCESSOR_RW_INTR_BIT(0x180, trig)
184#define GIC_TRIG_LEVEL 0
185#define GIC_TRIG_EDGE 1
186
187/* GIC_SH_DUAL_* - Configures whether interrupts trigger on both edges */
188GIC_ACCESSOR_RW_INTR_BIT(0x200, dual)
189#define GIC_DUAL_SINGLE 0 /* when edge-triggered */
190#define GIC_DUAL_DUAL 1 /* when edge-triggered */
191
192/* GIC_SH_WEDGE - Write an 'edge', ie. trigger an interrupt */
193GIC_ACCESSOR_RW(32, 0x280, wedge)
194#define GIC_WEDGE_RW BIT(31)
195#define GIC_WEDGE_INTR GENMASK(7, 0)
196
197/* GIC_SH_RMASK_* - Reset/clear shared interrupt mask bits */
198GIC_ACCESSOR_RW_INTR_BIT(0x300, rmask)
199
200/* GIC_SH_SMASK_* - Set shared interrupt mask bits */
201GIC_ACCESSOR_RW_INTR_BIT(0x380, smask)
202
203/* GIC_SH_MASK_* - Read the current shared interrupt mask */
204GIC_ACCESSOR_RO_INTR_BIT(0x400, mask)
205
206/* GIC_SH_PEND_* - Read currently pending shared interrupts */
207GIC_ACCESSOR_RO_INTR_BIT(0x480, pend)
208
209/* GIC_SH_MAPx_PIN - Map shared interrupts to a particular CPU pin */
210GIC_ACCESSOR_RW_INTR_REG(32, 0x500, 0x4, map_pin)
211#define GIC_MAP_PIN_MAP_TO_PIN BIT(31)
212#define GIC_MAP_PIN_MAP_TO_NMI BIT(30)
213#define GIC_MAP_PIN_MAP GENMASK(5, 0)
214
215/* GIC_SH_MAPx_VP - Map shared interrupts to a particular Virtual Processor */
216GIC_ACCESSOR_RW_INTR_REG(32, 0x2000, 0x20, map_vp)
217
218/* GIC_Vx_CTL - VP-level interrupt control */
219GIC_VX_ACCESSOR_RW(32, 0x000, ctl)
220#define GIC_VX_CTL_FDC_ROUTABLE BIT(4)
221#define GIC_VX_CTL_SWINT_ROUTABLE BIT(3)
222#define GIC_VX_CTL_PERFCNT_ROUTABLE BIT(2)
223#define GIC_VX_CTL_TIMER_ROUTABLE BIT(1)
224#define GIC_VX_CTL_EIC BIT(0)
225
226/* GIC_Vx_PEND - Read currently pending local interrupts */
227GIC_VX_ACCESSOR_RO(32, 0x004, pend)
228
229/* GIC_Vx_MASK - Read the current local interrupt mask */
230GIC_VX_ACCESSOR_RO(32, 0x008, mask)
231
232/* GIC_Vx_RMASK - Reset/clear local interrupt mask bits */
233GIC_VX_ACCESSOR_RW(32, 0x00c, rmask)
234
235/* GIC_Vx_SMASK - Set local interrupt mask bits */
236GIC_VX_ACCESSOR_RW(32, 0x010, smask)
237
238/* GIC_Vx_*_MAP - Route local interrupts to the desired pins */
239GIC_VX_ACCESSOR_RW_INTR_REG(32, 0x040, 0x4, map)
240
241/* GIC_Vx_WD_MAP - Route the local watchdog timer interrupt */
242GIC_VX_ACCESSOR_RW(32, 0x040, wd_map)
243
244/* GIC_Vx_COMPARE_MAP - Route the local count/compare interrupt */
245GIC_VX_ACCESSOR_RW(32, 0x044, compare_map)
246
247/* GIC_Vx_TIMER_MAP - Route the local CPU timer (cp0 count/compare) interrupt */
248GIC_VX_ACCESSOR_RW(32, 0x048, timer_map)
249
250/* GIC_Vx_FDC_MAP - Route the local fast debug channel interrupt */
251GIC_VX_ACCESSOR_RW(32, 0x04c, fdc_map)
252
253/* GIC_Vx_PERFCTR_MAP - Route the local performance counter interrupt */
254GIC_VX_ACCESSOR_RW(32, 0x050, perfctr_map)
255
256/* GIC_Vx_SWINT0_MAP - Route the local software interrupt 0 */
257GIC_VX_ACCESSOR_RW(32, 0x054, swint0_map)
258
259/* GIC_Vx_SWINT1_MAP - Route the local software interrupt 1 */
260GIC_VX_ACCESSOR_RW(32, 0x058, swint1_map)
261
262/* GIC_Vx_OTHER - Configure access to other Virtual Processor registers */
263GIC_VX_ACCESSOR_RW(32, 0x080, other)
264#define GIC_VX_OTHER_VPNUM GENMASK(5, 0)
265
266/* GIC_Vx_IDENT - Retrieve the local Virtual Processor's ID */
267GIC_VX_ACCESSOR_RO(32, 0x088, ident)
268#define GIC_VX_IDENT_VPNUM GENMASK(5, 0)
269
270/* GIC_Vx_COMPARE - Value to compare with GIC_SH_COUNTER */
271GIC_VX_ACCESSOR_RW(64, 0x0a0, compare)
272
273/* GIC_Vx_EIC_SHADOW_SET_BASE - Set shadow register set for each interrupt */
274GIC_VX_ACCESSOR_RW_INTR_REG(32, 0x100, 0x4, eic_shadow_set)
275
276/**
277 * enum mips_gic_local_interrupt - GIC local interrupts
278 * @GIC_LOCAL_INT_WD: GIC watchdog timer interrupt
279 * @GIC_LOCAL_INT_COMPARE: GIC count/compare interrupt
280 * @GIC_LOCAL_INT_TIMER: CP0 count/compare interrupt
281 * @GIC_LOCAL_INT_PERFCTR: Performance counter interrupt
282 * @GIC_LOCAL_INT_SWINT0: Software interrupt 0
283 * @GIC_LOCAL_INT_SWINT1: Software interrupt 1
284 * @GIC_LOCAL_INT_FDC: Fast debug channel interrupt
285 * @GIC_NUM_LOCAL_INTRS: The number of local interrupts
286 *
287 * Enumerates interrupts provided by the GIC that are local to a VP.
288 */
289enum mips_gic_local_interrupt {
290 GIC_LOCAL_INT_WD,
291 GIC_LOCAL_INT_COMPARE,
292 GIC_LOCAL_INT_TIMER,
293 GIC_LOCAL_INT_PERFCTR,
294 GIC_LOCAL_INT_SWINT0,
295 GIC_LOCAL_INT_SWINT1,
296 GIC_LOCAL_INT_FDC,
297 GIC_NUM_LOCAL_INTRS
298};
299
300/**
301 * mips_gic_present() - Determine whether a GIC is present
302 *
303 * Determines whether a MIPS Global Interrupt Controller (GIC) is present in
304 * the system that the kernel is running on.
305 *
306 * Return true if a GIC is present, else false.
307 */
308static inline bool mips_gic_present(void)
309{
310 return IS_ENABLED(CONFIG_MIPS_GIC) && mips_gic_base;
311}
312
313/**
314 * mips_gic_vx_map_reg() - Return GIC_Vx_<intr>_MAP register offset
315 * @intr: A GIC local interrupt
316 *
317 * Determine the index of the GIC_VL_<intr>_MAP or GIC_VO_<intr>_MAP register
318 * within the block of GIC map registers. This is almost the same as the order
319 * of interrupts in the pending & mask registers, as used by enum
320 * mips_gic_local_interrupt, but moves the FDC interrupt & thus offsets the
321 * interrupts after it...
322 *
323 * Return: The map register index corresponding to @intr.
324 *
325 * The return value is suitable for use with the (read|write)_gic_v[lo]_map
326 * accessor functions.
327 */
328static inline unsigned int
329mips_gic_vx_map_reg(enum mips_gic_local_interrupt intr)
330{
331 /* WD, Compare & Timer are 1:1 */
332 if (intr <= GIC_LOCAL_INT_TIMER)
333 return intr;
334
335 /* FDC moves to after Timer... */
336 if (intr == GIC_LOCAL_INT_FDC)
337 return GIC_LOCAL_INT_TIMER + 1;
338
339 /* As a result everything else is offset by 1 */
340 return intr + 1;
341}
342
343/**
344 * gic_get_c0_compare_int() - Return cp0 count/compare interrupt virq
345 *
346 * Determine the virq number to use for the coprocessor 0 count/compare
347 * interrupt, which may be routed via the GIC.
348 *
349 * Returns the virq number or a negative error number.
350 */
351extern int gic_get_c0_compare_int(void);
352
353/**
354 * gic_get_c0_perfcount_int() - Return performance counter interrupt virq
355 *
356 * Determine the virq number to use for CPU performance counter interrupts,
357 * which may be routed via the GIC.
358 *
359 * Returns the virq number or a negative error number.
360 */
361extern int gic_get_c0_perfcount_int(void);
362
363/**
364 * gic_get_c0_fdc_int() - Return fast debug channel interrupt virq
365 *
366 * Determine the virq number to use for fast debug channel (FDC) interrupts,
367 * which may be routed via the GIC.
368 *
369 * Returns the virq number or a negative error number.
370 */
371extern int gic_get_c0_fdc_int(void);
372
373#endif /* __MIPS_ASM_MIPS_CPS_H__ */
1/*
2 * Copyright (C) 2017 Imagination Technologies
3 * Author: Paul Burton <paul.burton@mips.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 */
10
11#ifndef __MIPS_ASM_MIPS_CPS_H__
12# error Please include asm/mips-cps.h rather than asm/mips-gic.h
13#endif
14
15#ifndef __MIPS_ASM_MIPS_GIC_H__
16#define __MIPS_ASM_MIPS_GIC_H__
17
18#include <linux/bitops.h>
19
20/* The base address of the GIC registers */
21extern void __iomem *mips_gic_base;
22
23/* Offsets from the GIC base address to various control blocks */
24#define MIPS_GIC_SHARED_OFS 0x00000
25#define MIPS_GIC_SHARED_SZ 0x08000
26#define MIPS_GIC_LOCAL_OFS 0x08000
27#define MIPS_GIC_LOCAL_SZ 0x04000
28#define MIPS_GIC_REDIR_OFS 0x0c000
29#define MIPS_GIC_REDIR_SZ 0x04000
30#define MIPS_GIC_USER_OFS 0x10000
31#define MIPS_GIC_USER_SZ 0x10000
32
33/* For read-only shared registers */
34#define GIC_ACCESSOR_RO(sz, off, name) \
35 CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_SHARED_OFS + off, name)
36
37/* For read-write shared registers */
38#define GIC_ACCESSOR_RW(sz, off, name) \
39 CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_SHARED_OFS + off, name)
40
41/* For read-only local registers */
42#define GIC_VX_ACCESSOR_RO(sz, off, name) \
43 CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_##name) \
44 CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_##name)
45
46/* For read-write local registers */
47#define GIC_VX_ACCESSOR_RW(sz, off, name) \
48 CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_##name) \
49 CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_##name)
50
51/* For read-only shared per-interrupt registers */
52#define GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
53static inline void __iomem *addr_gic_##name(unsigned int intr) \
54{ \
55 return mips_gic_base + (off) + (intr * (stride)); \
56} \
57 \
58static inline unsigned int read_gic_##name(unsigned int intr) \
59{ \
60 BUILD_BUG_ON(sz != 32); \
61 return __raw_readl(addr_gic_##name(intr)); \
62}
63
64/* For read-write shared per-interrupt registers */
65#define GIC_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \
66 GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
67 \
68static inline void write_gic_##name(unsigned int intr, \
69 unsigned int val) \
70{ \
71 BUILD_BUG_ON(sz != 32); \
72 __raw_writel(val, addr_gic_##name(intr)); \
73}
74
75/* For read-only local per-interrupt registers */
76#define GIC_VX_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
77 GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off, \
78 stride, vl_##name) \
79 GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, \
80 stride, vo_##name)
81
82/* For read-write local per-interrupt registers */
83#define GIC_VX_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \
84 GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off, \
85 stride, vl_##name) \
86 GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, \
87 stride, vo_##name)
88
89/* For read-only shared bit-per-interrupt registers */
90#define GIC_ACCESSOR_RO_INTR_BIT(off, name) \
91static inline void __iomem *addr_gic_##name(void) \
92{ \
93 return mips_gic_base + (off); \
94} \
95 \
96static inline unsigned int read_gic_##name(unsigned int intr) \
97{ \
98 void __iomem *addr = addr_gic_##name(); \
99 unsigned int val; \
100 \
101 if (mips_cm_is64) { \
102 addr += (intr / 64) * sizeof(uint64_t); \
103 val = __raw_readq(addr) >> intr % 64; \
104 } else { \
105 addr += (intr / 32) * sizeof(uint32_t); \
106 val = __raw_readl(addr) >> intr % 32; \
107 } \
108 \
109 return val & 0x1; \
110}
111
112/* For read-write shared bit-per-interrupt registers */
113#define GIC_ACCESSOR_RW_INTR_BIT(off, name) \
114 GIC_ACCESSOR_RO_INTR_BIT(off, name) \
115 \
116static inline void write_gic_##name(unsigned int intr) \
117{ \
118 void __iomem *addr = addr_gic_##name(); \
119 \
120 if (mips_cm_is64) { \
121 addr += (intr / 64) * sizeof(uint64_t); \
122 __raw_writeq(BIT(intr % 64), addr); \
123 } else { \
124 addr += (intr / 32) * sizeof(uint32_t); \
125 __raw_writel(BIT(intr % 32), addr); \
126 } \
127} \
128 \
129static inline void change_gic_##name(unsigned int intr, \
130 unsigned int val) \
131{ \
132 void __iomem *addr = addr_gic_##name(); \
133 \
134 if (mips_cm_is64) { \
135 uint64_t _val; \
136 \
137 addr += (intr / 64) * sizeof(uint64_t); \
138 _val = __raw_readq(addr); \
139 _val &= ~BIT_ULL(intr % 64); \
140 _val |= (uint64_t)val << (intr % 64); \
141 __raw_writeq(_val, addr); \
142 } else { \
143 uint32_t _val; \
144 \
145 addr += (intr / 32) * sizeof(uint32_t); \
146 _val = __raw_readl(addr); \
147 _val &= ~BIT(intr % 32); \
148 _val |= val << (intr % 32); \
149 __raw_writel(_val, addr); \
150 } \
151}
152
153/* For read-only local bit-per-interrupt registers */
154#define GIC_VX_ACCESSOR_RO_INTR_BIT(sz, off, name) \
155 GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off, \
156 vl_##name) \
157 GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off, \
158 vo_##name)
159
160/* For read-write local bit-per-interrupt registers */
161#define GIC_VX_ACCESSOR_RW_INTR_BIT(sz, off, name) \
162 GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off, \
163 vl_##name) \
164 GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off, \
165 vo_##name)
166
167/* GIC_SH_CONFIG - Information about the GIC configuration */
168GIC_ACCESSOR_RW(32, 0x000, config)
169#define GIC_CONFIG_COUNTSTOP BIT(28)
170#define GIC_CONFIG_COUNTBITS GENMASK(27, 24)
171#define GIC_CONFIG_NUMINTERRUPTS GENMASK(23, 16)
172#define GIC_CONFIG_PVPS GENMASK(6, 0)
173
174/* GIC_SH_COUNTER - Shared global counter value */
175GIC_ACCESSOR_RW(64, 0x010, counter)
176GIC_ACCESSOR_RW(32, 0x010, counter_32l)
177GIC_ACCESSOR_RW(32, 0x014, counter_32h)
178
179/* GIC_SH_POL_* - Configures interrupt polarity */
180GIC_ACCESSOR_RW_INTR_BIT(0x100, pol)
181#define GIC_POL_ACTIVE_LOW 0 /* when level triggered */
182#define GIC_POL_ACTIVE_HIGH 1 /* when level triggered */
183#define GIC_POL_FALLING_EDGE 0 /* when single-edge triggered */
184#define GIC_POL_RISING_EDGE 1 /* when single-edge triggered */
185
186/* GIC_SH_TRIG_* - Configures interrupts to be edge or level triggered */
187GIC_ACCESSOR_RW_INTR_BIT(0x180, trig)
188#define GIC_TRIG_LEVEL 0
189#define GIC_TRIG_EDGE 1
190
191/* GIC_SH_DUAL_* - Configures whether interrupts trigger on both edges */
192GIC_ACCESSOR_RW_INTR_BIT(0x200, dual)
193#define GIC_DUAL_SINGLE 0 /* when edge-triggered */
194#define GIC_DUAL_DUAL 1 /* when edge-triggered */
195
196/* GIC_SH_WEDGE - Write an 'edge', ie. trigger an interrupt */
197GIC_ACCESSOR_RW(32, 0x280, wedge)
198#define GIC_WEDGE_RW BIT(31)
199#define GIC_WEDGE_INTR GENMASK(7, 0)
200
201/* GIC_SH_RMASK_* - Reset/clear shared interrupt mask bits */
202GIC_ACCESSOR_RW_INTR_BIT(0x300, rmask)
203
204/* GIC_SH_SMASK_* - Set shared interrupt mask bits */
205GIC_ACCESSOR_RW_INTR_BIT(0x380, smask)
206
207/* GIC_SH_MASK_* - Read the current shared interrupt mask */
208GIC_ACCESSOR_RO_INTR_BIT(0x400, mask)
209
210/* GIC_SH_PEND_* - Read currently pending shared interrupts */
211GIC_ACCESSOR_RO_INTR_BIT(0x480, pend)
212
213/* GIC_SH_MAPx_PIN - Map shared interrupts to a particular CPU pin */
214GIC_ACCESSOR_RW_INTR_REG(32, 0x500, 0x4, map_pin)
215#define GIC_MAP_PIN_MAP_TO_PIN BIT(31)
216#define GIC_MAP_PIN_MAP_TO_NMI BIT(30)
217#define GIC_MAP_PIN_MAP GENMASK(5, 0)
218
219/* GIC_SH_MAPx_VP - Map shared interrupts to a particular Virtual Processor */
220GIC_ACCESSOR_RW_INTR_REG(32, 0x2000, 0x20, map_vp)
221
222/* GIC_Vx_CTL - VP-level interrupt control */
223GIC_VX_ACCESSOR_RW(32, 0x000, ctl)
224#define GIC_VX_CTL_FDC_ROUTABLE BIT(4)
225#define GIC_VX_CTL_SWINT_ROUTABLE BIT(3)
226#define GIC_VX_CTL_PERFCNT_ROUTABLE BIT(2)
227#define GIC_VX_CTL_TIMER_ROUTABLE BIT(1)
228#define GIC_VX_CTL_EIC BIT(0)
229
230/* GIC_Vx_PEND - Read currently pending local interrupts */
231GIC_VX_ACCESSOR_RO(32, 0x004, pend)
232
233/* GIC_Vx_MASK - Read the current local interrupt mask */
234GIC_VX_ACCESSOR_RO(32, 0x008, mask)
235
236/* GIC_Vx_RMASK - Reset/clear local interrupt mask bits */
237GIC_VX_ACCESSOR_RW(32, 0x00c, rmask)
238
239/* GIC_Vx_SMASK - Set local interrupt mask bits */
240GIC_VX_ACCESSOR_RW(32, 0x010, smask)
241
242/* GIC_Vx_*_MAP - Route local interrupts to the desired pins */
243GIC_VX_ACCESSOR_RW_INTR_REG(32, 0x040, 0x4, map)
244
245/* GIC_Vx_WD_MAP - Route the local watchdog timer interrupt */
246GIC_VX_ACCESSOR_RW(32, 0x040, wd_map)
247
248/* GIC_Vx_COMPARE_MAP - Route the local count/compare interrupt */
249GIC_VX_ACCESSOR_RW(32, 0x044, compare_map)
250
251/* GIC_Vx_TIMER_MAP - Route the local CPU timer (cp0 count/compare) interrupt */
252GIC_VX_ACCESSOR_RW(32, 0x048, timer_map)
253
254/* GIC_Vx_FDC_MAP - Route the local fast debug channel interrupt */
255GIC_VX_ACCESSOR_RW(32, 0x04c, fdc_map)
256
257/* GIC_Vx_PERFCTR_MAP - Route the local performance counter interrupt */
258GIC_VX_ACCESSOR_RW(32, 0x050, perfctr_map)
259
260/* GIC_Vx_SWINT0_MAP - Route the local software interrupt 0 */
261GIC_VX_ACCESSOR_RW(32, 0x054, swint0_map)
262
263/* GIC_Vx_SWINT1_MAP - Route the local software interrupt 1 */
264GIC_VX_ACCESSOR_RW(32, 0x058, swint1_map)
265
266/* GIC_Vx_OTHER - Configure access to other Virtual Processor registers */
267GIC_VX_ACCESSOR_RW(32, 0x080, other)
268#define GIC_VX_OTHER_VPNUM GENMASK(5, 0)
269
270/* GIC_Vx_IDENT - Retrieve the local Virtual Processor's ID */
271GIC_VX_ACCESSOR_RO(32, 0x088, ident)
272#define GIC_VX_IDENT_VPNUM GENMASK(5, 0)
273
274/* GIC_Vx_COMPARE - Value to compare with GIC_SH_COUNTER */
275GIC_VX_ACCESSOR_RW(64, 0x0a0, compare)
276
277/* GIC_Vx_EIC_SHADOW_SET_BASE - Set shadow register set for each interrupt */
278GIC_VX_ACCESSOR_RW_INTR_REG(32, 0x100, 0x4, eic_shadow_set)
279
280/**
281 * enum mips_gic_local_interrupt - GIC local interrupts
282 * @GIC_LOCAL_INT_WD: GIC watchdog timer interrupt
283 * @GIC_LOCAL_INT_COMPARE: GIC count/compare interrupt
284 * @GIC_LOCAL_INT_TIMER: CP0 count/compare interrupt
285 * @GIC_LOCAL_INT_PERFCTR: Performance counter interrupt
286 * @GIC_LOCAL_INT_SWINT0: Software interrupt 0
287 * @GIC_LOCAL_INT_SWINT1: Software interrupt 1
288 * @GIC_LOCAL_INT_FDC: Fast debug channel interrupt
289 * @GIC_NUM_LOCAL_INTRS: The number of local interrupts
290 *
291 * Enumerates interrupts provided by the GIC that are local to a VP.
292 */
293enum mips_gic_local_interrupt {
294 GIC_LOCAL_INT_WD,
295 GIC_LOCAL_INT_COMPARE,
296 GIC_LOCAL_INT_TIMER,
297 GIC_LOCAL_INT_PERFCTR,
298 GIC_LOCAL_INT_SWINT0,
299 GIC_LOCAL_INT_SWINT1,
300 GIC_LOCAL_INT_FDC,
301 GIC_NUM_LOCAL_INTRS
302};
303
304/**
305 * mips_gic_present() - Determine whether a GIC is present
306 *
307 * Determines whether a MIPS Global Interrupt Controller (GIC) is present in
308 * the system that the kernel is running on.
309 *
310 * Return true if a GIC is present, else false.
311 */
312static inline bool mips_gic_present(void)
313{
314 return IS_ENABLED(CONFIG_MIPS_GIC) && mips_gic_base;
315}
316
317/**
318 * gic_get_c0_compare_int() - Return cp0 count/compare interrupt virq
319 *
320 * Determine the virq number to use for the coprocessor 0 count/compare
321 * interrupt, which may be routed via the GIC.
322 *
323 * Returns the virq number or a negative error number.
324 */
325extern int gic_get_c0_compare_int(void);
326
327/**
328 * gic_get_c0_perfcount_int() - Return performance counter interrupt virq
329 *
330 * Determine the virq number to use for CPU performance counter interrupts,
331 * which may be routed via the GIC.
332 *
333 * Returns the virq number or a negative error number.
334 */
335extern int gic_get_c0_perfcount_int(void);
336
337/**
338 * gic_get_c0_fdc_int() - Return fast debug channel interrupt virq
339 *
340 * Determine the virq number to use for fast debug channel (FDC) interrupts,
341 * which may be routed via the GIC.
342 *
343 * Returns the virq number or a negative error number.
344 */
345extern int gic_get_c0_fdc_int(void);
346
347#endif /* __MIPS_ASM_MIPS_CPS_H__ */