Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

irqchip/gic-v5: Add GICv5 IRS/SPI support

The GICv5 Interrupt Routing Service (IRS) component implements
interrupt management and routing in the GICv5 architecture.

A GICv5 system comprises one or more IRSes, that together
handle the interrupt routing and state for the system.

An IRS supports Shared Peripheral Interrupts (SPIs), that are
interrupt sources directly connected to the IRS; they do not
rely on memory for storage. The number of supported SPIs is
fixed for a given implementation and can be probed through IRS
IDR registers.

SPI interrupt state and routing are managed through GICv5
instructions.

Each core (PE in GICv5 terms) in a GICv5 system is identified with
an Interrupt AFFinity ID (IAFFID).

An IRS manages a set of cores that are connected to it.

Firmware provides a topology description that the driver uses
to detect to which IRS a CPU (ie an IAFFID) is associated with.

Use probeable information and firmware description to initialize
the IRSes and implement GICv5 IRS SPIs support through an
SPI-specific IRQ domain.

The GICv5 IRS driver:

- Probes IRSes in the system to detect SPI ranges
- Associates an IRS with a set of cores connected to it
- Adds an IRQchip structure for SPI handling

SPIs priority is set to a value corresponding to the lowest
permissible priority in the system (taking into account the
implemented priority bits of the IRS and CPU interface).

Since all IRQs are set to the same priority value, the value
itself does not matter as long as it is a valid one.

Co-developed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
Co-developed-by: Timothy Hayes <timothy.hayes@arm.com>
Signed-off-by: Timothy Hayes <timothy.hayes@arm.com>
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/20250703-gicv5-host-v7-21-12e71f1b3528@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>

authored by

Lorenzo Pieralisi and committed by
Marc Zyngier
5cb1b6da 7ec80fb3

+937 -22
+36
arch/arm64/include/asm/sysreg.h
··· 1085 1085 /* 1086 1086 * Definitions for GICv5 instructions 1087 1087 */ 1088 + #define GICV5_OP_GIC_CDAFF sys_insn(1, 0, 12, 1, 3) 1088 1089 #define GICV5_OP_GIC_CDDI sys_insn(1, 0, 12, 2, 0) 1090 + #define GICV5_OP_GIC_CDDIS sys_insn(1, 0, 12, 1, 0) 1091 + #define GICV5_OP_GIC_CDEN sys_insn(1, 0, 12, 1, 1) 1089 1092 #define GICV5_OP_GIC_CDEOI sys_insn(1, 0, 12, 1, 7) 1093 + #define GICV5_OP_GIC_CDPEND sys_insn(1, 0, 12, 1, 4) 1094 + #define GICV5_OP_GIC_CDPRI sys_insn(1, 0, 12, 1, 2) 1095 + #define GICV5_OP_GIC_CDRCFG sys_insn(1, 0, 12, 1, 5) 1090 1096 #define GICV5_OP_GICR_CDIA sys_insn(1, 0, 12, 3, 0) 1097 + 1098 + /* Definitions for GIC CDAFF */ 1099 + #define GICV5_GIC_CDAFF_IAFFID_MASK GENMASK_ULL(47, 32) 1100 + #define GICV5_GIC_CDAFF_TYPE_MASK GENMASK_ULL(31, 29) 1101 + #define GICV5_GIC_CDAFF_IRM_MASK BIT_ULL(28) 1102 + #define GICV5_GIC_CDAFF_ID_MASK GENMASK_ULL(23, 0) 1091 1103 1092 1104 /* Definitions for GIC CDDI */ 1093 1105 #define GICV5_GIC_CDDI_TYPE_MASK GENMASK_ULL(31, 29) 1094 1106 #define GICV5_GIC_CDDI_ID_MASK GENMASK_ULL(23, 0) 1107 + 1108 + /* Definitions for GIC CDDIS */ 1109 + #define GICV5_GIC_CDDIS_TYPE_MASK GENMASK_ULL(31, 29) 1110 + #define GICV5_GIC_CDDIS_TYPE(r) FIELD_GET(GICV5_GIC_CDDIS_TYPE_MASK, r) 1111 + #define GICV5_GIC_CDDIS_ID_MASK GENMASK_ULL(23, 0) 1112 + #define GICV5_GIC_CDDIS_ID(r) FIELD_GET(GICV5_GIC_CDDIS_ID_MASK, r) 1113 + 1114 + /* Definitions for GIC CDEN */ 1115 + #define GICV5_GIC_CDEN_TYPE_MASK GENMASK_ULL(31, 29) 1116 + #define GICV5_GIC_CDEN_ID_MASK GENMASK_ULL(23, 0) 1117 + 1118 + /* Definitions for GIC CDPEND */ 1119 + #define GICV5_GIC_CDPEND_PENDING_MASK BIT_ULL(32) 1120 + #define GICV5_GIC_CDPEND_TYPE_MASK GENMASK_ULL(31, 29) 1121 + #define GICV5_GIC_CDPEND_ID_MASK GENMASK_ULL(23, 0) 1122 + 1123 + /* Definitions for GIC CDPRI */ 1124 + #define GICV5_GIC_CDPRI_PRIORITY_MASK GENMASK_ULL(39, 35) 1125 + #define GICV5_GIC_CDPRI_TYPE_MASK GENMASK_ULL(31, 29) 1126 + #define GICV5_GIC_CDPRI_ID_MASK GENMASK_ULL(23, 0) 1127 + 1128 + /* Definitions for GIC CDRCFG */ 1129 + #define GICV5_GIC_CDRCFG_TYPE_MASK GENMASK_ULL(31, 29) 1130 + #define GICV5_GIC_CDRCFG_ID_MASK GENMASK_ULL(23, 0) 1095 1131 1096 1132 /* Definitions for GICR CDIA */ 1097 1133 #define GICV5_GIC_CDIA_VALID_MASK BIT_ULL(32)
+1 -1
drivers/irqchip/Makefile
··· 36 36 obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v4.o irq-gic-v3-its-msi-parent.o 37 37 obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o 38 38 obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o 39 - obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o 39 + obj-$(CONFIG_ARM_GIC_V5) += irq-gic-v5.o irq-gic-v5-irs.o 40 40 obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o 41 41 obj-$(CONFIG_ARM_NVIC) += irq-nvic.o 42 42 obj-$(CONFIG_ARM_VIC) += irq-vic.o
+434
drivers/irqchip/irq-gic-v5-irs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2024-2025 ARM Limited, All Rights Reserved. 4 + */ 5 + 6 + #define pr_fmt(fmt) "GICv5 IRS: " fmt 7 + 8 + #include <linux/of.h> 9 + #include <linux/of_address.h> 10 + 11 + #include <linux/irqchip.h> 12 + #include <linux/irqchip/arm-gic-v5.h> 13 + 14 + #define IRS_FLAGS_NON_COHERENT BIT(0) 15 + 16 + static DEFINE_PER_CPU_READ_MOSTLY(struct gicv5_irs_chip_data *, per_cpu_irs_data); 17 + static LIST_HEAD(irs_nodes); 18 + 19 + static u32 irs_readl_relaxed(struct gicv5_irs_chip_data *irs_data, 20 + const u32 reg_offset) 21 + { 22 + return readl_relaxed(irs_data->irs_base + reg_offset); 23 + } 24 + 25 + static void irs_writel_relaxed(struct gicv5_irs_chip_data *irs_data, 26 + const u32 val, const u32 reg_offset) 27 + { 28 + writel_relaxed(val, irs_data->irs_base + reg_offset); 29 + } 30 + 31 + struct iaffid_entry { 32 + u16 iaffid; 33 + bool valid; 34 + }; 35 + 36 + static DEFINE_PER_CPU(struct iaffid_entry, cpu_iaffid); 37 + 38 + int gicv5_irs_cpu_to_iaffid(int cpuid, u16 *iaffid) 39 + { 40 + if (!per_cpu(cpu_iaffid, cpuid).valid) { 41 + pr_err("IAFFID for CPU %d has not been initialised\n", cpuid); 42 + return -ENODEV; 43 + } 44 + 45 + *iaffid = per_cpu(cpu_iaffid, cpuid).iaffid; 46 + 47 + return 0; 48 + } 49 + 50 + struct gicv5_irs_chip_data *gicv5_irs_lookup_by_spi_id(u32 spi_id) 51 + { 52 + struct gicv5_irs_chip_data *irs_data; 53 + u32 min, max; 54 + 55 + list_for_each_entry(irs_data, &irs_nodes, entry) { 56 + if (!irs_data->spi_range) 57 + continue; 58 + 59 + min = irs_data->spi_min; 60 + max = irs_data->spi_min + irs_data->spi_range - 1; 61 + if (spi_id >= min && spi_id <= max) 62 + return irs_data; 63 + } 64 + 65 + return NULL; 66 + } 67 + 68 + static int gicv5_irs_wait_for_spi_op(struct gicv5_irs_chip_data *irs_data) 69 + { 70 + u32 statusr; 71 + int ret; 72 + 73 + ret = gicv5_wait_for_op_atomic(irs_data->irs_base, GICV5_IRS_SPI_STATUSR, 74 + GICV5_IRS_SPI_STATUSR_IDLE, &statusr); 75 + if (ret) 76 + return ret; 77 + 78 + return !!FIELD_GET(GICV5_IRS_SPI_STATUSR_V, statusr) ? 0 : -EIO; 79 + } 80 + 81 + static int gicv5_irs_wait_for_irs_pe(struct gicv5_irs_chip_data *irs_data, 82 + bool selr) 83 + { 84 + bool valid = true; 85 + u32 statusr; 86 + int ret; 87 + 88 + ret = gicv5_wait_for_op_atomic(irs_data->irs_base, GICV5_IRS_PE_STATUSR, 89 + GICV5_IRS_PE_STATUSR_IDLE, &statusr); 90 + if (ret) 91 + return ret; 92 + 93 + if (selr) 94 + valid = !!FIELD_GET(GICV5_IRS_PE_STATUSR_V, statusr); 95 + 96 + return valid ? 0 : -EIO; 97 + } 98 + 99 + static int gicv5_irs_wait_for_pe_selr(struct gicv5_irs_chip_data *irs_data) 100 + { 101 + return gicv5_irs_wait_for_irs_pe(irs_data, true); 102 + } 103 + 104 + static int gicv5_irs_wait_for_pe_cr0(struct gicv5_irs_chip_data *irs_data) 105 + { 106 + return gicv5_irs_wait_for_irs_pe(irs_data, false); 107 + } 108 + 109 + int gicv5_spi_irq_set_type(struct irq_data *d, unsigned int type) 110 + { 111 + struct gicv5_irs_chip_data *irs_data = d->chip_data; 112 + u32 selr, cfgr; 113 + bool level; 114 + int ret; 115 + 116 + /* 117 + * There is no distinction between HIGH/LOW for level IRQs 118 + * and RISING/FALLING for edge IRQs in the architecture, 119 + * hence consider them equivalent. 120 + */ 121 + switch (type) { 122 + case IRQ_TYPE_EDGE_RISING: 123 + case IRQ_TYPE_EDGE_FALLING: 124 + level = false; 125 + break; 126 + case IRQ_TYPE_LEVEL_HIGH: 127 + case IRQ_TYPE_LEVEL_LOW: 128 + level = true; 129 + break; 130 + default: 131 + return -EINVAL; 132 + } 133 + 134 + guard(raw_spinlock)(&irs_data->spi_config_lock); 135 + 136 + selr = FIELD_PREP(GICV5_IRS_SPI_SELR_ID, d->hwirq); 137 + irs_writel_relaxed(irs_data, selr, GICV5_IRS_SPI_SELR); 138 + ret = gicv5_irs_wait_for_spi_op(irs_data); 139 + if (ret) 140 + return ret; 141 + 142 + cfgr = FIELD_PREP(GICV5_IRS_SPI_CFGR_TM, level); 143 + irs_writel_relaxed(irs_data, cfgr, GICV5_IRS_SPI_CFGR); 144 + 145 + return gicv5_irs_wait_for_spi_op(irs_data); 146 + } 147 + 148 + static int gicv5_irs_wait_for_idle(struct gicv5_irs_chip_data *irs_data) 149 + { 150 + return gicv5_wait_for_op_atomic(irs_data->irs_base, GICV5_IRS_CR0, 151 + GICV5_IRS_CR0_IDLE, NULL); 152 + } 153 + 154 + int gicv5_irs_register_cpu(int cpuid) 155 + { 156 + struct gicv5_irs_chip_data *irs_data; 157 + u32 selr, cr0; 158 + u16 iaffid; 159 + int ret; 160 + 161 + ret = gicv5_irs_cpu_to_iaffid(cpuid, &iaffid); 162 + if (ret) { 163 + pr_err("IAFFID for CPU %d has not been initialised\n", cpuid); 164 + return ret; 165 + } 166 + 167 + irs_data = per_cpu(per_cpu_irs_data, cpuid); 168 + if (!irs_data) { 169 + pr_err("No IRS associated with CPU %u\n", cpuid); 170 + return -ENXIO; 171 + } 172 + 173 + selr = FIELD_PREP(GICV5_IRS_PE_SELR_IAFFID, iaffid); 174 + irs_writel_relaxed(irs_data, selr, GICV5_IRS_PE_SELR); 175 + 176 + ret = gicv5_irs_wait_for_pe_selr(irs_data); 177 + if (ret) { 178 + pr_err("IAFFID 0x%x used in IRS_PE_SELR is invalid\n", iaffid); 179 + return -ENXIO; 180 + } 181 + 182 + cr0 = FIELD_PREP(GICV5_IRS_PE_CR0_DPS, 0x1); 183 + irs_writel_relaxed(irs_data, cr0, GICV5_IRS_PE_CR0); 184 + 185 + ret = gicv5_irs_wait_for_pe_cr0(irs_data); 186 + if (ret) 187 + return ret; 188 + 189 + pr_debug("CPU %d enabled PE IAFFID 0x%x\n", cpuid, iaffid); 190 + 191 + return 0; 192 + } 193 + 194 + static void __init gicv5_irs_init_bases(struct gicv5_irs_chip_data *irs_data, 195 + void __iomem *irs_base, 196 + struct fwnode_handle *handle) 197 + { 198 + struct device_node *np = to_of_node(handle); 199 + u32 cr0, cr1; 200 + 201 + irs_data->fwnode = handle; 202 + irs_data->irs_base = irs_base; 203 + 204 + if (of_property_read_bool(np, "dma-noncoherent")) { 205 + /* 206 + * A non-coherent IRS implies that some cache levels cannot be 207 + * used coherently by the cores and GIC. Our only option is to mark 208 + * memory attributes for the GIC as non-cacheable; by default, 209 + * non-cacheable memory attributes imply outer-shareable 210 + * shareability, the value written into IRS_CR1_SH is ignored. 211 + */ 212 + cr1 = FIELD_PREP(GICV5_IRS_CR1_VPED_WA, GICV5_NO_WRITE_ALLOC) | 213 + FIELD_PREP(GICV5_IRS_CR1_VPED_RA, GICV5_NO_READ_ALLOC) | 214 + FIELD_PREP(GICV5_IRS_CR1_VMD_WA, GICV5_NO_WRITE_ALLOC) | 215 + FIELD_PREP(GICV5_IRS_CR1_VMD_RA, GICV5_NO_READ_ALLOC) | 216 + FIELD_PREP(GICV5_IRS_CR1_VPET_RA, GICV5_NO_READ_ALLOC) | 217 + FIELD_PREP(GICV5_IRS_CR1_VMT_RA, GICV5_NO_READ_ALLOC) | 218 + FIELD_PREP(GICV5_IRS_CR1_IST_WA, GICV5_NO_WRITE_ALLOC) | 219 + FIELD_PREP(GICV5_IRS_CR1_IST_RA, GICV5_NO_READ_ALLOC) | 220 + FIELD_PREP(GICV5_IRS_CR1_IC, GICV5_NON_CACHE) | 221 + FIELD_PREP(GICV5_IRS_CR1_OC, GICV5_NON_CACHE); 222 + irs_data->flags |= IRS_FLAGS_NON_COHERENT; 223 + } else { 224 + cr1 = FIELD_PREP(GICV5_IRS_CR1_VPED_WA, GICV5_WRITE_ALLOC) | 225 + FIELD_PREP(GICV5_IRS_CR1_VPED_RA, GICV5_READ_ALLOC) | 226 + FIELD_PREP(GICV5_IRS_CR1_VMD_WA, GICV5_WRITE_ALLOC) | 227 + FIELD_PREP(GICV5_IRS_CR1_VMD_RA, GICV5_READ_ALLOC) | 228 + FIELD_PREP(GICV5_IRS_CR1_VPET_RA, GICV5_READ_ALLOC) | 229 + FIELD_PREP(GICV5_IRS_CR1_VMT_RA, GICV5_READ_ALLOC) | 230 + FIELD_PREP(GICV5_IRS_CR1_IST_WA, GICV5_WRITE_ALLOC) | 231 + FIELD_PREP(GICV5_IRS_CR1_IST_RA, GICV5_READ_ALLOC) | 232 + FIELD_PREP(GICV5_IRS_CR1_IC, GICV5_WB_CACHE) | 233 + FIELD_PREP(GICV5_IRS_CR1_OC, GICV5_WB_CACHE) | 234 + FIELD_PREP(GICV5_IRS_CR1_SH, GICV5_INNER_SHARE); 235 + } 236 + 237 + irs_writel_relaxed(irs_data, cr1, GICV5_IRS_CR1); 238 + 239 + cr0 = FIELD_PREP(GICV5_IRS_CR0_IRSEN, 0x1); 240 + irs_writel_relaxed(irs_data, cr0, GICV5_IRS_CR0); 241 + gicv5_irs_wait_for_idle(irs_data); 242 + } 243 + 244 + static int __init gicv5_irs_of_init_affinity(struct device_node *node, 245 + struct gicv5_irs_chip_data *irs_data, 246 + u8 iaffid_bits) 247 + { 248 + /* 249 + * Detect IAFFID<->CPU mappings from the device tree and 250 + * record IRS<->CPU topology information. 251 + */ 252 + u16 iaffid_mask = GENMASK(iaffid_bits - 1, 0); 253 + int ret, i, ncpus, niaffids; 254 + 255 + ncpus = of_count_phandle_with_args(node, "cpus", NULL); 256 + if (ncpus < 0) 257 + return -EINVAL; 258 + 259 + niaffids = of_property_count_elems_of_size(node, "arm,iaffids", 260 + sizeof(u16)); 261 + if (niaffids != ncpus) 262 + return -EINVAL; 263 + 264 + u16 *iaffids __free(kfree) = kcalloc(niaffids, sizeof(*iaffids), GFP_KERNEL); 265 + if (!iaffids) 266 + return -ENOMEM; 267 + 268 + ret = of_property_read_u16_array(node, "arm,iaffids", iaffids, niaffids); 269 + if (ret) 270 + return ret; 271 + 272 + for (i = 0; i < ncpus; i++) { 273 + struct device_node *cpu_node; 274 + int cpu; 275 + 276 + cpu_node = of_parse_phandle(node, "cpus", i); 277 + if (WARN_ON(!cpu_node)) 278 + continue; 279 + 280 + cpu = of_cpu_node_to_id(cpu_node); 281 + of_node_put(cpu_node); 282 + if (WARN_ON(cpu < 0)) 283 + continue; 284 + 285 + if (iaffids[i] & ~iaffid_mask) { 286 + pr_warn("CPU %d iaffid 0x%x exceeds IRS iaffid bits\n", 287 + cpu, iaffids[i]); 288 + continue; 289 + } 290 + 291 + per_cpu(cpu_iaffid, cpu).iaffid = iaffids[i]; 292 + per_cpu(cpu_iaffid, cpu).valid = true; 293 + 294 + /* We also know that the CPU is connected to this IRS */ 295 + per_cpu(per_cpu_irs_data, cpu) = irs_data; 296 + } 297 + 298 + return ret; 299 + } 300 + 301 + static void irs_setup_pri_bits(u32 idr1) 302 + { 303 + switch (FIELD_GET(GICV5_IRS_IDR1_PRIORITY_BITS, idr1)) { 304 + case GICV5_IRS_IDR1_PRIORITY_BITS_1BITS: 305 + gicv5_global_data.irs_pri_bits = 1; 306 + break; 307 + case GICV5_IRS_IDR1_PRIORITY_BITS_2BITS: 308 + gicv5_global_data.irs_pri_bits = 2; 309 + break; 310 + case GICV5_IRS_IDR1_PRIORITY_BITS_3BITS: 311 + gicv5_global_data.irs_pri_bits = 3; 312 + break; 313 + case GICV5_IRS_IDR1_PRIORITY_BITS_4BITS: 314 + gicv5_global_data.irs_pri_bits = 4; 315 + break; 316 + case GICV5_IRS_IDR1_PRIORITY_BITS_5BITS: 317 + gicv5_global_data.irs_pri_bits = 5; 318 + break; 319 + default: 320 + pr_warn("Detected wrong IDR priority bits value 0x%lx\n", 321 + FIELD_GET(GICV5_IRS_IDR1_PRIORITY_BITS, idr1)); 322 + gicv5_global_data.irs_pri_bits = 1; 323 + break; 324 + } 325 + } 326 + 327 + static int __init gicv5_irs_init(struct device_node *node) 328 + { 329 + struct gicv5_irs_chip_data *irs_data; 330 + void __iomem *irs_base; 331 + u32 idr, spi_count; 332 + u8 iaffid_bits; 333 + int ret; 334 + 335 + irs_data = kzalloc(sizeof(*irs_data), GFP_KERNEL); 336 + if (!irs_data) 337 + return -ENOMEM; 338 + 339 + raw_spin_lock_init(&irs_data->spi_config_lock); 340 + 341 + ret = of_property_match_string(node, "reg-names", "ns-config"); 342 + if (ret < 0) { 343 + pr_err("%pOF: ns-config reg-name not present\n", node); 344 + goto out_err; 345 + } 346 + 347 + irs_base = of_io_request_and_map(node, ret, of_node_full_name(node)); 348 + if (IS_ERR(irs_base)) { 349 + pr_err("%pOF: unable to map GICv5 IRS registers\n", node); 350 + ret = PTR_ERR(irs_base); 351 + goto out_err; 352 + } 353 + 354 + gicv5_irs_init_bases(irs_data, irs_base, &node->fwnode); 355 + 356 + idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1); 357 + iaffid_bits = FIELD_GET(GICV5_IRS_IDR1_IAFFID_BITS, idr) + 1; 358 + 359 + ret = gicv5_irs_of_init_affinity(node, irs_data, iaffid_bits); 360 + if (ret) { 361 + pr_err("Failed to parse CPU IAFFIDs from the device tree!\n"); 362 + goto out_iomem; 363 + } 364 + 365 + idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR7); 366 + irs_data->spi_min = FIELD_GET(GICV5_IRS_IDR7_SPI_BASE, idr); 367 + 368 + idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR6); 369 + irs_data->spi_range = FIELD_GET(GICV5_IRS_IDR6_SPI_IRS_RANGE, idr); 370 + 371 + if (irs_data->spi_range) { 372 + pr_info("%s detected SPI range [%u-%u]\n", 373 + of_node_full_name(node), 374 + irs_data->spi_min, 375 + irs_data->spi_min + 376 + irs_data->spi_range - 1); 377 + } 378 + 379 + /* 380 + * Do the global setting only on the first IRS. 381 + * Global properties (iaffid_bits, global spi count) are guaranteed to 382 + * be consistent across IRSes by the architecture. 383 + */ 384 + if (list_empty(&irs_nodes)) { 385 + 386 + idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1); 387 + irs_setup_pri_bits(idr); 388 + 389 + idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR5); 390 + 391 + spi_count = FIELD_GET(GICV5_IRS_IDR5_SPI_RANGE, idr); 392 + gicv5_global_data.global_spi_count = spi_count; 393 + 394 + pr_debug("Detected %u SPIs globally\n", spi_count); 395 + } 396 + 397 + list_add_tail(&irs_data->entry, &irs_nodes); 398 + 399 + return 0; 400 + 401 + out_iomem: 402 + iounmap(irs_base); 403 + out_err: 404 + kfree(irs_data); 405 + return ret; 406 + } 407 + 408 + void __init gicv5_irs_remove(void) 409 + { 410 + struct gicv5_irs_chip_data *irs_data, *tmp_data; 411 + 412 + list_for_each_entry_safe(irs_data, tmp_data, &irs_nodes, entry) { 413 + iounmap(irs_data->irs_base); 414 + list_del(&irs_data->entry); 415 + kfree(irs_data); 416 + } 417 + } 418 + 419 + int __init gicv5_irs_of_probe(struct device_node *parent) 420 + { 421 + struct device_node *np; 422 + int ret; 423 + 424 + for_each_available_child_of_node(parent, np) { 425 + if (!of_device_is_compatible(np, "arm,gic-v5-irs")) 426 + continue; 427 + 428 + ret = gicv5_irs_init(np); 429 + if (ret) 430 + pr_err("Failed to init IRS %s\n", np->full_name); 431 + } 432 + 433 + return list_empty(&irs_nodes) ? -ENODEV : 0; 434 + }
+326 -21
drivers/irqchip/irq-gic-v5.c
··· 26 26 return this_cpu_has_cap(ARM64_HAS_GICV5_CPUIF); 27 27 } 28 28 29 - struct gicv5_chip_data { 30 - struct fwnode_handle *fwnode; 31 - struct irq_domain *ppi_domain; 32 - }; 33 - 34 - static struct gicv5_chip_data gicv5_global_data __read_mostly; 29 + struct gicv5_chip_data gicv5_global_data __read_mostly; 35 30 36 31 static void gicv5_ppi_priority_init(void) 37 32 { ··· 54 59 isb(); 55 60 } 56 61 62 + static void gicv5_hwirq_init(irq_hw_number_t hwirq, u8 priority, u8 hwirq_type) 63 + { 64 + u64 cdpri, cdaff; 65 + u16 iaffid; 66 + int ret; 67 + 68 + if (hwirq_type == GICV5_HWIRQ_TYPE_SPI) { 69 + cdpri = FIELD_PREP(GICV5_GIC_CDPRI_PRIORITY_MASK, priority) | 70 + FIELD_PREP(GICV5_GIC_CDPRI_TYPE_MASK, hwirq_type) | 71 + FIELD_PREP(GICV5_GIC_CDPRI_ID_MASK, hwirq); 72 + gic_insn(cdpri, CDPRI); 73 + 74 + ret = gicv5_irs_cpu_to_iaffid(smp_processor_id(), &iaffid); 75 + 76 + if (WARN_ON_ONCE(ret)) 77 + return; 78 + 79 + cdaff = FIELD_PREP(GICV5_GIC_CDAFF_IAFFID_MASK, iaffid) | 80 + FIELD_PREP(GICV5_GIC_CDAFF_TYPE_MASK, hwirq_type) | 81 + FIELD_PREP(GICV5_GIC_CDAFF_ID_MASK, hwirq); 82 + gic_insn(cdaff, CDAFF); 83 + } 84 + } 85 + 57 86 static void gicv5_ppi_irq_mask(struct irq_data *d) 58 87 { 59 88 u64 hwirq_id_bit = BIT_ULL(d->hwirq % 64); ··· 94 75 * Reference: I_ZLTKB/R_YRGMH GICv5 specification - section 2.9.1. 95 76 */ 96 77 isb(); 78 + } 79 + 80 + static void gicv5_iri_irq_mask(struct irq_data *d, u8 hwirq_type) 81 + { 82 + u64 cddis; 83 + 84 + cddis = FIELD_PREP(GICV5_GIC_CDDIS_ID_MASK, d->hwirq) | 85 + FIELD_PREP(GICV5_GIC_CDDIS_TYPE_MASK, hwirq_type); 86 + 87 + gic_insn(cddis, CDDIS); 88 + /* 89 + * We must make sure that GIC CDDIS write effects are propagated 90 + * immediately to make sure the disable takes effect to guarantee 91 + * that the lazy-disabled IRQ mechanism works. 92 + * Rule R_XCLJC states that the effects of a GIC system instruction 93 + * complete in finite time. 94 + * The GSB ensures completion of the GIC instruction and prevents 95 + * loads, stores and GIC instructions from executing part of their 96 + * functionality before the GSB SYS. 97 + */ 98 + gsb_sys(); 99 + } 100 + 101 + static void gicv5_spi_irq_mask(struct irq_data *d) 102 + { 103 + gicv5_iri_irq_mask(d, GICV5_HWIRQ_TYPE_SPI); 97 104 } 98 105 99 106 static void gicv5_ppi_irq_unmask(struct irq_data *d) ··· 140 95 isb(); 141 96 } 142 97 98 + static void gicv5_iri_irq_unmask(struct irq_data *d, u8 hwirq_type) 99 + { 100 + u64 cden; 101 + 102 + cden = FIELD_PREP(GICV5_GIC_CDEN_ID_MASK, d->hwirq) | 103 + FIELD_PREP(GICV5_GIC_CDEN_TYPE_MASK, hwirq_type); 104 + /* 105 + * Rule R_XCLJC states that the effects of a GIC system instruction 106 + * complete in finite time and that's the only requirement when 107 + * unmasking an SPI IRQ. 108 + */ 109 + gic_insn(cden, CDEN); 110 + } 111 + 112 + static void gicv5_spi_irq_unmask(struct irq_data *d) 113 + { 114 + gicv5_iri_irq_unmask(d, GICV5_HWIRQ_TYPE_SPI); 115 + } 116 + 143 117 static void gicv5_hwirq_eoi(u32 hwirq_id, u8 hwirq_type) 144 118 { 145 119 u64 cddi; ··· 174 110 static void gicv5_ppi_irq_eoi(struct irq_data *d) 175 111 { 176 112 gicv5_hwirq_eoi(d->hwirq, GICV5_HWIRQ_TYPE_PPI); 113 + } 114 + 115 + static void gicv5_spi_irq_eoi(struct irq_data *d) 116 + { 117 + gicv5_hwirq_eoi(d->hwirq, GICV5_HWIRQ_TYPE_SPI); 118 + } 119 + 120 + static int gicv5_iri_irq_set_affinity(struct irq_data *d, 121 + const struct cpumask *mask_val, 122 + bool force, u8 hwirq_type) 123 + { 124 + int ret, cpuid; 125 + u16 iaffid; 126 + u64 cdaff; 127 + 128 + if (force) 129 + cpuid = cpumask_first(mask_val); 130 + else 131 + cpuid = cpumask_any_and(mask_val, cpu_online_mask); 132 + 133 + ret = gicv5_irs_cpu_to_iaffid(cpuid, &iaffid); 134 + if (ret) 135 + return ret; 136 + 137 + cdaff = FIELD_PREP(GICV5_GIC_CDAFF_IAFFID_MASK, iaffid) | 138 + FIELD_PREP(GICV5_GIC_CDAFF_TYPE_MASK, hwirq_type) | 139 + FIELD_PREP(GICV5_GIC_CDAFF_ID_MASK, d->hwirq); 140 + gic_insn(cdaff, CDAFF); 141 + 142 + irq_data_update_effective_affinity(d, cpumask_of(cpuid)); 143 + 144 + return IRQ_SET_MASK_OK_DONE; 145 + } 146 + 147 + static int gicv5_spi_irq_set_affinity(struct irq_data *d, 148 + const struct cpumask *mask_val, 149 + bool force) 150 + { 151 + return gicv5_iri_irq_set_affinity(d, mask_val, force, 152 + GICV5_HWIRQ_TYPE_SPI); 177 153 } 178 154 179 155 enum ppi_reg { ··· 296 192 } 297 193 } 298 194 195 + static int gicv5_iri_irq_get_irqchip_state(struct irq_data *d, 196 + enum irqchip_irq_state which, 197 + bool *state, u8 hwirq_type) 198 + { 199 + u64 icsr, cdrcfg; 200 + 201 + cdrcfg = d->hwirq | FIELD_PREP(GICV5_GIC_CDRCFG_TYPE_MASK, hwirq_type); 202 + 203 + gic_insn(cdrcfg, CDRCFG); 204 + isb(); 205 + icsr = read_sysreg_s(SYS_ICC_ICSR_EL1); 206 + 207 + if (FIELD_GET(ICC_ICSR_EL1_F, icsr)) { 208 + pr_err("ICSR_EL1 is invalid\n"); 209 + return -EINVAL; 210 + } 211 + 212 + switch (which) { 213 + case IRQCHIP_STATE_PENDING: 214 + *state = !!(FIELD_GET(ICC_ICSR_EL1_Pending, icsr)); 215 + return 0; 216 + 217 + case IRQCHIP_STATE_ACTIVE: 218 + *state = !!(FIELD_GET(ICC_ICSR_EL1_Active, icsr)); 219 + return 0; 220 + 221 + default: 222 + pr_debug("Unexpected irqchip_irq_state\n"); 223 + return -EINVAL; 224 + } 225 + } 226 + 227 + static int gicv5_spi_irq_get_irqchip_state(struct irq_data *d, 228 + enum irqchip_irq_state which, 229 + bool *state) 230 + { 231 + return gicv5_iri_irq_get_irqchip_state(d, which, state, 232 + GICV5_HWIRQ_TYPE_SPI); 233 + } 234 + 299 235 static int gicv5_ppi_irq_set_irqchip_state(struct irq_data *d, 300 236 enum irqchip_irq_state which, 301 237 bool state) ··· 351 207 pr_debug("Unexpected PPI irqchip state\n"); 352 208 return -EINVAL; 353 209 } 210 + } 211 + 212 + static void gicv5_iri_irq_write_pending_state(struct irq_data *d, bool state, 213 + u8 hwirq_type) 214 + { 215 + u64 cdpend; 216 + 217 + cdpend = FIELD_PREP(GICV5_GIC_CDPEND_TYPE_MASK, hwirq_type) | 218 + FIELD_PREP(GICV5_GIC_CDPEND_ID_MASK, d->hwirq) | 219 + FIELD_PREP(GICV5_GIC_CDPEND_PENDING_MASK, state); 220 + 221 + gic_insn(cdpend, CDPEND); 222 + } 223 + 224 + static void gicv5_spi_irq_write_pending_state(struct irq_data *d, bool state) 225 + { 226 + gicv5_iri_irq_write_pending_state(d, state, GICV5_HWIRQ_TYPE_SPI); 227 + } 228 + 229 + static int gicv5_spi_irq_set_irqchip_state(struct irq_data *d, 230 + enum irqchip_irq_state which, 231 + bool state) 232 + { 233 + switch (which) { 234 + case IRQCHIP_STATE_PENDING: 235 + gicv5_spi_irq_write_pending_state(d, state); 236 + break; 237 + default: 238 + pr_debug("Unexpected irqchip_irq_state\n"); 239 + return -EINVAL; 240 + } 241 + 242 + return 0; 243 + } 244 + 245 + static int gicv5_spi_irq_retrigger(struct irq_data *data) 246 + { 247 + return !gicv5_spi_irq_set_irqchip_state(data, IRQCHIP_STATE_PENDING, 248 + true); 354 249 } 355 250 356 251 static bool gicv5_ppi_irq_is_level(irq_hw_number_t hwirq) ··· 410 227 IRQCHIP_MASK_ON_SUSPEND, 411 228 }; 412 229 413 - static int gicv5_irq_ppi_domain_translate(struct irq_domain *d, 414 - struct irq_fwspec *fwspec, 415 - irq_hw_number_t *hwirq, 416 - unsigned int *type) 230 + static const struct irq_chip gicv5_spi_irq_chip = { 231 + .name = "GICv5-SPI", 232 + .irq_mask = gicv5_spi_irq_mask, 233 + .irq_unmask = gicv5_spi_irq_unmask, 234 + .irq_eoi = gicv5_spi_irq_eoi, 235 + .irq_set_type = gicv5_spi_irq_set_type, 236 + .irq_set_affinity = gicv5_spi_irq_set_affinity, 237 + .irq_retrigger = gicv5_spi_irq_retrigger, 238 + .irq_get_irqchip_state = gicv5_spi_irq_get_irqchip_state, 239 + .irq_set_irqchip_state = gicv5_spi_irq_set_irqchip_state, 240 + .flags = IRQCHIP_SET_TYPE_MASKED | 241 + IRQCHIP_SKIP_SET_WAKE | 242 + IRQCHIP_MASK_ON_SUSPEND, 243 + }; 244 + 245 + static __always_inline int gicv5_irq_domain_translate(struct irq_domain *d, 246 + struct irq_fwspec *fwspec, 247 + irq_hw_number_t *hwirq, 248 + unsigned int *type, 249 + const u8 hwirq_type) 417 250 { 418 251 if (!is_of_node(fwspec->fwnode)) 419 252 return -EINVAL; ··· 437 238 if (fwspec->param_count < 3) 438 239 return -EINVAL; 439 240 440 - if (fwspec->param[0] != GICV5_HWIRQ_TYPE_PPI) 241 + if (fwspec->param[0] != hwirq_type) 441 242 return -EINVAL; 442 243 443 244 *hwirq = fwspec->param[1]; 444 245 445 - /* 446 - * Handling mode is hardcoded for PPIs, set the type using 447 - * HW reported value. 448 - */ 449 - *type = gicv5_ppi_irq_is_level(*hwirq) ? IRQ_TYPE_LEVEL_LOW : IRQ_TYPE_EDGE_RISING; 246 + switch (hwirq_type) { 247 + case GICV5_HWIRQ_TYPE_PPI: 248 + /* 249 + * Handling mode is hardcoded for PPIs, set the type using 250 + * HW reported value. 251 + */ 252 + *type = gicv5_ppi_irq_is_level(*hwirq) ? IRQ_TYPE_LEVEL_LOW : 253 + IRQ_TYPE_EDGE_RISING; 254 + break; 255 + case GICV5_HWIRQ_TYPE_SPI: 256 + *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; 257 + break; 258 + default: 259 + BUILD_BUG_ON(1); 260 + } 450 261 451 262 return 0; 263 + } 264 + 265 + static int gicv5_irq_ppi_domain_translate(struct irq_domain *d, 266 + struct irq_fwspec *fwspec, 267 + irq_hw_number_t *hwirq, 268 + unsigned int *type) 269 + { 270 + return gicv5_irq_domain_translate(d, fwspec, hwirq, type, 271 + GICV5_HWIRQ_TYPE_PPI); 452 272 } 453 273 454 274 static int gicv5_irq_ppi_domain_alloc(struct irq_domain *domain, unsigned int virq, ··· 528 310 .select = gicv5_irq_ppi_domain_select 529 311 }; 530 312 313 + static int gicv5_irq_spi_domain_translate(struct irq_domain *d, 314 + struct irq_fwspec *fwspec, 315 + irq_hw_number_t *hwirq, 316 + unsigned int *type) 317 + { 318 + return gicv5_irq_domain_translate(d, fwspec, hwirq, type, 319 + GICV5_HWIRQ_TYPE_SPI); 320 + } 321 + 322 + static int gicv5_irq_spi_domain_alloc(struct irq_domain *domain, unsigned int virq, 323 + unsigned int nr_irqs, void *arg) 324 + { 325 + struct gicv5_irs_chip_data *chip_data; 326 + unsigned int type = IRQ_TYPE_NONE; 327 + struct irq_fwspec *fwspec = arg; 328 + struct irq_data *irqd; 329 + irq_hw_number_t hwirq; 330 + int ret; 331 + 332 + if (WARN_ON_ONCE(nr_irqs != 1)) 333 + return -EINVAL; 334 + 335 + ret = gicv5_irq_spi_domain_translate(domain, fwspec, &hwirq, &type); 336 + if (ret) 337 + return ret; 338 + 339 + irqd = irq_desc_get_irq_data(irq_to_desc(virq)); 340 + chip_data = gicv5_irs_lookup_by_spi_id(hwirq); 341 + 342 + irq_domain_set_info(domain, virq, hwirq, &gicv5_spi_irq_chip, chip_data, 343 + handle_fasteoi_irq, NULL, NULL); 344 + irq_set_probe(virq); 345 + irqd_set_single_target(irqd); 346 + 347 + gicv5_hwirq_init(hwirq, GICV5_IRQ_PRI_MI, GICV5_HWIRQ_TYPE_SPI); 348 + 349 + return 0; 350 + } 351 + 352 + static int gicv5_irq_spi_domain_select(struct irq_domain *d, struct irq_fwspec *fwspec, 353 + enum irq_domain_bus_token bus_token) 354 + { 355 + if (fwspec->fwnode != d->fwnode) 356 + return 0; 357 + 358 + if (fwspec->param[0] != GICV5_HWIRQ_TYPE_SPI) 359 + return 0; 360 + 361 + return (d == gicv5_global_data.spi_domain); 362 + } 363 + 364 + static const struct irq_domain_ops gicv5_irq_spi_domain_ops = { 365 + .translate = gicv5_irq_spi_domain_translate, 366 + .alloc = gicv5_irq_spi_domain_alloc, 367 + .free = gicv5_irq_domain_free, 368 + .select = gicv5_irq_spi_domain_select 369 + }; 531 370 static void handle_irq_per_domain(u32 hwirq) 532 371 { 533 372 u8 hwirq_type = FIELD_GET(GICV5_HWIRQ_TYPE, hwirq); ··· 594 319 switch (hwirq_type) { 595 320 case GICV5_HWIRQ_TYPE_PPI: 596 321 domain = gicv5_global_data.ppi_domain; 322 + break; 323 + case GICV5_HWIRQ_TYPE_SPI: 324 + domain = gicv5_global_data.spi_domain; 597 325 break; 598 326 default: 599 327 pr_err_once("Unknown IRQ type, bail out\n"); ··· 670 392 671 393 gicv5_cpu_enable_interrupts(); 672 394 673 - return 0; 395 + return gicv5_irs_register_cpu(cpu); 674 396 } 675 397 676 398 static void __init gicv5_free_domains(void) 677 399 { 678 400 if (gicv5_global_data.ppi_domain) 679 401 irq_domain_remove(gicv5_global_data.ppi_domain); 402 + if (gicv5_global_data.spi_domain) 403 + irq_domain_remove(gicv5_global_data.spi_domain); 680 404 681 405 gicv5_global_data.ppi_domain = NULL; 406 + gicv5_global_data.spi_domain = NULL; 682 407 } 683 408 684 409 static int __init gicv5_init_domains(struct fwnode_handle *handle) 685 410 { 411 + u32 spi_count = gicv5_global_data.global_spi_count; 686 412 struct irq_domain *d; 687 413 688 414 d = irq_domain_create_linear(handle, PPI_NR, &gicv5_irq_ppi_domain_ops, NULL); ··· 695 413 696 414 irq_domain_update_bus_token(d, DOMAIN_BUS_WIRED); 697 415 gicv5_global_data.ppi_domain = d; 416 + 417 + if (spi_count) { 418 + d = irq_domain_create_linear(handle, spi_count, 419 + &gicv5_irq_spi_domain_ops, NULL); 420 + 421 + if (!d) { 422 + gicv5_free_domains(); 423 + return -ENOMEM; 424 + } 425 + 426 + gicv5_global_data.spi_domain = d; 427 + irq_domain_update_bus_token(d, DOMAIN_BUS_WIRED); 428 + } 429 + 698 430 gicv5_global_data.fwnode = handle; 699 431 700 432 return 0; ··· 720 424 721 425 switch (FIELD_GET(ICC_IDR0_EL1_PRI_BITS, icc_idr0)) { 722 426 case ICC_IDR0_EL1_PRI_BITS_4BITS: 723 - pri_bits = 4; 427 + gicv5_global_data.cpuif_pri_bits = 4; 724 428 break; 725 429 case ICC_IDR0_EL1_PRI_BITS_5BITS: 726 - pri_bits = 5; 430 + gicv5_global_data.cpuif_pri_bits = 5; 727 431 break; 728 432 default: 729 433 pr_err("Unexpected ICC_IDR0_EL1_PRI_BITS value, default to 4"); 730 - pri_bits = 4; 434 + gicv5_global_data.cpuif_pri_bits = 4; 731 435 break; 732 436 } 733 437 } 734 438 735 439 static int __init gicv5_of_init(struct device_node *node, struct device_node *parent) 736 440 { 737 - int ret = gicv5_init_domains(of_fwnode_handle(node)); 441 + int ret = gicv5_irs_of_probe(node); 738 442 if (ret) 739 443 return ret; 740 444 445 + ret = gicv5_init_domains(of_fwnode_handle(node)); 446 + if (ret) 447 + goto out_irs; 448 + 741 449 gicv5_set_cpuif_pribits(); 450 + 451 + pri_bits = min_not_zero(gicv5_global_data.cpuif_pri_bits, 452 + gicv5_global_data.irs_pri_bits); 742 453 743 454 ret = gicv5_starting_cpu(smp_processor_id()); 744 455 if (ret) ··· 761 458 gicv5_cpu_disable_interrupts(); 762 459 out_dom: 763 460 gicv5_free_domains(); 461 + out_irs: 462 + gicv5_irs_remove(); 764 463 765 464 return ret; 766 465 }
+140
include/linux/irqchip/arm-gic-v5.h
··· 5 5 #ifndef __LINUX_IRQCHIP_ARM_GIC_V5_H 6 6 #define __LINUX_IRQCHIP_ARM_GIC_V5_H 7 7 8 + #include <linux/iopoll.h> 9 + 8 10 #include <asm/sysreg.h> 9 11 10 12 /* ··· 17 15 #define GICV5_HWIRQ_INTID GENMASK_ULL(31, 0) 18 16 19 17 #define GICV5_HWIRQ_TYPE_PPI UL(0x1) 18 + #define GICV5_HWIRQ_TYPE_SPI UL(0x3) 20 19 20 + /* 21 + * Tables attributes 22 + */ 23 + #define GICV5_NO_READ_ALLOC 0b0 24 + #define GICV5_READ_ALLOC 0b1 25 + #define GICV5_NO_WRITE_ALLOC 0b0 26 + #define GICV5_WRITE_ALLOC 0b1 27 + 28 + #define GICV5_NON_CACHE 0b00 29 + #define GICV5_WB_CACHE 0b01 30 + #define GICV5_WT_CACHE 0b10 31 + 32 + #define GICV5_NON_SHARE 0b00 33 + #define GICV5_OUTER_SHARE 0b10 34 + #define GICV5_INNER_SHARE 0b11 35 + 36 + /* 37 + * IRS registers 38 + */ 39 + #define GICV5_IRS_IDR1 0x0004 40 + #define GICV5_IRS_IDR2 0x0008 41 + #define GICV5_IRS_IDR5 0x0014 42 + #define GICV5_IRS_IDR6 0x0018 43 + #define GICV5_IRS_IDR7 0x001c 44 + #define GICV5_IRS_CR0 0x0080 45 + #define GICV5_IRS_CR1 0x0084 46 + #define GICV5_IRS_SPI_SELR 0x0108 47 + #define GICV5_IRS_SPI_CFGR 0x0114 48 + #define GICV5_IRS_SPI_STATUSR 0x0118 49 + #define GICV5_IRS_PE_SELR 0x0140 50 + #define GICV5_IRS_PE_STATUSR 0x0144 51 + #define GICV5_IRS_PE_CR0 0x0148 52 + 53 + #define GICV5_IRS_IDR1_PRIORITY_BITS GENMASK(22, 20) 54 + #define GICV5_IRS_IDR1_IAFFID_BITS GENMASK(19, 16) 55 + 56 + #define GICV5_IRS_IDR1_PRIORITY_BITS_1BITS 0b000 57 + #define GICV5_IRS_IDR1_PRIORITY_BITS_2BITS 0b001 58 + #define GICV5_IRS_IDR1_PRIORITY_BITS_3BITS 0b010 59 + #define GICV5_IRS_IDR1_PRIORITY_BITS_4BITS 0b011 60 + #define GICV5_IRS_IDR1_PRIORITY_BITS_5BITS 0b100 61 + 62 + #define GICV5_IRS_IDR2_ISTMD_SZ GENMASK(19, 15) 63 + #define GICV5_IRS_IDR2_ISTMD BIT(14) 64 + #define GICV5_IRS_IDR2_IST_L2SZ GENMASK(13, 11) 65 + #define GICV5_IRS_IDR2_IST_LEVELS BIT(10) 66 + #define GICV5_IRS_IDR2_MIN_LPI_ID_BITS GENMASK(9, 6) 67 + #define GICV5_IRS_IDR2_LPI BIT(5) 68 + #define GICV5_IRS_IDR2_ID_BITS GENMASK(4, 0) 69 + 70 + #define GICV5_IRS_IDR5_SPI_RANGE GENMASK(24, 0) 71 + #define GICV5_IRS_IDR6_SPI_IRS_RANGE GENMASK(24, 0) 72 + #define GICV5_IRS_IDR7_SPI_BASE GENMASK(23, 0) 73 + #define GICV5_IRS_CR0_IDLE BIT(1) 74 + #define GICV5_IRS_CR0_IRSEN BIT(0) 75 + 76 + #define GICV5_IRS_CR1_VPED_WA BIT(15) 77 + #define GICV5_IRS_CR1_VPED_RA BIT(14) 78 + #define GICV5_IRS_CR1_VMD_WA BIT(13) 79 + #define GICV5_IRS_CR1_VMD_RA BIT(12) 80 + #define GICV5_IRS_CR1_VPET_WA BIT(11) 81 + #define GICV5_IRS_CR1_VPET_RA BIT(10) 82 + #define GICV5_IRS_CR1_VMT_WA BIT(9) 83 + #define GICV5_IRS_CR1_VMT_RA BIT(8) 84 + #define GICV5_IRS_CR1_IST_WA BIT(7) 85 + #define GICV5_IRS_CR1_IST_RA BIT(6) 86 + #define GICV5_IRS_CR1_IC GENMASK(5, 4) 87 + #define GICV5_IRS_CR1_OC GENMASK(3, 2) 88 + #define GICV5_IRS_CR1_SH GENMASK(1, 0) 89 + 90 + #define GICV5_IRS_SPI_STATUSR_V BIT(1) 91 + #define GICV5_IRS_SPI_STATUSR_IDLE BIT(0) 92 + 93 + #define GICV5_IRS_SPI_SELR_ID GENMASK(23, 0) 94 + 95 + #define GICV5_IRS_SPI_CFGR_TM BIT(0) 96 + 97 + #define GICV5_IRS_PE_SELR_IAFFID GENMASK(15, 0) 98 + 99 + #define GICV5_IRS_PE_STATUSR_V BIT(1) 100 + #define GICV5_IRS_PE_STATUSR_IDLE BIT(0) 101 + 102 + #define GICV5_IRS_PE_CR0_DPS BIT(0) 103 + 104 + /* 105 + * Global Data structures and functions 106 + */ 107 + struct gicv5_chip_data { 108 + struct fwnode_handle *fwnode; 109 + struct irq_domain *ppi_domain; 110 + struct irq_domain *spi_domain; 111 + u32 global_spi_count; 112 + u8 cpuif_pri_bits; 113 + u8 irs_pri_bits; 114 + }; 115 + 116 + extern struct gicv5_chip_data gicv5_global_data __read_mostly; 117 + 118 + struct gicv5_irs_chip_data { 119 + struct list_head entry; 120 + struct fwnode_handle *fwnode; 121 + void __iomem *irs_base; 122 + u32 flags; 123 + u32 spi_min; 124 + u32 spi_range; 125 + raw_spinlock_t spi_config_lock; 126 + }; 127 + 128 + static inline int gicv5_wait_for_op_s_atomic(void __iomem *addr, u32 offset, 129 + const char *reg_s, u32 mask, 130 + u32 *val) 131 + { 132 + void __iomem *reg = addr + offset; 133 + u32 tmp; 134 + int ret; 135 + 136 + ret = readl_poll_timeout_atomic(reg, tmp, tmp & mask, 1, 10 * USEC_PER_MSEC); 137 + if (unlikely(ret == -ETIMEDOUT)) { 138 + pr_err_ratelimited("%s timeout...\n", reg_s); 139 + return ret; 140 + } 141 + 142 + if (val) 143 + *val = tmp; 144 + 145 + return 0; 146 + } 147 + 148 + #define gicv5_wait_for_op_atomic(base, reg, mask, val) \ 149 + gicv5_wait_for_op_s_atomic(base, reg, #reg, mask, val) 150 + 151 + int gicv5_irs_of_probe(struct device_node *parent); 152 + void gicv5_irs_remove(void); 153 + int gicv5_irs_register_cpu(int cpuid); 154 + int gicv5_irs_cpu_to_iaffid(int cpu_id, u16 *iaffid); 155 + struct gicv5_irs_chip_data *gicv5_irs_lookup_by_spi_id(u32 spi_id); 156 + int gicv5_spi_irq_set_type(struct irq_data *d, unsigned int type); 21 157 #endif