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