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