xref: /linux/arch/loongarch/include/asm/kvm_eiointc.h (revision c34e9ab9a612ee8b18273398ef75c207b01f516d)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2024 Loongson Technology Corporation Limited
4  */
5 
6 #ifndef __ASM_KVM_EIOINTC_H
7 #define __ASM_KVM_EIOINTC_H
8 
9 #include <kvm/iodev.h>
10 
11 #define EIOINTC_IRQS			256
12 #define EIOINTC_ROUTE_MAX_VCPUS		256
13 #define EIOINTC_IRQS_U8_NUMS		(EIOINTC_IRQS / 8)
14 #define EIOINTC_IRQS_U16_NUMS		(EIOINTC_IRQS_U8_NUMS / 2)
15 #define EIOINTC_IRQS_U32_NUMS		(EIOINTC_IRQS_U8_NUMS / 4)
16 #define EIOINTC_IRQS_U64_NUMS		(EIOINTC_IRQS_U8_NUMS / 8)
17 /* map to ipnum per 32 irqs */
18 #define EIOINTC_IRQS_NODETYPE_COUNT	16
19 
20 #define EIOINTC_BASE			0x1400
21 #define EIOINTC_SIZE			0x900
22 
23 #define EIOINTC_NODETYPE_START		0xa0
24 #define EIOINTC_NODETYPE_END		0xbf
25 #define EIOINTC_IPMAP_START		0xc0
26 #define EIOINTC_IPMAP_END		0xc7
27 #define EIOINTC_ENABLE_START		0x200
28 #define EIOINTC_ENABLE_END		0x21f
29 #define EIOINTC_BOUNCE_START		0x280
30 #define EIOINTC_BOUNCE_END		0x29f
31 #define EIOINTC_ISR_START		0x300
32 #define EIOINTC_ISR_END			0x31f
33 #define EIOINTC_COREISR_START		0x400
34 #define EIOINTC_COREISR_END		0x41f
35 #define EIOINTC_COREMAP_START		0x800
36 #define EIOINTC_COREMAP_END		0x8ff
37 
38 #define EIOINTC_VIRT_BASE		(0x40000000)
39 #define EIOINTC_VIRT_SIZE		(0x1000)
40 
41 #define EIOINTC_VIRT_FEATURES		(0x0)
42 #define EIOINTC_HAS_VIRT_EXTENSION	(0)
43 #define EIOINTC_HAS_ENABLE_OPTION	(1)
44 #define EIOINTC_HAS_INT_ENCODE		(2)
45 #define EIOINTC_HAS_CPU_ENCODE		(3)
46 #define EIOINTC_VIRT_HAS_FEATURES	((1U << EIOINTC_HAS_VIRT_EXTENSION) \
47 					| (1U << EIOINTC_HAS_ENABLE_OPTION) \
48 					| (1U << EIOINTC_HAS_INT_ENCODE)    \
49 					| (1U << EIOINTC_HAS_CPU_ENCODE))
50 #define EIOINTC_VIRT_CONFIG		(0x4)
51 #define EIOINTC_ENABLE			(1)
52 #define EIOINTC_ENABLE_INT_ENCODE	(2)
53 #define EIOINTC_ENABLE_CPU_ENCODE	(3)
54 
55 #define LOONGSON_IP_NUM			8
56 
57 struct loongarch_eiointc {
58 	spinlock_t lock;
59 	struct kvm *kvm;
60 	struct kvm_io_device device;
61 	struct kvm_io_device device_vext;
62 	uint32_t num_cpu;
63 	uint32_t features;
64 	uint32_t status;
65 
66 	/* hardware state */
67 	union nodetype {
68 		u64 reg_u64[EIOINTC_IRQS_NODETYPE_COUNT / 4];
69 		u32 reg_u32[EIOINTC_IRQS_NODETYPE_COUNT / 2];
70 		u16 reg_u16[EIOINTC_IRQS_NODETYPE_COUNT];
71 		u8 reg_u8[EIOINTC_IRQS_NODETYPE_COUNT * 2];
72 	} nodetype;
73 
74 	/* one bit shows the state of one irq */
75 	union bounce {
76 		u64 reg_u64[EIOINTC_IRQS_U64_NUMS];
77 		u32 reg_u32[EIOINTC_IRQS_U32_NUMS];
78 		u16 reg_u16[EIOINTC_IRQS_U16_NUMS];
79 		u8 reg_u8[EIOINTC_IRQS_U8_NUMS];
80 	} bounce;
81 
82 	union isr {
83 		u64 reg_u64[EIOINTC_IRQS_U64_NUMS];
84 		u32 reg_u32[EIOINTC_IRQS_U32_NUMS];
85 		u16 reg_u16[EIOINTC_IRQS_U16_NUMS];
86 		u8 reg_u8[EIOINTC_IRQS_U8_NUMS];
87 	} isr;
88 	union coreisr {
89 		u64 reg_u64[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U64_NUMS];
90 		u32 reg_u32[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U32_NUMS];
91 		u16 reg_u16[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U16_NUMS];
92 		u8 reg_u8[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U8_NUMS];
93 	} coreisr;
94 	union enable {
95 		u64 reg_u64[EIOINTC_IRQS_U64_NUMS];
96 		u32 reg_u32[EIOINTC_IRQS_U32_NUMS];
97 		u16 reg_u16[EIOINTC_IRQS_U16_NUMS];
98 		u8 reg_u8[EIOINTC_IRQS_U8_NUMS];
99 	} enable;
100 
101 	/* use one byte to config ipmap for 32 irqs at once */
102 	union ipmap {
103 		u64 reg_u64;
104 		u32 reg_u32[EIOINTC_IRQS_U32_NUMS / 4];
105 		u16 reg_u16[EIOINTC_IRQS_U16_NUMS / 4];
106 		u8 reg_u8[EIOINTC_IRQS_U8_NUMS / 4];
107 	} ipmap;
108 	/* use one byte to config coremap for one irq */
109 	union coremap {
110 		u64 reg_u64[EIOINTC_IRQS / 8];
111 		u32 reg_u32[EIOINTC_IRQS / 4];
112 		u16 reg_u16[EIOINTC_IRQS / 2];
113 		u8 reg_u8[EIOINTC_IRQS];
114 	} coremap;
115 
116 	DECLARE_BITMAP(sw_coreisr[EIOINTC_ROUTE_MAX_VCPUS][LOONGSON_IP_NUM], EIOINTC_IRQS);
117 	uint8_t  sw_coremap[EIOINTC_IRQS];
118 };
119 
120 int kvm_loongarch_register_eiointc_device(void);
121 void eiointc_set_irq(struct loongarch_eiointc *s, int irq, int level);
122 
123 #endif /* __ASM_KVM_EIOINTC_H */
124