1ac4a67b6SAndrew Jones /* 2ac4a67b6SAndrew Jones * GIC tests 3ac4a67b6SAndrew Jones * 4ac4a67b6SAndrew Jones * GICv2 5ac4a67b6SAndrew Jones * + test sending/receiving IPIs 6*78ad7e95SAndre Przywara * + MMIO access tests 72e2d471dSAndrew Jones * GICv3 82e2d471dSAndrew Jones * + test sending/receiving IPIs 9ac4a67b6SAndrew Jones * 10ac4a67b6SAndrew Jones * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 11ac4a67b6SAndrew Jones * 12ac4a67b6SAndrew Jones * This work is licensed under the terms of the GNU LGPL, version 2. 13ac4a67b6SAndrew Jones */ 14ac4a67b6SAndrew Jones #include <libcflat.h> 15ac4a67b6SAndrew Jones #include <asm/setup.h> 16ac4a67b6SAndrew Jones #include <asm/processor.h> 17ac4a67b6SAndrew Jones #include <asm/delay.h> 18ac4a67b6SAndrew Jones #include <asm/gic.h> 19ac4a67b6SAndrew Jones #include <asm/smp.h> 20ac4a67b6SAndrew Jones #include <asm/barrier.h> 21ac4a67b6SAndrew Jones #include <asm/io.h> 22ac4a67b6SAndrew Jones 23ca1b7a7bSAndrew Jones #define IPI_SENDER 1 24ca1b7a7bSAndrew Jones #define IPI_IRQ 1 25ca1b7a7bSAndrew Jones 262e2d471dSAndrew Jones struct gic { 272e2d471dSAndrew Jones struct { 282e2d471dSAndrew Jones void (*send_self)(void); 292e2d471dSAndrew Jones void (*send_broadcast)(void); 302e2d471dSAndrew Jones } ipi; 312e2d471dSAndrew Jones }; 322e2d471dSAndrew Jones 332e2d471dSAndrew Jones static struct gic *gic; 34ac4a67b6SAndrew Jones static int acked[NR_CPUS], spurious[NR_CPUS]; 35ca1b7a7bSAndrew Jones static int bad_sender[NR_CPUS], bad_irq[NR_CPUS]; 36ac4a67b6SAndrew Jones static cpumask_t ready; 37ac4a67b6SAndrew Jones 38ac4a67b6SAndrew Jones static void nr_cpu_check(int nr) 39ac4a67b6SAndrew Jones { 40ac4a67b6SAndrew Jones if (nr_cpus < nr) 41ac4a67b6SAndrew Jones report_abort("At least %d cpus required", nr); 42ac4a67b6SAndrew Jones } 43ac4a67b6SAndrew Jones 44ac4a67b6SAndrew Jones static void wait_on_ready(void) 45ac4a67b6SAndrew Jones { 46ac4a67b6SAndrew Jones cpumask_set_cpu(smp_processor_id(), &ready); 47ac4a67b6SAndrew Jones while (!cpumask_full(&ready)) 48ac4a67b6SAndrew Jones cpu_relax(); 49ac4a67b6SAndrew Jones } 50ac4a67b6SAndrew Jones 51ca1b7a7bSAndrew Jones static void stats_reset(void) 52ca1b7a7bSAndrew Jones { 53ca1b7a7bSAndrew Jones int i; 54ca1b7a7bSAndrew Jones 55ca1b7a7bSAndrew Jones for (i = 0; i < nr_cpus; ++i) { 56ca1b7a7bSAndrew Jones acked[i] = 0; 57ca1b7a7bSAndrew Jones bad_sender[i] = -1; 58ca1b7a7bSAndrew Jones bad_irq[i] = -1; 59ca1b7a7bSAndrew Jones } 60ca1b7a7bSAndrew Jones smp_wmb(); 61ca1b7a7bSAndrew Jones } 62ca1b7a7bSAndrew Jones 63ac4a67b6SAndrew Jones static void check_acked(cpumask_t *mask) 64ac4a67b6SAndrew Jones { 65ac4a67b6SAndrew Jones int missing = 0, extra = 0, unexpected = 0; 66ac4a67b6SAndrew Jones int nr_pass, cpu, i; 67ca1b7a7bSAndrew Jones bool bad = false; 68ac4a67b6SAndrew Jones 69ac4a67b6SAndrew Jones /* Wait up to 5s for all interrupts to be delivered */ 70ac4a67b6SAndrew Jones for (i = 0; i < 50; ++i) { 71ac4a67b6SAndrew Jones mdelay(100); 72ac4a67b6SAndrew Jones nr_pass = 0; 73ac4a67b6SAndrew Jones for_each_present_cpu(cpu) { 74ac4a67b6SAndrew Jones smp_rmb(); 75ac4a67b6SAndrew Jones nr_pass += cpumask_test_cpu(cpu, mask) ? 76ac4a67b6SAndrew Jones acked[cpu] == 1 : acked[cpu] == 0; 77ca1b7a7bSAndrew Jones 78ca1b7a7bSAndrew Jones if (bad_sender[cpu] != -1) { 79ca1b7a7bSAndrew Jones printf("cpu%d received IPI from wrong sender %d\n", 80ca1b7a7bSAndrew Jones cpu, bad_sender[cpu]); 81ca1b7a7bSAndrew Jones bad = true; 82ca1b7a7bSAndrew Jones } 83ca1b7a7bSAndrew Jones 84ca1b7a7bSAndrew Jones if (bad_irq[cpu] != -1) { 85ca1b7a7bSAndrew Jones printf("cpu%d received wrong irq %d\n", 86ca1b7a7bSAndrew Jones cpu, bad_irq[cpu]); 87ca1b7a7bSAndrew Jones bad = true; 88ca1b7a7bSAndrew Jones } 89ac4a67b6SAndrew Jones } 90ac4a67b6SAndrew Jones if (nr_pass == nr_cpus) { 91ca1b7a7bSAndrew Jones report("Completed in %d ms", !bad, ++i * 100); 92ac4a67b6SAndrew Jones return; 93ac4a67b6SAndrew Jones } 94ac4a67b6SAndrew Jones } 95ac4a67b6SAndrew Jones 96ac4a67b6SAndrew Jones for_each_present_cpu(cpu) { 97ac4a67b6SAndrew Jones if (cpumask_test_cpu(cpu, mask)) { 98ac4a67b6SAndrew Jones if (!acked[cpu]) 99ac4a67b6SAndrew Jones ++missing; 100ac4a67b6SAndrew Jones else if (acked[cpu] > 1) 101ac4a67b6SAndrew Jones ++extra; 102ac4a67b6SAndrew Jones } else { 103ac4a67b6SAndrew Jones if (acked[cpu]) 104ac4a67b6SAndrew Jones ++unexpected; 105ac4a67b6SAndrew Jones } 106ac4a67b6SAndrew Jones } 107ac4a67b6SAndrew Jones 108ac4a67b6SAndrew Jones report("Timed-out (5s). ACKS: missing=%d extra=%d unexpected=%d", 109ac4a67b6SAndrew Jones false, missing, extra, unexpected); 110ac4a67b6SAndrew Jones } 111ac4a67b6SAndrew Jones 112ac4a67b6SAndrew Jones static void check_spurious(void) 113ac4a67b6SAndrew Jones { 114ac4a67b6SAndrew Jones int cpu; 115ac4a67b6SAndrew Jones 116ac4a67b6SAndrew Jones smp_rmb(); 117ac4a67b6SAndrew Jones for_each_present_cpu(cpu) { 118ac4a67b6SAndrew Jones if (spurious[cpu]) 119ac4a67b6SAndrew Jones report_info("WARN: cpu%d got %d spurious interrupts", 120ac4a67b6SAndrew Jones cpu, spurious[cpu]); 121ac4a67b6SAndrew Jones } 122ac4a67b6SAndrew Jones } 123ac4a67b6SAndrew Jones 124ca1b7a7bSAndrew Jones static void check_ipi_sender(u32 irqstat) 125ca1b7a7bSAndrew Jones { 126ca1b7a7bSAndrew Jones if (gic_version() == 2) { 127ca1b7a7bSAndrew Jones int src = (irqstat >> 10) & 7; 128ca1b7a7bSAndrew Jones 129ca1b7a7bSAndrew Jones if (src != IPI_SENDER) 130ca1b7a7bSAndrew Jones bad_sender[smp_processor_id()] = src; 131ca1b7a7bSAndrew Jones } 132ca1b7a7bSAndrew Jones } 133ca1b7a7bSAndrew Jones 134ca1b7a7bSAndrew Jones static void check_irqnr(u32 irqnr) 135ca1b7a7bSAndrew Jones { 136ca1b7a7bSAndrew Jones if (irqnr != IPI_IRQ) 137ca1b7a7bSAndrew Jones bad_irq[smp_processor_id()] = irqnr; 138ca1b7a7bSAndrew Jones } 139ca1b7a7bSAndrew Jones 140ac4a67b6SAndrew Jones static void ipi_handler(struct pt_regs *regs __unused) 141ac4a67b6SAndrew Jones { 1422e2d471dSAndrew Jones u32 irqstat = gic_read_iar(); 1432e2d471dSAndrew Jones u32 irqnr = gic_iar_irqnr(irqstat); 144ac4a67b6SAndrew Jones 145ac4a67b6SAndrew Jones if (irqnr != GICC_INT_SPURIOUS) { 1462e2d471dSAndrew Jones gic_write_eoir(irqstat); 147ca1b7a7bSAndrew Jones smp_rmb(); /* pairs with wmb in stats_reset */ 148ac4a67b6SAndrew Jones ++acked[smp_processor_id()]; 149ca1b7a7bSAndrew Jones check_ipi_sender(irqstat); 150ca1b7a7bSAndrew Jones check_irqnr(irqnr); 151ac4a67b6SAndrew Jones smp_wmb(); /* pairs with rmb in check_acked */ 152ac4a67b6SAndrew Jones } else { 153ac4a67b6SAndrew Jones ++spurious[smp_processor_id()]; 154ac4a67b6SAndrew Jones smp_wmb(); 155ac4a67b6SAndrew Jones } 156ac4a67b6SAndrew Jones } 157ac4a67b6SAndrew Jones 1582e2d471dSAndrew Jones static void gicv2_ipi_send_self(void) 1592e2d471dSAndrew Jones { 160ca1b7a7bSAndrew Jones writel(2 << 24 | IPI_IRQ, gicv2_dist_base() + GICD_SGIR); 1612e2d471dSAndrew Jones } 1622e2d471dSAndrew Jones 1632e2d471dSAndrew Jones static void gicv2_ipi_send_broadcast(void) 1642e2d471dSAndrew Jones { 165ca1b7a7bSAndrew Jones writel(1 << 24 | IPI_IRQ, gicv2_dist_base() + GICD_SGIR); 1662e2d471dSAndrew Jones } 1672e2d471dSAndrew Jones 1682e2d471dSAndrew Jones static void gicv3_ipi_send_self(void) 1692e2d471dSAndrew Jones { 170ca1b7a7bSAndrew Jones gic_ipi_send_single(IPI_IRQ, smp_processor_id()); 1712e2d471dSAndrew Jones } 1722e2d471dSAndrew Jones 1732e2d471dSAndrew Jones static void gicv3_ipi_send_broadcast(void) 1742e2d471dSAndrew Jones { 175ca1b7a7bSAndrew Jones gicv3_write_sgi1r(1ULL << 40 | IPI_IRQ << 24); 1762e2d471dSAndrew Jones isb(); 1772e2d471dSAndrew Jones } 1782e2d471dSAndrew Jones 179ac4a67b6SAndrew Jones static void ipi_test_self(void) 180ac4a67b6SAndrew Jones { 181ac4a67b6SAndrew Jones cpumask_t mask; 182ac4a67b6SAndrew Jones 183ac4a67b6SAndrew Jones report_prefix_push("self"); 184ca1b7a7bSAndrew Jones stats_reset(); 185ac4a67b6SAndrew Jones cpumask_clear(&mask); 186ca1b7a7bSAndrew Jones cpumask_set_cpu(smp_processor_id(), &mask); 1872e2d471dSAndrew Jones gic->ipi.send_self(); 188ac4a67b6SAndrew Jones check_acked(&mask); 189ac4a67b6SAndrew Jones report_prefix_pop(); 190ac4a67b6SAndrew Jones } 191ac4a67b6SAndrew Jones 192ac4a67b6SAndrew Jones static void ipi_test_smp(void) 193ac4a67b6SAndrew Jones { 194ac4a67b6SAndrew Jones cpumask_t mask; 1952e2d471dSAndrew Jones int i; 196ac4a67b6SAndrew Jones 197ac4a67b6SAndrew Jones report_prefix_push("target-list"); 198ca1b7a7bSAndrew Jones stats_reset(); 1992e2d471dSAndrew Jones cpumask_copy(&mask, &cpu_present_mask); 200ca1b7a7bSAndrew Jones for (i = smp_processor_id() & 1; i < nr_cpus; i += 2) 2012e2d471dSAndrew Jones cpumask_clear_cpu(i, &mask); 202ca1b7a7bSAndrew Jones gic_ipi_send_mask(IPI_IRQ, &mask); 203ac4a67b6SAndrew Jones check_acked(&mask); 204ac4a67b6SAndrew Jones report_prefix_pop(); 205ac4a67b6SAndrew Jones 206ac4a67b6SAndrew Jones report_prefix_push("broadcast"); 207ca1b7a7bSAndrew Jones stats_reset(); 208ac4a67b6SAndrew Jones cpumask_copy(&mask, &cpu_present_mask); 209ca1b7a7bSAndrew Jones cpumask_clear_cpu(smp_processor_id(), &mask); 2102e2d471dSAndrew Jones gic->ipi.send_broadcast(); 211ac4a67b6SAndrew Jones check_acked(&mask); 212ac4a67b6SAndrew Jones report_prefix_pop(); 213ac4a67b6SAndrew Jones } 214ac4a67b6SAndrew Jones 215ac4a67b6SAndrew Jones static void ipi_enable(void) 216ac4a67b6SAndrew Jones { 2172e2d471dSAndrew Jones gic_enable_defaults(); 218ac4a67b6SAndrew Jones #ifdef __arm__ 219ac4a67b6SAndrew Jones install_exception_handler(EXCPTN_IRQ, ipi_handler); 220ac4a67b6SAndrew Jones #else 221ac4a67b6SAndrew Jones install_irq_handler(EL1H_IRQ, ipi_handler); 222ac4a67b6SAndrew Jones #endif 223ac4a67b6SAndrew Jones local_irq_enable(); 224ac4a67b6SAndrew Jones } 225ac4a67b6SAndrew Jones 226ca1b7a7bSAndrew Jones static void ipi_send(void) 227ca1b7a7bSAndrew Jones { 228ca1b7a7bSAndrew Jones ipi_enable(); 229ca1b7a7bSAndrew Jones wait_on_ready(); 230ca1b7a7bSAndrew Jones ipi_test_self(); 231ca1b7a7bSAndrew Jones ipi_test_smp(); 232ca1b7a7bSAndrew Jones check_spurious(); 233ca1b7a7bSAndrew Jones exit(report_summary()); 234ca1b7a7bSAndrew Jones } 235ca1b7a7bSAndrew Jones 236ac4a67b6SAndrew Jones static void ipi_recv(void) 237ac4a67b6SAndrew Jones { 238ac4a67b6SAndrew Jones ipi_enable(); 239ac4a67b6SAndrew Jones cpumask_set_cpu(smp_processor_id(), &ready); 240ac4a67b6SAndrew Jones while (1) 241ac4a67b6SAndrew Jones wfi(); 242ac4a67b6SAndrew Jones } 243ac4a67b6SAndrew Jones 24400b34f56SAndrew Jones static void ipi_test(void *data __unused) 245bfd500b4SAndrew Jones { 246bfd500b4SAndrew Jones if (smp_processor_id() == IPI_SENDER) 247bfd500b4SAndrew Jones ipi_send(); 248bfd500b4SAndrew Jones else 249bfd500b4SAndrew Jones ipi_recv(); 250bfd500b4SAndrew Jones } 251bfd500b4SAndrew Jones 2522e2d471dSAndrew Jones static struct gic gicv2 = { 2532e2d471dSAndrew Jones .ipi = { 2542e2d471dSAndrew Jones .send_self = gicv2_ipi_send_self, 2552e2d471dSAndrew Jones .send_broadcast = gicv2_ipi_send_broadcast, 2562e2d471dSAndrew Jones }, 2572e2d471dSAndrew Jones }; 2582e2d471dSAndrew Jones 2592e2d471dSAndrew Jones static struct gic gicv3 = { 2602e2d471dSAndrew Jones .ipi = { 2612e2d471dSAndrew Jones .send_self = gicv3_ipi_send_self, 2622e2d471dSAndrew Jones .send_broadcast = gicv3_ipi_send_broadcast, 2632e2d471dSAndrew Jones }, 2642e2d471dSAndrew Jones }; 2652e2d471dSAndrew Jones 266c152d8bcSChristoffer Dall static void ipi_clear_active_handler(struct pt_regs *regs __unused) 267c152d8bcSChristoffer Dall { 268c152d8bcSChristoffer Dall u32 irqstat = gic_read_iar(); 269c152d8bcSChristoffer Dall u32 irqnr = gic_iar_irqnr(irqstat); 270c152d8bcSChristoffer Dall 271c152d8bcSChristoffer Dall if (irqnr != GICC_INT_SPURIOUS) { 272c152d8bcSChristoffer Dall void *base; 273c152d8bcSChristoffer Dall u32 val = 1 << IPI_IRQ; 274c152d8bcSChristoffer Dall 275c152d8bcSChristoffer Dall if (gic_version() == 2) 276c152d8bcSChristoffer Dall base = gicv2_dist_base(); 277c152d8bcSChristoffer Dall else 2786d4d7c4bSAndrew Jones base = gicv3_sgi_base(); 279c152d8bcSChristoffer Dall 280c152d8bcSChristoffer Dall writel(val, base + GICD_ICACTIVER); 281c152d8bcSChristoffer Dall 282c152d8bcSChristoffer Dall smp_rmb(); /* pairs with wmb in stats_reset */ 283c152d8bcSChristoffer Dall ++acked[smp_processor_id()]; 284c152d8bcSChristoffer Dall check_irqnr(irqnr); 285c152d8bcSChristoffer Dall smp_wmb(); /* pairs with rmb in check_acked */ 286c152d8bcSChristoffer Dall } else { 287c152d8bcSChristoffer Dall ++spurious[smp_processor_id()]; 288c152d8bcSChristoffer Dall smp_wmb(); 289c152d8bcSChristoffer Dall } 290c152d8bcSChristoffer Dall } 291c152d8bcSChristoffer Dall 292c152d8bcSChristoffer Dall static void run_active_clear_test(void) 293c152d8bcSChristoffer Dall { 294c152d8bcSChristoffer Dall report_prefix_push("active"); 295c152d8bcSChristoffer Dall gic_enable_defaults(); 296c152d8bcSChristoffer Dall #ifdef __arm__ 297c152d8bcSChristoffer Dall install_exception_handler(EXCPTN_IRQ, ipi_clear_active_handler); 298c152d8bcSChristoffer Dall #else 299c152d8bcSChristoffer Dall install_irq_handler(EL1H_IRQ, ipi_clear_active_handler); 300c152d8bcSChristoffer Dall #endif 301c152d8bcSChristoffer Dall local_irq_enable(); 302c152d8bcSChristoffer Dall 303c152d8bcSChristoffer Dall ipi_test_self(); 304c152d8bcSChristoffer Dall report_prefix_pop(); 305c152d8bcSChristoffer Dall } 306c152d8bcSChristoffer Dall 307*78ad7e95SAndre Przywara static bool test_ro_pattern_32(void *address, u32 pattern, u32 orig) 308*78ad7e95SAndre Przywara { 309*78ad7e95SAndre Przywara u32 reg; 310*78ad7e95SAndre Przywara 311*78ad7e95SAndre Przywara writel(pattern, address); 312*78ad7e95SAndre Przywara reg = readl(address); 313*78ad7e95SAndre Przywara 314*78ad7e95SAndre Przywara if (reg != orig) 315*78ad7e95SAndre Przywara writel(orig, address); 316*78ad7e95SAndre Przywara 317*78ad7e95SAndre Przywara return reg == orig; 318*78ad7e95SAndre Przywara } 319*78ad7e95SAndre Przywara 320*78ad7e95SAndre Przywara static bool test_readonly_32(void *address, bool razwi) 321*78ad7e95SAndre Przywara { 322*78ad7e95SAndre Przywara u32 orig, pattern; 323*78ad7e95SAndre Przywara 324*78ad7e95SAndre Przywara orig = readl(address); 325*78ad7e95SAndre Przywara if (razwi && orig) 326*78ad7e95SAndre Przywara return false; 327*78ad7e95SAndre Przywara 328*78ad7e95SAndre Przywara pattern = 0xffffffff; 329*78ad7e95SAndre Przywara if (orig != pattern) { 330*78ad7e95SAndre Przywara if (!test_ro_pattern_32(address, pattern, orig)) 331*78ad7e95SAndre Przywara return false; 332*78ad7e95SAndre Przywara } 333*78ad7e95SAndre Przywara 334*78ad7e95SAndre Przywara pattern = 0xa5a55a5a; 335*78ad7e95SAndre Przywara if (orig != pattern) { 336*78ad7e95SAndre Przywara if (!test_ro_pattern_32(address, pattern, orig)) 337*78ad7e95SAndre Przywara return false; 338*78ad7e95SAndre Przywara } 339*78ad7e95SAndre Przywara 340*78ad7e95SAndre Przywara pattern = 0; 341*78ad7e95SAndre Przywara if (orig != pattern) { 342*78ad7e95SAndre Przywara if (!test_ro_pattern_32(address, pattern, orig)) 343*78ad7e95SAndre Przywara return false; 344*78ad7e95SAndre Przywara } 345*78ad7e95SAndre Przywara 346*78ad7e95SAndre Przywara return true; 347*78ad7e95SAndre Przywara } 348*78ad7e95SAndre Przywara 349*78ad7e95SAndre Przywara static void test_typer_v2(uint32_t reg) 350*78ad7e95SAndre Przywara { 351*78ad7e95SAndre Przywara int nr_gic_cpus = ((reg >> 5) & 0x7) + 1; 352*78ad7e95SAndre Przywara 353*78ad7e95SAndre Przywara report("all %d CPUs have interrupts", nr_cpus == nr_gic_cpus, 354*78ad7e95SAndre Przywara nr_gic_cpus); 355*78ad7e95SAndre Przywara } 356*78ad7e95SAndre Przywara 357*78ad7e95SAndre Przywara static void gic_test_mmio(void) 358*78ad7e95SAndre Przywara { 359*78ad7e95SAndre Przywara u32 reg; 360*78ad7e95SAndre Przywara int nr_irqs; 361*78ad7e95SAndre Przywara void *gic_dist_base, *idreg; 362*78ad7e95SAndre Przywara 363*78ad7e95SAndre Przywara switch(gic_version()) { 364*78ad7e95SAndre Przywara case 0x2: 365*78ad7e95SAndre Przywara gic_dist_base = gicv2_dist_base(); 366*78ad7e95SAndre Przywara idreg = gic_dist_base + GICD_ICPIDR2; 367*78ad7e95SAndre Przywara break; 368*78ad7e95SAndre Przywara case 0x3: 369*78ad7e95SAndre Przywara report_abort("GICv3 MMIO tests NYI"); 370*78ad7e95SAndre Przywara default: 371*78ad7e95SAndre Przywara report_abort("GIC version %d not supported", gic_version()); 372*78ad7e95SAndre Przywara } 373*78ad7e95SAndre Przywara 374*78ad7e95SAndre Przywara reg = readl(gic_dist_base + GICD_TYPER); 375*78ad7e95SAndre Przywara nr_irqs = GICD_TYPER_IRQS(reg); 376*78ad7e95SAndre Przywara report_info("number of implemented SPIs: %d", nr_irqs - GIC_FIRST_SPI); 377*78ad7e95SAndre Przywara 378*78ad7e95SAndre Przywara test_typer_v2(reg); 379*78ad7e95SAndre Przywara 380*78ad7e95SAndre Przywara report_info("IIDR: 0x%08x", readl(gic_dist_base + GICD_IIDR)); 381*78ad7e95SAndre Przywara 382*78ad7e95SAndre Przywara report("GICD_TYPER is read-only", 383*78ad7e95SAndre Przywara test_readonly_32(gic_dist_base + GICD_TYPER, false)); 384*78ad7e95SAndre Przywara report("GICD_IIDR is read-only", 385*78ad7e95SAndre Przywara test_readonly_32(gic_dist_base + GICD_IIDR, false)); 386*78ad7e95SAndre Przywara 387*78ad7e95SAndre Przywara reg = readl(idreg); 388*78ad7e95SAndre Przywara report("ICPIDR2 is read-only (0x%08x)", 389*78ad7e95SAndre Przywara test_readonly_32(idreg, false), 390*78ad7e95SAndre Przywara reg); 391*78ad7e95SAndre Przywara } 392*78ad7e95SAndre Przywara 393ac4a67b6SAndrew Jones int main(int argc, char **argv) 394ac4a67b6SAndrew Jones { 3952e2d471dSAndrew Jones if (!gic_init()) { 396ac4a67b6SAndrew Jones printf("No supported gic present, skipping tests...\n"); 397ac4a67b6SAndrew Jones return report_summary(); 398ac4a67b6SAndrew Jones } 399ac4a67b6SAndrew Jones 4002b19b829SAndrew Jones report_prefix_pushf("gicv%d", gic_version()); 401ac4a67b6SAndrew Jones 4022e2d471dSAndrew Jones switch (gic_version()) { 4032e2d471dSAndrew Jones case 2: 4042e2d471dSAndrew Jones gic = &gicv2; 4052e2d471dSAndrew Jones break; 4062e2d471dSAndrew Jones case 3: 4072e2d471dSAndrew Jones gic = &gicv3; 4082e2d471dSAndrew Jones break; 4092e2d471dSAndrew Jones } 4102e2d471dSAndrew Jones 411ac4a67b6SAndrew Jones if (argc < 2) 412ac4a67b6SAndrew Jones report_abort("no test specified"); 413ac4a67b6SAndrew Jones 414ac4a67b6SAndrew Jones if (strcmp(argv[1], "ipi") == 0) { 415ac4a67b6SAndrew Jones report_prefix_push(argv[1]); 416ac4a67b6SAndrew Jones nr_cpu_check(2); 41700b34f56SAndrew Jones on_cpus(ipi_test, NULL); 418c152d8bcSChristoffer Dall } else if (strcmp(argv[1], "active") == 0) { 419c152d8bcSChristoffer Dall run_active_clear_test(); 420*78ad7e95SAndre Przywara } else if (strcmp(argv[1], "mmio") == 0) { 421*78ad7e95SAndre Przywara report_prefix_push(argv[1]); 422*78ad7e95SAndre Przywara gic_test_mmio(); 423*78ad7e95SAndre Przywara report_prefix_pop(); 424ac4a67b6SAndrew Jones } else { 425ac4a67b6SAndrew Jones report_abort("Unknown subtest '%s'", argv[1]); 426ac4a67b6SAndrew Jones } 427ac4a67b6SAndrew Jones 428ac4a67b6SAndrew Jones return report_summary(); 429ac4a67b6SAndrew Jones } 430