diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-02-05 14:38:25 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-04-08 18:13:14 +0200 |
commit | 3bd884511f8dc44a01e32878b2972443a16db70d (patch) | |
tree | 97bf4af7947076a7e23f905a370a157e422fd967 /hw/grlib_gptimer.c | |
parent | 47934d0aadc075b05ce2d9e8a44fa6a46edd1afa (diff) |
hw: move timer devices to hw/timer/, configure with default-configs/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/grlib_gptimer.c')
-rw-r--r-- | hw/grlib_gptimer.c | 404 |
1 files changed, 0 insertions, 404 deletions
diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c deleted file mode 100644 index 7043a34684..0000000000 --- a/hw/grlib_gptimer.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * QEMU GRLIB GPTimer Emulator - * - * Copyright (c) 2010-2011 AdaCore - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "hw/sysbus.h" -#include "qemu/timer.h" -#include "hw/ptimer.h" - -#include "trace.h" - -#define UNIT_REG_SIZE 16 /* Size of memory mapped regs for the unit */ -#define GPTIMER_REG_SIZE 16 /* Size of memory mapped regs for a GPTimer */ - -#define GPTIMER_MAX_TIMERS 8 - -/* GPTimer Config register fields */ -#define GPTIMER_ENABLE (1 << 0) -#define GPTIMER_RESTART (1 << 1) -#define GPTIMER_LOAD (1 << 2) -#define GPTIMER_INT_ENABLE (1 << 3) -#define GPTIMER_INT_PENDING (1 << 4) -#define GPTIMER_CHAIN (1 << 5) /* Not supported */ -#define GPTIMER_DEBUG_HALT (1 << 6) /* Not supported */ - -/* Memory mapped register offsets */ -#define SCALER_OFFSET 0x00 -#define SCALER_RELOAD_OFFSET 0x04 -#define CONFIG_OFFSET 0x08 -#define COUNTER_OFFSET 0x00 -#define COUNTER_RELOAD_OFFSET 0x04 -#define TIMER_BASE 0x10 - -typedef struct GPTimer GPTimer; -typedef struct GPTimerUnit GPTimerUnit; - -struct GPTimer { - QEMUBH *bh; - struct ptimer_state *ptimer; - - qemu_irq irq; - int id; - GPTimerUnit *unit; - - /* registers */ - uint32_t counter; - uint32_t reload; - uint32_t config; -}; - -struct GPTimerUnit { - SysBusDevice busdev; - MemoryRegion iomem; - - uint32_t nr_timers; /* Number of timers available */ - uint32_t freq_hz; /* System frequency */ - uint32_t irq_line; /* Base irq line */ - - GPTimer *timers; - - /* registers */ - uint32_t scaler; - uint32_t reload; - uint32_t config; -}; - -static void grlib_gptimer_enable(GPTimer *timer) -{ - assert(timer != NULL); - - - ptimer_stop(timer->ptimer); - - if (!(timer->config & GPTIMER_ENABLE)) { - /* Timer disabled */ - trace_grlib_gptimer_disabled(timer->id, timer->config); - return; - } - - /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at - underflow. Set count + 1 to simulate the GPTimer behavior. */ - - trace_grlib_gptimer_enable(timer->id, timer->counter + 1); - - ptimer_set_count(timer->ptimer, timer->counter + 1); - ptimer_run(timer->ptimer, 1); -} - -static void grlib_gptimer_restart(GPTimer *timer) -{ - assert(timer != NULL); - - trace_grlib_gptimer_restart(timer->id, timer->reload); - - timer->counter = timer->reload; - grlib_gptimer_enable(timer); -} - -static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler) -{ - int i = 0; - uint32_t value = 0; - - assert(unit != NULL); - - if (scaler > 0) { - value = unit->freq_hz / (scaler + 1); - } else { - value = unit->freq_hz; - } - - trace_grlib_gptimer_set_scaler(scaler, value); - - for (i = 0; i < unit->nr_timers; i++) { - ptimer_set_freq(unit->timers[i].ptimer, value); - } -} - -static void grlib_gptimer_hit(void *opaque) -{ - GPTimer *timer = opaque; - assert(timer != NULL); - - trace_grlib_gptimer_hit(timer->id); - - /* Timer expired */ - - if (timer->config & GPTIMER_INT_ENABLE) { - /* Set the pending bit (only unset by write in the config register) */ - timer->config |= GPTIMER_INT_PENDING; - qemu_irq_pulse(timer->irq); - } - - if (timer->config & GPTIMER_RESTART) { - grlib_gptimer_restart(timer); - } -} - -static uint64_t grlib_gptimer_read(void *opaque, hwaddr addr, - unsigned size) -{ - GPTimerUnit *unit = opaque; - hwaddr timer_addr; - int id; - uint32_t value = 0; - - addr &= 0xff; - - /* Unit registers */ - switch (addr) { - case SCALER_OFFSET: - trace_grlib_gptimer_readl(-1, addr, unit->scaler); - return unit->scaler; - - case SCALER_RELOAD_OFFSET: - trace_grlib_gptimer_readl(-1, addr, unit->reload); - return unit->reload; - - case CONFIG_OFFSET: - trace_grlib_gptimer_readl(-1, addr, unit->config); - return unit->config; - - default: - break; - } - - timer_addr = (addr % TIMER_BASE); - id = (addr - TIMER_BASE) / TIMER_BASE; - - if (id >= 0 && id < unit->nr_timers) { - - /* GPTimer registers */ - switch (timer_addr) { - case COUNTER_OFFSET: - value = ptimer_get_count(unit->timers[id].ptimer); - trace_grlib_gptimer_readl(id, addr, value); - return value; - - case COUNTER_RELOAD_OFFSET: - value = unit->timers[id].reload; - trace_grlib_gptimer_readl(id, addr, value); - return value; - - case CONFIG_OFFSET: - trace_grlib_gptimer_readl(id, addr, unit->timers[id].config); - return unit->timers[id].config; - - default: - break; - } - - } - - trace_grlib_gptimer_readl(-1, addr, 0); - return 0; -} - -static void grlib_gptimer_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - GPTimerUnit *unit = opaque; - hwaddr timer_addr; - int id; - - addr &= 0xff; - - /* Unit registers */ - switch (addr) { - case SCALER_OFFSET: - value &= 0xFFFF; /* clean up the value */ - unit->scaler = value; - trace_grlib_gptimer_writel(-1, addr, unit->scaler); - return; - - case SCALER_RELOAD_OFFSET: - value &= 0xFFFF; /* clean up the value */ - unit->reload = value; - trace_grlib_gptimer_writel(-1, addr, unit->reload); - grlib_gptimer_set_scaler(unit, value); - return; - - case CONFIG_OFFSET: - /* Read Only (disable timer freeze not supported) */ - trace_grlib_gptimer_writel(-1, addr, 0); - return; - - default: - break; - } - - timer_addr = (addr % TIMER_BASE); - id = (addr - TIMER_BASE) / TIMER_BASE; - - if (id >= 0 && id < unit->nr_timers) { - - /* GPTimer registers */ - switch (timer_addr) { - case COUNTER_OFFSET: - trace_grlib_gptimer_writel(id, addr, value); - unit->timers[id].counter = value; - grlib_gptimer_enable(&unit->timers[id]); - return; - - case COUNTER_RELOAD_OFFSET: - trace_grlib_gptimer_writel(id, addr, value); - unit->timers[id].reload = value; - return; - - case CONFIG_OFFSET: - trace_grlib_gptimer_writel(id, addr, value); - - if (value & GPTIMER_INT_PENDING) { - /* clear pending bit */ - value &= ~GPTIMER_INT_PENDING; - } else { - /* keep pending bit */ - value |= unit->timers[id].config & GPTIMER_INT_PENDING; - } - - unit->timers[id].config = value; - - /* gptimer_restart calls gptimer_enable, so if "enable" and "load" - bits are present, we just have to call restart. */ - - if (value & GPTIMER_LOAD) { - grlib_gptimer_restart(&unit->timers[id]); - } else if (value & GPTIMER_ENABLE) { - grlib_gptimer_enable(&unit->timers[id]); - } - - /* These fields must always be read as 0 */ - value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT); - - unit->timers[id].config = value; - return; - - default: - break; - } - - } - - trace_grlib_gptimer_writel(-1, addr, value); -} - -static const MemoryRegionOps grlib_gptimer_ops = { - .read = grlib_gptimer_read, - .write = grlib_gptimer_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; - -static void grlib_gptimer_reset(DeviceState *d) -{ - GPTimerUnit *unit = container_of(d, GPTimerUnit, busdev.qdev); - int i = 0; - - assert(unit != NULL); - - unit->scaler = 0; - unit->reload = 0; - unit->config = 0; - - unit->config = unit->nr_timers; - unit->config |= unit->irq_line << 3; - unit->config |= 1 << 8; /* separate interrupt */ - unit->config |= 1 << 9; /* Disable timer freeze */ - - - for (i = 0; i < unit->nr_timers; i++) { - GPTimer *timer = &unit->timers[i]; - - timer->counter = 0; - timer->reload = 0; - timer->config = 0; - ptimer_stop(timer->ptimer); - ptimer_set_count(timer->ptimer, 0); - ptimer_set_freq(timer->ptimer, unit->freq_hz); - } -} - -static int grlib_gptimer_init(SysBusDevice *dev) -{ - GPTimerUnit *unit = FROM_SYSBUS(typeof(*unit), dev); - unsigned int i; - - assert(unit->nr_timers > 0); - assert(unit->nr_timers <= GPTIMER_MAX_TIMERS); - - unit->timers = g_malloc0(sizeof unit->timers[0] * unit->nr_timers); - - for (i = 0; i < unit->nr_timers; i++) { - GPTimer *timer = &unit->timers[i]; - - timer->unit = unit; - timer->bh = qemu_bh_new(grlib_gptimer_hit, timer); - timer->ptimer = ptimer_init(timer->bh); - timer->id = i; - - /* One IRQ line for each timer */ - sysbus_init_irq(dev, &timer->irq); - - ptimer_set_freq(timer->ptimer, unit->freq_hz); - } - - memory_region_init_io(&unit->iomem, &grlib_gptimer_ops, unit, "gptimer", - UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers); - - sysbus_init_mmio(dev, &unit->iomem); - return 0; -} - -static Property grlib_gptimer_properties[] = { - DEFINE_PROP_UINT32("frequency", GPTimerUnit, freq_hz, 40000000), - DEFINE_PROP_UINT32("irq-line", GPTimerUnit, irq_line, 8), - DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2), - DEFINE_PROP_END_OF_LIST(), -}; - -static void grlib_gptimer_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = grlib_gptimer_init; - dc->reset = grlib_gptimer_reset; - dc->props = grlib_gptimer_properties; -} - -static const TypeInfo grlib_gptimer_info = { - .name = "grlib,gptimer", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(GPTimerUnit), - .class_init = grlib_gptimer_class_init, -}; - -static void grlib_gptimer_register_types(void) -{ - type_register_static(&grlib_gptimer_info); -} - -type_init(grlib_gptimer_register_types) |