1 /* 2 * QEMU GRLIB GPTimer Emulator 3 * 4 * Copyright (c) 2010-2019 AdaCore 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "hw/sparc/grlib.h" 27 #include "hw/sysbus.h" 28 #include "qemu/timer.h" 29 #include "hw/irq.h" 30 #include "hw/ptimer.h" 31 #include "qemu/main-loop.h" 32 #include "qemu/module.h" 33 34 #include "trace.h" 35 36 #define UNIT_REG_SIZE 16 /* Size of memory mapped regs for the unit */ 37 #define GPTIMER_REG_SIZE 16 /* Size of memory mapped regs for a GPTimer */ 38 39 #define GPTIMER_MAX_TIMERS 8 40 41 /* GPTimer Config register fields */ 42 #define GPTIMER_ENABLE (1 << 0) 43 #define GPTIMER_RESTART (1 << 1) 44 #define GPTIMER_LOAD (1 << 2) 45 #define GPTIMER_INT_ENABLE (1 << 3) 46 #define GPTIMER_INT_PENDING (1 << 4) 47 #define GPTIMER_CHAIN (1 << 5) /* Not supported */ 48 #define GPTIMER_DEBUG_HALT (1 << 6) /* Not supported */ 49 50 /* Memory mapped register offsets */ 51 #define SCALER_OFFSET 0x00 52 #define SCALER_RELOAD_OFFSET 0x04 53 #define CONFIG_OFFSET 0x08 54 #define COUNTER_OFFSET 0x00 55 #define COUNTER_RELOAD_OFFSET 0x04 56 #define TIMER_BASE 0x10 57 58 #define GRLIB_GPTIMER(obj) \ 59 OBJECT_CHECK(GPTimerUnit, (obj), TYPE_GRLIB_GPTIMER) 60 61 typedef struct GPTimer GPTimer; 62 typedef struct GPTimerUnit GPTimerUnit; 63 64 struct GPTimer { 65 QEMUBH *bh; 66 struct ptimer_state *ptimer; 67 68 qemu_irq irq; 69 int id; 70 GPTimerUnit *unit; 71 72 /* registers */ 73 uint32_t counter; 74 uint32_t reload; 75 uint32_t config; 76 }; 77 78 struct GPTimerUnit { 79 SysBusDevice parent_obj; 80 81 MemoryRegion iomem; 82 83 uint32_t nr_timers; /* Number of timers available */ 84 uint32_t freq_hz; /* System frequency */ 85 uint32_t irq_line; /* Base irq line */ 86 87 GPTimer *timers; 88 89 /* registers */ 90 uint32_t scaler; 91 uint32_t reload; 92 uint32_t config; 93 }; 94 95 static void grlib_gptimer_enable(GPTimer *timer) 96 { 97 assert(timer != NULL); 98 99 100 ptimer_stop(timer->ptimer); 101 102 if (!(timer->config & GPTIMER_ENABLE)) { 103 /* Timer disabled */ 104 trace_grlib_gptimer_disabled(timer->id, timer->config); 105 return; 106 } 107 108 /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at 109 underflow. Set count + 1 to simulate the GPTimer behavior. */ 110 111 trace_grlib_gptimer_enable(timer->id, timer->counter); 112 113 ptimer_set_count(timer->ptimer, (uint64_t)timer->counter + 1); 114 ptimer_run(timer->ptimer, 1); 115 } 116 117 static void grlib_gptimer_restart(GPTimer *timer) 118 { 119 assert(timer != NULL); 120 121 trace_grlib_gptimer_restart(timer->id, timer->reload); 122 123 timer->counter = timer->reload; 124 grlib_gptimer_enable(timer); 125 } 126 127 static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler) 128 { 129 int i = 0; 130 uint32_t value = 0; 131 132 assert(unit != NULL); 133 134 if (scaler > 0) { 135 value = unit->freq_hz / (scaler + 1); 136 } else { 137 value = unit->freq_hz; 138 } 139 140 trace_grlib_gptimer_set_scaler(scaler, value); 141 142 for (i = 0; i < unit->nr_timers; i++) { 143 ptimer_set_freq(unit->timers[i].ptimer, value); 144 } 145 } 146 147 static void grlib_gptimer_hit(void *opaque) 148 { 149 GPTimer *timer = opaque; 150 assert(timer != NULL); 151 152 trace_grlib_gptimer_hit(timer->id); 153 154 /* Timer expired */ 155 156 if (timer->config & GPTIMER_INT_ENABLE) { 157 /* Set the pending bit (only unset by write in the config register) */ 158 timer->config |= GPTIMER_INT_PENDING; 159 qemu_irq_pulse(timer->irq); 160 } 161 162 if (timer->config & GPTIMER_RESTART) { 163 grlib_gptimer_restart(timer); 164 } 165 } 166 167 static uint64_t grlib_gptimer_read(void *opaque, hwaddr addr, 168 unsigned size) 169 { 170 GPTimerUnit *unit = opaque; 171 hwaddr timer_addr; 172 int id; 173 uint32_t value = 0; 174 175 addr &= 0xff; 176 177 /* Unit registers */ 178 switch (addr) { 179 case SCALER_OFFSET: 180 trace_grlib_gptimer_readl(-1, addr, unit->scaler); 181 return unit->scaler; 182 183 case SCALER_RELOAD_OFFSET: 184 trace_grlib_gptimer_readl(-1, addr, unit->reload); 185 return unit->reload; 186 187 case CONFIG_OFFSET: 188 trace_grlib_gptimer_readl(-1, addr, unit->config); 189 return unit->config; 190 191 default: 192 break; 193 } 194 195 timer_addr = (addr % TIMER_BASE); 196 id = (addr - TIMER_BASE) / TIMER_BASE; 197 198 if (id >= 0 && id < unit->nr_timers) { 199 200 /* GPTimer registers */ 201 switch (timer_addr) { 202 case COUNTER_OFFSET: 203 value = ptimer_get_count(unit->timers[id].ptimer); 204 trace_grlib_gptimer_readl(id, addr, value); 205 return value; 206 207 case COUNTER_RELOAD_OFFSET: 208 value = unit->timers[id].reload; 209 trace_grlib_gptimer_readl(id, addr, value); 210 return value; 211 212 case CONFIG_OFFSET: 213 trace_grlib_gptimer_readl(id, addr, unit->timers[id].config); 214 return unit->timers[id].config; 215 216 default: 217 break; 218 } 219 220 } 221 222 trace_grlib_gptimer_readl(-1, addr, 0); 223 return 0; 224 } 225 226 static void grlib_gptimer_write(void *opaque, hwaddr addr, 227 uint64_t value, unsigned size) 228 { 229 GPTimerUnit *unit = opaque; 230 hwaddr timer_addr; 231 int id; 232 233 addr &= 0xff; 234 235 /* Unit registers */ 236 switch (addr) { 237 case SCALER_OFFSET: 238 value &= 0xFFFF; /* clean up the value */ 239 unit->scaler = value; 240 trace_grlib_gptimer_writel(-1, addr, unit->scaler); 241 return; 242 243 case SCALER_RELOAD_OFFSET: 244 value &= 0xFFFF; /* clean up the value */ 245 unit->reload = value; 246 trace_grlib_gptimer_writel(-1, addr, unit->reload); 247 grlib_gptimer_set_scaler(unit, value); 248 return; 249 250 case CONFIG_OFFSET: 251 /* Read Only (disable timer freeze not supported) */ 252 trace_grlib_gptimer_writel(-1, addr, 0); 253 return; 254 255 default: 256 break; 257 } 258 259 timer_addr = (addr % TIMER_BASE); 260 id = (addr - TIMER_BASE) / TIMER_BASE; 261 262 if (id >= 0 && id < unit->nr_timers) { 263 264 /* GPTimer registers */ 265 switch (timer_addr) { 266 case COUNTER_OFFSET: 267 trace_grlib_gptimer_writel(id, addr, value); 268 unit->timers[id].counter = value; 269 grlib_gptimer_enable(&unit->timers[id]); 270 return; 271 272 case COUNTER_RELOAD_OFFSET: 273 trace_grlib_gptimer_writel(id, addr, value); 274 unit->timers[id].reload = value; 275 return; 276 277 case CONFIG_OFFSET: 278 trace_grlib_gptimer_writel(id, addr, value); 279 280 if (value & GPTIMER_INT_PENDING) { 281 /* clear pending bit */ 282 value &= ~GPTIMER_INT_PENDING; 283 } else { 284 /* keep pending bit */ 285 value |= unit->timers[id].config & GPTIMER_INT_PENDING; 286 } 287 288 unit->timers[id].config = value; 289 290 /* gptimer_restart calls gptimer_enable, so if "enable" and "load" 291 bits are present, we just have to call restart. */ 292 293 if (value & GPTIMER_LOAD) { 294 grlib_gptimer_restart(&unit->timers[id]); 295 } else if (value & GPTIMER_ENABLE) { 296 grlib_gptimer_enable(&unit->timers[id]); 297 } 298 299 /* These fields must always be read as 0 */ 300 value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT); 301 302 unit->timers[id].config = value; 303 return; 304 305 default: 306 break; 307 } 308 309 } 310 311 trace_grlib_gptimer_writel(-1, addr, value); 312 } 313 314 static const MemoryRegionOps grlib_gptimer_ops = { 315 .read = grlib_gptimer_read, 316 .write = grlib_gptimer_write, 317 .endianness = DEVICE_NATIVE_ENDIAN, 318 .valid = { 319 .min_access_size = 4, 320 .max_access_size = 4, 321 }, 322 }; 323 324 static void grlib_gptimer_reset(DeviceState *d) 325 { 326 GPTimerUnit *unit = GRLIB_GPTIMER(d); 327 int i = 0; 328 329 assert(unit != NULL); 330 331 unit->scaler = 0; 332 unit->reload = 0; 333 334 unit->config = unit->nr_timers; 335 unit->config |= unit->irq_line << 3; 336 unit->config |= 1 << 8; /* separate interrupt */ 337 unit->config |= 1 << 9; /* Disable timer freeze */ 338 339 340 for (i = 0; i < unit->nr_timers; i++) { 341 GPTimer *timer = &unit->timers[i]; 342 343 timer->counter = 0; 344 timer->reload = 0; 345 timer->config = 0; 346 ptimer_stop(timer->ptimer); 347 ptimer_set_count(timer->ptimer, 0); 348 ptimer_set_freq(timer->ptimer, unit->freq_hz); 349 } 350 } 351 352 static void grlib_gptimer_realize(DeviceState *dev, Error **errp) 353 { 354 GPTimerUnit *unit = GRLIB_GPTIMER(dev); 355 unsigned int i; 356 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 357 358 assert(unit->nr_timers > 0); 359 assert(unit->nr_timers <= GPTIMER_MAX_TIMERS); 360 361 unit->timers = g_malloc0(sizeof unit->timers[0] * unit->nr_timers); 362 363 for (i = 0; i < unit->nr_timers; i++) { 364 GPTimer *timer = &unit->timers[i]; 365 366 timer->unit = unit; 367 timer->bh = qemu_bh_new(grlib_gptimer_hit, timer); 368 timer->ptimer = ptimer_init(timer->bh, PTIMER_POLICY_DEFAULT); 369 timer->id = i; 370 371 /* One IRQ line for each timer */ 372 sysbus_init_irq(sbd, &timer->irq); 373 374 ptimer_set_freq(timer->ptimer, unit->freq_hz); 375 } 376 377 memory_region_init_io(&unit->iomem, OBJECT(unit), &grlib_gptimer_ops, 378 unit, "gptimer", 379 UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers); 380 381 sysbus_init_mmio(sbd, &unit->iomem); 382 } 383 384 static Property grlib_gptimer_properties[] = { 385 DEFINE_PROP_UINT32("frequency", GPTimerUnit, freq_hz, 40000000), 386 DEFINE_PROP_UINT32("irq-line", GPTimerUnit, irq_line, 8), 387 DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2), 388 DEFINE_PROP_END_OF_LIST(), 389 }; 390 391 static void grlib_gptimer_class_init(ObjectClass *klass, void *data) 392 { 393 DeviceClass *dc = DEVICE_CLASS(klass); 394 395 dc->realize = grlib_gptimer_realize; 396 dc->reset = grlib_gptimer_reset; 397 dc->props = grlib_gptimer_properties; 398 } 399 400 static const TypeInfo grlib_gptimer_info = { 401 .name = TYPE_GRLIB_GPTIMER, 402 .parent = TYPE_SYS_BUS_DEVICE, 403 .instance_size = sizeof(GPTimerUnit), 404 .class_init = grlib_gptimer_class_init, 405 }; 406 407 static void grlib_gptimer_register_types(void) 408 { 409 type_register_static(&grlib_gptimer_info); 410 } 411 412 type_init(grlib_gptimer_register_types) 413