/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2024 Loongson Technology Corporation Limited */ #ifndef __ASM_KVM_EIOINTC_H #define __ASM_KVM_EIOINTC_H #include #define EIOINTC_IRQS 256 #define EIOINTC_ROUTE_MAX_VCPUS 256 #define EIOINTC_IRQS_U8_NUMS (EIOINTC_IRQS / 8) #define EIOINTC_IRQS_U16_NUMS (EIOINTC_IRQS_U8_NUMS / 2) #define EIOINTC_IRQS_U32_NUMS (EIOINTC_IRQS_U8_NUMS / 4) #define EIOINTC_IRQS_U64_NUMS (EIOINTC_IRQS_U8_NUMS / 8) /* map to ipnum per 32 irqs */ #define EIOINTC_IRQS_NODETYPE_COUNT 16 #define EIOINTC_BASE 0x1400 #define EIOINTC_SIZE 0x900 #define EIOINTC_NODETYPE_START 0xa0 #define EIOINTC_NODETYPE_END 0xbf #define EIOINTC_IPMAP_START 0xc0 #define EIOINTC_IPMAP_END 0xc7 #define EIOINTC_ENABLE_START 0x200 #define EIOINTC_ENABLE_END 0x21f #define EIOINTC_BOUNCE_START 0x280 #define EIOINTC_BOUNCE_END 0x29f #define EIOINTC_ISR_START 0x300 #define EIOINTC_ISR_END 0x31f #define EIOINTC_COREISR_START 0x400 #define EIOINTC_COREISR_END 0x41f #define EIOINTC_COREMAP_START 0x800 #define EIOINTC_COREMAP_END 0x8ff #define EIOINTC_VIRT_BASE (0x40000000) #define EIOINTC_VIRT_SIZE (0x1000) #define EIOINTC_VIRT_FEATURES (0x0) #define EIOINTC_HAS_VIRT_EXTENSION (0) #define EIOINTC_HAS_ENABLE_OPTION (1) #define EIOINTC_HAS_INT_ENCODE (2) #define EIOINTC_HAS_CPU_ENCODE (3) #define EIOINTC_VIRT_HAS_FEATURES ((1U << EIOINTC_HAS_VIRT_EXTENSION) \ | (1U << EIOINTC_HAS_ENABLE_OPTION) \ | (1U << EIOINTC_HAS_INT_ENCODE) \ | (1U << EIOINTC_HAS_CPU_ENCODE)) #define EIOINTC_VIRT_CONFIG (0x4) #define EIOINTC_ENABLE (1) #define EIOINTC_ENABLE_INT_ENCODE (2) #define EIOINTC_ENABLE_CPU_ENCODE (3) #define LOONGSON_IP_NUM 8 struct loongarch_eiointc { spinlock_t lock; struct kvm *kvm; struct kvm_io_device device; struct kvm_io_device device_vext; uint32_t num_cpu; uint32_t features; uint32_t status; /* hardware state */ union nodetype { u64 reg_u64[EIOINTC_IRQS_NODETYPE_COUNT / 4]; u32 reg_u32[EIOINTC_IRQS_NODETYPE_COUNT / 2]; u16 reg_u16[EIOINTC_IRQS_NODETYPE_COUNT]; u8 reg_u8[EIOINTC_IRQS_NODETYPE_COUNT * 2]; } nodetype; /* one bit shows the state of one irq */ union bounce { u64 reg_u64[EIOINTC_IRQS_U64_NUMS]; u32 reg_u32[EIOINTC_IRQS_U32_NUMS]; u16 reg_u16[EIOINTC_IRQS_U16_NUMS]; u8 reg_u8[EIOINTC_IRQS_U8_NUMS]; } bounce; union isr { u64 reg_u64[EIOINTC_IRQS_U64_NUMS]; u32 reg_u32[EIOINTC_IRQS_U32_NUMS]; u16 reg_u16[EIOINTC_IRQS_U16_NUMS]; u8 reg_u8[EIOINTC_IRQS_U8_NUMS]; } isr; union coreisr { u64 reg_u64[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U64_NUMS]; u32 reg_u32[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U32_NUMS]; u16 reg_u16[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U16_NUMS]; u8 reg_u8[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U8_NUMS]; } coreisr; union enable { u64 reg_u64[EIOINTC_IRQS_U64_NUMS]; u32 reg_u32[EIOINTC_IRQS_U32_NUMS]; u16 reg_u16[EIOINTC_IRQS_U16_NUMS]; u8 reg_u8[EIOINTC_IRQS_U8_NUMS]; } enable; /* use one byte to config ipmap for 32 irqs at once */ union ipmap { u64 reg_u64; u32 reg_u32[EIOINTC_IRQS_U32_NUMS / 4]; u16 reg_u16[EIOINTC_IRQS_U16_NUMS / 4]; u8 reg_u8[EIOINTC_IRQS_U8_NUMS / 4]; } ipmap; /* use one byte to config coremap for one irq */ union coremap { u64 reg_u64[EIOINTC_IRQS / 8]; u32 reg_u32[EIOINTC_IRQS / 4]; u16 reg_u16[EIOINTC_IRQS / 2]; u8 reg_u8[EIOINTC_IRQS]; } coremap; DECLARE_BITMAP(sw_coreisr[EIOINTC_ROUTE_MAX_VCPUS][LOONGSON_IP_NUM], EIOINTC_IRQS); uint8_t sw_coremap[EIOINTC_IRQS]; }; int kvm_loongarch_register_eiointc_device(void); void eiointc_set_irq(struct loongarch_eiointc *s, int irq, int level); #endif /* __ASM_KVM_EIOINTC_H */