slavio_timer.c (14912B)
1/* 2 * QEMU Sparc SLAVIO timer controller emulation 3 * 4 * Copyright (c) 2003-2005 Fabrice Bellard 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 "qemu/timer.h" 27#include "hw/irq.h" 28#include "hw/ptimer.h" 29#include "hw/qdev-properties.h" 30#include "hw/sysbus.h" 31#include "migration/vmstate.h" 32#include "trace.h" 33#include "qemu/module.h" 34#include "qom/object.h" 35 36/* 37 * Registers of hardware timer in sun4m. 38 * 39 * This is the timer/counter part of chip STP2001 (Slave I/O), also 40 * produced as NCR89C105. See 41 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt 42 * 43 * The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0 44 * are zero. Bit 31 is 1 when count has been reached. 45 * 46 * Per-CPU timers interrupt local CPU, system timer uses normal 47 * interrupt routing. 48 * 49 */ 50 51#define MAX_CPUS 16 52 53typedef struct CPUTimerState { 54 qemu_irq irq; 55 ptimer_state *timer; 56 uint32_t count, counthigh, reached; 57 /* processor only */ 58 uint32_t run; 59 uint64_t limit; 60} CPUTimerState; 61 62#define TYPE_SLAVIO_TIMER "slavio_timer" 63OBJECT_DECLARE_SIMPLE_TYPE(SLAVIO_TIMERState, SLAVIO_TIMER) 64 65struct SLAVIO_TIMERState { 66 SysBusDevice parent_obj; 67 68 uint32_t num_cpus; 69 uint32_t cputimer_mode; 70 CPUTimerState cputimer[MAX_CPUS + 1]; 71}; 72 73typedef struct TimerContext { 74 MemoryRegion iomem; 75 SLAVIO_TIMERState *s; 76 unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */ 77} TimerContext; 78 79#define SYS_TIMER_SIZE 0x14 80#define CPU_TIMER_SIZE 0x10 81 82#define TIMER_LIMIT 0 83#define TIMER_COUNTER 1 84#define TIMER_COUNTER_NORST 2 85#define TIMER_STATUS 3 86#define TIMER_MODE 4 87 88#define TIMER_COUNT_MASK32 0xfffffe00 89#define TIMER_LIMIT_MASK32 0x7fffffff 90#define TIMER_MAX_COUNT64 0x7ffffffffffffe00ULL 91#define TIMER_MAX_COUNT32 0x7ffffe00ULL 92#define TIMER_REACHED 0x80000000 93#define TIMER_PERIOD 500ULL // 500ns 94#define LIMIT_TO_PERIODS(l) (((l) >> 9) - 1) 95#define PERIODS_TO_LIMIT(l) (((l) + 1) << 9) 96 97static int slavio_timer_is_user(TimerContext *tc) 98{ 99 SLAVIO_TIMERState *s = tc->s; 100 unsigned int timer_index = tc->timer_index; 101 102 return timer_index != 0 && (s->cputimer_mode & (1 << (timer_index - 1))); 103} 104 105// Update count, set irq, update expire_time 106// Convert from ptimer countdown units 107static void slavio_timer_get_out(CPUTimerState *t) 108{ 109 uint64_t count, limit; 110 111 if (t->limit == 0) { /* free-run system or processor counter */ 112 limit = TIMER_MAX_COUNT32; 113 } else { 114 limit = t->limit; 115 } 116 count = limit - PERIODS_TO_LIMIT(ptimer_get_count(t->timer)); 117 118 trace_slavio_timer_get_out(t->limit, t->counthigh, t->count); 119 t->count = count & TIMER_COUNT_MASK32; 120 t->counthigh = count >> 32; 121} 122 123// timer callback 124static void slavio_timer_irq(void *opaque) 125{ 126 TimerContext *tc = opaque; 127 SLAVIO_TIMERState *s = tc->s; 128 CPUTimerState *t = &s->cputimer[tc->timer_index]; 129 130 slavio_timer_get_out(t); 131 trace_slavio_timer_irq(t->counthigh, t->count); 132 /* if limit is 0 (free-run), there will be no match */ 133 if (t->limit != 0) { 134 t->reached = TIMER_REACHED; 135 } 136 /* there is no interrupt if user timer or free-run */ 137 if (!slavio_timer_is_user(tc) && t->limit != 0) { 138 qemu_irq_raise(t->irq); 139 } 140} 141 142static uint64_t slavio_timer_mem_readl(void *opaque, hwaddr addr, 143 unsigned size) 144{ 145 TimerContext *tc = opaque; 146 SLAVIO_TIMERState *s = tc->s; 147 uint32_t saddr, ret; 148 unsigned int timer_index = tc->timer_index; 149 CPUTimerState *t = &s->cputimer[timer_index]; 150 151 saddr = addr >> 2; 152 switch (saddr) { 153 case TIMER_LIMIT: 154 // read limit (system counter mode) or read most signifying 155 // part of counter (user mode) 156 if (slavio_timer_is_user(tc)) { 157 // read user timer MSW 158 slavio_timer_get_out(t); 159 ret = t->counthigh | t->reached; 160 } else { 161 // read limit 162 // clear irq 163 qemu_irq_lower(t->irq); 164 t->reached = 0; 165 ret = t->limit & TIMER_LIMIT_MASK32; 166 } 167 break; 168 case TIMER_COUNTER: 169 // read counter and reached bit (system mode) or read lsbits 170 // of counter (user mode) 171 slavio_timer_get_out(t); 172 if (slavio_timer_is_user(tc)) { // read user timer LSW 173 ret = t->count & TIMER_MAX_COUNT64; 174 } else { // read limit 175 ret = (t->count & TIMER_MAX_COUNT32) | 176 t->reached; 177 } 178 break; 179 case TIMER_STATUS: 180 // only available in processor counter/timer 181 // read start/stop status 182 if (timer_index > 0) { 183 ret = t->run; 184 } else { 185 ret = 0; 186 } 187 break; 188 case TIMER_MODE: 189 // only available in system counter 190 // read user/system mode 191 ret = s->cputimer_mode; 192 break; 193 default: 194 trace_slavio_timer_mem_readl_invalid(addr); 195 ret = 0; 196 break; 197 } 198 trace_slavio_timer_mem_readl(addr, ret); 199 return ret; 200} 201 202static void slavio_timer_mem_writel(void *opaque, hwaddr addr, 203 uint64_t val, unsigned size) 204{ 205 TimerContext *tc = opaque; 206 SLAVIO_TIMERState *s = tc->s; 207 uint32_t saddr; 208 unsigned int timer_index = tc->timer_index; 209 CPUTimerState *t = &s->cputimer[timer_index]; 210 211 trace_slavio_timer_mem_writel(addr, val); 212 saddr = addr >> 2; 213 switch (saddr) { 214 case TIMER_LIMIT: 215 ptimer_transaction_begin(t->timer); 216 if (slavio_timer_is_user(tc)) { 217 uint64_t count; 218 219 // set user counter MSW, reset counter 220 t->limit = TIMER_MAX_COUNT64; 221 t->counthigh = val & (TIMER_MAX_COUNT64 >> 32); 222 t->reached = 0; 223 count = ((uint64_t)t->counthigh << 32) | t->count; 224 trace_slavio_timer_mem_writel_limit(timer_index, count); 225 ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count)); 226 } else { 227 // set limit, reset counter 228 qemu_irq_lower(t->irq); 229 t->limit = val & TIMER_MAX_COUNT32; 230 if (t->limit == 0) { /* free-run */ 231 ptimer_set_limit(t->timer, 232 LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1); 233 } else { 234 ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1); 235 } 236 } 237 ptimer_transaction_commit(t->timer); 238 break; 239 case TIMER_COUNTER: 240 if (slavio_timer_is_user(tc)) { 241 uint64_t count; 242 243 // set user counter LSW, reset counter 244 t->limit = TIMER_MAX_COUNT64; 245 t->count = val & TIMER_MAX_COUNT64; 246 t->reached = 0; 247 count = ((uint64_t)t->counthigh) << 32 | t->count; 248 trace_slavio_timer_mem_writel_limit(timer_index, count); 249 ptimer_transaction_begin(t->timer); 250 ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count)); 251 ptimer_transaction_commit(t->timer); 252 } else { 253 trace_slavio_timer_mem_writel_counter_invalid(); 254 } 255 break; 256 case TIMER_COUNTER_NORST: 257 // set limit without resetting counter 258 t->limit = val & TIMER_MAX_COUNT32; 259 ptimer_transaction_begin(t->timer); 260 if (t->limit == 0) { /* free-run */ 261 ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0); 262 } else { 263 ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0); 264 } 265 ptimer_transaction_commit(t->timer); 266 break; 267 case TIMER_STATUS: 268 ptimer_transaction_begin(t->timer); 269 if (slavio_timer_is_user(tc)) { 270 // start/stop user counter 271 if (val & 1) { 272 trace_slavio_timer_mem_writel_status_start(timer_index); 273 ptimer_run(t->timer, 0); 274 } else { 275 trace_slavio_timer_mem_writel_status_stop(timer_index); 276 ptimer_stop(t->timer); 277 } 278 } 279 t->run = val & 1; 280 ptimer_transaction_commit(t->timer); 281 break; 282 case TIMER_MODE: 283 if (timer_index == 0) { 284 unsigned int i; 285 286 for (i = 0; i < s->num_cpus; i++) { 287 unsigned int processor = 1 << i; 288 CPUTimerState *curr_timer = &s->cputimer[i + 1]; 289 290 ptimer_transaction_begin(curr_timer->timer); 291 // check for a change in timer mode for this processor 292 if ((val & processor) != (s->cputimer_mode & processor)) { 293 if (val & processor) { // counter -> user timer 294 qemu_irq_lower(curr_timer->irq); 295 // counters are always running 296 if (!curr_timer->run) { 297 ptimer_stop(curr_timer->timer); 298 } 299 // user timer limit is always the same 300 curr_timer->limit = TIMER_MAX_COUNT64; 301 ptimer_set_limit(curr_timer->timer, 302 LIMIT_TO_PERIODS(curr_timer->limit), 303 1); 304 // set this processors user timer bit in config 305 // register 306 s->cputimer_mode |= processor; 307 trace_slavio_timer_mem_writel_mode_user(timer_index); 308 } else { // user timer -> counter 309 // start the counter 310 ptimer_run(curr_timer->timer, 0); 311 // clear this processors user timer bit in config 312 // register 313 s->cputimer_mode &= ~processor; 314 trace_slavio_timer_mem_writel_mode_counter(timer_index); 315 } 316 } 317 ptimer_transaction_commit(curr_timer->timer); 318 } 319 } else { 320 trace_slavio_timer_mem_writel_mode_invalid(); 321 } 322 break; 323 default: 324 trace_slavio_timer_mem_writel_invalid(addr); 325 break; 326 } 327} 328 329static const MemoryRegionOps slavio_timer_mem_ops = { 330 .read = slavio_timer_mem_readl, 331 .write = slavio_timer_mem_writel, 332 .endianness = DEVICE_NATIVE_ENDIAN, 333 .valid = { 334 .min_access_size = 4, 335 .max_access_size = 8, 336 }, 337 .impl = { 338 .min_access_size = 4, 339 .max_access_size = 4, 340 }, 341}; 342 343static const VMStateDescription vmstate_timer = { 344 .name ="timer", 345 .version_id = 3, 346 .minimum_version_id = 3, 347 .fields = (VMStateField[]) { 348 VMSTATE_UINT64(limit, CPUTimerState), 349 VMSTATE_UINT32(count, CPUTimerState), 350 VMSTATE_UINT32(counthigh, CPUTimerState), 351 VMSTATE_UINT32(reached, CPUTimerState), 352 VMSTATE_UINT32(run , CPUTimerState), 353 VMSTATE_PTIMER(timer, CPUTimerState), 354 VMSTATE_END_OF_LIST() 355 } 356}; 357 358static const VMStateDescription vmstate_slavio_timer = { 359 .name ="slavio_timer", 360 .version_id = 3, 361 .minimum_version_id = 3, 362 .fields = (VMStateField[]) { 363 VMSTATE_STRUCT_ARRAY(cputimer, SLAVIO_TIMERState, MAX_CPUS + 1, 3, 364 vmstate_timer, CPUTimerState), 365 VMSTATE_END_OF_LIST() 366 } 367}; 368 369static void slavio_timer_reset(DeviceState *d) 370{ 371 SLAVIO_TIMERState *s = SLAVIO_TIMER(d); 372 unsigned int i; 373 CPUTimerState *curr_timer; 374 375 for (i = 0; i <= MAX_CPUS; i++) { 376 curr_timer = &s->cputimer[i]; 377 curr_timer->limit = 0; 378 curr_timer->count = 0; 379 curr_timer->reached = 0; 380 if (i <= s->num_cpus) { 381 ptimer_transaction_begin(curr_timer->timer); 382 ptimer_set_limit(curr_timer->timer, 383 LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1); 384 ptimer_run(curr_timer->timer, 0); 385 curr_timer->run = 1; 386 ptimer_transaction_commit(curr_timer->timer); 387 } 388 } 389 s->cputimer_mode = 0; 390} 391 392static void slavio_timer_init(Object *obj) 393{ 394 SLAVIO_TIMERState *s = SLAVIO_TIMER(obj); 395 SysBusDevice *dev = SYS_BUS_DEVICE(obj); 396 unsigned int i; 397 TimerContext *tc; 398 399 for (i = 0; i <= MAX_CPUS; i++) { 400 uint64_t size; 401 char timer_name[20]; 402 403 tc = g_malloc0(sizeof(TimerContext)); 404 tc->s = s; 405 tc->timer_index = i; 406 407 s->cputimer[i].timer = ptimer_init(slavio_timer_irq, tc, 408 PTIMER_POLICY_DEFAULT); 409 ptimer_transaction_begin(s->cputimer[i].timer); 410 ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD); 411 ptimer_transaction_commit(s->cputimer[i].timer); 412 413 size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE; 414 snprintf(timer_name, sizeof(timer_name), "timer-%i", i); 415 memory_region_init_io(&tc->iomem, obj, &slavio_timer_mem_ops, tc, 416 timer_name, size); 417 sysbus_init_mmio(dev, &tc->iomem); 418 419 sysbus_init_irq(dev, &s->cputimer[i].irq); 420 } 421} 422 423static Property slavio_timer_properties[] = { 424 DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0), 425 DEFINE_PROP_END_OF_LIST(), 426}; 427 428static void slavio_timer_class_init(ObjectClass *klass, void *data) 429{ 430 DeviceClass *dc = DEVICE_CLASS(klass); 431 432 dc->reset = slavio_timer_reset; 433 dc->vmsd = &vmstate_slavio_timer; 434 device_class_set_props(dc, slavio_timer_properties); 435} 436 437static const TypeInfo slavio_timer_info = { 438 .name = TYPE_SLAVIO_TIMER, 439 .parent = TYPE_SYS_BUS_DEVICE, 440 .instance_size = sizeof(SLAVIO_TIMERState), 441 .instance_init = slavio_timer_init, 442 .class_init = slavio_timer_class_init, 443}; 444 445static void slavio_timer_register_types(void) 446{ 447 type_register_static(&slavio_timer_info); 448} 449 450type_init(slavio_timer_register_types)