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