1 /* 2 * Verify PL031 functionality 3 * 4 * This test verifies whether the emulated PL031 behaves correctly. 5 * 6 * Copyright 2019 Amazon.com, Inc. or its affiliates. 7 * Author: Alexander Graf <graf@amazon.com> 8 * 9 * This work is licensed under the terms of the GNU LGPL, version 2. 10 */ 11 #include <libcflat.h> 12 #include <devicetree.h> 13 #include <asm/processor.h> 14 #include <asm/io.h> 15 #include <asm/gic.h> 16 17 struct pl031_regs { 18 uint32_t dr; /* Data Register */ 19 uint32_t mr; /* Match Register */ 20 uint32_t lr; /* Load Register */ 21 union { 22 uint8_t cr; /* Control Register */ 23 uint32_t cr32; 24 }; 25 union { 26 uint8_t imsc; /* Interrupt Mask Set or Clear register */ 27 uint32_t imsc32; 28 }; 29 union { 30 uint8_t ris; /* Raw Interrupt Status */ 31 uint32_t ris32; 32 }; 33 union { 34 uint8_t mis; /* Masked Interrupt Status */ 35 uint32_t mis32; 36 }; 37 union { 38 uint8_t icr; /* Interrupt Clear Register */ 39 uint32_t icr32; 40 }; 41 uint32_t reserved[1008]; 42 uint32_t periph_id[4]; 43 uint32_t pcell_id[4]; 44 }; 45 46 static u32 cntfrq; 47 static struct pl031_regs *pl031; 48 static int pl031_irq; 49 static void *gic_ispendr; 50 static void *gic_isenabler; 51 static volatile bool irq_triggered; 52 53 static int check_id(void) 54 { 55 uint32_t id[] = { 0x31, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; 56 int i; 57 58 for (i = 0; i < ARRAY_SIZE(id); i++) 59 if (id[i] != readl(&pl031->periph_id[i])) 60 return 1; 61 62 return 0; 63 } 64 65 static int check_ro(void) 66 { 67 uint32_t offs[] = { offsetof(struct pl031_regs, ris), 68 offsetof(struct pl031_regs, mis), 69 offsetof(struct pl031_regs, periph_id[0]), 70 offsetof(struct pl031_regs, periph_id[1]), 71 offsetof(struct pl031_regs, periph_id[2]), 72 offsetof(struct pl031_regs, periph_id[3]), 73 offsetof(struct pl031_regs, pcell_id[0]), 74 offsetof(struct pl031_regs, pcell_id[1]), 75 offsetof(struct pl031_regs, pcell_id[2]), 76 offsetof(struct pl031_regs, pcell_id[3]) }; 77 int i; 78 79 for (i = 0; i < ARRAY_SIZE(offs); i++) { 80 uint32_t before32; 81 uint16_t before16; 82 uint8_t before8; 83 void *addr = (void*)pl031 + offs[i]; 84 uint32_t poison = 0xdeadbeefULL; 85 86 before8 = readb(addr); 87 before16 = readw(addr); 88 before32 = readl(addr); 89 90 writeb(poison, addr); 91 writew(poison, addr); 92 writel(poison, addr); 93 94 if (before8 != readb(addr)) 95 return 1; 96 if (before16 != readw(addr)) 97 return 1; 98 if (before32 != readl(addr)) 99 return 1; 100 } 101 102 return 0; 103 } 104 105 static int check_rtc_freq(void) 106 { 107 uint32_t seconds_to_wait = 2; 108 uint32_t before = readl(&pl031->dr); 109 uint64_t before_tick = get_cntvct(); 110 uint64_t target_tick = before_tick + (cntfrq * seconds_to_wait); 111 112 /* Wait for 2 seconds */ 113 while (get_cntvct() < target_tick) ; 114 115 if (readl(&pl031->dr) != before + seconds_to_wait) 116 return 1; 117 118 return 0; 119 } 120 121 static bool gic_irq_pending(void) 122 { 123 uint32_t offset = (pl031_irq / 32) * 4; 124 125 return readl(gic_ispendr + offset) & (1 << (pl031_irq & 31)); 126 } 127 128 static void gic_irq_unmask(void) 129 { 130 uint32_t offset = (pl031_irq / 32) * 4; 131 132 writel(1 << (pl031_irq & 31), gic_isenabler + offset); 133 } 134 135 static void irq_handler(struct pt_regs *regs) 136 { 137 u32 irqstat = gic_read_iar(); 138 u32 irqnr = gic_iar_irqnr(irqstat); 139 140 gic_write_eoir(irqstat); 141 142 if (irqnr == pl031_irq) { 143 report(readl(&pl031->ris) == 1, " RTC RIS == 1"); 144 report(readl(&pl031->mis) == 1, " RTC MIS == 1"); 145 146 /* Writing one to bit zero should clear IRQ status */ 147 writel(1, &pl031->icr); 148 149 report(readl(&pl031->ris) == 0, " RTC RIS == 0"); 150 report(readl(&pl031->mis) == 0, " RTC MIS == 0"); 151 irq_triggered = true; 152 } else { 153 report_info("Unexpected interrupt: %"PRIu32"\n", irqnr); 154 return; 155 } 156 } 157 158 static int check_rtc_irq(void) 159 { 160 uint32_t seconds_to_wait = 1; 161 uint32_t before = readl(&pl031->dr); 162 uint64_t before_tick = get_cntvct(); 163 uint64_t target_tick = before_tick + (cntfrq * (seconds_to_wait + 1)); 164 165 report_info("Checking IRQ trigger (MR)"); 166 167 irq_triggered = false; 168 169 /* Fire IRQ in 1 second */ 170 writel(before + seconds_to_wait, &pl031->mr); 171 172 #ifdef __aarch64__ 173 install_irq_handler(EL1H_IRQ, irq_handler); 174 #else 175 install_exception_handler(EXCPTN_IRQ, irq_handler); 176 #endif 177 178 /* Wait until 2 seconds are over */ 179 while (get_cntvct() < target_tick) ; 180 181 report(!gic_irq_pending(), " RTC IRQ not delivered without mask"); 182 183 /* Mask the IRQ so that it gets delivered */ 184 writel(1, &pl031->imsc); 185 report(gic_irq_pending(), " RTC IRQ pending now"); 186 187 /* Enable retrieval of IRQ */ 188 gic_irq_unmask(); 189 local_irq_enable(); 190 191 report(irq_triggered, " IRQ triggered"); 192 report(!gic_irq_pending(), " RTC IRQ not pending anymore"); 193 if (!irq_triggered) { 194 report_info(" RTC RIS: %"PRIx32, readl(&pl031->ris)); 195 report_info(" RTC MIS: %"PRIx32, readl(&pl031->mis)); 196 report_info(" RTC IMSC: %"PRIx32, readl(&pl031->imsc)); 197 report_info(" GIC IRQs pending: %08"PRIx32" %08"PRIx32, readl(gic_ispendr), readl(gic_ispendr + 4)); 198 } 199 200 local_irq_disable(); 201 return 0; 202 } 203 204 static void rtc_irq_init(void) 205 { 206 gic_enable_defaults(); 207 208 switch (gic_version()) { 209 case 2: 210 gic_ispendr = gicv2_dist_base() + GICD_ISPENDR; 211 gic_isenabler = gicv2_dist_base() + GICD_ISENABLER; 212 break; 213 case 3: 214 gic_ispendr = gicv3_dist_base() + GICD_ISPENDR; 215 gic_isenabler = gicv3_dist_base() + GICD_ISENABLER; 216 break; 217 } 218 } 219 220 static int rtc_fdt_init(void) 221 { 222 const struct fdt_property *prop; 223 const void *fdt = dt_fdt(); 224 struct dt_pbus_reg base; 225 int node, len; 226 u32 *data; 227 int ret; 228 229 node = fdt_node_offset_by_compatible(fdt, -1, "arm,pl031"); 230 if (node < 0) 231 return -1; 232 233 prop = fdt_get_property(fdt, node, "interrupts", &len); 234 assert(prop && len == (3 * sizeof(u32))); 235 data = (u32 *)prop->data; 236 assert(data[0] == 0); /* SPI */ 237 pl031_irq = SPI(fdt32_to_cpu(data[1])); 238 239 ret = dt_pbus_translate_node(node, 0, &base); 240 assert(!ret); 241 pl031 = ioremap(base.addr, base.size); 242 243 return 0; 244 } 245 246 int main(int argc, char **argv) 247 { 248 cntfrq = get_cntfrq(); 249 rtc_irq_init(); 250 if (rtc_fdt_init()) { 251 report_skip("Skipping PL031 tests. No device present."); 252 return 0; 253 } 254 255 report_prefix_push("pl031"); 256 report(!check_id(), "Periph/PCell IDs match"); 257 report(!check_ro(), "R/O fields are R/O"); 258 report(!check_rtc_freq(), "RTC ticks at 1HZ"); 259 report(!gic_irq_pending(), "RTC IRQ not pending yet"); 260 check_rtc_irq(); 261 262 return report_summary(); 263 } 264