Linux Audio

Check our new training course

Loading...
v4.17
 
  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__ */
v6.13.7
  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__ */