12e996783SAnup Patel #include "kvm/kvm.h" 22e996783SAnup Patel #include "kvm/kvm-cpu.h" 32e996783SAnup Patel #include "kvm/irq.h" 4*0dff3501SAnup Patel #include "kvm/fdt.h" 5*0dff3501SAnup Patel #include "kvm/virtio.h" 6*0dff3501SAnup Patel 7*0dff3501SAnup Patel enum irqchip_type riscv_irqchip = IRQCHIP_UNKNOWN; 8*0dff3501SAnup Patel bool riscv_irqchip_inkernel; 9*0dff3501SAnup Patel void (*riscv_irqchip_trigger)(struct kvm *kvm, int irq, int level, bool edge) 10*0dff3501SAnup Patel = NULL; 11*0dff3501SAnup Patel void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm) = NULL; 12*0dff3501SAnup Patel u32 riscv_irqchip_phandle = PHANDLE_RESERVED; 13*0dff3501SAnup Patel u32 riscv_irqchip_msi_phandle = PHANDLE_RESERVED; 14*0dff3501SAnup Patel bool riscv_irqchip_line_sensing; 152e996783SAnup Patel 162e996783SAnup Patel void kvm__irq_line(struct kvm *kvm, int irq, int level) 172e996783SAnup Patel { 18*0dff3501SAnup Patel struct kvm_irq_level irq_level; 19*0dff3501SAnup Patel 20*0dff3501SAnup Patel if (riscv_irqchip_inkernel) { 21*0dff3501SAnup Patel irq_level.irq = irq; 22*0dff3501SAnup Patel irq_level.level = !!level; 23*0dff3501SAnup Patel if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0) 24*0dff3501SAnup Patel pr_warning("%s: Could not KVM_IRQ_LINE for irq %d\n", 25*0dff3501SAnup Patel __func__, irq); 26*0dff3501SAnup Patel } else { 27*0dff3501SAnup Patel if (riscv_irqchip_trigger) 28*0dff3501SAnup Patel riscv_irqchip_trigger(kvm, irq, level, false); 29*0dff3501SAnup Patel else 30*0dff3501SAnup Patel pr_warning("%s: Can't change level for irq %d\n", 31*0dff3501SAnup Patel __func__, irq); 32*0dff3501SAnup Patel } 332e996783SAnup Patel } 342e996783SAnup Patel 352e996783SAnup Patel void kvm__irq_trigger(struct kvm *kvm, int irq) 362e996783SAnup Patel { 37*0dff3501SAnup Patel if (riscv_irqchip_inkernel) { 38*0dff3501SAnup Patel kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH); 39*0dff3501SAnup Patel kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW); 40*0dff3501SAnup Patel } else { 41*0dff3501SAnup Patel if (riscv_irqchip_trigger) 42*0dff3501SAnup Patel riscv_irqchip_trigger(kvm, irq, 1, true); 43*0dff3501SAnup Patel else 44*0dff3501SAnup Patel pr_warning("%s: Can't trigger irq %d\n", 45*0dff3501SAnup Patel __func__, irq); 46*0dff3501SAnup Patel } 47*0dff3501SAnup Patel } 48*0dff3501SAnup Patel 49*0dff3501SAnup Patel void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type) 50*0dff3501SAnup Patel { 51*0dff3501SAnup Patel u32 prop[2], size; 52*0dff3501SAnup Patel 53*0dff3501SAnup Patel prop[0] = cpu_to_fdt32(irq); 54*0dff3501SAnup Patel size = sizeof(u32); 55*0dff3501SAnup Patel if (riscv_irqchip_line_sensing) { 56*0dff3501SAnup Patel prop[1] = cpu_to_fdt32(irq_type); 57*0dff3501SAnup Patel size += sizeof(u32); 58*0dff3501SAnup Patel } 59*0dff3501SAnup Patel 60*0dff3501SAnup Patel _FDT(fdt_property(fdt, "interrupts", prop, size)); 61*0dff3501SAnup Patel } 62*0dff3501SAnup Patel 63*0dff3501SAnup Patel void riscv__irqchip_create(struct kvm *kvm) 64*0dff3501SAnup Patel { 65*0dff3501SAnup Patel /* Try PLIC irqchip */ 66*0dff3501SAnup Patel plic__create(kvm); 67*0dff3501SAnup Patel 68*0dff3501SAnup Patel /* Fail if irqchip unknown */ 69*0dff3501SAnup Patel if (riscv_irqchip == IRQCHIP_UNKNOWN) 70*0dff3501SAnup Patel die("No IRQCHIP found\n"); 712e996783SAnup Patel } 72