18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef __LS7A_KVM_IRQ_H 78c2ecf20Sopenharmony_ci#define __LS7A_KVM_IRQ_H 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/mm_types.h> 108c2ecf20Sopenharmony_ci#include <linux/hrtimer.h> 118c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 128c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 138c2ecf20Sopenharmony_ci#include <loongson.h> 148c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 158c2ecf20Sopenharmony_ci#include "kvmcpu.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <kvm/iodev.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define LS7A_APIC_NUM_PINS 64 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define LS7A_ROUTE_ENTRY_OFFSET 0x100 228c2ecf20Sopenharmony_ci#define LS7A_INT_ID_OFFSET 0x0 238c2ecf20Sopenharmony_ci#define LS7A_INT_ID_VAL 0x7000000UL 248c2ecf20Sopenharmony_ci#define LS7A_INT_ID_VER 0x1f0001UL 258c2ecf20Sopenharmony_ci#define LS7A_INT_MASK_OFFSET 0x20 268c2ecf20Sopenharmony_ci#define LS7A_INT_EDGE_OFFSET 0x60 278c2ecf20Sopenharmony_ci#define LS7A_INT_CLEAR_OFFSET 0x80 288c2ecf20Sopenharmony_ci#define LS7A_INT_STATUS_OFFSET 0x3a0 298c2ecf20Sopenharmony_ci#define LS7A_INT_POL_OFFSET 0x3e0 308c2ecf20Sopenharmony_ci#define LS7A_HTMSI_EN_OFFSET 0x40 318c2ecf20Sopenharmony_ci#define LS7A_HTMSI_VEC_OFFSET 0x200 328c2ecf20Sopenharmony_ci#define LS7A_AUTO_CTRL0_OFFSET 0xc0 338c2ecf20Sopenharmony_ci#define LS7A_AUTO_CTRL1_OFFSET 0xe0 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define LS7A_IOAPIC_GUEST_REG_BASE 0x10000000UL 368c2ecf20Sopenharmony_ci#define LS7A_IOAPIC_GUEST_REG_BASE_ALIAS 0xe0010000000UL 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define LS7A_IOAPIC_NUM_PINS 32 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_citypedef struct kvm_ls7a_ioapic_state { 418c2ecf20Sopenharmony_ci u64 int_id; 428c2ecf20Sopenharmony_ci /* 0x020 interrupt mask register */ 438c2ecf20Sopenharmony_ci u64 int_mask; 448c2ecf20Sopenharmony_ci /* 0x040 1=msi */ 458c2ecf20Sopenharmony_ci u64 htmsi_en; 468c2ecf20Sopenharmony_ci /* 0x060 edge=1 level =0 */ 478c2ecf20Sopenharmony_ci u64 intedge; 488c2ecf20Sopenharmony_ci /* 0x080 for clean edge int,set 1 clean,set 0 is noused */ 498c2ecf20Sopenharmony_ci u64 intclr; 508c2ecf20Sopenharmony_ci /* 0x0c0 */ 518c2ecf20Sopenharmony_ci u64 auto_crtl0; 528c2ecf20Sopenharmony_ci /* 0x0e0 */ 538c2ecf20Sopenharmony_ci u64 auto_crtl1; 548c2ecf20Sopenharmony_ci /* 0x100 - 0x140 */ 558c2ecf20Sopenharmony_ci u8 route_entry[64]; 568c2ecf20Sopenharmony_ci /* 0x200 - 0x240 */ 578c2ecf20Sopenharmony_ci u8 htmsi_vector[64]; 588c2ecf20Sopenharmony_ci /* 0x300 */ 598c2ecf20Sopenharmony_ci u64 intisr_chip0; 608c2ecf20Sopenharmony_ci /* 0x320 */ 618c2ecf20Sopenharmony_ci u64 intisr_chip1; 628c2ecf20Sopenharmony_ci /* edge detection */ 638c2ecf20Sopenharmony_ci u64 last_intirr; 648c2ecf20Sopenharmony_ci /* 0x380 interrupt request register */ 658c2ecf20Sopenharmony_ci u64 intirr; 668c2ecf20Sopenharmony_ci /* 0x3a0 interrupt service register */ 678c2ecf20Sopenharmony_ci u64 intisr; 688c2ecf20Sopenharmony_ci /* 0x3e0 interrupt level polarity selection register, 698c2ecf20Sopenharmony_ci * 0 for high level tirgger 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci u64 int_polarity; 728c2ecf20Sopenharmony_ci} LS7AApicState; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistruct ls7a_kvm_ioapic { 758c2ecf20Sopenharmony_ci spinlock_t lock; 768c2ecf20Sopenharmony_ci bool wakeup_needed; 778c2ecf20Sopenharmony_ci unsigned pending_acks; 788c2ecf20Sopenharmony_ci struct kvm *kvm; 798c2ecf20Sopenharmony_ci struct kvm_ls7a_ioapic_state ls7a_ioapic; 808c2ecf20Sopenharmony_ci struct kvm_io_device dev_ls7a_ioapic; 818c2ecf20Sopenharmony_ci struct kvm_io_device ls7a_ioapic_alias; 828c2ecf20Sopenharmony_ci void (*ack_notifier)(void *opaque, int irq); 838c2ecf20Sopenharmony_ci unsigned long irq_states[LS7A_APIC_NUM_PINS]; 848c2ecf20Sopenharmony_ci}; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic inline struct ls7a_kvm_ioapic *ls7a_ioapic_irqchip(struct kvm *kvm) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci return kvm->arch.v_ioapic; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic inline int ls7a_ioapic_in_kernel(struct kvm *kvm) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci int ret; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci ret = (ls7a_ioapic_irqchip(kvm) != NULL); 968c2ecf20Sopenharmony_ci return ret; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ciint kvm_set_ls7a_ioapic(struct kvm *kvm, struct ls7a_ioapic_state *state); 1008c2ecf20Sopenharmony_ciint kvm_get_ls7a_ioapic(struct kvm *kvm, struct ls7a_ioapic_state *state); 1018c2ecf20Sopenharmony_ciint kvm_create_ls7a_ioapic(struct kvm *kvm); 1028c2ecf20Sopenharmony_civoid kvm_destroy_ls7a_ioapic(struct kvm *kvm); 1038c2ecf20Sopenharmony_ciint kvm_ls7a_ioapic_set_irq(struct kvm *kvm, int irq, int level); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_civoid ls7a_ioapic_lock(struct ls7a_kvm_ioapic *s, unsigned long *flags); 1068c2ecf20Sopenharmony_civoid ls7a_ioapic_unlock(struct ls7a_kvm_ioapic *s, unsigned long *flags); 1078c2ecf20Sopenharmony_ciint kvm_ls7a_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi); 1088c2ecf20Sopenharmony_ciint kvm_ls7a_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm, 1098c2ecf20Sopenharmony_ci int irq_source_id, int level, bool line_status); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_civoid kvm_dump_ls7a_ioapic_state(struct seq_file *m, struct ls7a_kvm_ioapic *ioapic); 1128c2ecf20Sopenharmony_ci#endif 113