1 /* 2 * Copyright (C) 2015, 2016 ARM Ltd. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 #ifndef __XEN_ARM_VGIC_VGIC_MMIO_H__ 17 #define __XEN_ARM_VGIC_VGIC_MMIO_H__ 18 19 struct vgic_register_region { 20 unsigned int reg_offset; 21 unsigned int len; 22 unsigned int bits_per_irq; 23 unsigned int access_flags; 24 unsigned long (*read)(struct vcpu *vcpu, paddr_t addr, 25 unsigned int len); 26 void (*write)(struct vcpu *vcpu, paddr_t addr, 27 unsigned int len, unsigned long val); 28 }; 29 30 extern struct mmio_handler_ops vgic_io_ops; 31 32 #define VGIC_ACCESS_8bit 1 33 #define VGIC_ACCESS_32bit 2 34 #define VGIC_ACCESS_64bit 4 35 36 /* 37 * Generate a mask that covers the number of bytes required to address 38 * up to 1024 interrupts, each represented by <bits> bits. This assumes 39 * that <bits> is a power of two. 40 */ 41 #define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1) 42 43 /* 44 * (addr & mask) gives us the _byte_ offset for the INT ID. 45 * We multiply this by 8 the get the _bit_ offset, then divide this by 46 * the number of bits to learn the actual INT ID. 47 * But instead of a division (which requires a "long long div" implementation), 48 * we shift by the binary logarithm of <bits>. 49 * This assumes that <bits> is a power of two. 50 */ 51 #define VGIC_ADDR_TO_INTID(addr, bits) (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \ 52 8 >> ilog2(bits)) 53 54 /* 55 * Some VGIC registers store per-IRQ information, with a different number 56 * of bits per IRQ. For those registers this macro is used. 57 * The _WITH_LENGTH version instantiates registers with a fixed length 58 * and is mutually exclusive with the _PER_IRQ version. 59 */ 60 #define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, bpi, acc) \ 61 { \ 62 .reg_offset = off, \ 63 .bits_per_irq = bpi, \ 64 .len = bpi * 1024 / 8, \ 65 .access_flags = acc, \ 66 .read = rd, \ 67 .write = wr, \ 68 } 69 70 #define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc) \ 71 { \ 72 .reg_offset = off, \ 73 .bits_per_irq = 0, \ 74 .len = length, \ 75 .access_flags = acc, \ 76 .read = rd, \ 77 .write = wr, \ 78 } 79 80 unsigned long vgic_mmio_read_raz(struct vcpu *vcpu, 81 paddr_t addr, unsigned int len); 82 83 unsigned long vgic_mmio_read_rao(struct vcpu *vcpu, 84 paddr_t addr, unsigned int len); 85 86 void vgic_mmio_write_wi(struct vcpu *vcpu, paddr_t addr, 87 unsigned int len, unsigned long val); 88 89 unsigned long vgic_mmio_read_enable(struct vcpu *vcpu, 90 paddr_t addr, unsigned int len); 91 92 void vgic_mmio_write_senable(struct vcpu *vcpu, 93 paddr_t addr, unsigned int len, 94 unsigned long val); 95 96 void vgic_mmio_write_cenable(struct vcpu *vcpu, 97 paddr_t addr, unsigned int len, 98 unsigned long val); 99 100 unsigned long vgic_mmio_read_pending(struct vcpu *vcpu, 101 paddr_t addr, unsigned int len); 102 103 void vgic_mmio_write_spending(struct vcpu *vcpu, 104 paddr_t addr, unsigned int len, 105 unsigned long val); 106 107 void vgic_mmio_write_cpending(struct vcpu *vcpu, 108 paddr_t addr, unsigned int len, 109 unsigned long val); 110 111 unsigned long vgic_mmio_read_active(struct vcpu *vcpu, 112 paddr_t addr, unsigned int len); 113 114 void vgic_mmio_write_cactive(struct vcpu *vcpu, 115 paddr_t addr, unsigned int len, 116 unsigned long val); 117 118 void vgic_mmio_write_sactive(struct vcpu *vcpu, 119 paddr_t addr, unsigned int len, 120 unsigned long val); 121 122 unsigned long vgic_mmio_read_priority(struct vcpu *vcpu, 123 paddr_t addr, unsigned int len); 124 125 void vgic_mmio_write_priority(struct vcpu *vcpu, 126 paddr_t addr, unsigned int len, 127 unsigned long val); 128 129 unsigned long vgic_mmio_read_config(struct vcpu *vcpu, 130 paddr_t addr, unsigned int len); 131 132 void vgic_mmio_write_config(struct vcpu *vcpu, 133 paddr_t addr, unsigned int len, 134 unsigned long val); 135 136 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev); 137 138 #endif 139