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