summaryrefslogtreecommitdiffstats
path: root/arch/loongarch/include/asm/kvm_eiointc.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/loongarch/include/asm/kvm_eiointc.h')
-rw-r--r--arch/loongarch/include/asm/kvm_eiointc.h123
1 files changed, 123 insertions, 0 deletions
diff --git a/arch/loongarch/include/asm/kvm_eiointc.h b/arch/loongarch/include/asm/kvm_eiointc.h
new file mode 100644
index 000000000000..a3a40aba8acf
--- /dev/null
+++ b/arch/loongarch/include/asm/kvm_eiointc.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
+ */
+
+#ifndef __ASM_KVM_EIOINTC_H
+#define __ASM_KVM_EIOINTC_H
+
+#include <kvm/iodev.h>
+
+#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 */