/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright ( C ) 2017 Imagination Technologies
* Author : Paul Burton < paul . burton @ mips . com >
*/
#ifndef __MIPS_ASM_MIPS_CPS_H__
# error Please include asm /mips-cps.h rather than asm /mips-gic.h
#endif
#ifndef __MIPS_ASM_MIPS_GIC_H__
#define __MIPS_ASM_MIPS_GIC_H__
#include <linux/bitops.h>
/* The base address of the GIC registers */
extern void __iomem *mips_gic_base;
/* Offsets from the GIC base address to various control blocks */
#define MIPS_GIC_SHARED_OFS 0 x00000
#define MIPS_GIC_SHARED_SZ 0 x08000
#define MIPS_GIC_LOCAL_OFS 0 x08000
#define MIPS_GIC_LOCAL_SZ 0 x04000
#define MIPS_GIC_REDIR_OFS 0 x0c000
#define MIPS_GIC_REDIR_SZ 0 x04000
#define MIPS_GIC_USER_OFS 0 x10000
#define MIPS_GIC_USER_SZ 0 x10000
/* For read-only shared registers */
#define GIC_ACCESSOR_RO(sz, off, name) \
CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_SHARED_OFS + off, name) \
CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_REDIR_OFS + off, redir_## name)
/* For read-write shared registers */
#define GIC_ACCESSOR_RW(sz, off, name) \
CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_SHARED_OFS + off, name) \
CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_REDIR_OFS + off, redir_## name)
/* For read-only local registers */
#define GIC_VX_ACCESSOR_RO(sz, off, name) \
CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_## name) \
CPS_ACCESSOR_RO(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_## name)
/* For read-write local registers */
#define GIC_VX_ACCESSOR_RW(sz, off, name) \
CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_LOCAL_OFS + off, vl_## name) \
CPS_ACCESSOR_RW(gic, sz, MIPS_GIC_REDIR_OFS + off, vo_## name)
/* For read-only shared per-interrupt registers */
#define _GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
static inline void __iomem *addr_gic_## name(unsigned int intr) \
{ \
return mips_gic_base + (off) + (intr * (stride)); \
} \
\
static inline unsigned int read_gic_## name(unsigned int intr) \
{ \
BUILD_BUG_ON(sz != 32 ); \
return __raw_readl(addr_gic_## name(intr)); \
}
/* For read-write shared per-interrupt registers */
#define _GIC_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \
_GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
\
static inline void write_gic_## name(unsigned int intr, \
unsigned int val) \
{ \
BUILD_BUG_ON(sz != 32 ); \
__raw_writel(val, addr_gic_## name(intr)); \
}
#define GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
_GIC_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
_GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, stride, redir_## name)
#define GIC_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \
_GIC_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \
_GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, stride, redir_## name)
/* For read-only local per-interrupt registers */
#define GIC_VX_ACCESSOR_RO_INTR_REG(sz, off, stride, name) \
_GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off, \
stride, vl_## name) \
_GIC_ACCESSOR_RO_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, \
stride, vo_## name)
/* For read-write local per-interrupt registers */
#define GIC_VX_ACCESSOR_RW_INTR_REG(sz, off, stride, name) \
_GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_LOCAL_OFS + off, \
stride, vl_## name) \
_GIC_ACCESSOR_RW_INTR_REG(sz, MIPS_GIC_REDIR_OFS + off, \
stride, vo_## name)
/* For read-only shared bit-per-interrupt registers */
#define _GIC_ACCESSOR_RO_INTR_BIT(off, name) \
static inline void __iomem *addr_gic_## name(void ) \
{ \
return mips_gic_base + (off); \
} \
\
static inline unsigned int read_gic_## name(unsigned int intr) \
{ \
void __iomem *addr = addr_gic_## name(); \
unsigned int val; \
\
if (mips_cm_is64) { \
addr += (intr / 64 ) * sizeof (uint64_t); \
val = __raw_readq(addr) >> intr % 64 ; \
} else { \
addr += (intr / 32 ) * sizeof (uint32_t); \
val = __raw_readl(addr) >> intr % 32 ; \
} \
\
return val & 0 x1; \
}
/* For read-write shared bit-per-interrupt registers */
#define _GIC_ACCESSOR_RW_INTR_BIT(off, name) \
_GIC_ACCESSOR_RO_INTR_BIT(off, name) \
\
static inline void write_gic_## name(unsigned int intr) \
{ \
void __iomem *addr = addr_gic_## name(); \
\
if (mips_cm_is64) { \
addr += (intr / 64 ) * sizeof (uint64_t); \
__raw_writeq(BIT(intr % 64 ), addr); \
} else { \
addr += (intr / 32 ) * sizeof (uint32_t); \
__raw_writel(BIT(intr % 32 ), addr); \
} \
} \
\
static inline void change_gic_## name(unsigned int intr, \
unsigned int val) \
{ \
void __iomem *addr = addr_gic_## name(); \
\
if (mips_cm_is64) { \
uint64_t _val; \
\
addr += (intr / 64 ) * sizeof (uint64_t); \
_val = __raw_readq(addr); \
_val &= ~BIT_ULL(intr % 64 ); \
_val |= (uint64_t)val << (intr % 64 ); \
__raw_writeq(_val, addr); \
} else { \
uint32_t _val; \
\
addr += (intr / 32 ) * sizeof (uint32_t); \
_val = __raw_readl(addr); \
_val &= ~BIT(intr % 32 ); \
_val |= val << (intr % 32 ); \
__raw_writel(_val, addr); \
} \
}
#define GIC_ACCESSOR_RO_INTR_BIT(off, name) \
_GIC_ACCESSOR_RO_INTR_BIT(off, name) \
_GIC_ACCESSOR_RO_INTR_BIT(MIPS_GIC_REDIR_OFS + off, redir_## name)
#define GIC_ACCESSOR_RW_INTR_BIT(off, name) \
_GIC_ACCESSOR_RW_INTR_BIT(off, name) \
_GIC_ACCESSOR_RW_INTR_BIT(MIPS_GIC_REDIR_OFS + off, redir_## name)
/* For read-only local bit-per-interrupt registers */
#define GIC_VX_ACCESSOR_RO_INTR_BIT(sz, off, name) \
GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off, \
vl_## name) \
GIC_ACCESSOR_RO_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off, \
vo_## name)
/* For read-write local bit-per-interrupt registers */
#define GIC_VX_ACCESSOR_RW_INTR_BIT(sz, off, name) \
_GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_LOCAL_OFS + off, \
vl_## name) \
_GIC_ACCESSOR_RW_INTR_BIT(sz, MIPS_GIC_REDIR_OFS + off, \
vo_## name)
/* GIC_SH_CONFIG - Information about the GIC configuration */
GIC_ACCESSOR_RW(32 , 0 x000, config)
#define GIC_CONFIG_COUNTSTOP BIT(28 )
#define GIC_CONFIG_COUNTBITS GENMASK(27 , 24 )
#define GIC_CONFIG_NUMINTERRUPTS GENMASK(23 , 16 )
#define GIC_CONFIG_PVPS GENMASK(6 , 0 )
/* GIC_SH_COUNTER - Shared global counter value */
GIC_ACCESSOR_RW(64 , 0 x010, counter)
GIC_ACCESSOR_RW(32 , 0 x010, counter_32l)
GIC_ACCESSOR_RW(32 , 0 x014, counter_32h)
/* GIC_SH_POL_* - Configures interrupt polarity */
GIC_ACCESSOR_RW_INTR_BIT(0 x100, pol)
#define GIC_POL_ACTIVE_LOW 0 /* when level triggered */
#define GIC_POL_ACTIVE_HIGH 1 /* when level triggered */
#define GIC_POL_FALLING_EDGE 0 /* when single-edge triggered */
#define GIC_POL_RISING_EDGE 1 /* when single-edge triggered */
/* GIC_SH_TRIG_* - Configures interrupts to be edge or level triggered */
GIC_ACCESSOR_RW_INTR_BIT(0 x180, trig)
#define GIC_TRIG_LEVEL 0
#define GIC_TRIG_EDGE 1
/* GIC_SH_DUAL_* - Configures whether interrupts trigger on both edges */
GIC_ACCESSOR_RW_INTR_BIT(0 x200, dual)
#define GIC_DUAL_SINGLE 0 /* when edge-triggered */
#define GIC_DUAL_DUAL 1 /* when edge-triggered */
/* GIC_SH_WEDGE - Write an 'edge', ie. trigger an interrupt */
GIC_ACCESSOR_RW(32 , 0 x280, wedge)
#define GIC_WEDGE_RW BIT(31 )
#define GIC_WEDGE_INTR GENMASK(7 , 0 )
/* GIC_SH_RMASK_* - Reset/clear shared interrupt mask bits */
GIC_ACCESSOR_RW_INTR_BIT(0 x300, rmask)
/* GIC_SH_SMASK_* - Set shared interrupt mask bits */
GIC_ACCESSOR_RW_INTR_BIT(0 x380, smask)
/* GIC_SH_MASK_* - Read the current shared interrupt mask */
GIC_ACCESSOR_RO_INTR_BIT(0 x400, mask)
/* GIC_SH_PEND_* - Read currently pending shared interrupts */
GIC_ACCESSOR_RO_INTR_BIT(0 x480, pend)
/* GIC_SH_MAPx_PIN - Map shared interrupts to a particular CPU pin */
GIC_ACCESSOR_RW_INTR_REG(32 , 0 x500, 0 x4, map_pin)
#define GIC_MAP_PIN_MAP_TO_PIN BIT(31 )
#define GIC_MAP_PIN_MAP_TO_NMI BIT(30 )
#define GIC_MAP_PIN_MAP GENMASK(5 , 0 )
/* GIC_SH_MAPx_VP - Map shared interrupts to a particular Virtual Processor */
GIC_ACCESSOR_RW_INTR_REG(32 , 0 x2000, 0 x20, map_vp)
/* GIC_Vx_CTL - VP-level interrupt control */
GIC_VX_ACCESSOR_RW(32 , 0 x000, ctl)
#define GIC_VX_CTL_FDC_ROUTABLE BIT(4 )
#define GIC_VX_CTL_SWINT_ROUTABLE BIT(3 )
#define GIC_VX_CTL_PERFCNT_ROUTABLE BIT(2 )
#define GIC_VX_CTL_TIMER_ROUTABLE BIT(1 )
#define GIC_VX_CTL_EIC BIT(0 )
/* GIC_Vx_PEND - Read currently pending local interrupts */
GIC_VX_ACCESSOR_RO(32 , 0 x004, pend)
/* GIC_Vx_MASK - Read the current local interrupt mask */
GIC_VX_ACCESSOR_RO(32 , 0 x008, mask)
/* GIC_Vx_RMASK - Reset/clear local interrupt mask bits */
GIC_VX_ACCESSOR_RW(32 , 0 x00c, rmask)
/* GIC_Vx_SMASK - Set local interrupt mask bits */
GIC_VX_ACCESSOR_RW(32 , 0 x010, smask)
/* GIC_Vx_*_MAP - Route local interrupts to the desired pins */
GIC_VX_ACCESSOR_RW_INTR_REG(32 , 0 x040, 0 x4, map)
/* GIC_Vx_WD_MAP - Route the local watchdog timer interrupt */
GIC_VX_ACCESSOR_RW(32 , 0 x040, wd_map)
/* GIC_Vx_COMPARE_MAP - Route the local count/compare interrupt */
GIC_VX_ACCESSOR_RW(32 , 0 x044, compare_map)
/* GIC_Vx_TIMER_MAP - Route the local CPU timer (cp0 count/compare) interrupt */
GIC_VX_ACCESSOR_RW(32 , 0 x048, timer_map)
/* GIC_Vx_FDC_MAP - Route the local fast debug channel interrupt */
GIC_VX_ACCESSOR_RW(32 , 0 x04c, fdc_map)
/* GIC_Vx_PERFCTR_MAP - Route the local performance counter interrupt */
GIC_VX_ACCESSOR_RW(32 , 0 x050, perfctr_map)
/* GIC_Vx_SWINT0_MAP - Route the local software interrupt 0 */
GIC_VX_ACCESSOR_RW(32 , 0 x054, swint0_map)
/* GIC_Vx_SWINT1_MAP - Route the local software interrupt 1 */
GIC_VX_ACCESSOR_RW(32 , 0 x058, swint1_map)
/* GIC_Vx_OTHER - Configure access to other Virtual Processor registers */
GIC_VX_ACCESSOR_RW(32 , 0 x080, other)
#define GIC_VX_OTHER_VPNUM GENMASK(5 , 0 )
/* GIC_Vx_IDENT - Retrieve the local Virtual Processor's ID */
GIC_VX_ACCESSOR_RO(32 , 0 x088, ident)
#define GIC_VX_IDENT_VPNUM GENMASK(5 , 0 )
/* GIC_Vx_COMPARE - Value to compare with GIC_SH_COUNTER */
GIC_VX_ACCESSOR_RW(64 , 0 x0a0, compare)
/* GIC_Vx_EIC_SHADOW_SET_BASE - Set shadow register set for each interrupt */
GIC_VX_ACCESSOR_RW_INTR_REG(32 , 0 x100, 0 x4, eic_shadow_set)
/**
* enum mips_gic_local_interrupt - GIC local interrupts
* @ GIC_LOCAL_INT_WD : GIC watchdog timer interrupt
* @ GIC_LOCAL_INT_COMPARE : GIC count / compare interrupt
* @ GIC_LOCAL_INT_TIMER : CP0 count / compare interrupt
* @ GIC_LOCAL_INT_PERFCTR : Performance counter interrupt
* @ GIC_LOCAL_INT_SWINT0 : Software interrupt 0
* @ GIC_LOCAL_INT_SWINT1 : Software interrupt 1
* @ GIC_LOCAL_INT_FDC : Fast debug channel interrupt
* @ GIC_NUM_LOCAL_INTRS : The number of local interrupts
*
* Enumerates interrupts provided by the GIC that are local to a VP .
*/
enum mips_gic_local_interrupt {
GIC_LOCAL_INT_WD,
GIC_LOCAL_INT_COMPARE,
GIC_LOCAL_INT_TIMER,
GIC_LOCAL_INT_PERFCTR,
GIC_LOCAL_INT_SWINT0,
GIC_LOCAL_INT_SWINT1,
GIC_LOCAL_INT_FDC,
GIC_NUM_LOCAL_INTRS
};
/**
* mips_gic_present ( ) - Determine whether a GIC is present
*
* Determines whether a MIPS Global Interrupt Controller ( GIC ) is present in
* the system that the kernel is running on .
*
* Return true if a GIC is present , else false .
*/
static inline bool mips_gic_present(void )
{
return IS_ENABLED(CONFIG_MIPS_GIC) && mips_gic_base;
}
/**
* mips_gic_vx_map_reg ( ) - Return GIC_Vx_ < intr > _ MAP register offset
* @ intr : A GIC local interrupt
*
* Determine the index of the GIC_VL_ < intr > _ MAP or GIC_VO_ < intr > _ MAP register
* within the block of GIC map registers . This is almost the same as the order
* of interrupts in the pending & mask registers , as used by enum
* mips_gic_local_interrupt , but moves the FDC interrupt & thus offsets the
* interrupts after it . . .
*
* Return : The map register index corresponding to @ intr .
*
* The return value is suitable for use with the ( read | write ) _ gic_v [ lo ] _ map
* accessor functions .
*/
static inline unsigned int
mips_gic_vx_map_reg(enum mips_gic_local_interrupt intr)
{
/* WD, Compare & Timer are 1:1 */
if (intr <= GIC_LOCAL_INT_TIMER)
return intr;
/* FDC moves to after Timer... */
if (intr == GIC_LOCAL_INT_FDC)
return GIC_LOCAL_INT_TIMER + 1 ;
/* As a result everything else is offset by 1 */
return intr + 1 ;
}
/**
* gic_get_c0_compare_int ( ) - Return cp0 count / compare interrupt virq
*
* Determine the virq number to use for the coprocessor 0 count / compare
* interrupt , which may be routed via the GIC .
*
* Returns the virq number or a negative error number .
*/
extern int gic_get_c0_compare_int(void );
/**
* gic_get_c0_perfcount_int ( ) - Return performance counter interrupt virq
*
* Determine the virq number to use for CPU performance counter interrupts ,
* which may be routed via the GIC .
*
* Returns the virq number or a negative error number .
*/
extern int gic_get_c0_perfcount_int(void );
/**
* gic_get_c0_fdc_int ( ) - Return fast debug channel interrupt virq
*
* Determine the virq number to use for fast debug channel ( FDC ) interrupts ,
* which may be routed via the GIC .
*
* Returns the virq number or a negative error number .
*/
extern int gic_get_c0_fdc_int(void );
#endif /* __MIPS_ASM_MIPS_CPS_H__ */
Messung V0.5 in Prozent C=85 H=96 G=90
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-10-01)
¤
*© Formatika GbR, Deutschland