1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4 */
5
6#ifndef __LS7A_KVM_IRQ_H
7#define __LS7A_KVM_IRQ_H
8
9#include <linux/mm_types.h>
10#include <linux/hrtimer.h>
11#include <linux/kvm_host.h>
12#include <linux/spinlock.h>
13#include <loongson.h>
14#include <linux/seq_file.h>
15#include "kvmcpu.h"
16
17#include <kvm/iodev.h>
18
19#define LS7A_APIC_NUM_PINS	64
20
21#define LS7A_ROUTE_ENTRY_OFFSET	0x100
22#define LS7A_INT_ID_OFFSET	0x0
23#define LS7A_INT_ID_VAL		0x7000000UL
24#define LS7A_INT_ID_VER		0x1f0001UL
25#define LS7A_INT_MASK_OFFSET	0x20
26#define LS7A_INT_EDGE_OFFSET	0x60
27#define LS7A_INT_CLEAR_OFFSET	0x80
28#define LS7A_INT_STATUS_OFFSET	0x3a0
29#define LS7A_INT_POL_OFFSET	0x3e0
30#define LS7A_HTMSI_EN_OFFSET	0x40
31#define LS7A_HTMSI_VEC_OFFSET	0x200
32#define LS7A_AUTO_CTRL0_OFFSET	0xc0
33#define LS7A_AUTO_CTRL1_OFFSET	0xe0
34
35#define LS7A_IOAPIC_GUEST_REG_BASE		0x10000000UL
36#define LS7A_IOAPIC_GUEST_REG_BASE_ALIAS	0xe0010000000UL
37
38#define LS7A_IOAPIC_NUM_PINS			32
39
40typedef struct kvm_ls7a_ioapic_state {
41	u64 int_id;
42	/* 0x020 interrupt mask register */
43	u64 int_mask;
44	/* 0x040 1=msi */
45	u64 htmsi_en;
46	/* 0x060 edge=1 level  =0 */
47	u64 intedge;
48	/* 0x080 for clean edge int,set 1 clean,set 0 is noused */
49	u64 intclr;
50	/* 0x0c0 */
51	u64 auto_crtl0;
52	/* 0x0e0 */
53	u64 auto_crtl1;
54	/* 0x100 - 0x140 */
55	u8 route_entry[64];
56	/* 0x200 - 0x240 */
57	u8 htmsi_vector[64];
58	/* 0x300 */
59	u64 intisr_chip0;
60	/* 0x320 */
61	u64 intisr_chip1;
62	/* edge detection */
63	u64 last_intirr;
64	/* 0x380 interrupt request register */
65	u64 intirr;
66	/* 0x3a0 interrupt service register */
67	u64 intisr;
68	/* 0x3e0 interrupt level polarity selection register,
69	 * 0 for high level tirgger
70	 */
71	u64 int_polarity;
72} LS7AApicState;
73
74struct ls7a_kvm_ioapic {
75	spinlock_t lock;
76	bool wakeup_needed;
77	unsigned pending_acks;
78	struct kvm *kvm;
79	struct kvm_ls7a_ioapic_state ls7a_ioapic;
80	struct kvm_io_device dev_ls7a_ioapic;
81	struct kvm_io_device ls7a_ioapic_alias;
82	void (*ack_notifier)(void *opaque, int irq);
83	unsigned long irq_states[LS7A_APIC_NUM_PINS];
84};
85
86static inline struct ls7a_kvm_ioapic *ls7a_ioapic_irqchip(struct kvm *kvm)
87{
88	return kvm->arch.v_ioapic;
89}
90
91static inline int ls7a_ioapic_in_kernel(struct kvm *kvm)
92{
93	int ret;
94
95	ret = (ls7a_ioapic_irqchip(kvm) != NULL);
96	return ret;
97}
98
99int kvm_set_ls7a_ioapic(struct kvm *kvm, struct ls7a_ioapic_state *state);
100int kvm_get_ls7a_ioapic(struct kvm *kvm, struct ls7a_ioapic_state *state);
101int kvm_create_ls7a_ioapic(struct kvm *kvm);
102void kvm_destroy_ls7a_ioapic(struct kvm *kvm);
103int kvm_ls7a_ioapic_set_irq(struct kvm *kvm, int irq, int level);
104
105void ls7a_ioapic_lock(struct ls7a_kvm_ioapic *s, unsigned long *flags);
106void ls7a_ioapic_unlock(struct ls7a_kvm_ioapic *s, unsigned long *flags);
107int kvm_ls7a_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
108int kvm_ls7a_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
109					int irq_source_id, int level, bool line_status);
110
111void kvm_dump_ls7a_ioapic_state(struct seq_file *m, struct ls7a_kvm_ioapic *ioapic);
112#endif
113