summaryrefslogtreecommitdiffstats
path: root/qemu/hw/timer
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/hw/timer')
-rw-r--r--qemu/hw/timer/Makefile.objs35
-rw-r--r--qemu/hw/timer/a9gtimer.c372
-rw-r--r--qemu/hw/timer/allwinner-a10-pit.c296
-rw-r--r--qemu/hw/timer/arm_mptimer.c303
-rw-r--r--qemu/hw/timer/arm_timer.c409
-rw-r--r--qemu/hw/timer/aspeed_timer.c449
-rw-r--r--qemu/hw/timer/cadence_ttc.c492
-rw-r--r--qemu/hw/timer/digic-timer.c163
-rw-r--r--qemu/hw/timer/ds1338.c243
-rw-r--r--qemu/hw/timer/etraxfs_timer.c358
-rw-r--r--qemu/hw/timer/exynos4210_mct.c1480
-rw-r--r--qemu/hw/timer/exynos4210_pwm.c424
-rw-r--r--qemu/hw/timer/exynos4210_rtc.c595
-rw-r--r--qemu/hw/timer/grlib_gptimer.c412
-rw-r--r--qemu/hw/timer/hpet.c789
-rw-r--r--qemu/hw/timer/i8254.c384
-rw-r--r--qemu/hw/timer/i8254_common.c307
-rw-r--r--qemu/hw/timer/imx_epit.c344
-rw-r--r--qemu/hw/timer/imx_gpt.c467
-rw-r--r--qemu/hw/timer/lm32_timer.c236
-rw-r--r--qemu/hw/timer/m48t59.c947
-rw-r--r--qemu/hw/timer/mc146818rtc.c971
-rw-r--r--qemu/hw/timer/milkymist-sysctl.c342
-rw-r--r--qemu/hw/timer/omap_gptimer.c488
-rw-r--r--qemu/hw/timer/omap_synctimer.c104
-rw-r--r--qemu/hw/timer/pl031.c270
-rw-r--r--qemu/hw/timer/puv3_ost.c157
-rw-r--r--qemu/hw/timer/pxa2xx_timer.c605
-rw-r--r--qemu/hw/timer/sh_timer.c335
-rw-r--r--qemu/hw/timer/slavio_timer.c435
-rw-r--r--qemu/hw/timer/stm32f2xx_timer.c329
-rw-r--r--qemu/hw/timer/twl92230.c889
-rw-r--r--qemu/hw/timer/xilinx_timer.c266
33 files changed, 0 insertions, 14696 deletions
diff --git a/qemu/hw/timer/Makefile.objs b/qemu/hw/timer/Makefile.objs
deleted file mode 100644
index 003c14fa2..000000000
--- a/qemu/hw/timer/Makefile.objs
+++ /dev/null
@@ -1,35 +0,0 @@
-common-obj-$(CONFIG_ARM_TIMER) += arm_timer.o
-common-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o
-common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o
-common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
-common-obj-$(CONFIG_DS1338) += ds1338.o
-common-obj-$(CONFIG_HPET) += hpet.o
-common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
-common-obj-$(CONFIG_M48T59) += m48t59.o
-common-obj-$(CONFIG_PL031) += pl031.o
-common-obj-$(CONFIG_PUV3) += puv3_ost.o
-common-obj-$(CONFIG_TWL92230) += twl92230.o
-common-obj-$(CONFIG_XILINX) += xilinx_timer.o
-common-obj-$(CONFIG_SLAVIO) += slavio_timer.o
-common-obj-$(CONFIG_ETRAXFS) += etraxfs_timer.o
-common-obj-$(CONFIG_GRLIB) += grlib_gptimer.o
-common-obj-$(CONFIG_IMX) += imx_epit.o
-common-obj-$(CONFIG_IMX) += imx_gpt.o
-common-obj-$(CONFIG_LM32) += lm32_timer.o
-common-obj-$(CONFIG_MILKYMIST) += milkymist-sysctl.o
-
-obj-$(CONFIG_EXYNOS4) += exynos4210_mct.o
-obj-$(CONFIG_EXYNOS4) += exynos4210_pwm.o
-obj-$(CONFIG_EXYNOS4) += exynos4210_rtc.o
-obj-$(CONFIG_OMAP) += omap_gptimer.o
-obj-$(CONFIG_OMAP) += omap_synctimer.o
-obj-$(CONFIG_PXA2XX) += pxa2xx_timer.o
-obj-$(CONFIG_SH4) += sh_timer.o
-obj-$(CONFIG_DIGIC) += digic-timer.o
-
-obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
-
-obj-$(CONFIG_ALLWINNER_A10_PIT) += allwinner-a10-pit.o
-
-common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o
-common-obj-$(CONFIG_ASPEED_SOC) += aspeed_timer.o
diff --git a/qemu/hw/timer/a9gtimer.c b/qemu/hw/timer/a9gtimer.c
deleted file mode 100644
index afe577c76..000000000
--- a/qemu/hw/timer/a9gtimer.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Global peripheral timer block for ARM A9MP
- *
- * (C) 2013 Xilinx Inc.
- *
- * Written by François LEGAL
- * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "hw/timer/a9gtimer.h"
-#include "qapi/error.h"
-#include "qemu/timer.h"
-#include "qemu/bitops.h"
-#include "qemu/log.h"
-#include "qom/cpu.h"
-
-#ifndef A9_GTIMER_ERR_DEBUG
-#define A9_GTIMER_ERR_DEBUG 0
-#endif
-
-#define DB_PRINT_L(level, ...) do { \
- if (A9_GTIMER_ERR_DEBUG > (level)) { \
- fprintf(stderr, ": %s: ", __func__); \
- fprintf(stderr, ## __VA_ARGS__); \
- } \
-} while (0);
-
-#define DB_PRINT(...) DB_PRINT_L(0, ## __VA_ARGS__)
-
-static inline int a9_gtimer_get_current_cpu(A9GTimerState *s)
-{
- if (current_cpu->cpu_index >= s->num_cpu) {
- hw_error("a9gtimer: num-cpu %d but this cpu is %d!\n",
- s->num_cpu, current_cpu->cpu_index);
- }
- return current_cpu->cpu_index;
-}
-
-static inline uint64_t a9_gtimer_get_conv(A9GTimerState *s)
-{
- uint64_t prescale = extract32(s->control, R_CONTROL_PRESCALER_SHIFT,
- R_CONTROL_PRESCALER_LEN);
-
- return (prescale + 1) * 10;
-}
-
-static A9GTimerUpdate a9_gtimer_get_update(A9GTimerState *s)
-{
- A9GTimerUpdate ret;
-
- ret.now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- ret.new = s->ref_counter +
- (ret.now - s->cpu_ref_time) / a9_gtimer_get_conv(s);
- return ret;
-}
-
-static void a9_gtimer_update(A9GTimerState *s, bool sync)
-{
-
- A9GTimerUpdate update = a9_gtimer_get_update(s);
- int i;
- int64_t next_cdiff = 0;
-
- for (i = 0; i < s->num_cpu; ++i) {
- A9GTimerPerCPU *gtb = &s->per_cpu[i];
- int64_t cdiff = 0;
-
- if ((s->control & R_CONTROL_TIMER_ENABLE) &&
- (gtb->control & R_CONTROL_COMP_ENABLE)) {
- /* R2p0+, where the compare function is >= */
- while (gtb->compare < update.new) {
- DB_PRINT("Compare event happened for CPU %d\n", i);
- gtb->status = 1;
- if (gtb->control & R_CONTROL_AUTO_INCREMENT) {
- DB_PRINT("Auto incrementing timer compare by %" PRId32 "\n",
- gtb->inc);
- gtb->compare += gtb->inc;
- } else {
- break;
- }
- }
- cdiff = (int64_t)gtb->compare - (int64_t)update.new + 1;
- if (cdiff > 0 && (cdiff < next_cdiff || !next_cdiff)) {
- next_cdiff = cdiff;
- }
- }
-
- qemu_set_irq(gtb->irq,
- gtb->status && (gtb->control & R_CONTROL_IRQ_ENABLE));
- }
-
- timer_del(s->timer);
- if (next_cdiff) {
- DB_PRINT("scheduling qemu_timer to fire again in %"
- PRIx64 " cycles\n", next_cdiff);
- timer_mod(s->timer, update.now + next_cdiff * a9_gtimer_get_conv(s));
- }
-
- if (s->control & R_CONTROL_TIMER_ENABLE) {
- s->counter = update.new;
- }
-
- if (sync) {
- s->cpu_ref_time = update.now;
- s->ref_counter = s->counter;
- }
-}
-
-static void a9_gtimer_update_no_sync(void *opaque)
-{
- A9GTimerState *s = A9_GTIMER(opaque);
-
- a9_gtimer_update(s, false);
-}
-
-static uint64_t a9_gtimer_read(void *opaque, hwaddr addr, unsigned size)
-{
- A9GTimerPerCPU *gtb = (A9GTimerPerCPU *)opaque;
- A9GTimerState *s = gtb->parent;
- A9GTimerUpdate update;
- uint64_t ret = 0;
- int shift = 0;
-
- switch (addr) {
- case R_COUNTER_HI:
- shift = 32;
- /* fallthrough */
- case R_COUNTER_LO:
- update = a9_gtimer_get_update(s);
- ret = extract64(update.new, shift, 32);
- break;
- case R_CONTROL:
- ret = s->control | gtb->control;
- break;
- case R_INTERRUPT_STATUS:
- ret = gtb->status;
- break;
- case R_COMPARATOR_HI:
- shift = 32;
- /* fallthrough */
- case R_COMPARATOR_LO:
- ret = extract64(gtb->compare, shift, 32);
- break;
- case R_AUTO_INCREMENT:
- ret = gtb->inc;
- break;
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "bad a9gtimer register: %x\n",
- (unsigned)addr);
- return 0;
- }
-
- DB_PRINT("addr:%#x data:%#08" PRIx64 "\n", (unsigned)addr, ret);
- return ret;
-}
-
-static void a9_gtimer_write(void *opaque, hwaddr addr, uint64_t value,
- unsigned size)
-{
- A9GTimerPerCPU *gtb = (A9GTimerPerCPU *)opaque;
- A9GTimerState *s = gtb->parent;
- int shift = 0;
-
- DB_PRINT("addr:%#x data:%#08" PRIx64 "\n", (unsigned)addr, value);
-
- switch (addr) {
- case R_COUNTER_HI:
- shift = 32;
- /* fallthrough */
- case R_COUNTER_LO:
- /*
- * Keep it simple - ARM docco explicitly says to disable timer before
- * modding it, so dont bother trying to do all the difficult on the fly
- * timer modifications - (if they even work in real hardware??).
- */
- if (s->control & R_CONTROL_TIMER_ENABLE) {
- qemu_log_mask(LOG_GUEST_ERROR, "Cannot mod running ARM gtimer\n");
- return;
- }
- s->counter = deposit64(s->counter, shift, 32, value);
- return;
- case R_CONTROL:
- a9_gtimer_update(s, (value ^ s->control) & R_CONTROL_NEEDS_SYNC);
- gtb->control = value & R_CONTROL_BANKED;
- s->control = value & ~R_CONTROL_BANKED;
- break;
- case R_INTERRUPT_STATUS:
- a9_gtimer_update(s, false);
- gtb->status &= ~value;
- break;
- case R_COMPARATOR_HI:
- shift = 32;
- /* fallthrough */
- case R_COMPARATOR_LO:
- a9_gtimer_update(s, false);
- gtb->compare = deposit64(gtb->compare, shift, 32, value);
- break;
- case R_AUTO_INCREMENT:
- gtb->inc = value;
- return;
- default:
- return;
- }
-
- a9_gtimer_update(s, false);
-}
-
-/* Wrapper functions to implement the "read global timer for
- * the current CPU" memory regions.
- */
-static uint64_t a9_gtimer_this_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- A9GTimerState *s = A9_GTIMER(opaque);
- int id = a9_gtimer_get_current_cpu(s);
-
- /* no \n so concatenates with message from read fn */
- DB_PRINT("CPU:%d:", id);
-
- return a9_gtimer_read(&s->per_cpu[id], addr, size);
-}
-
-static void a9_gtimer_this_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- A9GTimerState *s = A9_GTIMER(opaque);
- int id = a9_gtimer_get_current_cpu(s);
-
- /* no \n so concatenates with message from write fn */
- DB_PRINT("CPU:%d:", id);
-
- a9_gtimer_write(&s->per_cpu[id], addr, value, size);
-}
-
-static const MemoryRegionOps a9_gtimer_this_ops = {
- .read = a9_gtimer_this_read,
- .write = a9_gtimer_this_write,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const MemoryRegionOps a9_gtimer_ops = {
- .read = a9_gtimer_read,
- .write = a9_gtimer_write,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void a9_gtimer_reset(DeviceState *dev)
-{
- A9GTimerState *s = A9_GTIMER(dev);
- int i;
-
- s->counter = 0;
- s->control = 0;
-
- for (i = 0; i < s->num_cpu; i++) {
- A9GTimerPerCPU *gtb = &s->per_cpu[i];
-
- gtb->control = 0;
- gtb->status = 0;
- gtb->compare = 0;
- gtb->inc = 0;
- }
- a9_gtimer_update(s, false);
-}
-
-static void a9_gtimer_realize(DeviceState *dev, Error **errp)
-{
- A9GTimerState *s = A9_GTIMER(dev);
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- int i;
-
- if (s->num_cpu < 1 || s->num_cpu > A9_GTIMER_MAX_CPUS) {
- error_setg(errp, "%s: num-cpu must be between 1 and %d",
- __func__, A9_GTIMER_MAX_CPUS);
- return;
- }
-
- memory_region_init_io(&s->iomem, OBJECT(dev), &a9_gtimer_this_ops, s,
- "a9gtimer shared", 0x20);
- sysbus_init_mmio(sbd, &s->iomem);
- s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, a9_gtimer_update_no_sync, s);
-
- for (i = 0; i < s->num_cpu; i++) {
- A9GTimerPerCPU *gtb = &s->per_cpu[i];
-
- gtb->parent = s;
- sysbus_init_irq(sbd, &gtb->irq);
- memory_region_init_io(&gtb->iomem, OBJECT(dev), &a9_gtimer_ops, gtb,
- "a9gtimer per cpu", 0x20);
- sysbus_init_mmio(sbd, &gtb->iomem);
- }
-}
-
-static const VMStateDescription vmstate_a9_gtimer_per_cpu = {
- .name = "arm.cortex-a9-global-timer.percpu",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(control, A9GTimerPerCPU),
- VMSTATE_UINT64(compare, A9GTimerPerCPU),
- VMSTATE_UINT32(status, A9GTimerPerCPU),
- VMSTATE_UINT32(inc, A9GTimerPerCPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_a9_gtimer = {
- .name = "arm.cortex-a9-global-timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_TIMER_PTR(timer, A9GTimerState),
- VMSTATE_UINT64(counter, A9GTimerState),
- VMSTATE_UINT64(ref_counter, A9GTimerState),
- VMSTATE_UINT64(cpu_ref_time, A9GTimerState),
- VMSTATE_STRUCT_VARRAY_UINT32(per_cpu, A9GTimerState, num_cpu,
- 1, vmstate_a9_gtimer_per_cpu,
- A9GTimerPerCPU),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static Property a9_gtimer_properties[] = {
- DEFINE_PROP_UINT32("num-cpu", A9GTimerState, num_cpu, 0),
- DEFINE_PROP_END_OF_LIST()
-};
-
-static void a9_gtimer_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = a9_gtimer_realize;
- dc->vmsd = &vmstate_a9_gtimer;
- dc->reset = a9_gtimer_reset;
- dc->props = a9_gtimer_properties;
-}
-
-static const TypeInfo a9_gtimer_info = {
- .name = TYPE_A9_GTIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(A9GTimerState),
- .class_init = a9_gtimer_class_init,
-};
-
-static void a9_gtimer_register_types(void)
-{
- type_register_static(&a9_gtimer_info);
-}
-
-type_init(a9_gtimer_register_types)
diff --git a/qemu/hw/timer/allwinner-a10-pit.c b/qemu/hw/timer/allwinner-a10-pit.c
deleted file mode 100644
index 51cdc98f3..000000000
--- a/qemu/hw/timer/allwinner-a10-pit.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Allwinner A10 timer device emulation
- *
- * Copyright (C) 2013 Li Guang
- * Written by Li Guang <lig.fnst@cn.fujitsu.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "sysemu/sysemu.h"
-#include "hw/timer/allwinner-a10-pit.h"
-
-static void a10_pit_update_irq(AwA10PITState *s)
-{
- int i;
-
- for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
- qemu_set_irq(s->irq[i], !!(s->irq_status & s->irq_enable & (1 << i)));
- }
-}
-
-static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
-{
- AwA10PITState *s = AW_A10_PIT(opaque);
- uint8_t index;
-
- switch (offset) {
- case AW_A10_PIT_TIMER_IRQ_EN:
- return s->irq_enable;
- case AW_A10_PIT_TIMER_IRQ_ST:
- return s->irq_status;
- case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE_END:
- index = offset & 0xf0;
- index >>= 4;
- index -= 1;
- switch (offset & 0x0f) {
- case AW_A10_PIT_TIMER_CONTROL:
- return s->control[index];
- case AW_A10_PIT_TIMER_INTERVAL:
- return s->interval[index];
- case AW_A10_PIT_TIMER_COUNT:
- s->count[index] = ptimer_get_count(s->timer[index]);
- return s->count[index];
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset 0x%x\n", __func__, (int)offset);
- break;
- }
- case AW_A10_PIT_WDOG_CONTROL:
- break;
- case AW_A10_PIT_WDOG_MODE:
- break;
- case AW_A10_PIT_COUNT_LO:
- return s->count_lo;
- case AW_A10_PIT_COUNT_HI:
- return s->count_hi;
- case AW_A10_PIT_COUNT_CTL:
- return s->count_ctl;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset 0x%x\n", __func__, (int)offset);
- break;
- }
-
- return 0;
-}
-
-static void a10_pit_set_freq(AwA10PITState *s, int index)
-{
- uint32_t prescaler, source, source_freq;
-
- prescaler = 1 << extract32(s->control[index], 4, 3);
- source = extract32(s->control[index], 2, 2);
- source_freq = s->clk_freq[source];
-
- if (source_freq) {
- ptimer_set_freq(s->timer[index], source_freq / prescaler);
- } else {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid clock source %u\n",
- __func__, source);
- }
-}
-
-static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- AwA10PITState *s = AW_A10_PIT(opaque);
- uint8_t index;
-
- switch (offset) {
- case AW_A10_PIT_TIMER_IRQ_EN:
- s->irq_enable = value;
- a10_pit_update_irq(s);
- break;
- case AW_A10_PIT_TIMER_IRQ_ST:
- s->irq_status &= ~value;
- a10_pit_update_irq(s);
- break;
- case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE_END:
- index = offset & 0xf0;
- index >>= 4;
- index -= 1;
- switch (offset & 0x0f) {
- case AW_A10_PIT_TIMER_CONTROL:
- s->control[index] = value;
- a10_pit_set_freq(s, index);
- if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
- ptimer_set_count(s->timer[index], s->interval[index]);
- }
- if (s->control[index] & AW_A10_PIT_TIMER_EN) {
- int oneshot = 0;
- if (s->control[index] & AW_A10_PIT_TIMER_MODE) {
- oneshot = 1;
- }
- ptimer_run(s->timer[index], oneshot);
- } else {
- ptimer_stop(s->timer[index]);
- }
- break;
- case AW_A10_PIT_TIMER_INTERVAL:
- s->interval[index] = value;
- ptimer_set_limit(s->timer[index], s->interval[index], 1);
- break;
- case AW_A10_PIT_TIMER_COUNT:
- s->count[index] = value;
- break;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset 0x%x\n", __func__, (int)offset);
- }
- break;
- case AW_A10_PIT_WDOG_CONTROL:
- s->watch_dog_control = value;
- break;
- case AW_A10_PIT_WDOG_MODE:
- s->watch_dog_mode = value;
- break;
- case AW_A10_PIT_COUNT_LO:
- s->count_lo = value;
- break;
- case AW_A10_PIT_COUNT_HI:
- s->count_hi = value;
- break;
- case AW_A10_PIT_COUNT_CTL:
- s->count_ctl = value;
- if (s->count_ctl & AW_A10_PIT_COUNT_RL_EN) {
- uint64_t tmp_count = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
- s->count_lo = tmp_count;
- s->count_hi = tmp_count >> 32;
- s->count_ctl &= ~AW_A10_PIT_COUNT_RL_EN;
- }
- if (s->count_ctl & AW_A10_PIT_COUNT_CLR_EN) {
- s->count_lo = 0;
- s->count_hi = 0;
- s->count_ctl &= ~AW_A10_PIT_COUNT_CLR_EN;
- }
- break;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset 0x%x\n", __func__, (int)offset);
- break;
- }
-}
-
-static const MemoryRegionOps a10_pit_ops = {
- .read = a10_pit_read,
- .write = a10_pit_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static Property a10_pit_properties[] = {
- DEFINE_PROP_UINT32("clk0-freq", AwA10PITState, clk_freq[0], 0),
- DEFINE_PROP_UINT32("clk1-freq", AwA10PITState, clk_freq[1], 0),
- DEFINE_PROP_UINT32("clk2-freq", AwA10PITState, clk_freq[2], 0),
- DEFINE_PROP_UINT32("clk3-freq", AwA10PITState, clk_freq[3], 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static const VMStateDescription vmstate_a10_pit = {
- .name = "a10.pit",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(irq_enable, AwA10PITState),
- VMSTATE_UINT32(irq_status, AwA10PITState),
- VMSTATE_UINT32_ARRAY(control, AwA10PITState, AW_A10_PIT_TIMER_NR),
- VMSTATE_UINT32_ARRAY(interval, AwA10PITState, AW_A10_PIT_TIMER_NR),
- VMSTATE_UINT32_ARRAY(count, AwA10PITState, AW_A10_PIT_TIMER_NR),
- VMSTATE_UINT32(watch_dog_mode, AwA10PITState),
- VMSTATE_UINT32(watch_dog_control, AwA10PITState),
- VMSTATE_UINT32(count_lo, AwA10PITState),
- VMSTATE_UINT32(count_hi, AwA10PITState),
- VMSTATE_UINT32(count_ctl, AwA10PITState),
- VMSTATE_PTIMER_ARRAY(timer, AwA10PITState, AW_A10_PIT_TIMER_NR),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void a10_pit_reset(DeviceState *dev)
-{
- AwA10PITState *s = AW_A10_PIT(dev);
- uint8_t i;
-
- s->irq_enable = 0;
- s->irq_status = 0;
- a10_pit_update_irq(s);
-
- for (i = 0; i < 6; i++) {
- s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
- s->interval[i] = 0;
- s->count[i] = 0;
- ptimer_stop(s->timer[i]);
- a10_pit_set_freq(s, i);
- }
- s->watch_dog_mode = 0;
- s->watch_dog_control = 0;
- s->count_lo = 0;
- s->count_hi = 0;
- s->count_ctl = 0;
-}
-
-static void a10_pit_timer_cb(void *opaque)
-{
- AwA10TimerContext *tc = opaque;
- AwA10PITState *s = tc->container;
- uint8_t i = tc->index;
-
- if (s->control[i] & AW_A10_PIT_TIMER_EN) {
- s->irq_status |= 1 << i;
- if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
- ptimer_stop(s->timer[i]);
- s->control[i] &= ~AW_A10_PIT_TIMER_EN;
- }
- a10_pit_update_irq(s);
- }
-}
-
-static void a10_pit_init(Object *obj)
-{
- AwA10PITState *s = AW_A10_PIT(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- QEMUBH * bh[AW_A10_PIT_TIMER_NR];
- uint8_t i;
-
- for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
- sysbus_init_irq(sbd, &s->irq[i]);
- }
- memory_region_init_io(&s->iomem, OBJECT(s), &a10_pit_ops, s,
- TYPE_AW_A10_PIT, 0x400);
- sysbus_init_mmio(sbd, &s->iomem);
-
- for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
- AwA10TimerContext *tc = &s->timer_context[i];
-
- tc->container = s;
- tc->index = i;
- bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
- s->timer[i] = ptimer_init(bh[i]);
- }
-}
-
-static void a10_pit_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->reset = a10_pit_reset;
- dc->props = a10_pit_properties;
- dc->desc = "allwinner a10 timer";
- dc->vmsd = &vmstate_a10_pit;
-}
-
-static const TypeInfo a10_pit_info = {
- .name = TYPE_AW_A10_PIT,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(AwA10PITState),
- .instance_init = a10_pit_init,
- .class_init = a10_pit_class_init,
-};
-
-static void a10_register_types(void)
-{
- type_register_static(&a10_pit_info);
-}
-
-type_init(a10_register_types);
diff --git a/qemu/hw/timer/arm_mptimer.c b/qemu/hw/timer/arm_mptimer.c
deleted file mode 100644
index d66bbf01b..000000000
--- a/qemu/hw/timer/arm_mptimer.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Private peripheral timer/watchdog blocks for ARM 11MPCore and A9MP
- *
- * Copyright (c) 2006-2007 CodeSourcery.
- * Copyright (c) 2011 Linaro Limited
- * Written by Paul Brook, Peter Maydell
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "hw/timer/arm_mptimer.h"
-#include "qapi/error.h"
-#include "qemu/timer.h"
-#include "qom/cpu.h"
-
-/* This device implements the per-cpu private timer and watchdog block
- * which is used in both the ARM11MPCore and Cortex-A9MP.
- */
-
-static inline int get_current_cpu(ARMMPTimerState *s)
-{
- if (current_cpu->cpu_index >= s->num_cpu) {
- hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",
- s->num_cpu, current_cpu->cpu_index);
- }
- return current_cpu->cpu_index;
-}
-
-static inline void timerblock_update_irq(TimerBlock *tb)
-{
- qemu_set_irq(tb->irq, tb->status && (tb->control & 4));
-}
-
-/* Return conversion factor from mpcore timer ticks to qemu timer ticks. */
-static inline uint32_t timerblock_scale(TimerBlock *tb)
-{
- return (((tb->control >> 8) & 0xff) + 1) * 10;
-}
-
-static void timerblock_reload(TimerBlock *tb, int restart)
-{
- if (tb->count == 0) {
- return;
- }
- if (restart) {
- tb->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- }
- tb->tick += (int64_t)tb->count * timerblock_scale(tb);
- timer_mod(tb->timer, tb->tick);
-}
-
-static void timerblock_tick(void *opaque)
-{
- TimerBlock *tb = (TimerBlock *)opaque;
- tb->status = 1;
- if (tb->control & 2) {
- tb->count = tb->load;
- timerblock_reload(tb, 0);
- } else {
- tb->count = 0;
- }
- timerblock_update_irq(tb);
-}
-
-static uint64_t timerblock_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- TimerBlock *tb = (TimerBlock *)opaque;
- int64_t val;
- switch (addr) {
- case 0: /* Load */
- return tb->load;
- case 4: /* Counter. */
- if (((tb->control & 1) == 0) || (tb->count == 0)) {
- return 0;
- }
- /* Slow and ugly, but hopefully won't happen too often. */
- val = tb->tick - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- val /= timerblock_scale(tb);
- if (val < 0) {
- val = 0;
- }
- return val;
- case 8: /* Control. */
- return tb->control;
- case 12: /* Interrupt status. */
- return tb->status;
- default:
- return 0;
- }
-}
-
-static void timerblock_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- TimerBlock *tb = (TimerBlock *)opaque;
- int64_t old;
- switch (addr) {
- case 0: /* Load */
- tb->load = value;
- /* Fall through. */
- case 4: /* Counter. */
- if ((tb->control & 1) && tb->count) {
- /* Cancel the previous timer. */
- timer_del(tb->timer);
- }
- tb->count = value;
- if (tb->control & 1) {
- timerblock_reload(tb, 1);
- }
- break;
- case 8: /* Control. */
- old = tb->control;
- tb->control = value;
- if (value & 1) {
- if ((old & 1) && (tb->count != 0)) {
- /* Do nothing if timer is ticking right now. */
- break;
- }
- if (tb->control & 2) {
- tb->count = tb->load;
- }
- timerblock_reload(tb, 1);
- } else if (old & 1) {
- /* Shutdown the timer. */
- timer_del(tb->timer);
- }
- break;
- case 12: /* Interrupt status. */
- tb->status &= ~value;
- timerblock_update_irq(tb);
- break;
- }
-}
-
-/* Wrapper functions to implement the "read timer/watchdog for
- * the current CPU" memory regions.
- */
-static uint64_t arm_thistimer_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- ARMMPTimerState *s = (ARMMPTimerState *)opaque;
- int id = get_current_cpu(s);
- return timerblock_read(&s->timerblock[id], addr, size);
-}
-
-static void arm_thistimer_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- ARMMPTimerState *s = (ARMMPTimerState *)opaque;
- int id = get_current_cpu(s);
- timerblock_write(&s->timerblock[id], addr, value, size);
-}
-
-static const MemoryRegionOps arm_thistimer_ops = {
- .read = arm_thistimer_read,
- .write = arm_thistimer_write,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const MemoryRegionOps timerblock_ops = {
- .read = timerblock_read,
- .write = timerblock_write,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void timerblock_reset(TimerBlock *tb)
-{
- tb->count = 0;
- tb->load = 0;
- tb->control = 0;
- tb->status = 0;
- tb->tick = 0;
- if (tb->timer) {
- timer_del(tb->timer);
- }
-}
-
-static void arm_mptimer_reset(DeviceState *dev)
-{
- ARMMPTimerState *s = ARM_MPTIMER(dev);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(s->timerblock); i++) {
- timerblock_reset(&s->timerblock[i]);
- }
-}
-
-static void arm_mptimer_init(Object *obj)
-{
- ARMMPTimerState *s = ARM_MPTIMER(obj);
-
- memory_region_init_io(&s->iomem, obj, &arm_thistimer_ops, s,
- "arm_mptimer_timer", 0x20);
- sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
-}
-
-static void arm_mptimer_realize(DeviceState *dev, Error **errp)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- ARMMPTimerState *s = ARM_MPTIMER(dev);
- int i;
-
- if (s->num_cpu < 1 || s->num_cpu > ARM_MPTIMER_MAX_CPUS) {
- error_setg(errp, "num-cpu must be between 1 and %d",
- ARM_MPTIMER_MAX_CPUS);
- return;
- }
- /* We implement one timer block per CPU, and expose multiple MMIO regions:
- * * region 0 is "timer for this core"
- * * region 1 is "timer for core 0"
- * * region 2 is "timer for core 1"
- * and so on.
- * The outgoing interrupt lines are
- * * timer for core 0
- * * timer for core 1
- * and so on.
- */
- for (i = 0; i < s->num_cpu; i++) {
- TimerBlock *tb = &s->timerblock[i];
- tb->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, timerblock_tick, tb);
- sysbus_init_irq(sbd, &tb->irq);
- memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
- "arm_mptimer_timerblock", 0x20);
- sysbus_init_mmio(sbd, &tb->iomem);
- }
-}
-
-static const VMStateDescription vmstate_timerblock = {
- .name = "arm_mptimer_timerblock",
- .version_id = 2,
- .minimum_version_id = 2,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(count, TimerBlock),
- VMSTATE_UINT32(load, TimerBlock),
- VMSTATE_UINT32(control, TimerBlock),
- VMSTATE_UINT32(status, TimerBlock),
- VMSTATE_INT64(tick, TimerBlock),
- VMSTATE_TIMER_PTR(timer, TimerBlock),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_arm_mptimer = {
- .name = "arm_mptimer",
- .version_id = 2,
- .minimum_version_id = 2,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT_VARRAY_UINT32(timerblock, ARMMPTimerState, num_cpu,
- 2, vmstate_timerblock, TimerBlock),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static Property arm_mptimer_properties[] = {
- DEFINE_PROP_UINT32("num-cpu", ARMMPTimerState, num_cpu, 0),
- DEFINE_PROP_END_OF_LIST()
-};
-
-static void arm_mptimer_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = arm_mptimer_realize;
- dc->vmsd = &vmstate_arm_mptimer;
- dc->reset = arm_mptimer_reset;
- dc->props = arm_mptimer_properties;
-}
-
-static const TypeInfo arm_mptimer_info = {
- .name = TYPE_ARM_MPTIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(ARMMPTimerState),
- .instance_init = arm_mptimer_init,
- .class_init = arm_mptimer_class_init,
-};
-
-static void arm_mptimer_register_types(void)
-{
- type_register_static(&arm_mptimer_info);
-}
-
-type_init(arm_mptimer_register_types)
diff --git a/qemu/hw/timer/arm_timer.c b/qemu/hw/timer/arm_timer.c
deleted file mode 100644
index f1ede5f53..000000000
--- a/qemu/hw/timer/arm_timer.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * ARM PrimeCell Timer modules.
- *
- * Copyright (c) 2005-2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GPL.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "qemu/timer.h"
-#include "qemu-common.h"
-#include "hw/qdev.h"
-#include "hw/ptimer.h"
-#include "qemu/main-loop.h"
-
-/* Common timer implementation. */
-
-#define TIMER_CTRL_ONESHOT (1 << 0)
-#define TIMER_CTRL_32BIT (1 << 1)
-#define TIMER_CTRL_DIV1 (0 << 2)
-#define TIMER_CTRL_DIV16 (1 << 2)
-#define TIMER_CTRL_DIV256 (2 << 2)
-#define TIMER_CTRL_IE (1 << 5)
-#define TIMER_CTRL_PERIODIC (1 << 6)
-#define TIMER_CTRL_ENABLE (1 << 7)
-
-typedef struct {
- ptimer_state *timer;
- uint32_t control;
- uint32_t limit;
- int freq;
- int int_level;
- qemu_irq irq;
-} arm_timer_state;
-
-/* Check all active timers, and schedule the next timer interrupt. */
-
-static void arm_timer_update(arm_timer_state *s)
-{
- /* Update interrupts. */
- if (s->int_level && (s->control & TIMER_CTRL_IE)) {
- qemu_irq_raise(s->irq);
- } else {
- qemu_irq_lower(s->irq);
- }
-}
-
-static uint32_t arm_timer_read(void *opaque, hwaddr offset)
-{
- arm_timer_state *s = (arm_timer_state *)opaque;
-
- switch (offset >> 2) {
- case 0: /* TimerLoad */
- case 6: /* TimerBGLoad */
- return s->limit;
- case 1: /* TimerValue */
- return ptimer_get_count(s->timer);
- case 2: /* TimerControl */
- return s->control;
- case 4: /* TimerRIS */
- return s->int_level;
- case 5: /* TimerMIS */
- if ((s->control & TIMER_CTRL_IE) == 0)
- return 0;
- return s->int_level;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset %x\n", __func__, (int)offset);
- return 0;
- }
-}
-
-/* Reset the timer limit after settings have changed. */
-static void arm_timer_recalibrate(arm_timer_state *s, int reload)
-{
- uint32_t limit;
-
- if ((s->control & (TIMER_CTRL_PERIODIC | TIMER_CTRL_ONESHOT)) == 0) {
- /* Free running. */
- if (s->control & TIMER_CTRL_32BIT)
- limit = 0xffffffff;
- else
- limit = 0xffff;
- } else {
- /* Periodic. */
- limit = s->limit;
- }
- ptimer_set_limit(s->timer, limit, reload);
-}
-
-static void arm_timer_write(void *opaque, hwaddr offset,
- uint32_t value)
-{
- arm_timer_state *s = (arm_timer_state *)opaque;
- int freq;
-
- switch (offset >> 2) {
- case 0: /* TimerLoad */
- s->limit = value;
- arm_timer_recalibrate(s, 1);
- break;
- case 1: /* TimerValue */
- /* ??? Linux seems to want to write to this readonly register.
- Ignore it. */
- break;
- case 2: /* TimerControl */
- if (s->control & TIMER_CTRL_ENABLE) {
- /* Pause the timer if it is running. This may cause some
- inaccuracy dure to rounding, but avoids a whole lot of other
- messyness. */
- ptimer_stop(s->timer);
- }
- s->control = value;
- freq = s->freq;
- /* ??? Need to recalculate expiry time after changing divisor. */
- switch ((value >> 2) & 3) {
- case 1: freq >>= 4; break;
- case 2: freq >>= 8; break;
- }
- arm_timer_recalibrate(s, s->control & TIMER_CTRL_ENABLE);
- ptimer_set_freq(s->timer, freq);
- if (s->control & TIMER_CTRL_ENABLE) {
- /* Restart the timer if still enabled. */
- ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
- }
- break;
- case 3: /* TimerIntClr */
- s->int_level = 0;
- break;
- case 6: /* TimerBGLoad */
- s->limit = value;
- arm_timer_recalibrate(s, 0);
- break;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset %x\n", __func__, (int)offset);
- }
- arm_timer_update(s);
-}
-
-static void arm_timer_tick(void *opaque)
-{
- arm_timer_state *s = (arm_timer_state *)opaque;
- s->int_level = 1;
- arm_timer_update(s);
-}
-
-static const VMStateDescription vmstate_arm_timer = {
- .name = "arm_timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(control, arm_timer_state),
- VMSTATE_UINT32(limit, arm_timer_state),
- VMSTATE_INT32(int_level, arm_timer_state),
- VMSTATE_PTIMER(timer, arm_timer_state),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static arm_timer_state *arm_timer_init(uint32_t freq)
-{
- arm_timer_state *s;
- QEMUBH *bh;
-
- s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
- s->freq = freq;
- s->control = TIMER_CTRL_IE;
-
- bh = qemu_bh_new(arm_timer_tick, s);
- s->timer = ptimer_init(bh);
- vmstate_register(NULL, -1, &vmstate_arm_timer, s);
- return s;
-}
-
-/* ARM PrimeCell SP804 dual timer module.
- * Docs at
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
-*/
-
-#define TYPE_SP804 "sp804"
-#define SP804(obj) OBJECT_CHECK(SP804State, (obj), TYPE_SP804)
-
-typedef struct SP804State {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- arm_timer_state *timer[2];
- uint32_t freq0, freq1;
- int level[2];
- qemu_irq irq;
-} SP804State;
-
-static const uint8_t sp804_ids[] = {
- /* Timer ID */
- 0x04, 0x18, 0x14, 0,
- /* PrimeCell ID */
- 0xd, 0xf0, 0x05, 0xb1
-};
-
-/* Merge the IRQs from the two component devices. */
-static void sp804_set_irq(void *opaque, int irq, int level)
-{
- SP804State *s = (SP804State *)opaque;
-
- s->level[irq] = level;
- qemu_set_irq(s->irq, s->level[0] || s->level[1]);
-}
-
-static uint64_t sp804_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- SP804State *s = (SP804State *)opaque;
-
- if (offset < 0x20) {
- return arm_timer_read(s->timer[0], offset);
- }
- if (offset < 0x40) {
- return arm_timer_read(s->timer[1], offset - 0x20);
- }
-
- /* TimerPeriphID */
- if (offset >= 0xfe0 && offset <= 0xffc) {
- return sp804_ids[(offset - 0xfe0) >> 2];
- }
-
- switch (offset) {
- /* Integration Test control registers, which we won't support */
- case 0xf00: /* TimerITCR */
- case 0xf04: /* TimerITOP (strictly write only but..) */
- qemu_log_mask(LOG_UNIMP,
- "%s: integration test registers unimplemented\n",
- __func__);
- return 0;
- }
-
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset %x\n", __func__, (int)offset);
- return 0;
-}
-
-static void sp804_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- SP804State *s = (SP804State *)opaque;
-
- if (offset < 0x20) {
- arm_timer_write(s->timer[0], offset, value);
- return;
- }
-
- if (offset < 0x40) {
- arm_timer_write(s->timer[1], offset - 0x20, value);
- return;
- }
-
- /* Technically we could be writing to the Test Registers, but not likely */
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %x\n",
- __func__, (int)offset);
-}
-
-static const MemoryRegionOps sp804_ops = {
- .read = sp804_read,
- .write = sp804_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_sp804 = {
- .name = "sp804",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_INT32_ARRAY(level, SP804State, 2),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void sp804_init(Object *obj)
-{
- SP804State *s = SP804(obj);
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-
- sysbus_init_irq(sbd, &s->irq);
- memory_region_init_io(&s->iomem, obj, &sp804_ops, s,
- "sp804", 0x1000);
- sysbus_init_mmio(sbd, &s->iomem);
-}
-
-static void sp804_realize(DeviceState *dev, Error **errp)
-{
- SP804State *s = SP804(dev);
-
- s->timer[0] = arm_timer_init(s->freq0);
- s->timer[1] = arm_timer_init(s->freq1);
- s->timer[0]->irq = qemu_allocate_irq(sp804_set_irq, s, 0);
- s->timer[1]->irq = qemu_allocate_irq(sp804_set_irq, s, 1);
-}
-
-/* Integrator/CP timer module. */
-
-#define TYPE_INTEGRATOR_PIT "integrator_pit"
-#define INTEGRATOR_PIT(obj) \
- OBJECT_CHECK(icp_pit_state, (obj), TYPE_INTEGRATOR_PIT)
-
-typedef struct {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- arm_timer_state *timer[3];
-} icp_pit_state;
-
-static uint64_t icp_pit_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- icp_pit_state *s = (icp_pit_state *)opaque;
- int n;
-
- /* ??? Don't know the PrimeCell ID for this device. */
- n = offset >> 8;
- if (n > 2) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
- return 0;
- }
-
- return arm_timer_read(s->timer[n], offset & 0xff);
-}
-
-static void icp_pit_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- icp_pit_state *s = (icp_pit_state *)opaque;
- int n;
-
- n = offset >> 8;
- if (n > 2) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
- return;
- }
-
- arm_timer_write(s->timer[n], offset & 0xff, value);
-}
-
-static const MemoryRegionOps icp_pit_ops = {
- .read = icp_pit_read,
- .write = icp_pit_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void icp_pit_init(Object *obj)
-{
- icp_pit_state *s = INTEGRATOR_PIT(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-
- /* Timer 0 runs at the system clock speed (40MHz). */
- s->timer[0] = arm_timer_init(40000000);
- /* The other two timers run at 1MHz. */
- s->timer[1] = arm_timer_init(1000000);
- s->timer[2] = arm_timer_init(1000000);
-
- sysbus_init_irq(dev, &s->timer[0]->irq);
- sysbus_init_irq(dev, &s->timer[1]->irq);
- sysbus_init_irq(dev, &s->timer[2]->irq);
-
- memory_region_init_io(&s->iomem, obj, &icp_pit_ops, s,
- "icp_pit", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- /* This device has no state to save/restore. The component timers will
- save themselves. */
-}
-
-static const TypeInfo icp_pit_info = {
- .name = TYPE_INTEGRATOR_PIT,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(icp_pit_state),
- .instance_init = icp_pit_init,
-};
-
-static Property sp804_properties[] = {
- DEFINE_PROP_UINT32("freq0", SP804State, freq0, 1000000),
- DEFINE_PROP_UINT32("freq1", SP804State, freq1, 1000000),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void sp804_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *k = DEVICE_CLASS(klass);
-
- k->realize = sp804_realize;
- k->props = sp804_properties;
- k->vmsd = &vmstate_sp804;
-}
-
-static const TypeInfo sp804_info = {
- .name = TYPE_SP804,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(SP804State),
- .instance_init = sp804_init,
- .class_init = sp804_class_init,
-};
-
-static void arm_timer_register_types(void)
-{
- type_register_static(&icp_pit_info);
- type_register_static(&sp804_info);
-}
-
-type_init(arm_timer_register_types)
diff --git a/qemu/hw/timer/aspeed_timer.c b/qemu/hw/timer/aspeed_timer.c
deleted file mode 100644
index 51e8303cd..000000000
--- a/qemu/hw/timer/aspeed_timer.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * ASPEED AST2400 Timer
- *
- * Andrew Jeffery <andrew@aj.id.au>
- *
- * Copyright (C) 2016 IBM Corp.
- *
- * This code is licensed under the GPL version 2 or later. See
- * the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "hw/ptimer.h"
-#include "hw/sysbus.h"
-#include "hw/timer/aspeed_timer.h"
-#include "qemu-common.h"
-#include "qemu/bitops.h"
-#include "qemu/main-loop.h"
-#include "qemu/timer.h"
-#include "trace.h"
-
-#define TIMER_NR_REGS 4
-
-#define TIMER_CTRL_BITS 4
-#define TIMER_CTRL_MASK ((1 << TIMER_CTRL_BITS) - 1)
-
-#define TIMER_CLOCK_USE_EXT true
-#define TIMER_CLOCK_EXT_HZ 1000000
-#define TIMER_CLOCK_USE_APB false
-#define TIMER_CLOCK_APB_HZ 24000000
-
-#define TIMER_REG_STATUS 0
-#define TIMER_REG_RELOAD 1
-#define TIMER_REG_MATCH_FIRST 2
-#define TIMER_REG_MATCH_SECOND 3
-
-#define TIMER_FIRST_CAP_PULSE 4
-
-enum timer_ctrl_op {
- op_enable = 0,
- op_external_clock,
- op_overflow_interrupt,
- op_pulse_enable
-};
-
-/**
- * Avoid mutual references between AspeedTimerCtrlState and AspeedTimer
- * structs, as it's a waste of memory. The ptimer BH callback needs to know
- * whether a specific AspeedTimer is enabled, but this information is held in
- * AspeedTimerCtrlState. So, provide a helper to hoist ourselves from an
- * arbitrary AspeedTimer to AspeedTimerCtrlState.
- */
-static inline AspeedTimerCtrlState *timer_to_ctrl(AspeedTimer *t)
-{
- const AspeedTimer (*timers)[] = (void *)t - (t->id * sizeof(*t));
- return container_of(timers, AspeedTimerCtrlState, timers);
-}
-
-static inline bool timer_ctrl_status(AspeedTimer *t, enum timer_ctrl_op op)
-{
- return !!(timer_to_ctrl(t)->ctrl & BIT(t->id * TIMER_CTRL_BITS + op));
-}
-
-static inline bool timer_enabled(AspeedTimer *t)
-{
- return timer_ctrl_status(t, op_enable);
-}
-
-static inline bool timer_overflow_interrupt(AspeedTimer *t)
-{
- return timer_ctrl_status(t, op_overflow_interrupt);
-}
-
-static inline bool timer_can_pulse(AspeedTimer *t)
-{
- return t->id >= TIMER_FIRST_CAP_PULSE;
-}
-
-static void aspeed_timer_expire(void *opaque)
-{
- AspeedTimer *t = opaque;
-
- /* Only support interrupts on match values of zero for the moment - this is
- * sufficient to boot an aspeed_defconfig Linux kernel.
- *
- * TODO: matching on arbitrary values (see e.g. hw/timer/a9gtimer.c)
- */
- bool match = !(t->match[0] && t->match[1]);
- bool interrupt = timer_overflow_interrupt(t) || match;
- if (timer_enabled(t) && interrupt) {
- t->level = !t->level;
- qemu_set_irq(t->irq, t->level);
- }
-}
-
-static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
-{
- uint64_t value;
-
- switch (reg) {
- case TIMER_REG_STATUS:
- value = ptimer_get_count(t->timer);
- break;
- case TIMER_REG_RELOAD:
- value = t->reload;
- break;
- case TIMER_REG_MATCH_FIRST:
- case TIMER_REG_MATCH_SECOND:
- value = t->match[reg - 2];
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
- __func__, reg);
- value = 0;
- break;
- }
- return value;
-}
-
-static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
-{
- AspeedTimerCtrlState *s = opaque;
- const int reg = (offset & 0xf) / 4;
- uint64_t value;
-
- switch (offset) {
- case 0x30: /* Control Register */
- value = s->ctrl;
- break;
- case 0x34: /* Control Register 2 */
- value = s->ctrl2;
- break;
- case 0x00 ... 0x2c: /* Timers 1 - 4 */
- value = aspeed_timer_get_value(&s->timers[(offset >> 4)], reg);
- break;
- case 0x40 ... 0x8c: /* Timers 5 - 8 */
- value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
- break;
- /* Illegal */
- case 0x38:
- case 0x3C:
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- value = 0;
- break;
- }
- trace_aspeed_timer_read(offset, size, value);
- return value;
-}
-
-static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
- uint32_t value)
-{
- AspeedTimer *t;
-
- trace_aspeed_timer_set_value(timer, reg, value);
- t = &s->timers[timer];
- switch (reg) {
- case TIMER_REG_STATUS:
- if (timer_enabled(t)) {
- ptimer_set_count(t->timer, value);
- }
- break;
- case TIMER_REG_RELOAD:
- t->reload = value;
- ptimer_set_limit(t->timer, value, 1);
- break;
- case TIMER_REG_MATCH_FIRST:
- case TIMER_REG_MATCH_SECOND:
- if (value) {
- /* Non-zero match values are unsupported. As such an interrupt will
- * always be triggered when the timer reaches zero even if the
- * overflow interrupt control bit is clear.
- */
- qemu_log_mask(LOG_UNIMP, "%s: Match value unsupported by device: "
- "0x%" PRIx32 "\n", __func__, value);
- } else {
- t->match[reg - 2] = value;
- }
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
- __func__, reg);
- break;
- }
-}
-
-/* Control register operations are broken out into helpers that can be
- * explictly called on aspeed_timer_reset(), but also from
- * aspeed_timer_ctrl_op().
- */
-
-static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool enable)
-{
- trace_aspeed_timer_ctrl_enable(t->id, enable);
- if (enable) {
- ptimer_run(t->timer, 0);
- } else {
- ptimer_stop(t->timer);
- ptimer_set_limit(t->timer, t->reload, 1);
- }
-}
-
-static void aspeed_timer_ctrl_external_clock(AspeedTimer *t, bool enable)
-{
- trace_aspeed_timer_ctrl_external_clock(t->id, enable);
- if (enable) {
- ptimer_set_freq(t->timer, TIMER_CLOCK_EXT_HZ);
- } else {
- ptimer_set_freq(t->timer, TIMER_CLOCK_APB_HZ);
- }
-}
-
-static void aspeed_timer_ctrl_overflow_interrupt(AspeedTimer *t, bool enable)
-{
- trace_aspeed_timer_ctrl_overflow_interrupt(t->id, enable);
-}
-
-static void aspeed_timer_ctrl_pulse_enable(AspeedTimer *t, bool enable)
-{
- if (timer_can_pulse(t)) {
- trace_aspeed_timer_ctrl_pulse_enable(t->id, enable);
- } else {
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Timer does not support pulse mode\n", __func__);
- }
-}
-
-/**
- * Given the actions are fixed in number and completely described in helper
- * functions, dispatch with a lookup table rather than manage control flow with
- * a switch statement.
- */
-static void (*const ctrl_ops[])(AspeedTimer *, bool) = {
- [op_enable] = aspeed_timer_ctrl_enable,
- [op_external_clock] = aspeed_timer_ctrl_external_clock,
- [op_overflow_interrupt] = aspeed_timer_ctrl_overflow_interrupt,
- [op_pulse_enable] = aspeed_timer_ctrl_pulse_enable,
-};
-
-/**
- * Conditionally affect changes chosen by a timer's control bit.
- *
- * The aspeed_timer_ctrl_op() interface is convenient for the
- * aspeed_timer_set_ctrl() function as the "no change" early exit can be
- * calculated for all operations, which cleans up the caller code. However the
- * interface isn't convenient for the reset function where we want to enter a
- * specific state without artificially constructing old and new values that
- * will fall through the change guard (and motivates extracting the actions
- * out to helper functions).
- *
- * @t: The timer to manipulate
- * @op: The type of operation to be performed
- * @old: The old state of the timer's control bits
- * @new: The incoming state for the timer's control bits
- */
-static void aspeed_timer_ctrl_op(AspeedTimer *t, enum timer_ctrl_op op,
- uint8_t old, uint8_t new)
-{
- const uint8_t mask = BIT(op);
- const bool enable = !!(new & mask);
- const bool changed = ((old ^ new) & mask);
- if (!changed) {
- return;
- }
- ctrl_ops[op](t, enable);
-}
-
-static void aspeed_timer_set_ctrl(AspeedTimerCtrlState *s, uint32_t reg)
-{
- int i;
- int shift;
- uint8_t t_old, t_new;
- AspeedTimer *t;
- const uint8_t enable_mask = BIT(op_enable);
-
- /* Handle a dependency between the 'enable' and remaining three
- * configuration bits - i.e. if more than one bit in the control set has
- * changed, including the 'enable' bit, then we want either disable the
- * timer and perform configuration, or perform configuration and then
- * enable the timer
- */
- for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
- t = &s->timers[i];
- shift = (i * TIMER_CTRL_BITS);
- t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK;
- t_new = (reg >> shift) & TIMER_CTRL_MASK;
-
- /* If we are disabling, do so first */
- if ((t_old & enable_mask) && !(t_new & enable_mask)) {
- aspeed_timer_ctrl_enable(t, false);
- }
- aspeed_timer_ctrl_op(t, op_external_clock, t_old, t_new);
- aspeed_timer_ctrl_op(t, op_overflow_interrupt, t_old, t_new);
- aspeed_timer_ctrl_op(t, op_pulse_enable, t_old, t_new);
- /* If we are enabling, do so last */
- if (!(t_old & enable_mask) && (t_new & enable_mask)) {
- aspeed_timer_ctrl_enable(t, true);
- }
- }
- s->ctrl = reg;
-}
-
-static void aspeed_timer_set_ctrl2(AspeedTimerCtrlState *s, uint32_t value)
-{
- trace_aspeed_timer_set_ctrl2(value);
-}
-
-static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
- const int reg = (offset & 0xf) / 4;
- AspeedTimerCtrlState *s = opaque;
-
- switch (offset) {
- /* Control Registers */
- case 0x30:
- aspeed_timer_set_ctrl(s, tv);
- break;
- case 0x34:
- aspeed_timer_set_ctrl2(s, tv);
- break;
- /* Timer Registers */
- case 0x00 ... 0x2c:
- aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS), reg, tv);
- break;
- case 0x40 ... 0x8c:
- aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
- break;
- /* Illegal */
- case 0x38:
- case 0x3C:
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
- __func__, offset);
- break;
- }
-}
-
-static const MemoryRegionOps aspeed_timer_ops = {
- .read = aspeed_timer_read,
- .write = aspeed_timer_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid.min_access_size = 4,
- .valid.max_access_size = 4,
- .valid.unaligned = false,
-};
-
-static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
-{
- QEMUBH *bh;
- AspeedTimer *t = &s->timers[id];
-
- t->id = id;
- bh = qemu_bh_new(aspeed_timer_expire, t);
- t->timer = ptimer_init(bh);
-}
-
-static void aspeed_timer_realize(DeviceState *dev, Error **errp)
-{
- int i;
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
-
- for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
- aspeed_init_one_timer(s, i);
- sysbus_init_irq(sbd, &s->timers[i].irq);
- }
- memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_timer_ops, s,
- TYPE_ASPEED_TIMER, 0x1000);
- sysbus_init_mmio(sbd, &s->iomem);
-}
-
-static void aspeed_timer_reset(DeviceState *dev)
-{
- int i;
- AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
-
- for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
- AspeedTimer *t = &s->timers[i];
- /* Explictly call helpers to avoid any conditional behaviour through
- * aspeed_timer_set_ctrl().
- */
- aspeed_timer_ctrl_enable(t, false);
- aspeed_timer_ctrl_external_clock(t, TIMER_CLOCK_USE_APB);
- aspeed_timer_ctrl_overflow_interrupt(t, false);
- aspeed_timer_ctrl_pulse_enable(t, false);
- t->level = 0;
- t->reload = 0;
- t->match[0] = 0;
- t->match[1] = 0;
- }
- s->ctrl = 0;
- s->ctrl2 = 0;
-}
-
-static const VMStateDescription vmstate_aspeed_timer = {
- .name = "aspeed.timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(id, AspeedTimer),
- VMSTATE_INT32(level, AspeedTimer),
- VMSTATE_PTIMER(timer, AspeedTimer),
- VMSTATE_UINT32(reload, AspeedTimer),
- VMSTATE_UINT32_ARRAY(match, AspeedTimer, 2),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_aspeed_timer_state = {
- .name = "aspeed.timerctrl",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(ctrl, AspeedTimerCtrlState),
- VMSTATE_UINT32(ctrl2, AspeedTimerCtrlState),
- VMSTATE_STRUCT_ARRAY(timers, AspeedTimerCtrlState,
- ASPEED_TIMER_NR_TIMERS, 1, vmstate_aspeed_timer,
- AspeedTimer),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void timer_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = aspeed_timer_realize;
- dc->reset = aspeed_timer_reset;
- dc->desc = "ASPEED Timer";
- dc->vmsd = &vmstate_aspeed_timer_state;
-}
-
-static const TypeInfo aspeed_timer_info = {
- .name = TYPE_ASPEED_TIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(AspeedTimerCtrlState),
- .class_init = timer_class_init,
-};
-
-static void aspeed_timer_register_types(void)
-{
- type_register_static(&aspeed_timer_info);
-}
-
-type_init(aspeed_timer_register_types)
diff --git a/qemu/hw/timer/cadence_ttc.c b/qemu/hw/timer/cadence_ttc.c
deleted file mode 100644
index 03f5b9c20..000000000
--- a/qemu/hw/timer/cadence_ttc.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Xilinx Zynq cadence TTC model
- *
- * Copyright (c) 2011 Xilinx Inc.
- * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
- * Copyright (c) 2012 PetaLogix Pty Ltd.
- * Written By Haibing Ma
- * M. Habib
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "qemu/timer.h"
-
-#ifdef CADENCE_TTC_ERR_DEBUG
-#define DB_PRINT(...) do { \
- fprintf(stderr, ": %s: ", __func__); \
- fprintf(stderr, ## __VA_ARGS__); \
- } while (0);
-#else
- #define DB_PRINT(...)
-#endif
-
-#define COUNTER_INTR_IV 0x00000001
-#define COUNTER_INTR_M1 0x00000002
-#define COUNTER_INTR_M2 0x00000004
-#define COUNTER_INTR_M3 0x00000008
-#define COUNTER_INTR_OV 0x00000010
-#define COUNTER_INTR_EV 0x00000020
-
-#define COUNTER_CTRL_DIS 0x00000001
-#define COUNTER_CTRL_INT 0x00000002
-#define COUNTER_CTRL_DEC 0x00000004
-#define COUNTER_CTRL_MATCH 0x00000008
-#define COUNTER_CTRL_RST 0x00000010
-
-#define CLOCK_CTRL_PS_EN 0x00000001
-#define CLOCK_CTRL_PS_V 0x0000001e
-
-typedef struct {
- QEMUTimer *timer;
- int freq;
-
- uint32_t reg_clock;
- uint32_t reg_count;
- uint32_t reg_value;
- uint16_t reg_interval;
- uint16_t reg_match[3];
- uint32_t reg_intr;
- uint32_t reg_intr_en;
- uint32_t reg_event_ctrl;
- uint32_t reg_event;
-
- uint64_t cpu_time;
- unsigned int cpu_time_valid;
-
- qemu_irq irq;
-} CadenceTimerState;
-
-#define TYPE_CADENCE_TTC "cadence_ttc"
-#define CADENCE_TTC(obj) \
- OBJECT_CHECK(CadenceTTCState, (obj), TYPE_CADENCE_TTC)
-
-typedef struct CadenceTTCState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- CadenceTimerState timer[3];
-} CadenceTTCState;
-
-static void cadence_timer_update(CadenceTimerState *s)
-{
- qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
-}
-
-static CadenceTimerState *cadence_timer_from_addr(void *opaque,
- hwaddr offset)
-{
- unsigned int index;
- CadenceTTCState *s = (CadenceTTCState *)opaque;
-
- index = (offset >> 2) % 3;
-
- return &s->timer[index];
-}
-
-static uint64_t cadence_timer_get_ns(CadenceTimerState *s, uint64_t timer_steps)
-{
- /* timer_steps has max value of 0x100000000. double check it
- * (or overflow can happen below) */
- assert(timer_steps <= 1ULL << 32);
-
- uint64_t r = timer_steps * 1000000000ULL;
- if (s->reg_clock & CLOCK_CTRL_PS_EN) {
- r >>= 16 - (((s->reg_clock & CLOCK_CTRL_PS_V) >> 1) + 1);
- } else {
- r >>= 16;
- }
- r /= (uint64_t)s->freq;
- return r;
-}
-
-static uint64_t cadence_timer_get_steps(CadenceTimerState *s, uint64_t ns)
-{
- uint64_t to_divide = 1000000000ULL;
-
- uint64_t r = ns;
- /* for very large intervals (> 8s) do some division first to stop
- * overflow (costs some prescision) */
- while (r >= 8ULL << 30 && to_divide > 1) {
- r /= 1000;
- to_divide /= 1000;
- }
- r <<= 16;
- /* keep early-dividing as needed */
- while (r >= 8ULL << 30 && to_divide > 1) {
- r /= 1000;
- to_divide /= 1000;
- }
- r *= (uint64_t)s->freq;
- if (s->reg_clock & CLOCK_CTRL_PS_EN) {
- r /= 1 << (((s->reg_clock & CLOCK_CTRL_PS_V) >> 1) + 1);
- }
-
- r /= to_divide;
- return r;
-}
-
-/* determine if x is in between a and b, exclusive of a, inclusive of b */
-
-static inline int64_t is_between(int64_t x, int64_t a, int64_t b)
-{
- if (a < b) {
- return x > a && x <= b;
- }
- return x < a && x >= b;
-}
-
-static void cadence_timer_run(CadenceTimerState *s)
-{
- int i;
- int64_t event_interval, next_value;
-
- assert(s->cpu_time_valid); /* cadence_timer_sync must be called first */
-
- if (s->reg_count & COUNTER_CTRL_DIS) {
- s->cpu_time_valid = 0;
- return;
- }
-
- { /* figure out what's going to happen next (rollover or match) */
- int64_t interval = (uint64_t)((s->reg_count & COUNTER_CTRL_INT) ?
- (int64_t)s->reg_interval + 1 : 0x10000ULL) << 16;
- next_value = (s->reg_count & COUNTER_CTRL_DEC) ? -1ULL : interval;
- for (i = 0; i < 3; ++i) {
- int64_t cand = (uint64_t)s->reg_match[i] << 16;
- if (is_between(cand, (uint64_t)s->reg_value, next_value)) {
- next_value = cand;
- }
- }
- }
- DB_PRINT("next timer event value: %09llx\n",
- (unsigned long long)next_value);
-
- event_interval = next_value - (int64_t)s->reg_value;
- event_interval = (event_interval < 0) ? -event_interval : event_interval;
-
- timer_mod(s->timer, s->cpu_time +
- cadence_timer_get_ns(s, event_interval));
-}
-
-static void cadence_timer_sync(CadenceTimerState *s)
-{
- int i;
- int64_t r, x;
- int64_t interval = ((s->reg_count & COUNTER_CTRL_INT) ?
- (int64_t)s->reg_interval + 1 : 0x10000ULL) << 16;
- uint64_t old_time = s->cpu_time;
-
- s->cpu_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- DB_PRINT("cpu time: %lld ns\n", (long long)old_time);
-
- if (!s->cpu_time_valid || old_time == s->cpu_time) {
- s->cpu_time_valid = 1;
- return;
- }
-
- r = (int64_t)cadence_timer_get_steps(s, s->cpu_time - old_time);
- x = (int64_t)s->reg_value + ((s->reg_count & COUNTER_CTRL_DEC) ? -r : r);
-
- for (i = 0; i < 3; ++i) {
- int64_t m = (int64_t)s->reg_match[i] << 16;
- if (m > interval) {
- continue;
- }
- /* check to see if match event has occurred. check m +/- interval
- * to account for match events in wrap around cases */
- if (is_between(m, s->reg_value, x) ||
- is_between(m + interval, s->reg_value, x) ||
- is_between(m - interval, s->reg_value, x)) {
- s->reg_intr |= (2 << i);
- }
- }
- if ((x < 0) || (x >= interval)) {
- s->reg_intr |= (s->reg_count & COUNTER_CTRL_INT) ?
- COUNTER_INTR_IV : COUNTER_INTR_OV;
- }
- while (x < 0) {
- x += interval;
- }
- s->reg_value = (uint32_t)(x % interval);
- cadence_timer_update(s);
-}
-
-static void cadence_timer_tick(void *opaque)
-{
- CadenceTimerState *s = opaque;
-
- DB_PRINT("\n");
- cadence_timer_sync(s);
- cadence_timer_run(s);
-}
-
-static uint32_t cadence_ttc_read_imp(void *opaque, hwaddr offset)
-{
- CadenceTimerState *s = cadence_timer_from_addr(opaque, offset);
- uint32_t value;
-
- cadence_timer_sync(s);
- cadence_timer_run(s);
-
- switch (offset) {
- case 0x00: /* clock control */
- case 0x04:
- case 0x08:
- return s->reg_clock;
-
- case 0x0c: /* counter control */
- case 0x10:
- case 0x14:
- return s->reg_count;
-
- case 0x18: /* counter value */
- case 0x1c:
- case 0x20:
- return (uint16_t)(s->reg_value >> 16);
-
- case 0x24: /* reg_interval counter */
- case 0x28:
- case 0x2c:
- return s->reg_interval;
-
- case 0x30: /* match 1 counter */
- case 0x34:
- case 0x38:
- return s->reg_match[0];
-
- case 0x3c: /* match 2 counter */
- case 0x40:
- case 0x44:
- return s->reg_match[1];
-
- case 0x48: /* match 3 counter */
- case 0x4c:
- case 0x50:
- return s->reg_match[2];
-
- case 0x54: /* interrupt register */
- case 0x58:
- case 0x5c:
- /* cleared after read */
- value = s->reg_intr;
- s->reg_intr = 0;
- cadence_timer_update(s);
- return value;
-
- case 0x60: /* interrupt enable */
- case 0x64:
- case 0x68:
- return s->reg_intr_en;
-
- case 0x6c:
- case 0x70:
- case 0x74:
- return s->reg_event_ctrl;
-
- case 0x78:
- case 0x7c:
- case 0x80:
- return s->reg_event;
-
- default:
- return 0;
- }
-}
-
-static uint64_t cadence_ttc_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- uint32_t ret = cadence_ttc_read_imp(opaque, offset);
-
- DB_PRINT("addr: %08x data: %08x\n", (unsigned)offset, (unsigned)ret);
- return ret;
-}
-
-static void cadence_ttc_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- CadenceTimerState *s = cadence_timer_from_addr(opaque, offset);
-
- DB_PRINT("addr: %08x data %08x\n", (unsigned)offset, (unsigned)value);
-
- cadence_timer_sync(s);
-
- switch (offset) {
- case 0x00: /* clock control */
- case 0x04:
- case 0x08:
- s->reg_clock = value & 0x3F;
- break;
-
- case 0x0c: /* counter control */
- case 0x10:
- case 0x14:
- if (value & COUNTER_CTRL_RST) {
- s->reg_value = 0;
- }
- s->reg_count = value & 0x3f & ~COUNTER_CTRL_RST;
- break;
-
- case 0x24: /* interval register */
- case 0x28:
- case 0x2c:
- s->reg_interval = value & 0xffff;
- break;
-
- case 0x30: /* match register */
- case 0x34:
- case 0x38:
- s->reg_match[0] = value & 0xffff;
- break;
-
- case 0x3c: /* match register */
- case 0x40:
- case 0x44:
- s->reg_match[1] = value & 0xffff;
- break;
-
- case 0x48: /* match register */
- case 0x4c:
- case 0x50:
- s->reg_match[2] = value & 0xffff;
- break;
-
- case 0x54: /* interrupt register */
- case 0x58:
- case 0x5c:
- break;
-
- case 0x60: /* interrupt enable */
- case 0x64:
- case 0x68:
- s->reg_intr_en = value & 0x3f;
- break;
-
- case 0x6c: /* event control */
- case 0x70:
- case 0x74:
- s->reg_event_ctrl = value & 0x07;
- break;
-
- default:
- return;
- }
-
- cadence_timer_run(s);
- cadence_timer_update(s);
-}
-
-static const MemoryRegionOps cadence_ttc_ops = {
- .read = cadence_ttc_read,
- .write = cadence_ttc_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void cadence_timer_reset(CadenceTimerState *s)
-{
- s->reg_count = 0x21;
-}
-
-static void cadence_timer_init(uint32_t freq, CadenceTimerState *s)
-{
- memset(s, 0, sizeof(CadenceTimerState));
- s->freq = freq;
-
- cadence_timer_reset(s);
-
- s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cadence_timer_tick, s);
-}
-
-static void cadence_ttc_init(Object *obj)
-{
- CadenceTTCState *s = CADENCE_TTC(obj);
- int i;
-
- for (i = 0; i < 3; ++i) {
- cadence_timer_init(133000000, &s->timer[i]);
- sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->timer[i].irq);
- }
-
- memory_region_init_io(&s->iomem, obj, &cadence_ttc_ops, s,
- "timer", 0x1000);
- sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
-}
-
-static void cadence_timer_pre_save(void *opaque)
-{
- cadence_timer_sync((CadenceTimerState *)opaque);
-}
-
-static int cadence_timer_post_load(void *opaque, int version_id)
-{
- CadenceTimerState *s = opaque;
-
- s->cpu_time_valid = 0;
- cadence_timer_sync(s);
- cadence_timer_run(s);
- cadence_timer_update(s);
- return 0;
-}
-
-static const VMStateDescription vmstate_cadence_timer = {
- .name = "cadence_timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .pre_save = cadence_timer_pre_save,
- .post_load = cadence_timer_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(reg_clock, CadenceTimerState),
- VMSTATE_UINT32(reg_count, CadenceTimerState),
- VMSTATE_UINT32(reg_value, CadenceTimerState),
- VMSTATE_UINT16(reg_interval, CadenceTimerState),
- VMSTATE_UINT16_ARRAY(reg_match, CadenceTimerState, 3),
- VMSTATE_UINT32(reg_intr, CadenceTimerState),
- VMSTATE_UINT32(reg_intr_en, CadenceTimerState),
- VMSTATE_UINT32(reg_event_ctrl, CadenceTimerState),
- VMSTATE_UINT32(reg_event, CadenceTimerState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_cadence_ttc = {
- .name = "cadence_TTC",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT_ARRAY(timer, CadenceTTCState, 3, 0,
- vmstate_cadence_timer,
- CadenceTimerState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void cadence_ttc_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->vmsd = &vmstate_cadence_ttc;
-}
-
-static const TypeInfo cadence_ttc_info = {
- .name = TYPE_CADENCE_TTC,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(CadenceTTCState),
- .instance_init = cadence_ttc_init,
- .class_init = cadence_ttc_class_init,
-};
-
-static void cadence_ttc_register_types(void)
-{
- type_register_static(&cadence_ttc_info);
-}
-
-type_init(cadence_ttc_register_types)
diff --git a/qemu/hw/timer/digic-timer.c b/qemu/hw/timer/digic-timer.c
deleted file mode 100644
index 5b97e1e1a..000000000
--- a/qemu/hw/timer/digic-timer.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * QEMU model of the Canon DIGIC timer block.
- *
- * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * This model is based on reverse engineering efforts
- * made by CHDK (http://chdk.wikia.com) and
- * Magic Lantern (http://www.magiclantern.fm) projects
- * contributors.
- *
- * See "Timer/Clock Module" docs here:
- * http://magiclantern.wikia.com/wiki/Register_Map
- *
- * The QEMU model of the OSTimer in PKUnity SoC by Guan Xuetao
- * is used as a template.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "hw/ptimer.h"
-#include "qemu/main-loop.h"
-
-#include "hw/timer/digic-timer.h"
-
-static const VMStateDescription vmstate_digic_timer = {
- .name = "digic.timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_PTIMER(ptimer, DigicTimerState),
- VMSTATE_UINT32(control, DigicTimerState),
- VMSTATE_UINT32(relvalue, DigicTimerState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void digic_timer_reset(DeviceState *dev)
-{
- DigicTimerState *s = DIGIC_TIMER(dev);
-
- ptimer_stop(s->ptimer);
- s->control = 0;
- s->relvalue = 0;
-}
-
-static uint64_t digic_timer_read(void *opaque, hwaddr offset, unsigned size)
-{
- DigicTimerState *s = opaque;
- uint64_t ret = 0;
-
- switch (offset) {
- case DIGIC_TIMER_CONTROL:
- ret = s->control;
- break;
- case DIGIC_TIMER_RELVALUE:
- ret = s->relvalue;
- break;
- case DIGIC_TIMER_VALUE:
- ret = ptimer_get_count(s->ptimer) & 0xffff;
- break;
- default:
- qemu_log_mask(LOG_UNIMP,
- "digic-timer: read access to unknown register 0x"
- TARGET_FMT_plx, offset);
- }
-
- return ret;
-}
-
-static void digic_timer_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- DigicTimerState *s = opaque;
-
- switch (offset) {
- case DIGIC_TIMER_CONTROL:
- if (value & DIGIC_TIMER_CONTROL_RST) {
- digic_timer_reset((DeviceState *)s);
- break;
- }
-
- if (value & DIGIC_TIMER_CONTROL_EN) {
- ptimer_run(s->ptimer, 0);
- }
-
- s->control = (uint32_t)value;
- break;
-
- case DIGIC_TIMER_RELVALUE:
- s->relvalue = extract32(value, 0, 16);
- ptimer_set_limit(s->ptimer, s->relvalue, 1);
- break;
-
- case DIGIC_TIMER_VALUE:
- break;
-
- default:
- qemu_log_mask(LOG_UNIMP,
- "digic-timer: read access to unknown register 0x"
- TARGET_FMT_plx, offset);
- }
-}
-
-static const MemoryRegionOps digic_timer_ops = {
- .read = digic_timer_read,
- .write = digic_timer_write,
- .impl = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void digic_timer_init(Object *obj)
-{
- DigicTimerState *s = DIGIC_TIMER(obj);
-
- s->ptimer = ptimer_init(NULL);
-
- /*
- * FIXME: there is no documentation on Digic timer
- * frequency setup so let it always run at 1 MHz
- */
- ptimer_set_freq(s->ptimer, 1 * 1000 * 1000);
-
- memory_region_init_io(&s->iomem, OBJECT(s), &digic_timer_ops, s,
- TYPE_DIGIC_TIMER, 0x100);
- sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
-}
-
-static void digic_timer_class_init(ObjectClass *klass, void *class_data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->reset = digic_timer_reset;
- dc->vmsd = &vmstate_digic_timer;
-}
-
-static const TypeInfo digic_timer_info = {
- .name = TYPE_DIGIC_TIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(DigicTimerState),
- .instance_init = digic_timer_init,
- .class_init = digic_timer_class_init,
-};
-
-static void digic_timer_register_type(void)
-{
- type_register_static(&digic_timer_info);
-}
-
-type_init(digic_timer_register_type)
diff --git a/qemu/hw/timer/ds1338.c b/qemu/hw/timer/ds1338.c
deleted file mode 100644
index 0112949e2..000000000
--- a/qemu/hw/timer/ds1338.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * MAXIM DS1338 I2C RTC+NVRAM
- *
- * Copyright (c) 2009 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "hw/i2c/i2c.h"
-#include "qemu/bcd.h"
-
-/* Size of NVRAM including both the user-accessible area and the
- * secondary register area.
- */
-#define NVRAM_SIZE 64
-
-/* Flags definitions */
-#define SECONDS_CH 0x80
-#define HOURS_12 0x40
-#define HOURS_PM 0x20
-#define CTRL_OSF 0x20
-
-#define TYPE_DS1338 "ds1338"
-#define DS1338(obj) OBJECT_CHECK(DS1338State, (obj), TYPE_DS1338)
-
-typedef struct DS1338State {
- I2CSlave parent_obj;
-
- int64_t offset;
- uint8_t wday_offset;
- uint8_t nvram[NVRAM_SIZE];
- int32_t ptr;
- bool addr_byte;
-} DS1338State;
-
-static const VMStateDescription vmstate_ds1338 = {
- .name = "ds1338",
- .version_id = 2,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_I2C_SLAVE(parent_obj, DS1338State),
- VMSTATE_INT64(offset, DS1338State),
- VMSTATE_UINT8_V(wday_offset, DS1338State, 2),
- VMSTATE_UINT8_ARRAY(nvram, DS1338State, NVRAM_SIZE),
- VMSTATE_INT32(ptr, DS1338State),
- VMSTATE_BOOL(addr_byte, DS1338State),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void capture_current_time(DS1338State *s)
-{
- /* Capture the current time into the secondary registers
- * which will be actually read by the data transfer operation.
- */
- struct tm now;
- qemu_get_timedate(&now, s->offset);
- s->nvram[0] = to_bcd(now.tm_sec);
- s->nvram[1] = to_bcd(now.tm_min);
- if (s->nvram[2] & HOURS_12) {
- int tmp = now.tm_hour;
- if (tmp % 12 == 0) {
- tmp += 12;
- }
- if (tmp <= 12) {
- s->nvram[2] = HOURS_12 | to_bcd(tmp);
- } else {
- s->nvram[2] = HOURS_12 | HOURS_PM | to_bcd(tmp - 12);
- }
- } else {
- s->nvram[2] = to_bcd(now.tm_hour);
- }
- s->nvram[3] = (now.tm_wday + s->wday_offset) % 7 + 1;
- s->nvram[4] = to_bcd(now.tm_mday);
- s->nvram[5] = to_bcd(now.tm_mon + 1);
- s->nvram[6] = to_bcd(now.tm_year - 100);
-}
-
-static void inc_regptr(DS1338State *s)
-{
- /* The register pointer wraps around after 0x3F; wraparound
- * causes the current time/date to be retransferred into
- * the secondary registers.
- */
- s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1);
- if (!s->ptr) {
- capture_current_time(s);
- }
-}
-
-static void ds1338_event(I2CSlave *i2c, enum i2c_event event)
-{
- DS1338State *s = DS1338(i2c);
-
- switch (event) {
- case I2C_START_RECV:
- /* In h/w, capture happens on any START condition, not just a
- * START_RECV, but there is no need to actually capture on
- * START_SEND, because the guest can't get at that data
- * without going through a START_RECV which would overwrite it.
- */
- capture_current_time(s);
- break;
- case I2C_START_SEND:
- s->addr_byte = true;
- break;
- default:
- break;
- }
-}
-
-static int ds1338_recv(I2CSlave *i2c)
-{
- DS1338State *s = DS1338(i2c);
- uint8_t res;
-
- res = s->nvram[s->ptr];
- inc_regptr(s);
- return res;
-}
-
-static int ds1338_send(I2CSlave *i2c, uint8_t data)
-{
- DS1338State *s = DS1338(i2c);
-
- if (s->addr_byte) {
- s->ptr = data & (NVRAM_SIZE - 1);
- s->addr_byte = false;
- return 0;
- }
- if (s->ptr < 7) {
- /* Time register. */
- struct tm now;
- qemu_get_timedate(&now, s->offset);
- switch(s->ptr) {
- case 0:
- /* TODO: Implement CH (stop) bit. */
- now.tm_sec = from_bcd(data & 0x7f);
- break;
- case 1:
- now.tm_min = from_bcd(data & 0x7f);
- break;
- case 2:
- if (data & HOURS_12) {
- int tmp = from_bcd(data & (HOURS_PM - 1));
- if (data & HOURS_PM) {
- tmp += 12;
- }
- if (tmp % 12 == 0) {
- tmp -= 12;
- }
- now.tm_hour = tmp;
- } else {
- now.tm_hour = from_bcd(data & (HOURS_12 - 1));
- }
- break;
- case 3:
- {
- /* The day field is supposed to contain a value in
- the range 1-7. Otherwise behavior is undefined.
- */
- int user_wday = (data & 7) - 1;
- s->wday_offset = (user_wday - now.tm_wday + 7) % 7;
- }
- break;
- case 4:
- now.tm_mday = from_bcd(data & 0x3f);
- break;
- case 5:
- now.tm_mon = from_bcd(data & 0x1f) - 1;
- break;
- case 6:
- now.tm_year = from_bcd(data) + 100;
- break;
- }
- s->offset = qemu_timedate_diff(&now);
- } else if (s->ptr == 7) {
- /* Control register. */
-
- /* Ensure bits 2, 3 and 6 will read back as zero. */
- data &= 0xB3;
-
- /* Attempting to write the OSF flag to logic 1 leaves the
- value unchanged. */
- data = (data & ~CTRL_OSF) | (data & s->nvram[s->ptr] & CTRL_OSF);
-
- s->nvram[s->ptr] = data;
- } else {
- s->nvram[s->ptr] = data;
- }
- inc_regptr(s);
- return 0;
-}
-
-static int ds1338_init(I2CSlave *i2c)
-{
- return 0;
-}
-
-static void ds1338_reset(DeviceState *dev)
-{
- DS1338State *s = DS1338(dev);
-
- /* The clock is running and synchronized with the host */
- s->offset = 0;
- s->wday_offset = 0;
- memset(s->nvram, 0, NVRAM_SIZE);
- s->ptr = 0;
- s->addr_byte = false;
-}
-
-static void ds1338_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
-
- k->init = ds1338_init;
- k->event = ds1338_event;
- k->recv = ds1338_recv;
- k->send = ds1338_send;
- dc->reset = ds1338_reset;
- dc->vmsd = &vmstate_ds1338;
-}
-
-static const TypeInfo ds1338_info = {
- .name = TYPE_DS1338,
- .parent = TYPE_I2C_SLAVE,
- .instance_size = sizeof(DS1338State),
- .class_init = ds1338_class_init,
-};
-
-static void ds1338_register_types(void)
-{
- type_register_static(&ds1338_info);
-}
-
-type_init(ds1338_register_types)
diff --git a/qemu/hw/timer/etraxfs_timer.c b/qemu/hw/timer/etraxfs_timer.c
deleted file mode 100644
index 36d8f462c..000000000
--- a/qemu/hw/timer/etraxfs_timer.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * QEMU ETRAX Timers
- *
- * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
- *
- * 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 "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "sysemu/sysemu.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-
-#define D(x)
-
-#define RW_TMR0_DIV 0x00
-#define R_TMR0_DATA 0x04
-#define RW_TMR0_CTRL 0x08
-#define RW_TMR1_DIV 0x10
-#define R_TMR1_DATA 0x14
-#define RW_TMR1_CTRL 0x18
-#define R_TIME 0x38
-#define RW_WD_CTRL 0x40
-#define R_WD_STAT 0x44
-#define RW_INTR_MASK 0x48
-#define RW_ACK_INTR 0x4c
-#define R_INTR 0x50
-#define R_MASKED_INTR 0x54
-
-#define TYPE_ETRAX_FS_TIMER "etraxfs,timer"
-#define ETRAX_TIMER(obj) \
- OBJECT_CHECK(ETRAXTimerState, (obj), TYPE_ETRAX_FS_TIMER)
-
-typedef struct ETRAXTimerState {
- SysBusDevice parent_obj;
-
- MemoryRegion mmio;
- qemu_irq irq;
- qemu_irq nmi;
-
- QEMUBH *bh_t0;
- QEMUBH *bh_t1;
- QEMUBH *bh_wd;
- ptimer_state *ptimer_t0;
- ptimer_state *ptimer_t1;
- ptimer_state *ptimer_wd;
-
- int wd_hits;
-
- /* Control registers. */
- uint32_t rw_tmr0_div;
- uint32_t r_tmr0_data;
- uint32_t rw_tmr0_ctrl;
-
- uint32_t rw_tmr1_div;
- uint32_t r_tmr1_data;
- uint32_t rw_tmr1_ctrl;
-
- uint32_t rw_wd_ctrl;
-
- uint32_t rw_intr_mask;
- uint32_t rw_ack_intr;
- uint32_t r_intr;
- uint32_t r_masked_intr;
-} ETRAXTimerState;
-
-static uint64_t
-timer_read(void *opaque, hwaddr addr, unsigned int size)
-{
- ETRAXTimerState *t = opaque;
- uint32_t r = 0;
-
- switch (addr) {
- case R_TMR0_DATA:
- r = ptimer_get_count(t->ptimer_t0);
- break;
- case R_TMR1_DATA:
- r = ptimer_get_count(t->ptimer_t1);
- break;
- case R_TIME:
- r = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 10;
- break;
- case RW_INTR_MASK:
- r = t->rw_intr_mask;
- break;
- case R_MASKED_INTR:
- r = t->r_intr & t->rw_intr_mask;
- break;
- default:
- D(printf ("%s %x\n", __func__, addr));
- break;
- }
- return r;
-}
-
-static void update_ctrl(ETRAXTimerState *t, int tnum)
-{
- unsigned int op;
- unsigned int freq;
- unsigned int freq_hz;
- unsigned int div;
- uint32_t ctrl;
-
- ptimer_state *timer;
-
- if (tnum == 0) {
- ctrl = t->rw_tmr0_ctrl;
- div = t->rw_tmr0_div;
- timer = t->ptimer_t0;
- } else {
- ctrl = t->rw_tmr1_ctrl;
- div = t->rw_tmr1_div;
- timer = t->ptimer_t1;
- }
-
-
- op = ctrl & 3;
- freq = ctrl >> 2;
- freq_hz = 32000000;
-
- switch (freq)
- {
- case 0:
- case 1:
- D(printf ("extern or disabled timer clock?\n"));
- break;
- case 4: freq_hz = 29493000; break;
- case 5: freq_hz = 32000000; break;
- case 6: freq_hz = 32768000; break;
- case 7: freq_hz = 100000000; break;
- default:
- abort();
- break;
- }
-
- D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
- ptimer_set_freq(timer, freq_hz);
- ptimer_set_limit(timer, div, 0);
-
- switch (op)
- {
- case 0:
- /* Load. */
- ptimer_set_limit(timer, div, 1);
- break;
- case 1:
- /* Hold. */
- ptimer_stop(timer);
- break;
- case 2:
- /* Run. */
- ptimer_run(timer, 0);
- break;
- default:
- abort();
- break;
- }
-}
-
-static void timer_update_irq(ETRAXTimerState *t)
-{
- t->r_intr &= ~(t->rw_ack_intr);
- t->r_masked_intr = t->r_intr & t->rw_intr_mask;
-
- D(printf("%s: masked_intr=%x\n", __func__, t->r_masked_intr));
- qemu_set_irq(t->irq, !!t->r_masked_intr);
-}
-
-static void timer0_hit(void *opaque)
-{
- ETRAXTimerState *t = opaque;
- t->r_intr |= 1;
- timer_update_irq(t);
-}
-
-static void timer1_hit(void *opaque)
-{
- ETRAXTimerState *t = opaque;
- t->r_intr |= 2;
- timer_update_irq(t);
-}
-
-static void watchdog_hit(void *opaque)
-{
- ETRAXTimerState *t = opaque;
- if (t->wd_hits == 0) {
- /* real hw gives a single tick before reseting but we are
- a bit friendlier to compensate for our slower execution. */
- ptimer_set_count(t->ptimer_wd, 10);
- ptimer_run(t->ptimer_wd, 1);
- qemu_irq_raise(t->nmi);
- }
- else
- qemu_system_reset_request();
-
- t->wd_hits++;
-}
-
-static inline void timer_watchdog_update(ETRAXTimerState *t, uint32_t value)
-{
- unsigned int wd_en = t->rw_wd_ctrl & (1 << 8);
- unsigned int wd_key = t->rw_wd_ctrl >> 9;
- unsigned int wd_cnt = t->rw_wd_ctrl & 511;
- unsigned int new_key = value >> 9 & ((1 << 7) - 1);
- unsigned int new_cmd = (value >> 8) & 1;
-
- /* If the watchdog is enabled, they written key must match the
- complement of the previous. */
- wd_key = ~wd_key & ((1 << 7) - 1);
-
- if (wd_en && wd_key != new_key)
- return;
-
- D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n",
- wd_en, new_key, wd_key, new_cmd, wd_cnt));
-
- if (t->wd_hits)
- qemu_irq_lower(t->nmi);
-
- t->wd_hits = 0;
-
- ptimer_set_freq(t->ptimer_wd, 760);
- if (wd_cnt == 0)
- wd_cnt = 256;
- ptimer_set_count(t->ptimer_wd, wd_cnt);
- if (new_cmd)
- ptimer_run(t->ptimer_wd, 1);
- else
- ptimer_stop(t->ptimer_wd);
-
- t->rw_wd_ctrl = value;
-}
-
-static void
-timer_write(void *opaque, hwaddr addr,
- uint64_t val64, unsigned int size)
-{
- ETRAXTimerState *t = opaque;
- uint32_t value = val64;
-
- switch (addr)
- {
- case RW_TMR0_DIV:
- t->rw_tmr0_div = value;
- break;
- case RW_TMR0_CTRL:
- D(printf ("RW_TMR0_CTRL=%x\n", value));
- t->rw_tmr0_ctrl = value;
- update_ctrl(t, 0);
- break;
- case RW_TMR1_DIV:
- t->rw_tmr1_div = value;
- break;
- case RW_TMR1_CTRL:
- D(printf ("RW_TMR1_CTRL=%x\n", value));
- t->rw_tmr1_ctrl = value;
- update_ctrl(t, 1);
- break;
- case RW_INTR_MASK:
- D(printf ("RW_INTR_MASK=%x\n", value));
- t->rw_intr_mask = value;
- timer_update_irq(t);
- break;
- case RW_WD_CTRL:
- timer_watchdog_update(t, value);
- break;
- case RW_ACK_INTR:
- t->rw_ack_intr = value;
- timer_update_irq(t);
- t->rw_ack_intr = 0;
- break;
- default:
- printf ("%s " TARGET_FMT_plx " %x\n",
- __func__, addr, value);
- break;
- }
-}
-
-static const MemoryRegionOps timer_ops = {
- .read = timer_read,
- .write = timer_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4
- }
-};
-
-static void etraxfs_timer_reset(void *opaque)
-{
- ETRAXTimerState *t = opaque;
-
- ptimer_stop(t->ptimer_t0);
- ptimer_stop(t->ptimer_t1);
- ptimer_stop(t->ptimer_wd);
- t->rw_wd_ctrl = 0;
- t->r_intr = 0;
- t->rw_intr_mask = 0;
- qemu_irq_lower(t->irq);
-}
-
-static int etraxfs_timer_init(SysBusDevice *dev)
-{
- ETRAXTimerState *t = ETRAX_TIMER(dev);
-
- t->bh_t0 = qemu_bh_new(timer0_hit, t);
- t->bh_t1 = qemu_bh_new(timer1_hit, t);
- t->bh_wd = qemu_bh_new(watchdog_hit, t);
- t->ptimer_t0 = ptimer_init(t->bh_t0);
- t->ptimer_t1 = ptimer_init(t->bh_t1);
- t->ptimer_wd = ptimer_init(t->bh_wd);
-
- sysbus_init_irq(dev, &t->irq);
- sysbus_init_irq(dev, &t->nmi);
-
- memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
- "etraxfs-timer", 0x5c);
- sysbus_init_mmio(dev, &t->mmio);
- qemu_register_reset(etraxfs_timer_reset, t);
- return 0;
-}
-
-static void etraxfs_timer_class_init(ObjectClass *klass, void *data)
-{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
- sdc->init = etraxfs_timer_init;
-}
-
-static const TypeInfo etraxfs_timer_info = {
- .name = TYPE_ETRAX_FS_TIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(ETRAXTimerState),
- .class_init = etraxfs_timer_class_init,
-};
-
-static void etraxfs_timer_register_types(void)
-{
- type_register_static(&etraxfs_timer_info);
-}
-
-type_init(etraxfs_timer_register_types)
diff --git a/qemu/hw/timer/exynos4210_mct.c b/qemu/hw/timer/exynos4210_mct.c
deleted file mode 100644
index ae69345f0..000000000
--- a/qemu/hw/timer/exynos4210_mct.c
+++ /dev/null
@@ -1,1480 +0,0 @@
-/*
- * Samsung exynos4210 Multi Core timer
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
- * All rights reserved.
- *
- * Evgeny Voevodin <e.voevodin@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Global Timer:
- *
- * Consists of two timers. First represents Free Running Counter and second
- * is used to measure interval from FRC to nearest comparator.
- *
- * 0 UINT64_MAX
- * | timer0 |
- * | <-------------------------------------------------------------- |
- * | --------------------------------------------frc---------------> |
- * |______________________________________________|__________________|
- * CMP0 CMP1 CMP2 | CMP3
- * __| |_
- * | timer1 |
- * | -------------> |
- * frc CMPx
- *
- * Problem: when implementing global timer as is, overflow arises.
- * next_time = cur_time + period * count;
- * period and count are 64 bits width.
- * Lets arm timer for MCT_GT_COUNTER_STEP count and update internal G_CNT
- * register during each event.
- *
- * Problem: both timers need to be implemented using MCT_XT_COUNTER_STEP because
- * local timer contains two counters: TCNT and ICNT. TCNT == 0 -> ICNT--.
- * IRQ is generated when ICNT riches zero. Implementation where TCNT == 0
- * generates IRQs suffers from too frequently events. Better to have one
- * uint64_t counter equal to TCNT*ICNT and arm ptimer.c for a minimum(TCNT*ICNT,
- * MCT_GT_COUNTER_STEP); (yes, if target tunes ICNT * TCNT to be too low values,
- * there is no way to avoid frequently events).
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "qemu/timer.h"
-#include "qemu/main-loop.h"
-#include "qemu-common.h"
-#include "hw/ptimer.h"
-
-#include "hw/arm/exynos4210.h"
-
-//#define DEBUG_MCT
-
-#ifdef DEBUG_MCT
-#define DPRINTF(fmt, ...) \
- do { fprintf(stdout, "MCT: [%24s:%5d] " fmt, __func__, __LINE__, \
- ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while (0)
-#endif
-
-#define MCT_CFG 0x000
-#define G_CNT_L 0x100
-#define G_CNT_U 0x104
-#define G_CNT_WSTAT 0x110
-#define G_COMP0_L 0x200
-#define G_COMP0_U 0x204
-#define G_COMP0_ADD_INCR 0x208
-#define G_COMP1_L 0x210
-#define G_COMP1_U 0x214
-#define G_COMP1_ADD_INCR 0x218
-#define G_COMP2_L 0x220
-#define G_COMP2_U 0x224
-#define G_COMP2_ADD_INCR 0x228
-#define G_COMP3_L 0x230
-#define G_COMP3_U 0x234
-#define G_COMP3_ADD_INCR 0x238
-#define G_TCON 0x240
-#define G_INT_CSTAT 0x244
-#define G_INT_ENB 0x248
-#define G_WSTAT 0x24C
-#define L0_TCNTB 0x300
-#define L0_TCNTO 0x304
-#define L0_ICNTB 0x308
-#define L0_ICNTO 0x30C
-#define L0_FRCNTB 0x310
-#define L0_FRCNTO 0x314
-#define L0_TCON 0x320
-#define L0_INT_CSTAT 0x330
-#define L0_INT_ENB 0x334
-#define L0_WSTAT 0x340
-#define L1_TCNTB 0x400
-#define L1_TCNTO 0x404
-#define L1_ICNTB 0x408
-#define L1_ICNTO 0x40C
-#define L1_FRCNTB 0x410
-#define L1_FRCNTO 0x414
-#define L1_TCON 0x420
-#define L1_INT_CSTAT 0x430
-#define L1_INT_ENB 0x434
-#define L1_WSTAT 0x440
-
-#define MCT_CFG_GET_PRESCALER(x) ((x) & 0xFF)
-#define MCT_CFG_GET_DIVIDER(x) (1 << ((x) >> 8 & 7))
-
-#define GET_G_COMP_IDX(offset) (((offset) - G_COMP0_L) / 0x10)
-#define GET_G_COMP_ADD_INCR_IDX(offset) (((offset) - G_COMP0_ADD_INCR) / 0x10)
-
-#define G_COMP_L(x) (G_COMP0_L + (x) * 0x10)
-#define G_COMP_U(x) (G_COMP0_U + (x) * 0x10)
-
-#define G_COMP_ADD_INCR(x) (G_COMP0_ADD_INCR + (x) * 0x10)
-
-/* MCT bits */
-#define G_TCON_COMP_ENABLE(x) (1 << 2 * (x))
-#define G_TCON_AUTO_ICREMENT(x) (1 << (2 * (x) + 1))
-#define G_TCON_TIMER_ENABLE (1 << 8)
-
-#define G_INT_ENABLE(x) (1 << (x))
-#define G_INT_CSTAT_COMP(x) (1 << (x))
-
-#define G_CNT_WSTAT_L 1
-#define G_CNT_WSTAT_U 2
-
-#define G_WSTAT_COMP_L(x) (1 << 4 * (x))
-#define G_WSTAT_COMP_U(x) (1 << ((4 * (x)) + 1))
-#define G_WSTAT_COMP_ADDINCR(x) (1 << ((4 * (x)) + 2))
-#define G_WSTAT_TCON_WRITE (1 << 16)
-
-#define GET_L_TIMER_IDX(offset) ((((offset) & 0xF00) - L0_TCNTB) / 0x100)
-#define GET_L_TIMER_CNT_REG_IDX(offset, lt_i) \
- (((offset) - (L0_TCNTB + 0x100 * (lt_i))) >> 2)
-
-#define L_ICNTB_MANUAL_UPDATE (1 << 31)
-
-#define L_TCON_TICK_START (1)
-#define L_TCON_INT_START (1 << 1)
-#define L_TCON_INTERVAL_MODE (1 << 2)
-#define L_TCON_FRC_START (1 << 3)
-
-#define L_INT_CSTAT_INTCNT (1 << 0)
-#define L_INT_CSTAT_FRCCNT (1 << 1)
-
-#define L_INT_INTENB_ICNTEIE (1 << 0)
-#define L_INT_INTENB_FRCEIE (1 << 1)
-
-#define L_WSTAT_TCNTB_WRITE (1 << 0)
-#define L_WSTAT_ICNTB_WRITE (1 << 1)
-#define L_WSTAT_FRCCNTB_WRITE (1 << 2)
-#define L_WSTAT_TCON_WRITE (1 << 3)
-
-enum LocalTimerRegCntIndexes {
- L_REG_CNT_TCNTB,
- L_REG_CNT_TCNTO,
- L_REG_CNT_ICNTB,
- L_REG_CNT_ICNTO,
- L_REG_CNT_FRCCNTB,
- L_REG_CNT_FRCCNTO,
-
- L_REG_CNT_AMOUNT
-};
-
-#define MCT_NIRQ 6
-#define MCT_SFR_SIZE 0x444
-
-#define MCT_GT_CMP_NUM 4
-
-#define MCT_GT_MAX_VAL UINT64_MAX
-
-#define MCT_GT_COUNTER_STEP 0x100000000ULL
-#define MCT_LT_COUNTER_STEP 0x100000000ULL
-#define MCT_LT_CNT_LOW_LIMIT 0x100
-
-/* global timer */
-typedef struct {
- qemu_irq irq[MCT_GT_CMP_NUM];
-
- struct gregs {
- uint64_t cnt;
- uint32_t cnt_wstat;
- uint32_t tcon;
- uint32_t int_cstat;
- uint32_t int_enb;
- uint32_t wstat;
- uint64_t comp[MCT_GT_CMP_NUM];
- uint32_t comp_add_incr[MCT_GT_CMP_NUM];
- } reg;
-
- uint64_t count; /* Value FRC was armed with */
- int32_t curr_comp; /* Current comparator FRC is running to */
-
- ptimer_state *ptimer_frc; /* FRC timer */
-
-} Exynos4210MCTGT;
-
-/* local timer */
-typedef struct {
- int id; /* timer id */
- qemu_irq irq; /* local timer irq */
-
- struct tick_timer {
- uint32_t cnt_run; /* cnt timer is running */
- uint32_t int_run; /* int timer is running */
-
- uint32_t last_icnto;
- uint32_t last_tcnto;
- uint32_t tcntb; /* initial value for TCNTB */
- uint32_t icntb; /* initial value for ICNTB */
-
- /* for step mode */
- uint64_t distance; /* distance to count to the next event */
- uint64_t progress; /* progress when counting by steps */
- uint64_t count; /* count to arm timer with */
-
- ptimer_state *ptimer_tick; /* timer for tick counter */
- } tick_timer;
-
- /* use ptimer.c to represent count down timer */
-
- ptimer_state *ptimer_frc; /* timer for free running counter */
-
- /* registers */
- struct lregs {
- uint32_t cnt[L_REG_CNT_AMOUNT];
- uint32_t tcon;
- uint32_t int_cstat;
- uint32_t int_enb;
- uint32_t wstat;
- } reg;
-
-} Exynos4210MCTLT;
-
-#define TYPE_EXYNOS4210_MCT "exynos4210.mct"
-#define EXYNOS4210_MCT(obj) \
- OBJECT_CHECK(Exynos4210MCTState, (obj), TYPE_EXYNOS4210_MCT)
-
-typedef struct Exynos4210MCTState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
-
- /* Registers */
- uint32_t reg_mct_cfg;
-
- Exynos4210MCTLT l_timer[2];
- Exynos4210MCTGT g_timer;
-
- uint32_t freq; /* all timers tick frequency, TCLK */
-} Exynos4210MCTState;
-
-/*** VMState ***/
-static const VMStateDescription vmstate_tick_timer = {
- .name = "exynos4210.mct.tick_timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(cnt_run, struct tick_timer),
- VMSTATE_UINT32(int_run, struct tick_timer),
- VMSTATE_UINT32(last_icnto, struct tick_timer),
- VMSTATE_UINT32(last_tcnto, struct tick_timer),
- VMSTATE_UINT32(tcntb, struct tick_timer),
- VMSTATE_UINT32(icntb, struct tick_timer),
- VMSTATE_UINT64(distance, struct tick_timer),
- VMSTATE_UINT64(progress, struct tick_timer),
- VMSTATE_UINT64(count, struct tick_timer),
- VMSTATE_PTIMER(ptimer_tick, struct tick_timer),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_lregs = {
- .name = "exynos4210.mct.lregs",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(cnt, struct lregs, L_REG_CNT_AMOUNT),
- VMSTATE_UINT32(tcon, struct lregs),
- VMSTATE_UINT32(int_cstat, struct lregs),
- VMSTATE_UINT32(int_enb, struct lregs),
- VMSTATE_UINT32(wstat, struct lregs),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_exynos4210_mct_lt = {
- .name = "exynos4210.mct.lt",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(id, Exynos4210MCTLT),
- VMSTATE_STRUCT(tick_timer, Exynos4210MCTLT, 0,
- vmstate_tick_timer,
- struct tick_timer),
- VMSTATE_PTIMER(ptimer_frc, Exynos4210MCTLT),
- VMSTATE_STRUCT(reg, Exynos4210MCTLT, 0,
- vmstate_lregs,
- struct lregs),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_gregs = {
- .name = "exynos4210.mct.lregs",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(cnt, struct gregs),
- VMSTATE_UINT32(cnt_wstat, struct gregs),
- VMSTATE_UINT32(tcon, struct gregs),
- VMSTATE_UINT32(int_cstat, struct gregs),
- VMSTATE_UINT32(int_enb, struct gregs),
- VMSTATE_UINT32(wstat, struct gregs),
- VMSTATE_UINT64_ARRAY(comp, struct gregs, MCT_GT_CMP_NUM),
- VMSTATE_UINT32_ARRAY(comp_add_incr, struct gregs,
- MCT_GT_CMP_NUM),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_exynos4210_mct_gt = {
- .name = "exynos4210.mct.lt",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT(reg, Exynos4210MCTGT, 0, vmstate_gregs,
- struct gregs),
- VMSTATE_UINT64(count, Exynos4210MCTGT),
- VMSTATE_INT32(curr_comp, Exynos4210MCTGT),
- VMSTATE_PTIMER(ptimer_frc, Exynos4210MCTGT),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_exynos4210_mct_state = {
- .name = "exynos4210.mct",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(reg_mct_cfg, Exynos4210MCTState),
- VMSTATE_STRUCT_ARRAY(l_timer, Exynos4210MCTState, 2, 0,
- vmstate_exynos4210_mct_lt, Exynos4210MCTLT),
- VMSTATE_STRUCT(g_timer, Exynos4210MCTState, 0,
- vmstate_exynos4210_mct_gt, Exynos4210MCTGT),
- VMSTATE_UINT32(freq, Exynos4210MCTState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void exynos4210_mct_update_freq(Exynos4210MCTState *s);
-
-/*
- * Set counter of FRC global timer.
- */
-static void exynos4210_gfrc_set_count(Exynos4210MCTGT *s, uint64_t count)
-{
- s->count = count;
- DPRINTF("global timer frc set count 0x%llx\n", count);
- ptimer_set_count(s->ptimer_frc, count);
-}
-
-/*
- * Get counter of FRC global timer.
- */
-static uint64_t exynos4210_gfrc_get_count(Exynos4210MCTGT *s)
-{
- uint64_t count = 0;
- count = ptimer_get_count(s->ptimer_frc);
- count = s->count - count;
- return s->reg.cnt + count;
-}
-
-/*
- * Stop global FRC timer
- */
-static void exynos4210_gfrc_stop(Exynos4210MCTGT *s)
-{
- DPRINTF("global timer frc stop\n");
-
- ptimer_stop(s->ptimer_frc);
-}
-
-/*
- * Start global FRC timer
- */
-static void exynos4210_gfrc_start(Exynos4210MCTGT *s)
-{
- DPRINTF("global timer frc start\n");
-
- ptimer_run(s->ptimer_frc, 1);
-}
-
-/*
- * Find next nearest Comparator. If current Comparator value equals to other
- * Comparator value, skip them both
- */
-static int32_t exynos4210_gcomp_find(Exynos4210MCTState *s)
-{
- int res;
- int i;
- int enabled;
- uint64_t min;
- int min_comp_i;
- uint64_t gfrc;
- uint64_t distance;
- uint64_t distance_min;
- int comp_i;
-
- /* get gfrc count */
- gfrc = exynos4210_gfrc_get_count(&s->g_timer);
-
- min = UINT64_MAX;
- distance_min = UINT64_MAX;
- comp_i = MCT_GT_CMP_NUM;
- min_comp_i = MCT_GT_CMP_NUM;
- enabled = 0;
-
- /* lookup for nearest comparator */
- for (i = 0; i < MCT_GT_CMP_NUM; i++) {
-
- if (s->g_timer.reg.tcon & G_TCON_COMP_ENABLE(i)) {
-
- enabled = 1;
-
- if (s->g_timer.reg.comp[i] > gfrc) {
- /* Comparator is upper then FRC */
- distance = s->g_timer.reg.comp[i] - gfrc;
-
- if (distance <= distance_min) {
- distance_min = distance;
- comp_i = i;
- }
- } else {
- /* Comparator is below FRC, find the smallest */
-
- if (s->g_timer.reg.comp[i] <= min) {
- min = s->g_timer.reg.comp[i];
- min_comp_i = i;
- }
- }
- }
- }
-
- if (!enabled) {
- /* All Comparators disabled */
- res = -1;
- } else if (comp_i < MCT_GT_CMP_NUM) {
- /* Found upper Comparator */
- res = comp_i;
- } else {
- /* All Comparators are below or equal to FRC */
- res = min_comp_i;
- }
-
- DPRINTF("found comparator %d: comp 0x%llx distance 0x%llx, gfrc 0x%llx\n",
- res,
- s->g_timer.reg.comp[res],
- distance_min,
- gfrc);
-
- return res;
-}
-
-/*
- * Get distance to nearest Comparator
- */
-static uint64_t exynos4210_gcomp_get_distance(Exynos4210MCTState *s, int32_t id)
-{
- if (id == -1) {
- /* no enabled Comparators, choose max distance */
- return MCT_GT_COUNTER_STEP;
- }
- if (s->g_timer.reg.comp[id] - s->g_timer.reg.cnt < MCT_GT_COUNTER_STEP) {
- return s->g_timer.reg.comp[id] - s->g_timer.reg.cnt;
- } else {
- return MCT_GT_COUNTER_STEP;
- }
-}
-
-/*
- * Restart global FRC timer
- */
-static void exynos4210_gfrc_restart(Exynos4210MCTState *s)
-{
- uint64_t distance;
-
- exynos4210_gfrc_stop(&s->g_timer);
-
- s->g_timer.curr_comp = exynos4210_gcomp_find(s);
-
- distance = exynos4210_gcomp_get_distance(s, s->g_timer.curr_comp);
-
- if (distance > MCT_GT_COUNTER_STEP || !distance) {
- distance = MCT_GT_COUNTER_STEP;
- }
-
- exynos4210_gfrc_set_count(&s->g_timer, distance);
- exynos4210_gfrc_start(&s->g_timer);
-}
-
-/*
- * Raise global timer CMP IRQ
- */
-static void exynos4210_gcomp_raise_irq(void *opaque, uint32_t id)
-{
- Exynos4210MCTGT *s = opaque;
-
- /* If CSTAT is pending and IRQ is enabled */
- if ((s->reg.int_cstat & G_INT_CSTAT_COMP(id)) &&
- (s->reg.int_enb & G_INT_ENABLE(id))) {
- DPRINTF("gcmp timer[%d] IRQ\n", id);
- qemu_irq_raise(s->irq[id]);
- }
-}
-
-/*
- * Lower global timer CMP IRQ
- */
-static void exynos4210_gcomp_lower_irq(void *opaque, uint32_t id)
-{
- Exynos4210MCTGT *s = opaque;
- qemu_irq_lower(s->irq[id]);
-}
-
-/*
- * Global timer FRC event handler.
- * Each event occurs when internal counter reaches counter + MCT_GT_COUNTER_STEP
- * Every time we arm global FRC timer to count for MCT_GT_COUNTER_STEP value
- */
-static void exynos4210_gfrc_event(void *opaque)
-{
- Exynos4210MCTState *s = (Exynos4210MCTState *)opaque;
- int i;
- uint64_t distance;
-
- DPRINTF("\n");
-
- s->g_timer.reg.cnt += s->g_timer.count;
-
- /* Process all comparators */
- for (i = 0; i < MCT_GT_CMP_NUM; i++) {
-
- if (s->g_timer.reg.cnt == s->g_timer.reg.comp[i]) {
- /* reached nearest comparator */
-
- s->g_timer.reg.int_cstat |= G_INT_CSTAT_COMP(i);
-
- /* Auto increment */
- if (s->g_timer.reg.tcon & G_TCON_AUTO_ICREMENT(i)) {
- s->g_timer.reg.comp[i] += s->g_timer.reg.comp_add_incr[i];
- }
-
- /* IRQ */
- exynos4210_gcomp_raise_irq(&s->g_timer, i);
- }
- }
-
- /* Reload FRC to reach nearest comparator */
- s->g_timer.curr_comp = exynos4210_gcomp_find(s);
- distance = exynos4210_gcomp_get_distance(s, s->g_timer.curr_comp);
- if (distance > MCT_GT_COUNTER_STEP || !distance) {
- distance = MCT_GT_COUNTER_STEP;
- }
- exynos4210_gfrc_set_count(&s->g_timer, distance);
-
- exynos4210_gfrc_start(&s->g_timer);
-}
-
-/*
- * Get counter of FRC local timer.
- */
-static uint64_t exynos4210_lfrc_get_count(Exynos4210MCTLT *s)
-{
- return ptimer_get_count(s->ptimer_frc);
-}
-
-/*
- * Set counter of FRC local timer.
- */
-static void exynos4210_lfrc_update_count(Exynos4210MCTLT *s)
-{
- if (!s->reg.cnt[L_REG_CNT_FRCCNTB]) {
- ptimer_set_count(s->ptimer_frc, MCT_LT_COUNTER_STEP);
- } else {
- ptimer_set_count(s->ptimer_frc, s->reg.cnt[L_REG_CNT_FRCCNTB]);
- }
-}
-
-/*
- * Start local FRC timer
- */
-static void exynos4210_lfrc_start(Exynos4210MCTLT *s)
-{
- ptimer_run(s->ptimer_frc, 1);
-}
-
-/*
- * Stop local FRC timer
- */
-static void exynos4210_lfrc_stop(Exynos4210MCTLT *s)
-{
- ptimer_stop(s->ptimer_frc);
-}
-
-/*
- * Local timer free running counter tick handler
- */
-static void exynos4210_lfrc_event(void *opaque)
-{
- Exynos4210MCTLT * s = (Exynos4210MCTLT *)opaque;
-
- /* local frc expired */
-
- DPRINTF("\n");
-
- s->reg.int_cstat |= L_INT_CSTAT_FRCCNT;
-
- /* update frc counter */
- exynos4210_lfrc_update_count(s);
-
- /* raise irq */
- if (s->reg.int_enb & L_INT_INTENB_FRCEIE) {
- qemu_irq_raise(s->irq);
- }
-
- /* we reached here, this means that timer is enabled */
- exynos4210_lfrc_start(s);
-}
-
-static uint32_t exynos4210_ltick_int_get_cnto(struct tick_timer *s);
-static uint32_t exynos4210_ltick_cnt_get_cnto(struct tick_timer *s);
-static void exynos4210_ltick_recalc_count(struct tick_timer *s);
-
-/*
- * Action on enabling local tick int timer
- */
-static void exynos4210_ltick_int_start(struct tick_timer *s)
-{
- if (!s->int_run) {
- s->int_run = 1;
- }
-}
-
-/*
- * Action on disabling local tick int timer
- */
-static void exynos4210_ltick_int_stop(struct tick_timer *s)
-{
- if (s->int_run) {
- s->last_icnto = exynos4210_ltick_int_get_cnto(s);
- s->int_run = 0;
- }
-}
-
-/*
- * Get count for INT timer
- */
-static uint32_t exynos4210_ltick_int_get_cnto(struct tick_timer *s)
-{
- uint32_t icnto;
- uint64_t remain;
- uint64_t count;
- uint64_t counted;
- uint64_t cur_progress;
-
- count = ptimer_get_count(s->ptimer_tick);
- if (count) {
- /* timer is still counting, called not from event */
- counted = s->count - ptimer_get_count(s->ptimer_tick);
- cur_progress = s->progress + counted;
- } else {
- /* timer expired earlier */
- cur_progress = s->progress;
- }
-
- remain = s->distance - cur_progress;
-
- if (!s->int_run) {
- /* INT is stopped. */
- icnto = s->last_icnto;
- } else {
- /* Both are counting */
- icnto = remain / s->tcntb;
- }
-
- return icnto;
-}
-
-/*
- * Start local tick cnt timer.
- */
-static void exynos4210_ltick_cnt_start(struct tick_timer *s)
-{
- if (!s->cnt_run) {
-
- exynos4210_ltick_recalc_count(s);
- ptimer_set_count(s->ptimer_tick, s->count);
- ptimer_run(s->ptimer_tick, 1);
-
- s->cnt_run = 1;
- }
-}
-
-/*
- * Stop local tick cnt timer.
- */
-static void exynos4210_ltick_cnt_stop(struct tick_timer *s)
-{
- if (s->cnt_run) {
-
- s->last_tcnto = exynos4210_ltick_cnt_get_cnto(s);
-
- if (s->int_run) {
- exynos4210_ltick_int_stop(s);
- }
-
- ptimer_stop(s->ptimer_tick);
-
- s->cnt_run = 0;
- }
-}
-
-/*
- * Get counter for CNT timer
- */
-static uint32_t exynos4210_ltick_cnt_get_cnto(struct tick_timer *s)
-{
- uint32_t tcnto;
- uint32_t icnto;
- uint64_t remain;
- uint64_t counted;
- uint64_t count;
- uint64_t cur_progress;
-
- count = ptimer_get_count(s->ptimer_tick);
- if (count) {
- /* timer is still counting, called not from event */
- counted = s->count - ptimer_get_count(s->ptimer_tick);
- cur_progress = s->progress + counted;
- } else {
- /* timer expired earlier */
- cur_progress = s->progress;
- }
-
- remain = s->distance - cur_progress;
-
- if (!s->cnt_run) {
- /* Both are stopped. */
- tcnto = s->last_tcnto;
- } else if (!s->int_run) {
- /* INT counter is stopped, progress is by CNT timer */
- tcnto = remain % s->tcntb;
- } else {
- /* Both are counting */
- icnto = remain / s->tcntb;
- if (icnto) {
- tcnto = remain % (icnto * s->tcntb);
- } else {
- tcnto = remain % s->tcntb;
- }
- }
-
- return tcnto;
-}
-
-/*
- * Set new values of counters for CNT and INT timers
- */
-static void exynos4210_ltick_set_cntb(struct tick_timer *s, uint32_t new_cnt,
- uint32_t new_int)
-{
- uint32_t cnt_stopped = 0;
- uint32_t int_stopped = 0;
-
- if (s->cnt_run) {
- exynos4210_ltick_cnt_stop(s);
- cnt_stopped = 1;
- }
-
- if (s->int_run) {
- exynos4210_ltick_int_stop(s);
- int_stopped = 1;
- }
-
- s->tcntb = new_cnt + 1;
- s->icntb = new_int + 1;
-
- if (cnt_stopped) {
- exynos4210_ltick_cnt_start(s);
- }
- if (int_stopped) {
- exynos4210_ltick_int_start(s);
- }
-
-}
-
-/*
- * Calculate new counter value for tick timer
- */
-static void exynos4210_ltick_recalc_count(struct tick_timer *s)
-{
- uint64_t to_count;
-
- if ((s->cnt_run && s->last_tcnto) || (s->int_run && s->last_icnto)) {
- /*
- * one or both timers run and not counted to the end;
- * distance is not passed, recalculate with last_tcnto * last_icnto
- */
-
- if (s->last_tcnto) {
- to_count = (uint64_t)s->last_tcnto * s->last_icnto;
- } else {
- to_count = s->last_icnto;
- }
- } else {
- /* distance is passed, recalculate with tcnto * icnto */
- if (s->icntb) {
- s->distance = (uint64_t)s->tcntb * s->icntb;
- } else {
- s->distance = s->tcntb;
- }
-
- to_count = s->distance;
- s->progress = 0;
- }
-
- if (to_count > MCT_LT_COUNTER_STEP) {
- /* count by step */
- s->count = MCT_LT_COUNTER_STEP;
- } else {
- s->count = to_count;
- }
-}
-
-/*
- * Initialize tick_timer
- */
-static void exynos4210_ltick_timer_init(struct tick_timer *s)
-{
- exynos4210_ltick_int_stop(s);
- exynos4210_ltick_cnt_stop(s);
-
- s->count = 0;
- s->distance = 0;
- s->progress = 0;
- s->icntb = 0;
- s->tcntb = 0;
-}
-
-/*
- * tick_timer event.
- * Raises when abstract tick_timer expires.
- */
-static void exynos4210_ltick_timer_event(struct tick_timer *s)
-{
- s->progress += s->count;
-}
-
-/*
- * Local timer tick counter handler.
- * Don't use reloaded timers. If timer counter = zero
- * then handler called but after handler finished no
- * timer reload occurs.
- */
-static void exynos4210_ltick_event(void *opaque)
-{
- Exynos4210MCTLT * s = (Exynos4210MCTLT *)opaque;
- uint32_t tcnto;
- uint32_t icnto;
-#ifdef DEBUG_MCT
- static uint64_t time1[2] = {0};
- static uint64_t time2[2] = {0};
-#endif
-
- /* Call tick_timer event handler, it will update its tcntb and icntb. */
- exynos4210_ltick_timer_event(&s->tick_timer);
-
- /* get tick_timer cnt */
- tcnto = exynos4210_ltick_cnt_get_cnto(&s->tick_timer);
-
- /* get tick_timer int */
- icnto = exynos4210_ltick_int_get_cnto(&s->tick_timer);
-
- /* raise IRQ if needed */
- if (!icnto && s->reg.tcon & L_TCON_INT_START) {
- /* INT counter enabled and expired */
-
- s->reg.int_cstat |= L_INT_CSTAT_INTCNT;
-
- /* raise interrupt if enabled */
- if (s->reg.int_enb & L_INT_INTENB_ICNTEIE) {
-#ifdef DEBUG_MCT
- time2[s->id] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- DPRINTF("local timer[%d] IRQ: %llx\n", s->id,
- time2[s->id] - time1[s->id]);
- time1[s->id] = time2[s->id];
-#endif
- qemu_irq_raise(s->irq);
- }
-
- /* reload ICNTB */
- if (s->reg.tcon & L_TCON_INTERVAL_MODE) {
- exynos4210_ltick_set_cntb(&s->tick_timer,
- s->reg.cnt[L_REG_CNT_TCNTB],
- s->reg.cnt[L_REG_CNT_ICNTB]);
- }
- } else {
- /* reload TCNTB */
- if (!tcnto) {
- exynos4210_ltick_set_cntb(&s->tick_timer,
- s->reg.cnt[L_REG_CNT_TCNTB],
- icnto);
- }
- }
-
- /* start tick_timer cnt */
- exynos4210_ltick_cnt_start(&s->tick_timer);
-
- /* start tick_timer int */
- exynos4210_ltick_int_start(&s->tick_timer);
-}
-
-/* update timer frequency */
-static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
-{
- uint32_t freq = s->freq;
- s->freq = 24000000 /
- ((MCT_CFG_GET_PRESCALER(s->reg_mct_cfg)+1) *
- MCT_CFG_GET_DIVIDER(s->reg_mct_cfg));
-
- if (freq != s->freq) {
- DPRINTF("freq=%dHz\n", s->freq);
-
- /* global timer */
- ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
-
- /* local timer */
- ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
- ptimer_set_freq(s->l_timer[0].ptimer_frc, s->freq);
- ptimer_set_freq(s->l_timer[1].tick_timer.ptimer_tick, s->freq);
- ptimer_set_freq(s->l_timer[1].ptimer_frc, s->freq);
- }
-}
-
-/* set defaul_timer values for all fields */
-static void exynos4210_mct_reset(DeviceState *d)
-{
- Exynos4210MCTState *s = EXYNOS4210_MCT(d);
- uint32_t i;
-
- s->reg_mct_cfg = 0;
-
- /* global timer */
- memset(&s->g_timer.reg, 0, sizeof(s->g_timer.reg));
- exynos4210_gfrc_stop(&s->g_timer);
-
- /* local timer */
- memset(s->l_timer[0].reg.cnt, 0, sizeof(s->l_timer[0].reg.cnt));
- memset(s->l_timer[1].reg.cnt, 0, sizeof(s->l_timer[1].reg.cnt));
- for (i = 0; i < 2; i++) {
- s->l_timer[i].reg.int_cstat = 0;
- s->l_timer[i].reg.int_enb = 0;
- s->l_timer[i].reg.tcon = 0;
- s->l_timer[i].reg.wstat = 0;
- s->l_timer[i].tick_timer.count = 0;
- s->l_timer[i].tick_timer.distance = 0;
- s->l_timer[i].tick_timer.progress = 0;
- ptimer_stop(s->l_timer[i].ptimer_frc);
-
- exynos4210_ltick_timer_init(&s->l_timer[i].tick_timer);
- }
-
- exynos4210_mct_update_freq(s);
-
-}
-
-/* Multi Core Timer read */
-static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- Exynos4210MCTState *s = (Exynos4210MCTState *)opaque;
- int index;
- int shift;
- uint64_t count;
- uint32_t value;
- int lt_i;
-
- switch (offset) {
-
- case MCT_CFG:
- value = s->reg_mct_cfg;
- break;
-
- case G_CNT_L: case G_CNT_U:
- shift = 8 * (offset & 0x4);
- count = exynos4210_gfrc_get_count(&s->g_timer);
- value = UINT32_MAX & (count >> shift);
- DPRINTF("read FRC=0x%llx\n", count);
- break;
-
- case G_CNT_WSTAT:
- value = s->g_timer.reg.cnt_wstat;
- break;
-
- case G_COMP_L(0): case G_COMP_L(1): case G_COMP_L(2): case G_COMP_L(3):
- case G_COMP_U(0): case G_COMP_U(1): case G_COMP_U(2): case G_COMP_U(3):
- index = GET_G_COMP_IDX(offset);
- shift = 8 * (offset & 0x4);
- value = UINT32_MAX & (s->g_timer.reg.comp[index] >> shift);
- break;
-
- case G_TCON:
- value = s->g_timer.reg.tcon;
- break;
-
- case G_INT_CSTAT:
- value = s->g_timer.reg.int_cstat;
- break;
-
- case G_INT_ENB:
- value = s->g_timer.reg.int_enb;
- break;
- case G_WSTAT:
- value = s->g_timer.reg.wstat;
- break;
-
- case G_COMP0_ADD_INCR: case G_COMP1_ADD_INCR:
- case G_COMP2_ADD_INCR: case G_COMP3_ADD_INCR:
- value = s->g_timer.reg.comp_add_incr[GET_G_COMP_ADD_INCR_IDX(offset)];
- break;
-
- /* Local timers */
- case L0_TCNTB: case L0_ICNTB: case L0_FRCNTB:
- case L1_TCNTB: case L1_ICNTB: case L1_FRCNTB:
- lt_i = GET_L_TIMER_IDX(offset);
- index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);
- value = s->l_timer[lt_i].reg.cnt[index];
- break;
-
- case L0_TCNTO: case L1_TCNTO:
- lt_i = GET_L_TIMER_IDX(offset);
-
- value = exynos4210_ltick_cnt_get_cnto(&s->l_timer[lt_i].tick_timer);
- DPRINTF("local timer[%d] read TCNTO %x\n", lt_i, value);
- break;
-
- case L0_ICNTO: case L1_ICNTO:
- lt_i = GET_L_TIMER_IDX(offset);
-
- value = exynos4210_ltick_int_get_cnto(&s->l_timer[lt_i].tick_timer);
- DPRINTF("local timer[%d] read ICNTO %x\n", lt_i, value);
- break;
-
- case L0_FRCNTO: case L1_FRCNTO:
- lt_i = GET_L_TIMER_IDX(offset);
-
- value = exynos4210_lfrc_get_count(&s->l_timer[lt_i]);
-
- break;
-
- case L0_TCON: case L1_TCON:
- lt_i = ((offset & 0xF00) - L0_TCNTB) / 0x100;
- value = s->l_timer[lt_i].reg.tcon;
- break;
-
- case L0_INT_CSTAT: case L1_INT_CSTAT:
- lt_i = ((offset & 0xF00) - L0_TCNTB) / 0x100;
- value = s->l_timer[lt_i].reg.int_cstat;
- break;
-
- case L0_INT_ENB: case L1_INT_ENB:
- lt_i = ((offset & 0xF00) - L0_TCNTB) / 0x100;
- value = s->l_timer[lt_i].reg.int_enb;
- break;
-
- case L0_WSTAT: case L1_WSTAT:
- lt_i = ((offset & 0xF00) - L0_TCNTB) / 0x100;
- value = s->l_timer[lt_i].reg.wstat;
- break;
-
- default:
- hw_error("exynos4210.mct: bad read offset "
- TARGET_FMT_plx "\n", offset);
- break;
- }
- return value;
-}
-
-/* MCT write */
-static void exynos4210_mct_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- Exynos4210MCTState *s = (Exynos4210MCTState *)opaque;
- int index; /* index in buffer which represents register set */
- int shift;
- int lt_i;
- uint64_t new_frc;
- uint32_t i;
- uint32_t old_val;
-#ifdef DEBUG_MCT
- static uint32_t icntb_max[2] = {0};
- static uint32_t icntb_min[2] = {UINT32_MAX, UINT32_MAX};
- static uint32_t tcntb_max[2] = {0};
- static uint32_t tcntb_min[2] = {UINT32_MAX, UINT32_MAX};
-#endif
-
- new_frc = s->g_timer.reg.cnt;
-
- switch (offset) {
-
- case MCT_CFG:
- s->reg_mct_cfg = value;
- exynos4210_mct_update_freq(s);
- break;
-
- case G_CNT_L:
- case G_CNT_U:
- if (offset == G_CNT_L) {
-
- DPRINTF("global timer write to reg.cntl %llx\n", value);
-
- new_frc = (s->g_timer.reg.cnt & (uint64_t)UINT32_MAX << 32) + value;
- s->g_timer.reg.cnt_wstat |= G_CNT_WSTAT_L;
- }
- if (offset == G_CNT_U) {
-
- DPRINTF("global timer write to reg.cntu %llx\n", value);
-
- new_frc = (s->g_timer.reg.cnt & UINT32_MAX) +
- ((uint64_t)value << 32);
- s->g_timer.reg.cnt_wstat |= G_CNT_WSTAT_U;
- }
-
- s->g_timer.reg.cnt = new_frc;
- exynos4210_gfrc_restart(s);
- break;
-
- case G_CNT_WSTAT:
- s->g_timer.reg.cnt_wstat &= ~(value);
- break;
-
- case G_COMP_L(0): case G_COMP_L(1): case G_COMP_L(2): case G_COMP_L(3):
- case G_COMP_U(0): case G_COMP_U(1): case G_COMP_U(2): case G_COMP_U(3):
- index = GET_G_COMP_IDX(offset);
- shift = 8 * (offset & 0x4);
- s->g_timer.reg.comp[index] =
- (s->g_timer.reg.comp[index] &
- (((uint64_t)UINT32_MAX << 32) >> shift)) +
- (value << shift);
-
- DPRINTF("comparator %d write 0x%llx val << %d\n", index, value, shift);
-
- if (offset&0x4) {
- s->g_timer.reg.wstat |= G_WSTAT_COMP_U(index);
- } else {
- s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
- }
-
- exynos4210_gfrc_restart(s);
- break;
-
- case G_TCON:
- old_val = s->g_timer.reg.tcon;
- s->g_timer.reg.tcon = value;
- s->g_timer.reg.wstat |= G_WSTAT_TCON_WRITE;
-
- DPRINTF("global timer write to reg.g_tcon %llx\n", value);
-
- /* Start FRC if transition from disabled to enabled */
- if ((value & G_TCON_TIMER_ENABLE) > (old_val &
- G_TCON_TIMER_ENABLE)) {
- exynos4210_gfrc_start(&s->g_timer);
- }
- if ((value & G_TCON_TIMER_ENABLE) < (old_val &
- G_TCON_TIMER_ENABLE)) {
- exynos4210_gfrc_stop(&s->g_timer);
- }
-
- /* Start CMP if transition from disabled to enabled */
- for (i = 0; i < MCT_GT_CMP_NUM; i++) {
- if ((value & G_TCON_COMP_ENABLE(i)) != (old_val &
- G_TCON_COMP_ENABLE(i))) {
- exynos4210_gfrc_restart(s);
- }
- }
- break;
-
- case G_INT_CSTAT:
- s->g_timer.reg.int_cstat &= ~(value);
- for (i = 0; i < MCT_GT_CMP_NUM; i++) {
- if (value & G_INT_CSTAT_COMP(i)) {
- exynos4210_gcomp_lower_irq(&s->g_timer, i);
- }
- }
- break;
-
- case G_INT_ENB:
-
- /* Raise IRQ if transition from disabled to enabled and CSTAT pending */
- for (i = 0; i < MCT_GT_CMP_NUM; i++) {
- if ((value & G_INT_ENABLE(i)) > (s->g_timer.reg.tcon &
- G_INT_ENABLE(i))) {
- if (s->g_timer.reg.int_cstat & G_INT_CSTAT_COMP(i)) {
- exynos4210_gcomp_raise_irq(&s->g_timer, i);
- }
- }
-
- if ((value & G_INT_ENABLE(i)) < (s->g_timer.reg.tcon &
- G_INT_ENABLE(i))) {
- exynos4210_gcomp_lower_irq(&s->g_timer, i);
- }
- }
-
- DPRINTF("global timer INT enable %llx\n", value);
- s->g_timer.reg.int_enb = value;
- break;
-
- case G_WSTAT:
- s->g_timer.reg.wstat &= ~(value);
- break;
-
- case G_COMP0_ADD_INCR: case G_COMP1_ADD_INCR:
- case G_COMP2_ADD_INCR: case G_COMP3_ADD_INCR:
- index = GET_G_COMP_ADD_INCR_IDX(offset);
- s->g_timer.reg.comp_add_incr[index] = value;
- s->g_timer.reg.wstat |= G_WSTAT_COMP_ADDINCR(index);
- break;
-
- /* Local timers */
- case L0_TCON: case L1_TCON:
- lt_i = GET_L_TIMER_IDX(offset);
- old_val = s->l_timer[lt_i].reg.tcon;
-
- s->l_timer[lt_i].reg.wstat |= L_WSTAT_TCON_WRITE;
- s->l_timer[lt_i].reg.tcon = value;
-
- /* Stop local CNT */
- if ((value & L_TCON_TICK_START) <
- (old_val & L_TCON_TICK_START)) {
- DPRINTF("local timer[%d] stop cnt\n", lt_i);
- exynos4210_ltick_cnt_stop(&s->l_timer[lt_i].tick_timer);
- }
-
- /* Stop local INT */
- if ((value & L_TCON_INT_START) <
- (old_val & L_TCON_INT_START)) {
- DPRINTF("local timer[%d] stop int\n", lt_i);
- exynos4210_ltick_int_stop(&s->l_timer[lt_i].tick_timer);
- }
-
- /* Start local CNT */
- if ((value & L_TCON_TICK_START) >
- (old_val & L_TCON_TICK_START)) {
- DPRINTF("local timer[%d] start cnt\n", lt_i);
- exynos4210_ltick_cnt_start(&s->l_timer[lt_i].tick_timer);
- }
-
- /* Start local INT */
- if ((value & L_TCON_INT_START) >
- (old_val & L_TCON_INT_START)) {
- DPRINTF("local timer[%d] start int\n", lt_i);
- exynos4210_ltick_int_start(&s->l_timer[lt_i].tick_timer);
- }
-
- /* Start or Stop local FRC if TCON changed */
- if ((value & L_TCON_FRC_START) >
- (s->l_timer[lt_i].reg.tcon & L_TCON_FRC_START)) {
- DPRINTF("local timer[%d] start frc\n", lt_i);
- exynos4210_lfrc_start(&s->l_timer[lt_i]);
- }
- if ((value & L_TCON_FRC_START) <
- (s->l_timer[lt_i].reg.tcon & L_TCON_FRC_START)) {
- DPRINTF("local timer[%d] stop frc\n", lt_i);
- exynos4210_lfrc_stop(&s->l_timer[lt_i]);
- }
- break;
-
- case L0_TCNTB: case L1_TCNTB:
-
- lt_i = GET_L_TIMER_IDX(offset);
- index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);
-
- /*
- * TCNTB is updated to internal register only after CNT expired.
- * Due to this we should reload timer to nearest moment when CNT is
- * expired and then in event handler update tcntb to new TCNTB value.
- */
- exynos4210_ltick_set_cntb(&s->l_timer[lt_i].tick_timer, value,
- s->l_timer[lt_i].tick_timer.icntb);
-
- s->l_timer[lt_i].reg.wstat |= L_WSTAT_TCNTB_WRITE;
- s->l_timer[lt_i].reg.cnt[L_REG_CNT_TCNTB] = value;
-
-#ifdef DEBUG_MCT
- if (tcntb_min[lt_i] > value) {
- tcntb_min[lt_i] = value;
- }
- if (tcntb_max[lt_i] < value) {
- tcntb_max[lt_i] = value;
- }
- DPRINTF("local timer[%d] TCNTB write %llx; max=%x, min=%x\n",
- lt_i, value, tcntb_max[lt_i], tcntb_min[lt_i]);
-#endif
- break;
-
- case L0_ICNTB: case L1_ICNTB:
-
- lt_i = GET_L_TIMER_IDX(offset);
- index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);
-
- s->l_timer[lt_i].reg.wstat |= L_WSTAT_ICNTB_WRITE;
- s->l_timer[lt_i].reg.cnt[L_REG_CNT_ICNTB] = value &
- ~L_ICNTB_MANUAL_UPDATE;
-
- /*
- * We need to avoid too small values for TCNTB*ICNTB. If not, IRQ event
- * could raise too fast disallowing QEMU to execute target code.
- */
- if (s->l_timer[lt_i].reg.cnt[L_REG_CNT_ICNTB] *
- s->l_timer[lt_i].reg.cnt[L_REG_CNT_TCNTB] < MCT_LT_CNT_LOW_LIMIT) {
- if (!s->l_timer[lt_i].reg.cnt[L_REG_CNT_TCNTB]) {
- s->l_timer[lt_i].reg.cnt[L_REG_CNT_ICNTB] =
- MCT_LT_CNT_LOW_LIMIT;
- } else {
- s->l_timer[lt_i].reg.cnt[L_REG_CNT_ICNTB] =
- MCT_LT_CNT_LOW_LIMIT /
- s->l_timer[lt_i].reg.cnt[L_REG_CNT_TCNTB];
- }
- }
-
- if (value & L_ICNTB_MANUAL_UPDATE) {
- exynos4210_ltick_set_cntb(&s->l_timer[lt_i].tick_timer,
- s->l_timer[lt_i].tick_timer.tcntb,
- s->l_timer[lt_i].reg.cnt[L_REG_CNT_ICNTB]);
- }
-
-#ifdef DEBUG_MCT
- if (icntb_min[lt_i] > value) {
- icntb_min[lt_i] = value;
- }
- if (icntb_max[lt_i] < value) {
- icntb_max[lt_i] = value;
- }
-DPRINTF("local timer[%d] ICNTB write %llx; max=%x, min=%x\n\n",
- lt_i, value, icntb_max[lt_i], icntb_min[lt_i]);
-#endif
-break;
-
- case L0_FRCNTB: case L1_FRCNTB:
-
- lt_i = GET_L_TIMER_IDX(offset);
- index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);
-
- DPRINTF("local timer[%d] FRCNTB write %llx\n", lt_i, value);
-
- s->l_timer[lt_i].reg.wstat |= L_WSTAT_FRCCNTB_WRITE;
- s->l_timer[lt_i].reg.cnt[L_REG_CNT_FRCCNTB] = value;
-
- break;
-
- case L0_TCNTO: case L1_TCNTO:
- case L0_ICNTO: case L1_ICNTO:
- case L0_FRCNTO: case L1_FRCNTO:
- fprintf(stderr, "\n[exynos4210.mct: write to RO register "
- TARGET_FMT_plx "]\n\n", offset);
- break;
-
- case L0_INT_CSTAT: case L1_INT_CSTAT:
- lt_i = GET_L_TIMER_IDX(offset);
-
- DPRINTF("local timer[%d] CSTAT write %llx\n", lt_i, value);
-
- s->l_timer[lt_i].reg.int_cstat &= ~value;
- if (!s->l_timer[lt_i].reg.int_cstat) {
- qemu_irq_lower(s->l_timer[lt_i].irq);
- }
- break;
-
- case L0_INT_ENB: case L1_INT_ENB:
- lt_i = GET_L_TIMER_IDX(offset);
- old_val = s->l_timer[lt_i].reg.int_enb;
-
- /* Raise Local timer IRQ if cstat is pending */
- if ((value & L_INT_INTENB_ICNTEIE) > (old_val & L_INT_INTENB_ICNTEIE)) {
- if (s->l_timer[lt_i].reg.int_cstat & L_INT_CSTAT_INTCNT) {
- qemu_irq_raise(s->l_timer[lt_i].irq);
- }
- }
-
- s->l_timer[lt_i].reg.int_enb = value;
-
- break;
-
- case L0_WSTAT: case L1_WSTAT:
- lt_i = GET_L_TIMER_IDX(offset);
-
- s->l_timer[lt_i].reg.wstat &= ~value;
- break;
-
- default:
- hw_error("exynos4210.mct: bad write offset "
- TARGET_FMT_plx "\n", offset);
- break;
- }
-}
-
-static const MemoryRegionOps exynos4210_mct_ops = {
- .read = exynos4210_mct_read,
- .write = exynos4210_mct_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/* MCT init */
-static void exynos4210_mct_init(Object *obj)
-{
- int i;
- Exynos4210MCTState *s = EXYNOS4210_MCT(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- QEMUBH *bh[2];
-
- /* Global timer */
- bh[0] = qemu_bh_new(exynos4210_gfrc_event, s);
- s->g_timer.ptimer_frc = ptimer_init(bh[0]);
- memset(&s->g_timer.reg, 0, sizeof(struct gregs));
-
- /* Local timers */
- for (i = 0; i < 2; i++) {
- bh[0] = qemu_bh_new(exynos4210_ltick_event, &s->l_timer[i]);
- bh[1] = qemu_bh_new(exynos4210_lfrc_event, &s->l_timer[i]);
- s->l_timer[i].tick_timer.ptimer_tick = ptimer_init(bh[0]);
- s->l_timer[i].ptimer_frc = ptimer_init(bh[1]);
- s->l_timer[i].id = i;
- }
-
- /* IRQs */
- for (i = 0; i < MCT_GT_CMP_NUM; i++) {
- sysbus_init_irq(dev, &s->g_timer.irq[i]);
- }
- for (i = 0; i < 2; i++) {
- sysbus_init_irq(dev, &s->l_timer[i].irq);
- }
-
- memory_region_init_io(&s->iomem, obj, &exynos4210_mct_ops, s,
- "exynos4210-mct", MCT_SFR_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
-}
-
-static void exynos4210_mct_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->reset = exynos4210_mct_reset;
- dc->vmsd = &vmstate_exynos4210_mct_state;
-}
-
-static const TypeInfo exynos4210_mct_info = {
- .name = TYPE_EXYNOS4210_MCT,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(Exynos4210MCTState),
- .instance_init = exynos4210_mct_init,
- .class_init = exynos4210_mct_class_init,
-};
-
-static void exynos4210_mct_register_types(void)
-{
- type_register_static(&exynos4210_mct_info);
-}
-
-type_init(exynos4210_mct_register_types)
diff --git a/qemu/hw/timer/exynos4210_pwm.c b/qemu/hw/timer/exynos4210_pwm.c
deleted file mode 100644
index 0e9e2e9bf..000000000
--- a/qemu/hw/timer/exynos4210_pwm.c
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Samsung exynos4210 Pulse Width Modulation Timer
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
- * All rights reserved.
- *
- * Evgeny Voevodin <e.voevodin@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "qemu/timer.h"
-#include "qemu-common.h"
-#include "qemu/main-loop.h"
-#include "hw/ptimer.h"
-
-#include "hw/arm/exynos4210.h"
-
-//#define DEBUG_PWM
-
-#ifdef DEBUG_PWM
-#define DPRINTF(fmt, ...) \
- do { fprintf(stdout, "PWM: [%24s:%5d] " fmt, __func__, __LINE__, \
- ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while (0)
-#endif
-
-#define EXYNOS4210_PWM_TIMERS_NUM 5
-#define EXYNOS4210_PWM_REG_MEM_SIZE 0x50
-
-#define TCFG0 0x0000
-#define TCFG1 0x0004
-#define TCON 0x0008
-#define TCNTB0 0x000C
-#define TCMPB0 0x0010
-#define TCNTO0 0x0014
-#define TCNTB1 0x0018
-#define TCMPB1 0x001C
-#define TCNTO1 0x0020
-#define TCNTB2 0x0024
-#define TCMPB2 0x0028
-#define TCNTO2 0x002C
-#define TCNTB3 0x0030
-#define TCMPB3 0x0034
-#define TCNTO3 0x0038
-#define TCNTB4 0x003C
-#define TCNTO4 0x0040
-#define TINT_CSTAT 0x0044
-
-#define TCNTB(x) (0xC * (x))
-#define TCMPB(x) (0xC * (x) + 1)
-#define TCNTO(x) (0xC * (x) + 2)
-
-#define GET_PRESCALER(reg, x) (((reg) & (0xFF << (8 * (x)))) >> 8 * (x))
-#define GET_DIVIDER(reg, x) (1 << (((reg) & (0xF << (4 * (x)))) >> (4 * (x))))
-
-/*
- * Attention! Timer4 doesn't have OUTPUT_INVERTER,
- * so Auto Reload bit is not accessible by macros!
- */
-#define TCON_TIMER_BASE(x) (((x) ? 1 : 0) * 4 + 4 * (x))
-#define TCON_TIMER_START(x) (1 << (TCON_TIMER_BASE(x) + 0))
-#define TCON_TIMER_MANUAL_UPD(x) (1 << (TCON_TIMER_BASE(x) + 1))
-#define TCON_TIMER_OUTPUT_INV(x) (1 << (TCON_TIMER_BASE(x) + 2))
-#define TCON_TIMER_AUTO_RELOAD(x) (1 << (TCON_TIMER_BASE(x) + 3))
-#define TCON_TIMER4_AUTO_RELOAD (1 << 22)
-
-#define TINT_CSTAT_STATUS(x) (1 << (5 + (x)))
-#define TINT_CSTAT_ENABLE(x) (1 << (x))
-
-/* timer struct */
-typedef struct {
- uint32_t id; /* timer id */
- qemu_irq irq; /* local timer irq */
- uint32_t freq; /* timer frequency */
-
- /* use ptimer.c to represent count down timer */
- ptimer_state *ptimer; /* timer */
-
- /* registers */
- uint32_t reg_tcntb; /* counter register buffer */
- uint32_t reg_tcmpb; /* compare register buffer */
-
- struct Exynos4210PWMState *parent;
-
-} Exynos4210PWM;
-
-#define TYPE_EXYNOS4210_PWM "exynos4210.pwm"
-#define EXYNOS4210_PWM(obj) \
- OBJECT_CHECK(Exynos4210PWMState, (obj), TYPE_EXYNOS4210_PWM)
-
-typedef struct Exynos4210PWMState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
-
- uint32_t reg_tcfg[2];
- uint32_t reg_tcon;
- uint32_t reg_tint_cstat;
-
- Exynos4210PWM timer[EXYNOS4210_PWM_TIMERS_NUM];
-
-} Exynos4210PWMState;
-
-/*** VMState ***/
-static const VMStateDescription vmstate_exynos4210_pwm = {
- .name = "exynos4210.pwm.pwm",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(id, Exynos4210PWM),
- VMSTATE_UINT32(freq, Exynos4210PWM),
- VMSTATE_PTIMER(ptimer, Exynos4210PWM),
- VMSTATE_UINT32(reg_tcntb, Exynos4210PWM),
- VMSTATE_UINT32(reg_tcmpb, Exynos4210PWM),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_exynos4210_pwm_state = {
- .name = "exynos4210.pwm",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(reg_tcfg, Exynos4210PWMState, 2),
- VMSTATE_UINT32(reg_tcon, Exynos4210PWMState),
- VMSTATE_UINT32(reg_tint_cstat, Exynos4210PWMState),
- VMSTATE_STRUCT_ARRAY(timer, Exynos4210PWMState,
- EXYNOS4210_PWM_TIMERS_NUM, 0,
- vmstate_exynos4210_pwm, Exynos4210PWM),
- VMSTATE_END_OF_LIST()
- }
-};
-
-/*
- * PWM update frequency
- */
-static void exynos4210_pwm_update_freq(Exynos4210PWMState *s, uint32_t id)
-{
- uint32_t freq;
- freq = s->timer[id].freq;
- if (id > 1) {
- s->timer[id].freq = 24000000 /
- ((GET_PRESCALER(s->reg_tcfg[0], 1) + 1) *
- (GET_DIVIDER(s->reg_tcfg[1], id)));
- } else {
- s->timer[id].freq = 24000000 /
- ((GET_PRESCALER(s->reg_tcfg[0], 0) + 1) *
- (GET_DIVIDER(s->reg_tcfg[1], id)));
- }
-
- if (freq != s->timer[id].freq) {
- ptimer_set_freq(s->timer[id].ptimer, s->timer[id].freq);
- DPRINTF("freq=%dHz\n", s->timer[id].freq);
- }
-}
-
-/*
- * Counter tick handler
- */
-static void exynos4210_pwm_tick(void *opaque)
-{
- Exynos4210PWM *s = (Exynos4210PWM *)opaque;
- Exynos4210PWMState *p = (Exynos4210PWMState *)s->parent;
- uint32_t id = s->id;
- bool cmp;
-
- DPRINTF("timer %d tick\n", id);
-
- /* set irq status */
- p->reg_tint_cstat |= TINT_CSTAT_STATUS(id);
-
- /* raise IRQ */
- if (p->reg_tint_cstat & TINT_CSTAT_ENABLE(id)) {
- DPRINTF("timer %d IRQ\n", id);
- qemu_irq_raise(p->timer[id].irq);
- }
-
- /* reload timer */
- if (id != 4) {
- cmp = p->reg_tcon & TCON_TIMER_AUTO_RELOAD(id);
- } else {
- cmp = p->reg_tcon & TCON_TIMER4_AUTO_RELOAD;
- }
-
- if (cmp) {
- DPRINTF("auto reload timer %d count to %x\n", id,
- p->timer[id].reg_tcntb);
- ptimer_set_count(p->timer[id].ptimer, p->timer[id].reg_tcntb);
- ptimer_run(p->timer[id].ptimer, 1);
- } else {
- /* stop timer, set status to STOP, see Basic Timer Operation */
- p->reg_tcon &= ~TCON_TIMER_START(id);
- ptimer_stop(p->timer[id].ptimer);
- }
-}
-
-/*
- * PWM Read
- */
-static uint64_t exynos4210_pwm_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- Exynos4210PWMState *s = (Exynos4210PWMState *)opaque;
- uint32_t value = 0;
- int index;
-
- switch (offset) {
- case TCFG0: case TCFG1:
- index = (offset - TCFG0) >> 2;
- value = s->reg_tcfg[index];
- break;
-
- case TCON:
- value = s->reg_tcon;
- break;
-
- case TCNTB0: case TCNTB1:
- case TCNTB2: case TCNTB3: case TCNTB4:
- index = (offset - TCNTB0) / 0xC;
- value = s->timer[index].reg_tcntb;
- break;
-
- case TCMPB0: case TCMPB1:
- case TCMPB2: case TCMPB3:
- index = (offset - TCMPB0) / 0xC;
- value = s->timer[index].reg_tcmpb;
- break;
-
- case TCNTO0: case TCNTO1:
- case TCNTO2: case TCNTO3: case TCNTO4:
- index = (offset == TCNTO4) ? 4 : (offset - TCNTO0) / 0xC;
- value = ptimer_get_count(s->timer[index].ptimer);
- break;
-
- case TINT_CSTAT:
- value = s->reg_tint_cstat;
- break;
-
- default:
- fprintf(stderr,
- "[exynos4210.pwm: bad read offset " TARGET_FMT_plx "]\n",
- offset);
- break;
- }
- return value;
-}
-
-/*
- * PWM Write
- */
-static void exynos4210_pwm_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- Exynos4210PWMState *s = (Exynos4210PWMState *)opaque;
- int index;
- uint32_t new_val;
- int i;
-
- switch (offset) {
- case TCFG0: case TCFG1:
- index = (offset - TCFG0) >> 2;
- s->reg_tcfg[index] = value;
-
- /* update timers frequencies */
- for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
- exynos4210_pwm_update_freq(s, s->timer[i].id);
- }
- break;
-
- case TCON:
- for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
- if ((value & TCON_TIMER_MANUAL_UPD(i)) >
- (s->reg_tcon & TCON_TIMER_MANUAL_UPD(i))) {
- /*
- * TCNTB and TCMPB are loaded into TCNT and TCMP.
- * Update timers.
- */
-
- /* this will start timer to run, this ok, because
- * during processing start bit timer will be stopped
- * if needed */
- ptimer_set_count(s->timer[i].ptimer, s->timer[i].reg_tcntb);
- DPRINTF("set timer %d count to %x\n", i,
- s->timer[i].reg_tcntb);
- }
-
- if ((value & TCON_TIMER_START(i)) >
- (s->reg_tcon & TCON_TIMER_START(i))) {
- /* changed to start */
- ptimer_run(s->timer[i].ptimer, 1);
- DPRINTF("run timer %d\n", i);
- }
-
- if ((value & TCON_TIMER_START(i)) <
- (s->reg_tcon & TCON_TIMER_START(i))) {
- /* changed to stop */
- ptimer_stop(s->timer[i].ptimer);
- DPRINTF("stop timer %d\n", i);
- }
- }
- s->reg_tcon = value;
- break;
-
- case TCNTB0: case TCNTB1:
- case TCNTB2: case TCNTB3: case TCNTB4:
- index = (offset - TCNTB0) / 0xC;
- s->timer[index].reg_tcntb = value;
- break;
-
- case TCMPB0: case TCMPB1:
- case TCMPB2: case TCMPB3:
- index = (offset - TCMPB0) / 0xC;
- s->timer[index].reg_tcmpb = value;
- break;
-
- case TINT_CSTAT:
- new_val = (s->reg_tint_cstat & 0x3E0) + (0x1F & value);
- new_val &= ~(0x3E0 & value);
-
- for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
- if ((new_val & TINT_CSTAT_STATUS(i)) <
- (s->reg_tint_cstat & TINT_CSTAT_STATUS(i))) {
- qemu_irq_lower(s->timer[i].irq);
- }
- }
-
- s->reg_tint_cstat = new_val;
- break;
-
- default:
- fprintf(stderr,
- "[exynos4210.pwm: bad write offset " TARGET_FMT_plx "]\n",
- offset);
- break;
-
- }
-}
-
-/*
- * Set default values to timer fields and registers
- */
-static void exynos4210_pwm_reset(DeviceState *d)
-{
- Exynos4210PWMState *s = EXYNOS4210_PWM(d);
- int i;
- s->reg_tcfg[0] = 0x0101;
- s->reg_tcfg[1] = 0x0;
- s->reg_tcon = 0;
- s->reg_tint_cstat = 0;
- for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
- s->timer[i].reg_tcmpb = 0;
- s->timer[i].reg_tcntb = 0;
-
- exynos4210_pwm_update_freq(s, s->timer[i].id);
- ptimer_stop(s->timer[i].ptimer);
- }
-}
-
-static const MemoryRegionOps exynos4210_pwm_ops = {
- .read = exynos4210_pwm_read,
- .write = exynos4210_pwm_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/*
- * PWM timer initialization
- */
-static void exynos4210_pwm_init(Object *obj)
-{
- Exynos4210PWMState *s = EXYNOS4210_PWM(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- int i;
- QEMUBH *bh;
-
- for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
- bh = qemu_bh_new(exynos4210_pwm_tick, &s->timer[i]);
- sysbus_init_irq(dev, &s->timer[i].irq);
- s->timer[i].ptimer = ptimer_init(bh);
- s->timer[i].id = i;
- s->timer[i].parent = s;
- }
-
- memory_region_init_io(&s->iomem, obj, &exynos4210_pwm_ops, s,
- "exynos4210-pwm", EXYNOS4210_PWM_REG_MEM_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
-}
-
-static void exynos4210_pwm_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->reset = exynos4210_pwm_reset;
- dc->vmsd = &vmstate_exynos4210_pwm_state;
-}
-
-static const TypeInfo exynos4210_pwm_info = {
- .name = TYPE_EXYNOS4210_PWM,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(Exynos4210PWMState),
- .instance_init = exynos4210_pwm_init,
- .class_init = exynos4210_pwm_class_init,
-};
-
-static void exynos4210_pwm_register_types(void)
-{
- type_register_static(&exynos4210_pwm_info);
-}
-
-type_init(exynos4210_pwm_register_types)
diff --git a/qemu/hw/timer/exynos4210_rtc.c b/qemu/hw/timer/exynos4210_rtc.c
deleted file mode 100644
index da4dd451b..000000000
--- a/qemu/hw/timer/exynos4210_rtc.c
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * Samsung exynos4210 Real Time Clock
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * Ogurtsov Oleg <o.ogurtsov@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* Description:
- * Register RTCCON:
- * CLKSEL Bit[1] not used
- * CLKOUTEN Bit[9] not used
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "qemu/timer.h"
-#include "qemu-common.h"
-#include "qemu/bcd.h"
-#include "hw/ptimer.h"
-
-#include "hw/hw.h"
-#include "sysemu/sysemu.h"
-
-#include "hw/arm/exynos4210.h"
-
-#define DEBUG_RTC 0
-
-#if DEBUG_RTC
-#define DPRINTF(fmt, ...) \
- do { fprintf(stdout, "RTC: [%24s:%5d] " fmt, __func__, __LINE__, \
- ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while (0)
-#endif
-
-#define EXYNOS4210_RTC_REG_MEM_SIZE 0x0100
-
-#define INTP 0x0030
-#define RTCCON 0x0040
-#define TICCNT 0x0044
-#define RTCALM 0x0050
-#define ALMSEC 0x0054
-#define ALMMIN 0x0058
-#define ALMHOUR 0x005C
-#define ALMDAY 0x0060
-#define ALMMON 0x0064
-#define ALMYEAR 0x0068
-#define BCDSEC 0x0070
-#define BCDMIN 0x0074
-#define BCDHOUR 0x0078
-#define BCDDAY 0x007C
-#define BCDDAYWEEK 0x0080
-#define BCDMON 0x0084
-#define BCDYEAR 0x0088
-#define CURTICNT 0x0090
-
-#define TICK_TIMER_ENABLE 0x0100
-#define TICNT_THRESHOLD 2
-
-
-#define RTC_ENABLE 0x0001
-
-#define INTP_TICK_ENABLE 0x0001
-#define INTP_ALM_ENABLE 0x0002
-
-#define ALARM_INT_ENABLE 0x0040
-
-#define RTC_BASE_FREQ 32768
-
-#define TYPE_EXYNOS4210_RTC "exynos4210.rtc"
-#define EXYNOS4210_RTC(obj) \
- OBJECT_CHECK(Exynos4210RTCState, (obj), TYPE_EXYNOS4210_RTC)
-
-typedef struct Exynos4210RTCState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
-
- /* registers */
- uint32_t reg_intp;
- uint32_t reg_rtccon;
- uint32_t reg_ticcnt;
- uint32_t reg_rtcalm;
- uint32_t reg_almsec;
- uint32_t reg_almmin;
- uint32_t reg_almhour;
- uint32_t reg_almday;
- uint32_t reg_almmon;
- uint32_t reg_almyear;
- uint32_t reg_curticcnt;
-
- ptimer_state *ptimer; /* tick timer */
- ptimer_state *ptimer_1Hz; /* clock timer */
- uint32_t freq;
-
- qemu_irq tick_irq; /* Time Tick Generator irq */
- qemu_irq alm_irq; /* alarm irq */
-
- struct tm current_tm; /* current time */
-} Exynos4210RTCState;
-
-#define TICCKSEL(value) ((value & (0x0F << 4)) >> 4)
-
-/*** VMState ***/
-static const VMStateDescription vmstate_exynos4210_rtc_state = {
- .name = "exynos4210.rtc",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(reg_intp, Exynos4210RTCState),
- VMSTATE_UINT32(reg_rtccon, Exynos4210RTCState),
- VMSTATE_UINT32(reg_ticcnt, Exynos4210RTCState),
- VMSTATE_UINT32(reg_rtcalm, Exynos4210RTCState),
- VMSTATE_UINT32(reg_almsec, Exynos4210RTCState),
- VMSTATE_UINT32(reg_almmin, Exynos4210RTCState),
- VMSTATE_UINT32(reg_almhour, Exynos4210RTCState),
- VMSTATE_UINT32(reg_almday, Exynos4210RTCState),
- VMSTATE_UINT32(reg_almmon, Exynos4210RTCState),
- VMSTATE_UINT32(reg_almyear, Exynos4210RTCState),
- VMSTATE_UINT32(reg_curticcnt, Exynos4210RTCState),
- VMSTATE_PTIMER(ptimer, Exynos4210RTCState),
- VMSTATE_PTIMER(ptimer_1Hz, Exynos4210RTCState),
- VMSTATE_UINT32(freq, Exynos4210RTCState),
- VMSTATE_INT32(current_tm.tm_sec, Exynos4210RTCState),
- VMSTATE_INT32(current_tm.tm_min, Exynos4210RTCState),
- VMSTATE_INT32(current_tm.tm_hour, Exynos4210RTCState),
- VMSTATE_INT32(current_tm.tm_wday, Exynos4210RTCState),
- VMSTATE_INT32(current_tm.tm_mday, Exynos4210RTCState),
- VMSTATE_INT32(current_tm.tm_mon, Exynos4210RTCState),
- VMSTATE_INT32(current_tm.tm_year, Exynos4210RTCState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-#define BCD3DIGITS(x) \
- ((uint32_t)to_bcd((uint8_t)(x % 100)) + \
- ((uint32_t)to_bcd((uint8_t)((x % 1000) / 100)) << 8))
-
-static void check_alarm_raise(Exynos4210RTCState *s)
-{
- unsigned int alarm_raise = 0;
- struct tm stm = s->current_tm;
-
- if ((s->reg_rtcalm & 0x01) &&
- (to_bcd((uint8_t)stm.tm_sec) == (uint8_t)s->reg_almsec)) {
- alarm_raise = 1;
- }
- if ((s->reg_rtcalm & 0x02) &&
- (to_bcd((uint8_t)stm.tm_min) == (uint8_t)s->reg_almmin)) {
- alarm_raise = 1;
- }
- if ((s->reg_rtcalm & 0x04) &&
- (to_bcd((uint8_t)stm.tm_hour) == (uint8_t)s->reg_almhour)) {
- alarm_raise = 1;
- }
- if ((s->reg_rtcalm & 0x08) &&
- (to_bcd((uint8_t)stm.tm_mday) == (uint8_t)s->reg_almday)) {
- alarm_raise = 1;
- }
- if ((s->reg_rtcalm & 0x10) &&
- (to_bcd((uint8_t)stm.tm_mon) == (uint8_t)s->reg_almmon)) {
- alarm_raise = 1;
- }
- if ((s->reg_rtcalm & 0x20) &&
- (BCD3DIGITS(stm.tm_year) == s->reg_almyear)) {
- alarm_raise = 1;
- }
-
- if (alarm_raise) {
- DPRINTF("ALARM IRQ\n");
- /* set irq status */
- s->reg_intp |= INTP_ALM_ENABLE;
- qemu_irq_raise(s->alm_irq);
- }
-}
-
-/*
- * RTC update frequency
- * Parameters:
- * reg_value - current RTCCON register or his new value
- */
-static void exynos4210_rtc_update_freq(Exynos4210RTCState *s,
- uint32_t reg_value)
-{
- uint32_t freq;
-
- freq = s->freq;
- /* set frequncy for time generator */
- s->freq = RTC_BASE_FREQ / (1 << TICCKSEL(reg_value));
-
- if (freq != s->freq) {
- ptimer_set_freq(s->ptimer, s->freq);
- DPRINTF("freq=%dHz\n", s->freq);
- }
-}
-
-/* month is between 0 and 11. */
-static int get_days_in_month(int month, int year)
-{
- static const int days_tab[12] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
- int d;
- if ((unsigned)month >= 12) {
- return 31;
- }
- d = days_tab[month];
- if (month == 1) {
- if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) {
- d++;
- }
- }
- return d;
-}
-
-/* update 'tm' to the next second */
-static void rtc_next_second(struct tm *tm)
-{
- int days_in_month;
-
- tm->tm_sec++;
- if ((unsigned)tm->tm_sec >= 60) {
- tm->tm_sec = 0;
- tm->tm_min++;
- if ((unsigned)tm->tm_min >= 60) {
- tm->tm_min = 0;
- tm->tm_hour++;
- if ((unsigned)tm->tm_hour >= 24) {
- tm->tm_hour = 0;
- /* next day */
- tm->tm_wday++;
- if ((unsigned)tm->tm_wday >= 7) {
- tm->tm_wday = 0;
- }
- days_in_month = get_days_in_month(tm->tm_mon,
- tm->tm_year + 1900);
- tm->tm_mday++;
- if (tm->tm_mday < 1) {
- tm->tm_mday = 1;
- } else if (tm->tm_mday > days_in_month) {
- tm->tm_mday = 1;
- tm->tm_mon++;
- if (tm->tm_mon >= 12) {
- tm->tm_mon = 0;
- tm->tm_year++;
- }
- }
- }
- }
- }
-}
-
-/*
- * tick handler
- */
-static void exynos4210_rtc_tick(void *opaque)
-{
- Exynos4210RTCState *s = (Exynos4210RTCState *)opaque;
-
- DPRINTF("TICK IRQ\n");
- /* set irq status */
- s->reg_intp |= INTP_TICK_ENABLE;
- /* raise IRQ */
- qemu_irq_raise(s->tick_irq);
-
- /* restart timer */
- ptimer_set_count(s->ptimer, s->reg_ticcnt);
- ptimer_run(s->ptimer, 1);
-}
-
-/*
- * 1Hz clock handler
- */
-static void exynos4210_rtc_1Hz_tick(void *opaque)
-{
- Exynos4210RTCState *s = (Exynos4210RTCState *)opaque;
-
- rtc_next_second(&s->current_tm);
- /* DPRINTF("1Hz tick\n"); */
-
- /* raise IRQ */
- if (s->reg_rtcalm & ALARM_INT_ENABLE) {
- check_alarm_raise(s);
- }
-
- ptimer_set_count(s->ptimer_1Hz, RTC_BASE_FREQ);
- ptimer_run(s->ptimer_1Hz, 1);
-}
-
-/*
- * RTC Read
- */
-static uint64_t exynos4210_rtc_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- uint32_t value = 0;
- Exynos4210RTCState *s = (Exynos4210RTCState *)opaque;
-
- switch (offset) {
- case INTP:
- value = s->reg_intp;
- break;
- case RTCCON:
- value = s->reg_rtccon;
- break;
- case TICCNT:
- value = s->reg_ticcnt;
- break;
- case RTCALM:
- value = s->reg_rtcalm;
- break;
- case ALMSEC:
- value = s->reg_almsec;
- break;
- case ALMMIN:
- value = s->reg_almmin;
- break;
- case ALMHOUR:
- value = s->reg_almhour;
- break;
- case ALMDAY:
- value = s->reg_almday;
- break;
- case ALMMON:
- value = s->reg_almmon;
- break;
- case ALMYEAR:
- value = s->reg_almyear;
- break;
-
- case BCDSEC:
- value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_sec);
- break;
- case BCDMIN:
- value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_min);
- break;
- case BCDHOUR:
- value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_hour);
- break;
- case BCDDAYWEEK:
- value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_wday);
- break;
- case BCDDAY:
- value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_mday);
- break;
- case BCDMON:
- value = (uint32_t)to_bcd((uint8_t)s->current_tm.tm_mon + 1);
- break;
- case BCDYEAR:
- value = BCD3DIGITS(s->current_tm.tm_year);
- break;
-
- case CURTICNT:
- s->reg_curticcnt = ptimer_get_count(s->ptimer);
- value = s->reg_curticcnt;
- break;
-
- default:
- fprintf(stderr,
- "[exynos4210.rtc: bad read offset " TARGET_FMT_plx "]\n",
- offset);
- break;
- }
- return value;
-}
-
-/*
- * RTC Write
- */
-static void exynos4210_rtc_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- Exynos4210RTCState *s = (Exynos4210RTCState *)opaque;
-
- switch (offset) {
- case INTP:
- if (value & INTP_ALM_ENABLE) {
- qemu_irq_lower(s->alm_irq);
- s->reg_intp &= (~INTP_ALM_ENABLE);
- }
- if (value & INTP_TICK_ENABLE) {
- qemu_irq_lower(s->tick_irq);
- s->reg_intp &= (~INTP_TICK_ENABLE);
- }
- break;
- case RTCCON:
- if (value & RTC_ENABLE) {
- exynos4210_rtc_update_freq(s, value);
- }
- if ((value & RTC_ENABLE) > (s->reg_rtccon & RTC_ENABLE)) {
- /* clock timer */
- ptimer_set_count(s->ptimer_1Hz, RTC_BASE_FREQ);
- ptimer_run(s->ptimer_1Hz, 1);
- DPRINTF("run clock timer\n");
- }
- if ((value & RTC_ENABLE) < (s->reg_rtccon & RTC_ENABLE)) {
- /* tick timer */
- ptimer_stop(s->ptimer);
- /* clock timer */
- ptimer_stop(s->ptimer_1Hz);
- DPRINTF("stop all timers\n");
- }
- if (value & RTC_ENABLE) {
- if ((value & TICK_TIMER_ENABLE) >
- (s->reg_rtccon & TICK_TIMER_ENABLE) &&
- (s->reg_ticcnt)) {
- ptimer_set_count(s->ptimer, s->reg_ticcnt);
- ptimer_run(s->ptimer, 1);
- DPRINTF("run tick timer\n");
- }
- if ((value & TICK_TIMER_ENABLE) <
- (s->reg_rtccon & TICK_TIMER_ENABLE)) {
- ptimer_stop(s->ptimer);
- }
- }
- s->reg_rtccon = value;
- break;
- case TICCNT:
- if (value > TICNT_THRESHOLD) {
- s->reg_ticcnt = value;
- } else {
- fprintf(stderr,
- "[exynos4210.rtc: bad TICNT value %u ]\n",
- (uint32_t)value);
- }
- break;
-
- case RTCALM:
- s->reg_rtcalm = value;
- break;
- case ALMSEC:
- s->reg_almsec = (value & 0x7f);
- break;
- case ALMMIN:
- s->reg_almmin = (value & 0x7f);
- break;
- case ALMHOUR:
- s->reg_almhour = (value & 0x3f);
- break;
- case ALMDAY:
- s->reg_almday = (value & 0x3f);
- break;
- case ALMMON:
- s->reg_almmon = (value & 0x1f);
- break;
- case ALMYEAR:
- s->reg_almyear = (value & 0x0fff);
- break;
-
- case BCDSEC:
- if (s->reg_rtccon & RTC_ENABLE) {
- s->current_tm.tm_sec = (int)from_bcd((uint8_t)value);
- }
- break;
- case BCDMIN:
- if (s->reg_rtccon & RTC_ENABLE) {
- s->current_tm.tm_min = (int)from_bcd((uint8_t)value);
- }
- break;
- case BCDHOUR:
- if (s->reg_rtccon & RTC_ENABLE) {
- s->current_tm.tm_hour = (int)from_bcd((uint8_t)value);
- }
- break;
- case BCDDAYWEEK:
- if (s->reg_rtccon & RTC_ENABLE) {
- s->current_tm.tm_wday = (int)from_bcd((uint8_t)value);
- }
- break;
- case BCDDAY:
- if (s->reg_rtccon & RTC_ENABLE) {
- s->current_tm.tm_mday = (int)from_bcd((uint8_t)value);
- }
- break;
- case BCDMON:
- if (s->reg_rtccon & RTC_ENABLE) {
- s->current_tm.tm_mon = (int)from_bcd((uint8_t)value) - 1;
- }
- break;
- case BCDYEAR:
- if (s->reg_rtccon & RTC_ENABLE) {
- /* 3 digits */
- s->current_tm.tm_year = (int)from_bcd((uint8_t)value) +
- (int)from_bcd((uint8_t)((value >> 8) & 0x0f)) * 100;
- }
- break;
-
- default:
- fprintf(stderr,
- "[exynos4210.rtc: bad write offset " TARGET_FMT_plx "]\n",
- offset);
- break;
-
- }
-}
-
-/*
- * Set default values to timer fields and registers
- */
-static void exynos4210_rtc_reset(DeviceState *d)
-{
- Exynos4210RTCState *s = EXYNOS4210_RTC(d);
-
- qemu_get_timedate(&s->current_tm, 0);
-
- DPRINTF("Get time from host: %d-%d-%d %2d:%02d:%02d\n",
- s->current_tm.tm_year, s->current_tm.tm_mon, s->current_tm.tm_mday,
- s->current_tm.tm_hour, s->current_tm.tm_min, s->current_tm.tm_sec);
-
- s->reg_intp = 0;
- s->reg_rtccon = 0;
- s->reg_ticcnt = 0;
- s->reg_rtcalm = 0;
- s->reg_almsec = 0;
- s->reg_almmin = 0;
- s->reg_almhour = 0;
- s->reg_almday = 0;
- s->reg_almmon = 0;
- s->reg_almyear = 0;
-
- s->reg_curticcnt = 0;
-
- exynos4210_rtc_update_freq(s, s->reg_rtccon);
- ptimer_stop(s->ptimer);
- ptimer_stop(s->ptimer_1Hz);
-}
-
-static const MemoryRegionOps exynos4210_rtc_ops = {
- .read = exynos4210_rtc_read,
- .write = exynos4210_rtc_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-/*
- * RTC timer initialization
- */
-static void exynos4210_rtc_init(Object *obj)
-{
- Exynos4210RTCState *s = EXYNOS4210_RTC(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- QEMUBH *bh;
-
- bh = qemu_bh_new(exynos4210_rtc_tick, s);
- s->ptimer = ptimer_init(bh);
- ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
- exynos4210_rtc_update_freq(s, 0);
-
- bh = qemu_bh_new(exynos4210_rtc_1Hz_tick, s);
- s->ptimer_1Hz = ptimer_init(bh);
- ptimer_set_freq(s->ptimer_1Hz, RTC_BASE_FREQ);
-
- sysbus_init_irq(dev, &s->alm_irq);
- sysbus_init_irq(dev, &s->tick_irq);
-
- memory_region_init_io(&s->iomem, obj, &exynos4210_rtc_ops, s,
- "exynos4210-rtc", EXYNOS4210_RTC_REG_MEM_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
-}
-
-static void exynos4210_rtc_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->reset = exynos4210_rtc_reset;
- dc->vmsd = &vmstate_exynos4210_rtc_state;
-}
-
-static const TypeInfo exynos4210_rtc_info = {
- .name = TYPE_EXYNOS4210_RTC,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(Exynos4210RTCState),
- .instance_init = exynos4210_rtc_init,
- .class_init = exynos4210_rtc_class_init,
-};
-
-static void exynos4210_rtc_register_types(void)
-{
- type_register_static(&exynos4210_rtc_info);
-}
-
-type_init(exynos4210_rtc_register_types)
diff --git a/qemu/hw/timer/grlib_gptimer.c b/qemu/hw/timer/grlib_gptimer.c
deleted file mode 100644
index dd000f5af..000000000
--- a/qemu/hw/timer/grlib_gptimer.c
+++ /dev/null
@@ -1,412 +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 "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "qemu/timer.h"
-#include "qemu/main-loop.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
-
-#define TYPE_GRLIB_GPTIMER "grlib,gptimer"
-#define GRLIB_GPTIMER(obj) \
- OBJECT_CHECK(GPTimerUnit, (obj), TYPE_GRLIB_GPTIMER)
-
-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 parent_obj;
-
- 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);
-
- ptimer_set_count(timer->ptimer, (uint64_t)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 = GRLIB_GPTIMER(d);
- int i = 0;
-
- assert(unit != NULL);
-
- unit->scaler = 0;
- unit->reload = 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 = GRLIB_GPTIMER(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, OBJECT(unit), &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 = TYPE_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)
diff --git a/qemu/hw/timer/hpet.c b/qemu/hw/timer/hpet.c
deleted file mode 100644
index a2c18b30c..000000000
--- a/qemu/hw/timer/hpet.c
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- * High Precision Event Timer emulation
- *
- * Copyright (c) 2007 Alexander Graf
- * Copyright (c) 2008 IBM Corporation
- *
- * Authors: Beth Kon <bkon@us.ibm.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- * *****************************************************************
- *
- * This driver attempts to emulate an HPET device in software.
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "ui/console.h"
-#include "qapi/error.h"
-#include "qemu/error-report.h"
-#include "qemu/timer.h"
-#include "hw/timer/hpet.h"
-#include "hw/sysbus.h"
-#include "hw/timer/mc146818rtc.h"
-#include "hw/timer/i8254.h"
-
-//#define HPET_DEBUG
-#ifdef HPET_DEBUG
-#define DPRINTF printf
-#else
-#define DPRINTF(...)
-#endif
-
-#define HPET_MSI_SUPPORT 0
-
-#define HPET(obj) OBJECT_CHECK(HPETState, (obj), TYPE_HPET)
-
-struct HPETState;
-typedef struct HPETTimer { /* timers */
- uint8_t tn; /*timer number*/
- QEMUTimer *qemu_timer;
- struct HPETState *state;
- /* Memory-mapped, software visible timer registers */
- uint64_t config; /* configuration/cap */
- uint64_t cmp; /* comparator */
- uint64_t fsb; /* FSB route */
- /* Hidden register state */
- uint64_t period; /* Last value written to comparator */
- uint8_t wrap_flag; /* timer pop will indicate wrap for one-shot 32-bit
- * mode. Next pop will be actual timer expiration.
- */
-} HPETTimer;
-
-typedef struct HPETState {
- /*< private >*/
- SysBusDevice parent_obj;
- /*< public >*/
-
- MemoryRegion iomem;
- uint64_t hpet_offset;
- qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
- uint32_t flags;
- uint8_t rtc_irq_level;
- qemu_irq pit_enabled;
- uint8_t num_timers;
- uint32_t intcap;
- HPETTimer timer[HPET_MAX_TIMERS];
-
- /* Memory-mapped, software visible registers */
- uint64_t capability; /* capabilities */
- uint64_t config; /* configuration */
- uint64_t isr; /* interrupt status reg */
- uint64_t hpet_counter; /* main counter */
- uint8_t hpet_id; /* instance id */
-} HPETState;
-
-static uint32_t hpet_in_legacy_mode(HPETState *s)
-{
- return s->config & HPET_CFG_LEGACY;
-}
-
-static uint32_t timer_int_route(struct HPETTimer *timer)
-{
- return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
-}
-
-static uint32_t timer_fsb_route(HPETTimer *t)
-{
- return t->config & HPET_TN_FSB_ENABLE;
-}
-
-static uint32_t hpet_enabled(HPETState *s)
-{
- return s->config & HPET_CFG_ENABLE;
-}
-
-static uint32_t timer_is_periodic(HPETTimer *t)
-{
- return t->config & HPET_TN_PERIODIC;
-}
-
-static uint32_t timer_enabled(HPETTimer *t)
-{
- return t->config & HPET_TN_ENABLE;
-}
-
-static uint32_t hpet_time_after(uint64_t a, uint64_t b)
-{
- return ((int32_t)(b - a) < 0);
-}
-
-static uint32_t hpet_time_after64(uint64_t a, uint64_t b)
-{
- return ((int64_t)(b - a) < 0);
-}
-
-static uint64_t ticks_to_ns(uint64_t value)
-{
- return value * HPET_CLK_PERIOD;
-}
-
-static uint64_t ns_to_ticks(uint64_t value)
-{
- return value / HPET_CLK_PERIOD;
-}
-
-static uint64_t hpet_fixup_reg(uint64_t new, uint64_t old, uint64_t mask)
-{
- new &= mask;
- new |= old & ~mask;
- return new;
-}
-
-static int activating_bit(uint64_t old, uint64_t new, uint64_t mask)
-{
- return (!(old & mask) && (new & mask));
-}
-
-static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
-{
- return ((old & mask) && !(new & mask));
-}
-
-static uint64_t hpet_get_ticks(HPETState *s)
-{
- return ns_to_ticks(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->hpet_offset);
-}
-
-/*
- * calculate diff between comparator value and current ticks
- */
-static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
-{
-
- if (t->config & HPET_TN_32BIT) {
- uint32_t diff, cmp;
-
- cmp = (uint32_t)t->cmp;
- diff = cmp - (uint32_t)current;
- diff = (int32_t)diff > 0 ? diff : (uint32_t)1;
- return (uint64_t)diff;
- } else {
- uint64_t diff, cmp;
-
- cmp = t->cmp;
- diff = cmp - current;
- diff = (int64_t)diff > 0 ? diff : (uint64_t)1;
- return diff;
- }
-}
-
-static void update_irq(struct HPETTimer *timer, int set)
-{
- uint64_t mask;
- HPETState *s;
- int route;
-
- if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
- /* if LegacyReplacementRoute bit is set, HPET specification requires
- * timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
- * timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
- */
- route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
- } else {
- route = timer_int_route(timer);
- }
- s = timer->state;
- mask = 1 << timer->tn;
- if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
- s->isr &= ~mask;
- if (!timer_fsb_route(timer)) {
- qemu_irq_lower(s->irqs[route]);
- }
- } else if (timer_fsb_route(timer)) {
- address_space_stl_le(&address_space_memory, timer->fsb >> 32,
- timer->fsb & 0xffffffff, MEMTXATTRS_UNSPECIFIED,
- NULL);
- } else if (timer->config & HPET_TN_TYPE_LEVEL) {
- s->isr |= mask;
- qemu_irq_raise(s->irqs[route]);
- } else {
- s->isr &= ~mask;
- qemu_irq_pulse(s->irqs[route]);
- }
-}
-
-static void hpet_pre_save(void *opaque)
-{
- HPETState *s = opaque;
-
- /* save current counter value */
- s->hpet_counter = hpet_get_ticks(s);
-}
-
-static int hpet_pre_load(void *opaque)
-{
- HPETState *s = opaque;
-
- /* version 1 only supports 3, later versions will load the actual value */
- s->num_timers = HPET_MIN_TIMERS;
- return 0;
-}
-
-static bool hpet_validate_num_timers(void *opaque, int version_id)
-{
- HPETState *s = opaque;
-
- if (s->num_timers < HPET_MIN_TIMERS) {
- return false;
- } else if (s->num_timers > HPET_MAX_TIMERS) {
- return false;
- }
- return true;
-}
-
-static int hpet_post_load(void *opaque, int version_id)
-{
- HPETState *s = opaque;
-
- /* Recalculate the offset between the main counter and guest time */
- s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
- /* Push number of timers into capability returned via HPET_ID */
- s->capability &= ~HPET_ID_NUM_TIM_MASK;
- s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
- hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
-
- /* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
- s->flags &= ~(1 << HPET_MSI_SUPPORT);
- if (s->timer[0].config & HPET_TN_FSB_CAP) {
- s->flags |= 1 << HPET_MSI_SUPPORT;
- }
- return 0;
-}
-
-static bool hpet_rtc_irq_level_needed(void *opaque)
-{
- HPETState *s = opaque;
-
- return s->rtc_irq_level != 0;
-}
-
-static const VMStateDescription vmstate_hpet_rtc_irq_level = {
- .name = "hpet/rtc_irq_level",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = hpet_rtc_irq_level_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(rtc_irq_level, HPETState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_hpet_timer = {
- .name = "hpet_timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(tn, HPETTimer),
- VMSTATE_UINT64(config, HPETTimer),
- VMSTATE_UINT64(cmp, HPETTimer),
- VMSTATE_UINT64(fsb, HPETTimer),
- VMSTATE_UINT64(period, HPETTimer),
- VMSTATE_UINT8(wrap_flag, HPETTimer),
- VMSTATE_TIMER_PTR(qemu_timer, HPETTimer),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_hpet = {
- .name = "hpet",
- .version_id = 2,
- .minimum_version_id = 1,
- .pre_save = hpet_pre_save,
- .pre_load = hpet_pre_load,
- .post_load = hpet_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(config, HPETState),
- VMSTATE_UINT64(isr, HPETState),
- VMSTATE_UINT64(hpet_counter, HPETState),
- VMSTATE_UINT8_V(num_timers, HPETState, 2),
- VMSTATE_VALIDATE("num_timers in range", hpet_validate_num_timers),
- VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
- vmstate_hpet_timer, HPETTimer),
- VMSTATE_END_OF_LIST()
- },
- .subsections = (const VMStateDescription*[]) {
- &vmstate_hpet_rtc_irq_level,
- NULL
- }
-};
-
-/*
- * timer expiration callback
- */
-static void hpet_timer(void *opaque)
-{
- HPETTimer *t = opaque;
- uint64_t diff;
-
- uint64_t period = t->period;
- uint64_t cur_tick = hpet_get_ticks(t->state);
-
- if (timer_is_periodic(t) && period != 0) {
- if (t->config & HPET_TN_32BIT) {
- while (hpet_time_after(cur_tick, t->cmp)) {
- t->cmp = (uint32_t)(t->cmp + t->period);
- }
- } else {
- while (hpet_time_after64(cur_tick, t->cmp)) {
- t->cmp += period;
- }
- }
- diff = hpet_calculate_diff(t, cur_tick);
- timer_mod(t->qemu_timer,
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (int64_t)ticks_to_ns(diff));
- } else if (t->config & HPET_TN_32BIT && !timer_is_periodic(t)) {
- if (t->wrap_flag) {
- diff = hpet_calculate_diff(t, cur_tick);
- timer_mod(t->qemu_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
- (int64_t)ticks_to_ns(diff));
- t->wrap_flag = 0;
- }
- }
- update_irq(t, 1);
-}
-
-static void hpet_set_timer(HPETTimer *t)
-{
- uint64_t diff;
- uint32_t wrap_diff; /* how many ticks until we wrap? */
- uint64_t cur_tick = hpet_get_ticks(t->state);
-
- /* whenever new timer is being set up, make sure wrap_flag is 0 */
- t->wrap_flag = 0;
- diff = hpet_calculate_diff(t, cur_tick);
-
- /* hpet spec says in one-shot 32-bit mode, generate an interrupt when
- * counter wraps in addition to an interrupt with comparator match.
- */
- if (t->config & HPET_TN_32BIT && !timer_is_periodic(t)) {
- wrap_diff = 0xffffffff - (uint32_t)cur_tick;
- if (wrap_diff < (uint32_t)diff) {
- diff = wrap_diff;
- t->wrap_flag = 1;
- }
- }
- timer_mod(t->qemu_timer,
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (int64_t)ticks_to_ns(diff));
-}
-
-static void hpet_del_timer(HPETTimer *t)
-{
- timer_del(t->qemu_timer);
- update_irq(t, 0);
-}
-
-#ifdef HPET_DEBUG
-static uint32_t hpet_ram_readb(void *opaque, hwaddr addr)
-{
- printf("qemu: hpet_read b at %" PRIx64 "\n", addr);
- return 0;
-}
-
-static uint32_t hpet_ram_readw(void *opaque, hwaddr addr)
-{
- printf("qemu: hpet_read w at %" PRIx64 "\n", addr);
- return 0;
-}
-#endif
-
-static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- HPETState *s = opaque;
- uint64_t cur_tick, index;
-
- DPRINTF("qemu: Enter hpet_ram_readl at %" PRIx64 "\n", addr);
- index = addr;
- /*address range of all TN regs*/
- if (index >= 0x100 && index <= 0x3ff) {
- uint8_t timer_id = (addr - 0x100) / 0x20;
- HPETTimer *timer = &s->timer[timer_id];
-
- if (timer_id > s->num_timers) {
- DPRINTF("qemu: timer id out of range\n");
- return 0;
- }
-
- switch ((addr - 0x100) % 0x20) {
- case HPET_TN_CFG:
- return timer->config;
- case HPET_TN_CFG + 4: // Interrupt capabilities
- return timer->config >> 32;
- case HPET_TN_CMP: // comparator register
- return timer->cmp;
- case HPET_TN_CMP + 4:
- return timer->cmp >> 32;
- case HPET_TN_ROUTE:
- return timer->fsb;
- case HPET_TN_ROUTE + 4:
- return timer->fsb >> 32;
- default:
- DPRINTF("qemu: invalid hpet_ram_readl\n");
- break;
- }
- } else {
- switch (index) {
- case HPET_ID:
- return s->capability;
- case HPET_PERIOD:
- return s->capability >> 32;
- case HPET_CFG:
- return s->config;
- case HPET_CFG + 4:
- DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl\n");
- return 0;
- case HPET_COUNTER:
- if (hpet_enabled(s)) {
- cur_tick = hpet_get_ticks(s);
- } else {
- cur_tick = s->hpet_counter;
- }
- DPRINTF("qemu: reading counter = %" PRIx64 "\n", cur_tick);
- return cur_tick;
- case HPET_COUNTER + 4:
- if (hpet_enabled(s)) {
- cur_tick = hpet_get_ticks(s);
- } else {
- cur_tick = s->hpet_counter;
- }
- DPRINTF("qemu: reading counter + 4 = %" PRIx64 "\n", cur_tick);
- return cur_tick >> 32;
- case HPET_STATUS:
- return s->isr;
- default:
- DPRINTF("qemu: invalid hpet_ram_readl\n");
- break;
- }
- }
- return 0;
-}
-
-static void hpet_ram_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- int i;
- HPETState *s = opaque;
- uint64_t old_val, new_val, val, index;
-
- DPRINTF("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value);
- index = addr;
- old_val = hpet_ram_read(opaque, addr, 4);
- new_val = value;
-
- /*address range of all TN regs*/
- if (index >= 0x100 && index <= 0x3ff) {
- uint8_t timer_id = (addr - 0x100) / 0x20;
- HPETTimer *timer = &s->timer[timer_id];
-
- DPRINTF("qemu: hpet_ram_writel timer_id = %#x\n", timer_id);
- if (timer_id > s->num_timers) {
- DPRINTF("qemu: timer id out of range\n");
- return;
- }
- switch ((addr - 0x100) % 0x20) {
- case HPET_TN_CFG:
- DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
- if (activating_bit(old_val, new_val, HPET_TN_FSB_ENABLE)) {
- update_irq(timer, 0);
- }
- val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
- timer->config = (timer->config & 0xffffffff00000000ULL) | val;
- if (new_val & HPET_TN_32BIT) {
- timer->cmp = (uint32_t)timer->cmp;
- timer->period = (uint32_t)timer->period;
- }
- if (activating_bit(old_val, new_val, HPET_TN_ENABLE) &&
- hpet_enabled(s)) {
- hpet_set_timer(timer);
- } else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
- hpet_del_timer(timer);
- }
- break;
- case HPET_TN_CFG + 4: // Interrupt capabilities
- DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
- break;
- case HPET_TN_CMP: // comparator register
- DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP\n");
- if (timer->config & HPET_TN_32BIT) {
- new_val = (uint32_t)new_val;
- }
- if (!timer_is_periodic(timer)
- || (timer->config & HPET_TN_SETVAL)) {
- timer->cmp = (timer->cmp & 0xffffffff00000000ULL) | new_val;
- }
- if (timer_is_periodic(timer)) {
- /*
- * FIXME: Clamp period to reasonable min value?
- * Clamp period to reasonable max value
- */
- new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
- timer->period =
- (timer->period & 0xffffffff00000000ULL) | new_val;
- }
- timer->config &= ~HPET_TN_SETVAL;
- if (hpet_enabled(s)) {
- hpet_set_timer(timer);
- }
- break;
- case HPET_TN_CMP + 4: // comparator register high order
- DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP + 4\n");
- if (!timer_is_periodic(timer)
- || (timer->config & HPET_TN_SETVAL)) {
- timer->cmp = (timer->cmp & 0xffffffffULL) | new_val << 32;
- } else {
- /*
- * FIXME: Clamp period to reasonable min value?
- * Clamp period to reasonable max value
- */
- new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
- timer->period =
- (timer->period & 0xffffffffULL) | new_val << 32;
- }
- timer->config &= ~HPET_TN_SETVAL;
- if (hpet_enabled(s)) {
- hpet_set_timer(timer);
- }
- break;
- case HPET_TN_ROUTE:
- timer->fsb = (timer->fsb & 0xffffffff00000000ULL) | new_val;
- break;
- case HPET_TN_ROUTE + 4:
- timer->fsb = (new_val << 32) | (timer->fsb & 0xffffffff);
- break;
- default:
- DPRINTF("qemu: invalid hpet_ram_writel\n");
- break;
- }
- return;
- } else {
- switch (index) {
- case HPET_ID:
- return;
- case HPET_CFG:
- val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
- s->config = (s->config & 0xffffffff00000000ULL) | val;
- if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
- /* Enable main counter and interrupt generation. */
- s->hpet_offset =
- ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- for (i = 0; i < s->num_timers; i++) {
- if ((&s->timer[i])->cmp != ~0ULL) {
- hpet_set_timer(&s->timer[i]);
- }
- }
- } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
- /* Halt main counter and disable interrupt generation. */
- s->hpet_counter = hpet_get_ticks(s);
- for (i = 0; i < s->num_timers; i++) {
- hpet_del_timer(&s->timer[i]);
- }
- }
- /* i8254 and RTC output pins are disabled
- * when HPET is in legacy mode */
- if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
- qemu_set_irq(s->pit_enabled, 0);
- qemu_irq_lower(s->irqs[0]);
- qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
- } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
- qemu_irq_lower(s->irqs[0]);
- qemu_set_irq(s->pit_enabled, 1);
- qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
- }
- break;
- case HPET_CFG + 4:
- DPRINTF("qemu: invalid HPET_CFG+4 write\n");
- break;
- case HPET_STATUS:
- val = new_val & s->isr;
- for (i = 0; i < s->num_timers; i++) {
- if (val & (1 << i)) {
- update_irq(&s->timer[i], 0);
- }
- }
- break;
- case HPET_COUNTER:
- if (hpet_enabled(s)) {
- DPRINTF("qemu: Writing counter while HPET enabled!\n");
- }
- s->hpet_counter =
- (s->hpet_counter & 0xffffffff00000000ULL) | value;
- DPRINTF("qemu: HPET counter written. ctr = %#x -> %" PRIx64 "\n",
- value, s->hpet_counter);
- break;
- case HPET_COUNTER + 4:
- if (hpet_enabled(s)) {
- DPRINTF("qemu: Writing counter while HPET enabled!\n");
- }
- s->hpet_counter =
- (s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32);
- DPRINTF("qemu: HPET counter + 4 written. ctr = %#x -> %" PRIx64 "\n",
- value, s->hpet_counter);
- break;
- default:
- DPRINTF("qemu: invalid hpet_ram_writel\n");
- break;
- }
- }
-}
-
-static const MemoryRegionOps hpet_ram_ops = {
- .read = hpet_ram_read,
- .write = hpet_ram_write,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void hpet_reset(DeviceState *d)
-{
- HPETState *s = HPET(d);
- SysBusDevice *sbd = SYS_BUS_DEVICE(d);
- int i;
-
- for (i = 0; i < s->num_timers; i++) {
- HPETTimer *timer = &s->timer[i];
-
- hpet_del_timer(timer);
- timer->cmp = ~0ULL;
- timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
- if (s->flags & (1 << HPET_MSI_SUPPORT)) {
- timer->config |= HPET_TN_FSB_CAP;
- }
- /* advertise availability of ioapic int */
- timer->config |= (uint64_t)s->intcap << 32;
- timer->period = 0ULL;
- timer->wrap_flag = 0;
- }
-
- qemu_set_irq(s->pit_enabled, 1);
- s->hpet_counter = 0ULL;
- s->hpet_offset = 0ULL;
- s->config = 0ULL;
- hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
- hpet_cfg.hpet[s->hpet_id].address = sbd->mmio[0].addr;
-
- /* to document that the RTC lowers its output on reset as well */
- s->rtc_irq_level = 0;
-}
-
-static void hpet_handle_legacy_irq(void *opaque, int n, int level)
-{
- HPETState *s = HPET(opaque);
-
- if (n == HPET_LEGACY_PIT_INT) {
- if (!hpet_in_legacy_mode(s)) {
- qemu_set_irq(s->irqs[0], level);
- }
- } else {
- s->rtc_irq_level = level;
- if (!hpet_in_legacy_mode(s)) {
- qemu_set_irq(s->irqs[RTC_ISA_IRQ], level);
- }
- }
-}
-
-static void hpet_init(Object *obj)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- HPETState *s = HPET(obj);
-
- /* HPET Area */
- memory_region_init_io(&s->iomem, obj, &hpet_ram_ops, s, "hpet", HPET_LEN);
- sysbus_init_mmio(sbd, &s->iomem);
-}
-
-static void hpet_realize(DeviceState *dev, Error **errp)
-{
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- HPETState *s = HPET(dev);
- int i;
- HPETTimer *timer;
-
- if (!s->intcap) {
- error_printf("Hpet's intcap not initialized.\n");
- }
- if (hpet_cfg.count == UINT8_MAX) {
- /* first instance */
- hpet_cfg.count = 0;
- }
-
- if (hpet_cfg.count == 8) {
- error_setg(errp, "Only 8 instances of HPET is allowed");
- return;
- }
-
- s->hpet_id = hpet_cfg.count++;
-
- for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
- sysbus_init_irq(sbd, &s->irqs[i]);
- }
-
- if (s->num_timers < HPET_MIN_TIMERS) {
- s->num_timers = HPET_MIN_TIMERS;
- } else if (s->num_timers > HPET_MAX_TIMERS) {
- s->num_timers = HPET_MAX_TIMERS;
- }
- for (i = 0; i < HPET_MAX_TIMERS; i++) {
- timer = &s->timer[i];
- timer->qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, hpet_timer, timer);
- timer->tn = i;
- timer->state = s;
- }
-
- /* 64-bit main counter; LegacyReplacementRoute. */
- s->capability = 0x8086a001ULL;
- s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
- s->capability |= ((uint64_t)(HPET_CLK_PERIOD * FS_PER_NS) << 32);
-
- qdev_init_gpio_in(dev, hpet_handle_legacy_irq, 2);
- qdev_init_gpio_out(dev, &s->pit_enabled, 1);
-}
-
-static Property hpet_device_properties[] = {
- DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
- DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
- DEFINE_PROP_UINT32(HPET_INTCAP, HPETState, intcap, 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void hpet_device_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = hpet_realize;
- dc->reset = hpet_reset;
- dc->vmsd = &vmstate_hpet;
- dc->props = hpet_device_properties;
-}
-
-static const TypeInfo hpet_device_info = {
- .name = TYPE_HPET,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(HPETState),
- .instance_init = hpet_init,
- .class_init = hpet_device_class_init,
-};
-
-static void hpet_register_types(void)
-{
- type_register_static(&hpet_device_info);
-}
-
-type_init(hpet_register_types)
diff --git a/qemu/hw/timer/i8254.c b/qemu/hw/timer/i8254.c
deleted file mode 100644
index 5e61ad50a..000000000
--- a/qemu/hw/timer/i8254.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * QEMU 8253/8254 interval timer emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * 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 "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/isa/isa.h"
-#include "qemu/timer.h"
-#include "hw/timer/i8254.h"
-#include "hw/timer/i8254_internal.h"
-
-//#define DEBUG_PIT
-
-#define RW_STATE_LSB 1
-#define RW_STATE_MSB 2
-#define RW_STATE_WORD0 3
-#define RW_STATE_WORD1 4
-
-#define PIT_CLASS(class) OBJECT_CLASS_CHECK(PITClass, (class), TYPE_I8254)
-#define PIT_GET_CLASS(obj) OBJECT_GET_CLASS(PITClass, (obj), TYPE_I8254)
-
-typedef struct PITClass {
- PITCommonClass parent_class;
-
- DeviceRealize parent_realize;
-} PITClass;
-
-static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
-
-static int pit_get_count(PITChannelState *s)
-{
- uint64_t d;
- int counter;
-
- d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->count_load_time, PIT_FREQ,
- NANOSECONDS_PER_SECOND);
- switch(s->mode) {
- case 0:
- case 1:
- case 4:
- case 5:
- counter = (s->count - d) & 0xffff;
- break;
- case 3:
- /* XXX: may be incorrect for odd counts */
- counter = s->count - ((2 * d) % s->count);
- break;
- default:
- counter = s->count - (d % s->count);
- break;
- }
- return counter;
-}
-
-/* val must be 0 or 1 */
-static void pit_set_channel_gate(PITCommonState *s, PITChannelState *sc,
- int val)
-{
- switch (sc->mode) {
- default:
- case 0:
- case 4:
- /* XXX: just disable/enable counting */
- break;
- case 1:
- case 5:
- if (sc->gate < val) {
- /* restart counting on rising edge */
- sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- pit_irq_timer_update(sc, sc->count_load_time);
- }
- break;
- case 2:
- case 3:
- if (sc->gate < val) {
- /* restart counting on rising edge */
- sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- pit_irq_timer_update(sc, sc->count_load_time);
- }
- /* XXX: disable/enable counting */
- break;
- }
- sc->gate = val;
-}
-
-static inline void pit_load_count(PITChannelState *s, int val)
-{
- if (val == 0)
- val = 0x10000;
- s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- s->count = val;
- pit_irq_timer_update(s, s->count_load_time);
-}
-
-/* if already latched, do not latch again */
-static void pit_latch_count(PITChannelState *s)
-{
- if (!s->count_latched) {
- s->latched_count = pit_get_count(s);
- s->count_latched = s->rw_mode;
- }
-}
-
-static void pit_ioport_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- PITCommonState *pit = opaque;
- int channel, access;
- PITChannelState *s;
-
- addr &= 3;
- if (addr == 3) {
- channel = val >> 6;
- if (channel == 3) {
- /* read back command */
- for(channel = 0; channel < 3; channel++) {
- s = &pit->channels[channel];
- if (val & (2 << channel)) {
- if (!(val & 0x20)) {
- pit_latch_count(s);
- }
- if (!(val & 0x10) && !s->status_latched) {
- /* status latch */
- /* XXX: add BCD and null count */
- s->status =
- (pit_get_out(s,
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) << 7) |
- (s->rw_mode << 4) |
- (s->mode << 1) |
- s->bcd;
- s->status_latched = 1;
- }
- }
- }
- } else {
- s = &pit->channels[channel];
- access = (val >> 4) & 3;
- if (access == 0) {
- pit_latch_count(s);
- } else {
- s->rw_mode = access;
- s->read_state = access;
- s->write_state = access;
-
- s->mode = (val >> 1) & 7;
- s->bcd = val & 1;
- /* XXX: update irq timer ? */
- }
- }
- } else {
- s = &pit->channels[addr];
- switch(s->write_state) {
- default:
- case RW_STATE_LSB:
- pit_load_count(s, val);
- break;
- case RW_STATE_MSB:
- pit_load_count(s, val << 8);
- break;
- case RW_STATE_WORD0:
- s->write_latch = val;
- s->write_state = RW_STATE_WORD1;
- break;
- case RW_STATE_WORD1:
- pit_load_count(s, s->write_latch | (val << 8));
- s->write_state = RW_STATE_WORD0;
- break;
- }
- }
-}
-
-static uint64_t pit_ioport_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- PITCommonState *pit = opaque;
- int ret, count;
- PITChannelState *s;
-
- addr &= 3;
-
- if (addr == 3) {
- /* Mode/Command register is write only, read is ignored */
- return 0;
- }
-
- s = &pit->channels[addr];
- if (s->status_latched) {
- s->status_latched = 0;
- ret = s->status;
- } else if (s->count_latched) {
- switch(s->count_latched) {
- default:
- case RW_STATE_LSB:
- ret = s->latched_count & 0xff;
- s->count_latched = 0;
- break;
- case RW_STATE_MSB:
- ret = s->latched_count >> 8;
- s->count_latched = 0;
- break;
- case RW_STATE_WORD0:
- ret = s->latched_count & 0xff;
- s->count_latched = RW_STATE_MSB;
- break;
- }
- } else {
- switch(s->read_state) {
- default:
- case RW_STATE_LSB:
- count = pit_get_count(s);
- ret = count & 0xff;
- break;
- case RW_STATE_MSB:
- count = pit_get_count(s);
- ret = (count >> 8) & 0xff;
- break;
- case RW_STATE_WORD0:
- count = pit_get_count(s);
- ret = count & 0xff;
- s->read_state = RW_STATE_WORD1;
- break;
- case RW_STATE_WORD1:
- count = pit_get_count(s);
- ret = (count >> 8) & 0xff;
- s->read_state = RW_STATE_WORD0;
- break;
- }
- }
- return ret;
-}
-
-static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
-{
- int64_t expire_time;
- int irq_level;
-
- if (!s->irq_timer || s->irq_disabled) {
- return;
- }
- expire_time = pit_get_next_transition_time(s, current_time);
- irq_level = pit_get_out(s, current_time);
- qemu_set_irq(s->irq, irq_level);
-#ifdef DEBUG_PIT
- printf("irq_level=%d next_delay=%f\n",
- irq_level,
- (double)(expire_time - current_time) / NANOSECONDS_PER_SECOND);
-#endif
- s->next_transition_time = expire_time;
- if (expire_time != -1)
- timer_mod(s->irq_timer, expire_time);
- else
- timer_del(s->irq_timer);
-}
-
-static void pit_irq_timer(void *opaque)
-{
- PITChannelState *s = opaque;
-
- pit_irq_timer_update(s, s->next_transition_time);
-}
-
-static void pit_reset(DeviceState *dev)
-{
- PITCommonState *pit = PIT_COMMON(dev);
- PITChannelState *s;
-
- pit_reset_common(pit);
-
- s = &pit->channels[0];
- if (!s->irq_disabled) {
- timer_mod(s->irq_timer, s->next_transition_time);
- }
-}
-
-/* When HPET is operating in legacy mode, suppress the ignored timer IRQ,
- * reenable it when legacy mode is left again. */
-static void pit_irq_control(void *opaque, int n, int enable)
-{
- PITCommonState *pit = opaque;
- PITChannelState *s = &pit->channels[0];
-
- if (enable) {
- s->irq_disabled = 0;
- pit_irq_timer_update(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
- } else {
- s->irq_disabled = 1;
- timer_del(s->irq_timer);
- }
-}
-
-static const MemoryRegionOps pit_ioport_ops = {
- .read = pit_ioport_read,
- .write = pit_ioport_write,
- .impl = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void pit_post_load(PITCommonState *s)
-{
- PITChannelState *sc = &s->channels[0];
-
- if (sc->next_transition_time != -1) {
- timer_mod(sc->irq_timer, sc->next_transition_time);
- } else {
- timer_del(sc->irq_timer);
- }
-}
-
-static void pit_realizefn(DeviceState *dev, Error **errp)
-{
- PITCommonState *pit = PIT_COMMON(dev);
- PITClass *pc = PIT_GET_CLASS(dev);
- PITChannelState *s;
-
- s = &pit->channels[0];
- /* the timer 0 is connected to an IRQ */
- s->irq_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pit_irq_timer, s);
- qdev_init_gpio_out(dev, &s->irq, 1);
-
- memory_region_init_io(&pit->ioports, OBJECT(pit), &pit_ioport_ops,
- pit, "pit", 4);
-
- qdev_init_gpio_in(dev, pit_irq_control, 1);
-
- pc->parent_realize(dev, errp);
-}
-
-static Property pit_properties[] = {
- DEFINE_PROP_UINT32("iobase", PITCommonState, iobase, -1),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void pit_class_initfn(ObjectClass *klass, void *data)
-{
- PITClass *pc = PIT_CLASS(klass);
- PITCommonClass *k = PIT_COMMON_CLASS(klass);
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- pc->parent_realize = dc->realize;
- dc->realize = pit_realizefn;
- k->set_channel_gate = pit_set_channel_gate;
- k->get_channel_info = pit_get_channel_info_common;
- k->post_load = pit_post_load;
- dc->reset = pit_reset;
- dc->props = pit_properties;
-}
-
-static const TypeInfo pit_info = {
- .name = TYPE_I8254,
- .parent = TYPE_PIT_COMMON,
- .instance_size = sizeof(PITCommonState),
- .class_init = pit_class_initfn,
- .class_size = sizeof(PITClass),
-};
-
-static void pit_register_types(void)
-{
- type_register_static(&pit_info);
-}
-
-type_init(pit_register_types)
diff --git a/qemu/hw/timer/i8254_common.c b/qemu/hw/timer/i8254_common.c
deleted file mode 100644
index e18299a48..000000000
--- a/qemu/hw/timer/i8254_common.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * QEMU 8253/8254 - common bits of emulated and KVM kernel model
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- * Copyright (c) 2012 Jan Kiszka, Siemens AG
- *
- * 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 "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/isa/isa.h"
-#include "qemu/timer.h"
-#include "hw/timer/i8254.h"
-#include "hw/timer/i8254_internal.h"
-
-/* val must be 0 or 1 */
-void pit_set_gate(ISADevice *dev, int channel, int val)
-{
- PITCommonState *pit = PIT_COMMON(dev);
- PITChannelState *s = &pit->channels[channel];
- PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
-
- c->set_channel_gate(pit, s, val);
-}
-
-/* get pit output bit */
-int pit_get_out(PITChannelState *s, int64_t current_time)
-{
- uint64_t d;
- int out;
-
- d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
- NANOSECONDS_PER_SECOND);
- switch (s->mode) {
- default:
- case 0:
- out = (d >= s->count);
- break;
- case 1:
- out = (d < s->count);
- break;
- case 2:
- if ((d % s->count) == 0 && d != 0) {
- out = 1;
- } else {
- out = 0;
- }
- break;
- case 3:
- out = (d % s->count) < ((s->count + 1) >> 1);
- break;
- case 4:
- case 5:
- out = (d == s->count);
- break;
- }
- return out;
-}
-
-/* return -1 if no transition will occur. */
-int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time)
-{
- uint64_t d, next_time, base;
- int period2;
-
- d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
- NANOSECONDS_PER_SECOND);
- switch (s->mode) {
- default:
- case 0:
- case 1:
- if (d < s->count) {
- next_time = s->count;
- } else {
- return -1;
- }
- break;
- case 2:
- base = (d / s->count) * s->count;
- if ((d - base) == 0 && d != 0) {
- next_time = base + s->count;
- } else {
- next_time = base + s->count + 1;
- }
- break;
- case 3:
- base = (d / s->count) * s->count;
- period2 = ((s->count + 1) >> 1);
- if ((d - base) < period2) {
- next_time = base + period2;
- } else {
- next_time = base + s->count;
- }
- break;
- case 4:
- case 5:
- if (d < s->count) {
- next_time = s->count;
- } else if (d == s->count) {
- next_time = s->count + 1;
- } else {
- return -1;
- }
- break;
- }
- /* convert to timer units */
- next_time = s->count_load_time + muldiv64(next_time, NANOSECONDS_PER_SECOND,
- PIT_FREQ);
- /* fix potential rounding problems */
- /* XXX: better solution: use a clock at PIT_FREQ Hz */
- if (next_time <= current_time) {
- next_time = current_time + 1;
- }
- return next_time;
-}
-
-void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc,
- PITChannelInfo *info)
-{
- info->gate = sc->gate;
- info->mode = sc->mode;
- info->initial_count = sc->count;
- info->out = pit_get_out(sc, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
-}
-
-void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info)
-{
- PITCommonState *pit = PIT_COMMON(dev);
- PITChannelState *s = &pit->channels[channel];
- PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
-
- c->get_channel_info(pit, s, info);
-}
-
-void pit_reset_common(PITCommonState *pit)
-{
- PITChannelState *s;
- int i;
-
- for (i = 0; i < 3; i++) {
- s = &pit->channels[i];
- s->mode = 3;
- s->gate = (i != 2);
- s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- s->count = 0x10000;
- if (i == 0 && !s->irq_disabled) {
- s->next_transition_time =
- pit_get_next_transition_time(s, s->count_load_time);
- }
- }
-}
-
-static void pit_common_realize(DeviceState *dev, Error **errp)
-{
- ISADevice *isadev = ISA_DEVICE(dev);
- PITCommonState *pit = PIT_COMMON(dev);
-
- isa_register_ioport(isadev, &pit->ioports, pit->iobase);
-
- qdev_set_legacy_instance_id(dev, pit->iobase, 2);
-}
-
-static const VMStateDescription vmstate_pit_channel = {
- .name = "pit channel",
- .version_id = 2,
- .minimum_version_id = 2,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(count, PITChannelState),
- VMSTATE_UINT16(latched_count, PITChannelState),
- VMSTATE_UINT8(count_latched, PITChannelState),
- VMSTATE_UINT8(status_latched, PITChannelState),
- VMSTATE_UINT8(status, PITChannelState),
- VMSTATE_UINT8(read_state, PITChannelState),
- VMSTATE_UINT8(write_state, PITChannelState),
- VMSTATE_UINT8(write_latch, PITChannelState),
- VMSTATE_UINT8(rw_mode, PITChannelState),
- VMSTATE_UINT8(mode, PITChannelState),
- VMSTATE_UINT8(bcd, PITChannelState),
- VMSTATE_UINT8(gate, PITChannelState),
- VMSTATE_INT64(count_load_time, PITChannelState),
- VMSTATE_INT64(next_transition_time, PITChannelState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
-{
- PITCommonState *pit = opaque;
- PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
- PITChannelState *s;
- int i;
-
- if (version_id != 1) {
- return -EINVAL;
- }
-
- for (i = 0; i < 3; i++) {
- s = &pit->channels[i];
- s->count = qemu_get_be32(f);
- qemu_get_be16s(f, &s->latched_count);
- qemu_get_8s(f, &s->count_latched);
- qemu_get_8s(f, &s->status_latched);
- qemu_get_8s(f, &s->status);
- qemu_get_8s(f, &s->read_state);
- qemu_get_8s(f, &s->write_state);
- qemu_get_8s(f, &s->write_latch);
- qemu_get_8s(f, &s->rw_mode);
- qemu_get_8s(f, &s->mode);
- qemu_get_8s(f, &s->bcd);
- qemu_get_8s(f, &s->gate);
- s->count_load_time = qemu_get_be64(f);
- s->irq_disabled = 0;
- if (i == 0) {
- s->next_transition_time = qemu_get_be64(f);
- }
- }
- if (c->post_load) {
- c->post_load(pit);
- }
- return 0;
-}
-
-static void pit_dispatch_pre_save(void *opaque)
-{
- PITCommonState *s = opaque;
- PITCommonClass *c = PIT_COMMON_GET_CLASS(s);
-
- if (c->pre_save) {
- c->pre_save(s);
- }
-}
-
-static int pit_dispatch_post_load(void *opaque, int version_id)
-{
- PITCommonState *s = opaque;
- PITCommonClass *c = PIT_COMMON_GET_CLASS(s);
-
- if (c->post_load) {
- c->post_load(s);
- }
- return 0;
-}
-
-static const VMStateDescription vmstate_pit_common = {
- .name = "i8254",
- .version_id = 3,
- .minimum_version_id = 2,
- .minimum_version_id_old = 1,
- .load_state_old = pit_load_old,
- .pre_save = pit_dispatch_pre_save,
- .post_load = pit_dispatch_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3),
- VMSTATE_STRUCT_ARRAY(channels, PITCommonState, 3, 2,
- vmstate_pit_channel, PITChannelState),
- VMSTATE_INT64(channels[0].next_transition_time,
- PITCommonState), /* formerly irq_timer */
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void pit_common_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = pit_common_realize;
- dc->vmsd = &vmstate_pit_common;
- /*
- * Reason: unlike ordinary ISA devices, the PIT may need to be
- * wired to the HPET, and because of that, some wiring is always
- * done by board code.
- */
- dc->cannot_instantiate_with_device_add_yet = true;
-}
-
-static const TypeInfo pit_common_type = {
- .name = TYPE_PIT_COMMON,
- .parent = TYPE_ISA_DEVICE,
- .instance_size = sizeof(PITCommonState),
- .class_size = sizeof(PITCommonClass),
- .class_init = pit_common_class_init,
- .abstract = true,
-};
-
-static void register_devices(void)
-{
- type_register_static(&pit_common_type);
-}
-
-type_init(register_devices);
diff --git a/qemu/hw/timer/imx_epit.c b/qemu/hw/timer/imx_epit.c
deleted file mode 100644
index f5836e21f..000000000
--- a/qemu/hw/timer/imx_epit.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * IMX EPIT Timer
- *
- * Copyright (c) 2008 OK Labs
- * Copyright (c) 2011 NICTA Pty Ltd
- * Originally written by Hans Jiang
- * Updated by Peter Chubb
- * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
- *
- * This code is licensed under GPL version 2 or later. See
- * the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/timer/imx_epit.h"
-#include "hw/misc/imx_ccm.h"
-#include "qemu/main-loop.h"
-
-#ifndef DEBUG_IMX_EPIT
-#define DEBUG_IMX_EPIT 0
-#endif
-
-#define DPRINTF(fmt, args...) \
- do { \
- if (DEBUG_IMX_EPIT) { \
- fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_EPIT, \
- __func__, ##args); \
- } \
- } while (0)
-
-static char const *imx_epit_reg_name(uint32_t reg)
-{
- switch (reg) {
- case 0:
- return "CR";
- case 1:
- return "SR";
- case 2:
- return "LR";
- case 3:
- return "CMP";
- case 4:
- return "CNT";
- default:
- return "[?]";
- }
-}
-
-/*
- * Exact clock frequencies vary from board to board.
- * These are typical.
- */
-static const IMXClk imx_epit_clocks[] = {
- CLK_NONE, /* 00 disabled */
- CLK_IPG, /* 01 ipg_clk, ~532MHz */
- CLK_IPG_HIGH, /* 10 ipg_clk_highfreq */
- CLK_32k, /* 11 ipg_clk_32k -- ~32kHz */
-};
-
-/*
- * Update interrupt status
- */
-static void imx_epit_update_int(IMXEPITState *s)
-{
- if (s->sr && (s->cr & CR_OCIEN) && (s->cr & CR_EN)) {
- qemu_irq_raise(s->irq);
- } else {
- qemu_irq_lower(s->irq);
- }
-}
-
-static void imx_epit_set_freq(IMXEPITState *s)
-{
- uint32_t clksrc;
- uint32_t prescaler;
-
- clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2);
- prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12);
-
- s->freq = imx_ccm_get_clock_frequency(s->ccm,
- imx_epit_clocks[clksrc]) / prescaler;
-
- DPRINTF("Setting ptimer frequency to %u\n", s->freq);
-
- if (s->freq) {
- ptimer_set_freq(s->timer_reload, s->freq);
- ptimer_set_freq(s->timer_cmp, s->freq);
- }
-}
-
-static void imx_epit_reset(DeviceState *dev)
-{
- IMXEPITState *s = IMX_EPIT(dev);
-
- /*
- * Soft reset doesn't touch some bits; hard reset clears them
- */
- s->cr &= (CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN);
- s->sr = 0;
- s->lr = EPIT_TIMER_MAX;
- s->cmp = 0;
- s->cnt = 0;
- /* stop both timers */
- ptimer_stop(s->timer_cmp);
- ptimer_stop(s->timer_reload);
- /* compute new frequency */
- imx_epit_set_freq(s);
- /* init both timers to EPIT_TIMER_MAX */
- ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1);
- ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1);
- if (s->freq && (s->cr & CR_EN)) {
- /* if the timer is still enabled, restart it */
- ptimer_run(s->timer_reload, 0);
- }
-}
-
-static uint32_t imx_epit_update_count(IMXEPITState *s)
-{
- s->cnt = ptimer_get_count(s->timer_reload);
-
- return s->cnt;
-}
-
-static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
-{
- IMXEPITState *s = IMX_EPIT(opaque);
- uint32_t reg_value = 0;
-
- switch (offset >> 2) {
- case 0: /* Control Register */
- reg_value = s->cr;
- break;
-
- case 1: /* Status Register */
- reg_value = s->sr;
- break;
-
- case 2: /* LR - ticks*/
- reg_value = s->lr;
- break;
-
- case 3: /* CMP */
- reg_value = s->cmp;
- break;
-
- case 4: /* CNT */
- imx_epit_update_count(s);
- reg_value = s->cnt;
- break;
-
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- HWADDR_PRIx "\n", TYPE_IMX_EPIT, __func__, offset);
- break;
- }
-
- DPRINTF("(%s) = 0x%08x\n", imx_epit_reg_name(offset >> 2), reg_value);
-
- return reg_value;
-}
-
-static void imx_epit_reload_compare_timer(IMXEPITState *s)
-{
- if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) {
- /* if the compare feature is on and timers are running */
- uint32_t tmp = imx_epit_update_count(s);
- uint64_t next;
- if (tmp > s->cmp) {
- /* It'll fire in this round of the timer */
- next = tmp - s->cmp;
- } else { /* catch it next time around */
- next = tmp - s->cmp + ((s->cr & CR_RLD) ? EPIT_TIMER_MAX : s->lr);
- }
- ptimer_set_count(s->timer_cmp, next);
- }
-}
-
-static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- IMXEPITState *s = IMX_EPIT(opaque);
- uint64_t oldcr;
-
- DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(offset >> 2),
- (uint32_t)value);
-
- switch (offset >> 2) {
- case 0: /* CR */
-
- oldcr = s->cr;
- s->cr = value & 0x03ffffff;
- if (s->cr & CR_SWR) {
- /* handle the reset */
- imx_epit_reset(DEVICE(s));
- } else {
- imx_epit_set_freq(s);
- }
-
- if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) {
- if (s->cr & CR_ENMOD) {
- if (s->cr & CR_RLD) {
- ptimer_set_limit(s->timer_reload, s->lr, 1);
- ptimer_set_limit(s->timer_cmp, s->lr, 1);
- } else {
- ptimer_set_limit(s->timer_reload, EPIT_TIMER_MAX, 1);
- ptimer_set_limit(s->timer_cmp, EPIT_TIMER_MAX, 1);
- }
- }
-
- imx_epit_reload_compare_timer(s);
- ptimer_run(s->timer_reload, 0);
- if (s->cr & CR_OCIEN) {
- ptimer_run(s->timer_cmp, 0);
- } else {
- ptimer_stop(s->timer_cmp);
- }
- } else if (!(s->cr & CR_EN)) {
- /* stop both timers */
- ptimer_stop(s->timer_reload);
- ptimer_stop(s->timer_cmp);
- } else if (s->cr & CR_OCIEN) {
- if (!(oldcr & CR_OCIEN)) {
- imx_epit_reload_compare_timer(s);
- ptimer_run(s->timer_cmp, 0);
- }
- } else {
- ptimer_stop(s->timer_cmp);
- }
- break;
-
- case 1: /* SR - ACK*/
- /* writing 1 to OCIF clear the OCIF bit */
- if (value & 0x01) {
- s->sr = 0;
- imx_epit_update_int(s);
- }
- break;
-
- case 2: /* LR - set ticks */
- s->lr = value;
-
- if (s->cr & CR_RLD) {
- /* Also set the limit if the LRD bit is set */
- /* If IOVW bit is set then set the timer value */
- ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW);
- ptimer_set_limit(s->timer_cmp, s->lr, 0);
- } else if (s->cr & CR_IOVW) {
- /* If IOVW bit is set then set the timer value */
- ptimer_set_count(s->timer_reload, s->lr);
- }
-
- imx_epit_reload_compare_timer(s);
- break;
-
- case 3: /* CMP */
- s->cmp = value;
-
- imx_epit_reload_compare_timer(s);
-
- break;
-
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- HWADDR_PRIx "\n", TYPE_IMX_EPIT, __func__, offset);
-
- break;
- }
-}
-static void imx_epit_cmp(void *opaque)
-{
- IMXEPITState *s = IMX_EPIT(opaque);
-
- DPRINTF("sr was %d\n", s->sr);
-
- s->sr = 1;
- imx_epit_update_int(s);
-}
-
-static const MemoryRegionOps imx_epit_ops = {
- .read = imx_epit_read,
- .write = imx_epit_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_imx_timer_epit = {
- .name = TYPE_IMX_EPIT,
- .version_id = 2,
- .minimum_version_id = 2,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(cr, IMXEPITState),
- VMSTATE_UINT32(sr, IMXEPITState),
- VMSTATE_UINT32(lr, IMXEPITState),
- VMSTATE_UINT32(cmp, IMXEPITState),
- VMSTATE_UINT32(cnt, IMXEPITState),
- VMSTATE_UINT32(freq, IMXEPITState),
- VMSTATE_PTIMER(timer_reload, IMXEPITState),
- VMSTATE_PTIMER(timer_cmp, IMXEPITState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void imx_epit_realize(DeviceState *dev, Error **errp)
-{
- IMXEPITState *s = IMX_EPIT(dev);
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- QEMUBH *bh;
-
- DPRINTF("\n");
-
- sysbus_init_irq(sbd, &s->irq);
- memory_region_init_io(&s->iomem, OBJECT(s), &imx_epit_ops, s, TYPE_IMX_EPIT,
- 0x00001000);
- sysbus_init_mmio(sbd, &s->iomem);
-
- s->timer_reload = ptimer_init(NULL);
-
- bh = qemu_bh_new(imx_epit_cmp, s);
- s->timer_cmp = ptimer_init(bh);
-}
-
-static void imx_epit_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = imx_epit_realize;
- dc->reset = imx_epit_reset;
- dc->vmsd = &vmstate_imx_timer_epit;
- dc->desc = "i.MX periodic timer";
-}
-
-static const TypeInfo imx_epit_info = {
- .name = TYPE_IMX_EPIT,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(IMXEPITState),
- .class_init = imx_epit_class_init,
-};
-
-static void imx_epit_register_types(void)
-{
- type_register_static(&imx_epit_info);
-}
-
-type_init(imx_epit_register_types)
diff --git a/qemu/hw/timer/imx_gpt.c b/qemu/hw/timer/imx_gpt.c
deleted file mode 100644
index ab2e213a1..000000000
--- a/qemu/hw/timer/imx_gpt.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * IMX GPT Timer
- *
- * Copyright (c) 2008 OK Labs
- * Copyright (c) 2011 NICTA Pty Ltd
- * Originally written by Hans Jiang
- * Updated by Peter Chubb
- * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
- *
- * This code is licensed under GPL version 2 or later. See
- * the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/timer/imx_gpt.h"
-#include "hw/misc/imx_ccm.h"
-#include "qemu/main-loop.h"
-
-#ifndef DEBUG_IMX_GPT
-#define DEBUG_IMX_GPT 0
-#endif
-
-#define DPRINTF(fmt, args...) \
- do { \
- if (DEBUG_IMX_GPT) { \
- fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_GPT, \
- __func__, ##args); \
- } \
- } while (0)
-
-static char const *imx_gpt_reg_name(uint32_t reg)
-{
- switch (reg) {
- case 0:
- return "CR";
- case 1:
- return "PR";
- case 2:
- return "SR";
- case 3:
- return "IR";
- case 4:
- return "OCR1";
- case 5:
- return "OCR2";
- case 6:
- return "OCR3";
- case 7:
- return "ICR1";
- case 8:
- return "ICR2";
- case 9:
- return "CNT";
- default:
- return "[?]";
- }
-}
-
-static const VMStateDescription vmstate_imx_timer_gpt = {
- .name = TYPE_IMX_GPT,
- .version_id = 3,
- .minimum_version_id = 3,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(cr, IMXGPTState),
- VMSTATE_UINT32(pr, IMXGPTState),
- VMSTATE_UINT32(sr, IMXGPTState),
- VMSTATE_UINT32(ir, IMXGPTState),
- VMSTATE_UINT32(ocr1, IMXGPTState),
- VMSTATE_UINT32(ocr2, IMXGPTState),
- VMSTATE_UINT32(ocr3, IMXGPTState),
- VMSTATE_UINT32(icr1, IMXGPTState),
- VMSTATE_UINT32(icr2, IMXGPTState),
- VMSTATE_UINT32(cnt, IMXGPTState),
- VMSTATE_UINT32(next_timeout, IMXGPTState),
- VMSTATE_UINT32(next_int, IMXGPTState),
- VMSTATE_UINT32(freq, IMXGPTState),
- VMSTATE_PTIMER(timer, IMXGPTState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const IMXClk imx_gpt_clocks[] = {
- CLK_NONE, /* 000 No clock source */
- CLK_IPG, /* 001 ipg_clk, 532MHz*/
- CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
- CLK_NONE, /* 011 not defined */
- CLK_32k, /* 100 ipg_clk_32k */
- CLK_NONE, /* 101 not defined */
- CLK_NONE, /* 110 not defined */
- CLK_NONE, /* 111 not defined */
-};
-
-static void imx_gpt_set_freq(IMXGPTState *s)
-{
- uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
-
- s->freq = imx_ccm_get_clock_frequency(s->ccm,
- imx_gpt_clocks[clksrc]) / (1 + s->pr);
-
- DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, s->freq);
-
- if (s->freq) {
- ptimer_set_freq(s->timer, s->freq);
- }
-}
-
-static void imx_gpt_update_int(IMXGPTState *s)
-{
- if ((s->sr & s->ir) && (s->cr & GPT_CR_EN)) {
- qemu_irq_raise(s->irq);
- } else {
- qemu_irq_lower(s->irq);
- }
-}
-
-static uint32_t imx_gpt_update_count(IMXGPTState *s)
-{
- s->cnt = s->next_timeout - (uint32_t)ptimer_get_count(s->timer);
-
- return s->cnt;
-}
-
-static inline uint32_t imx_gpt_find_limit(uint32_t count, uint32_t reg,
- uint32_t timeout)
-{
- if ((count < reg) && (timeout > reg)) {
- timeout = reg;
- }
-
- return timeout;
-}
-
-static void imx_gpt_compute_next_timeout(IMXGPTState *s, bool event)
-{
- uint32_t timeout = GPT_TIMER_MAX;
- uint32_t count;
- long long limit;
-
- if (!(s->cr & GPT_CR_EN)) {
- /* if not enabled just return */
- return;
- }
-
- /* update the count */
- count = imx_gpt_update_count(s);
-
- if (event) {
- /*
- * This is an event (the ptimer reached 0 and stopped), and the
- * timer counter is now equal to s->next_timeout.
- */
- if (!(s->cr & GPT_CR_FRR) && (count == s->ocr1)) {
- /* We are in restart mode and we crossed the compare channel 1
- * value. We need to reset the counter to 0.
- */
- count = s->cnt = s->next_timeout = 0;
- } else if (count == GPT_TIMER_MAX) {
- /* We reached GPT_TIMER_MAX so we need to rollover */
- count = s->cnt = s->next_timeout = 0;
- }
- }
-
- /* now, find the next timeout related to count */
-
- if (s->ir & GPT_IR_OF1IE) {
- timeout = imx_gpt_find_limit(count, s->ocr1, timeout);
- }
- if (s->ir & GPT_IR_OF2IE) {
- timeout = imx_gpt_find_limit(count, s->ocr2, timeout);
- }
- if (s->ir & GPT_IR_OF3IE) {
- timeout = imx_gpt_find_limit(count, s->ocr3, timeout);
- }
-
- /* find the next set of interrupts to raise for next timer event */
-
- s->next_int = 0;
- if ((s->ir & GPT_IR_OF1IE) && (timeout == s->ocr1)) {
- s->next_int |= GPT_SR_OF1;
- }
- if ((s->ir & GPT_IR_OF2IE) && (timeout == s->ocr2)) {
- s->next_int |= GPT_SR_OF2;
- }
- if ((s->ir & GPT_IR_OF3IE) && (timeout == s->ocr3)) {
- s->next_int |= GPT_SR_OF3;
- }
- if ((s->ir & GPT_IR_ROVIE) && (timeout == GPT_TIMER_MAX)) {
- s->next_int |= GPT_SR_ROV;
- }
-
- /* the new range to count down from */
- limit = timeout - imx_gpt_update_count(s);
-
- if (limit < 0) {
- /*
- * if we reach here, then QEMU is running too slow and we pass the
- * timeout limit while computing it. Let's deliver the interrupt
- * and compute a new limit.
- */
- s->sr |= s->next_int;
-
- imx_gpt_compute_next_timeout(s, event);
-
- imx_gpt_update_int(s);
- } else {
- /* New timeout value */
- s->next_timeout = timeout;
-
- /* reset the limit to the computed range */
- ptimer_set_limit(s->timer, limit, 1);
- }
-}
-
-static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
-{
- IMXGPTState *s = IMX_GPT(opaque);
- uint32_t reg_value = 0;
-
- switch (offset >> 2) {
- case 0: /* Control Register */
- reg_value = s->cr;
- break;
-
- case 1: /* prescaler */
- reg_value = s->pr;
- break;
-
- case 2: /* Status Register */
- reg_value = s->sr;
- break;
-
- case 3: /* Interrupt Register */
- reg_value = s->ir;
- break;
-
- case 4: /* Output Compare Register 1 */
- reg_value = s->ocr1;
- break;
-
- case 5: /* Output Compare Register 2 */
- reg_value = s->ocr2;
- break;
-
- case 6: /* Output Compare Register 3 */
- reg_value = s->ocr3;
- break;
-
- case 7: /* input Capture Register 1 */
- qemu_log_mask(LOG_UNIMP, "[%s]%s: icr1 feature is not implemented\n",
- TYPE_IMX_GPT, __func__);
- reg_value = s->icr1;
- break;
-
- case 8: /* input Capture Register 2 */
- qemu_log_mask(LOG_UNIMP, "[%s]%s: icr2 feature is not implemented\n",
- TYPE_IMX_GPT, __func__);
- reg_value = s->icr2;
- break;
-
- case 9: /* cnt */
- imx_gpt_update_count(s);
- reg_value = s->cnt;
- break;
-
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- HWADDR_PRIx "\n", TYPE_IMX_GPT, __func__, offset);
- break;
- }
-
- DPRINTF("(%s) = 0x%08x\n", imx_gpt_reg_name(offset >> 2), reg_value);
-
- return reg_value;
-}
-
-static void imx_gpt_reset(DeviceState *dev)
-{
- IMXGPTState *s = IMX_GPT(dev);
-
- /* stop timer */
- ptimer_stop(s->timer);
-
- /*
- * Soft reset doesn't touch some bits; hard reset clears them
- */
- s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN|
- GPT_CR_WAITEN|GPT_CR_DBGEN);
- s->sr = 0;
- s->pr = 0;
- s->ir = 0;
- s->cnt = 0;
- s->ocr1 = GPT_TIMER_MAX;
- s->ocr2 = GPT_TIMER_MAX;
- s->ocr3 = GPT_TIMER_MAX;
- s->icr1 = 0;
- s->icr2 = 0;
-
- s->next_timeout = GPT_TIMER_MAX;
- s->next_int = 0;
-
- /* compute new freq */
- imx_gpt_set_freq(s);
-
- /* reset the limit to GPT_TIMER_MAX */
- ptimer_set_limit(s->timer, GPT_TIMER_MAX, 1);
-
- /* if the timer is still enabled, restart it */
- if (s->freq && (s->cr & GPT_CR_EN)) {
- ptimer_run(s->timer, 1);
- }
-}
-
-static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
- unsigned size)
-{
- IMXGPTState *s = IMX_GPT(opaque);
- uint32_t oldreg;
-
- DPRINTF("(%s, value = 0x%08x)\n", imx_gpt_reg_name(offset >> 2),
- (uint32_t)value);
-
- switch (offset >> 2) {
- case 0:
- oldreg = s->cr;
- s->cr = value & ~0x7c14;
- if (s->cr & GPT_CR_SWR) { /* force reset */
- /* handle the reset */
- imx_gpt_reset(DEVICE(s));
- } else {
- /* set our freq, as the source might have changed */
- imx_gpt_set_freq(s);
-
- if ((oldreg ^ s->cr) & GPT_CR_EN) {
- if (s->cr & GPT_CR_EN) {
- if (s->cr & GPT_CR_ENMOD) {
- s->next_timeout = GPT_TIMER_MAX;
- ptimer_set_count(s->timer, GPT_TIMER_MAX);
- imx_gpt_compute_next_timeout(s, false);
- }
- ptimer_run(s->timer, 1);
- } else {
- /* stop timer */
- ptimer_stop(s->timer);
- }
- }
- }
- break;
-
- case 1: /* Prescaler */
- s->pr = value & 0xfff;
- imx_gpt_set_freq(s);
- break;
-
- case 2: /* SR */
- s->sr &= ~(value & 0x3f);
- imx_gpt_update_int(s);
- break;
-
- case 3: /* IR -- interrupt register */
- s->ir = value & 0x3f;
- imx_gpt_update_int(s);
-
- imx_gpt_compute_next_timeout(s, false);
-
- break;
-
- case 4: /* OCR1 -- output compare register */
- s->ocr1 = value;
-
- /* In non-freerun mode, reset count when this register is written */
- if (!(s->cr & GPT_CR_FRR)) {
- s->next_timeout = GPT_TIMER_MAX;
- ptimer_set_limit(s->timer, GPT_TIMER_MAX, 1);
- }
-
- /* compute the new timeout */
- imx_gpt_compute_next_timeout(s, false);
-
- break;
-
- case 5: /* OCR2 -- output compare register */
- s->ocr2 = value;
-
- /* compute the new timeout */
- imx_gpt_compute_next_timeout(s, false);
-
- break;
-
- case 6: /* OCR3 -- output compare register */
- s->ocr3 = value;
-
- /* compute the new timeout */
- imx_gpt_compute_next_timeout(s, false);
-
- break;
-
- default:
- qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
- HWADDR_PRIx "\n", TYPE_IMX_GPT, __func__, offset);
- break;
- }
-}
-
-static void imx_gpt_timeout(void *opaque)
-{
- IMXGPTState *s = IMX_GPT(opaque);
-
- DPRINTF("\n");
-
- s->sr |= s->next_int;
- s->next_int = 0;
-
- imx_gpt_compute_next_timeout(s, true);
-
- imx_gpt_update_int(s);
-
- if (s->freq && (s->cr & GPT_CR_EN)) {
- ptimer_run(s->timer, 1);
- }
-}
-
-static const MemoryRegionOps imx_gpt_ops = {
- .read = imx_gpt_read,
- .write = imx_gpt_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-
-static void imx_gpt_realize(DeviceState *dev, Error **errp)
-{
- IMXGPTState *s = IMX_GPT(dev);
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- QEMUBH *bh;
-
- sysbus_init_irq(sbd, &s->irq);
- memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpt_ops, s, TYPE_IMX_GPT,
- 0x00001000);
- sysbus_init_mmio(sbd, &s->iomem);
-
- bh = qemu_bh_new(imx_gpt_timeout, s);
- s->timer = ptimer_init(bh);
-}
-
-static void imx_gpt_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = imx_gpt_realize;
- dc->reset = imx_gpt_reset;
- dc->vmsd = &vmstate_imx_timer_gpt;
- dc->desc = "i.MX general timer";
-}
-
-static const TypeInfo imx_gpt_info = {
- .name = TYPE_IMX_GPT,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(IMXGPTState),
- .class_init = imx_gpt_class_init,
-};
-
-static void imx_gpt_register_types(void)
-{
- type_register_static(&imx_gpt_info);
-}
-
-type_init(imx_gpt_register_types)
diff --git a/qemu/hw/timer/lm32_timer.c b/qemu/hw/timer/lm32_timer.c
deleted file mode 100644
index 3198355aa..000000000
--- a/qemu/hw/timer/lm32_timer.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * QEMU model of the LatticeMico32 timer block.
- *
- * Copyright (c) 2010 Michael Walle <michael@walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- *
- * Specification available at:
- * http://www.latticesemi.com/documents/mico32timer.pdf
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "qemu/error-report.h"
-#include "qemu/main-loop.h"
-
-#define DEFAULT_FREQUENCY (50*1000000)
-
-enum {
- R_SR = 0,
- R_CR,
- R_PERIOD,
- R_SNAPSHOT,
- R_MAX
-};
-
-enum {
- SR_TO = (1 << 0),
- SR_RUN = (1 << 1),
-};
-
-enum {
- CR_ITO = (1 << 0),
- CR_CONT = (1 << 1),
- CR_START = (1 << 2),
- CR_STOP = (1 << 3),
-};
-
-#define TYPE_LM32_TIMER "lm32-timer"
-#define LM32_TIMER(obj) OBJECT_CHECK(LM32TimerState, (obj), TYPE_LM32_TIMER)
-
-struct LM32TimerState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
-
- QEMUBH *bh;
- ptimer_state *ptimer;
-
- qemu_irq irq;
- uint32_t freq_hz;
-
- uint32_t regs[R_MAX];
-};
-typedef struct LM32TimerState LM32TimerState;
-
-static void timer_update_irq(LM32TimerState *s)
-{
- int state = (s->regs[R_SR] & SR_TO) && (s->regs[R_CR] & CR_ITO);
-
- trace_lm32_timer_irq_state(state);
- qemu_set_irq(s->irq, state);
-}
-
-static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
-{
- LM32TimerState *s = opaque;
- uint32_t r = 0;
-
- addr >>= 2;
- switch (addr) {
- case R_SR:
- case R_CR:
- case R_PERIOD:
- r = s->regs[addr];
- break;
- case R_SNAPSHOT:
- r = (uint32_t)ptimer_get_count(s->ptimer);
- break;
- default:
- error_report("lm32_timer: read access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- }
-
- trace_lm32_timer_memory_read(addr << 2, r);
- return r;
-}
-
-static void timer_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned size)
-{
- LM32TimerState *s = opaque;
-
- trace_lm32_timer_memory_write(addr, value);
-
- addr >>= 2;
- switch (addr) {
- case R_SR:
- s->regs[R_SR] &= ~SR_TO;
- break;
- case R_CR:
- s->regs[R_CR] = value;
- if (s->regs[R_CR] & CR_START) {
- ptimer_run(s->ptimer, 1);
- }
- if (s->regs[R_CR] & CR_STOP) {
- ptimer_stop(s->ptimer);
- }
- break;
- case R_PERIOD:
- s->regs[R_PERIOD] = value;
- ptimer_set_count(s->ptimer, value);
- break;
- case R_SNAPSHOT:
- error_report("lm32_timer: write access to read only register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- default:
- error_report("lm32_timer: write access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- }
- timer_update_irq(s);
-}
-
-static const MemoryRegionOps timer_ops = {
- .read = timer_read,
- .write = timer_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-static void timer_hit(void *opaque)
-{
- LM32TimerState *s = opaque;
-
- trace_lm32_timer_hit();
-
- s->regs[R_SR] |= SR_TO;
-
- if (s->regs[R_CR] & CR_CONT) {
- ptimer_set_count(s->ptimer, s->regs[R_PERIOD]);
- ptimer_run(s->ptimer, 1);
- }
- timer_update_irq(s);
-}
-
-static void timer_reset(DeviceState *d)
-{
- LM32TimerState *s = LM32_TIMER(d);
- int i;
-
- for (i = 0; i < R_MAX; i++) {
- s->regs[i] = 0;
- }
- ptimer_stop(s->ptimer);
-}
-
-static int lm32_timer_init(SysBusDevice *dev)
-{
- LM32TimerState *s = LM32_TIMER(dev);
-
- sysbus_init_irq(dev, &s->irq);
-
- s->bh = qemu_bh_new(timer_hit, s);
- s->ptimer = ptimer_init(s->bh);
- ptimer_set_freq(s->ptimer, s->freq_hz);
-
- memory_region_init_io(&s->iomem, OBJECT(s), &timer_ops, s,
- "timer", R_MAX * 4);
- sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
-}
-
-static const VMStateDescription vmstate_lm32_timer = {
- .name = "lm32-timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_PTIMER(ptimer, LM32TimerState),
- VMSTATE_UINT32(freq_hz, LM32TimerState),
- VMSTATE_UINT32_ARRAY(regs, LM32TimerState, R_MAX),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static Property lm32_timer_properties[] = {
- DEFINE_PROP_UINT32("frequency", LM32TimerState, freq_hz, DEFAULT_FREQUENCY),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void lm32_timer_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = lm32_timer_init;
- dc->reset = timer_reset;
- dc->vmsd = &vmstate_lm32_timer;
- dc->props = lm32_timer_properties;
-}
-
-static const TypeInfo lm32_timer_info = {
- .name = TYPE_LM32_TIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(LM32TimerState),
- .class_init = lm32_timer_class_init,
-};
-
-static void lm32_timer_register_types(void)
-{
- type_register_static(&lm32_timer_info);
-}
-
-type_init(lm32_timer_register_types)
diff --git a/qemu/hw/timer/m48t59.c b/qemu/hw/timer/m48t59.c
deleted file mode 100644
index e46ca8839..000000000
--- a/qemu/hw/timer/m48t59.c
+++ /dev/null
@@ -1,947 +0,0 @@
-/*
- * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
- *
- * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
- * Copyright (c) 2013 Hervé Poussineau
- *
- * 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 "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/timer/m48t59.h"
-#include "qapi/error.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "hw/sysbus.h"
-#include "hw/isa/isa.h"
-#include "exec/address-spaces.h"
-#include "qemu/bcd.h"
-
-//#define DEBUG_NVRAM
-
-#if defined(DEBUG_NVRAM)
-#define NVRAM_PRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
-#else
-#define NVRAM_PRINTF(fmt, ...) do { } while (0)
-#endif
-
-#define TYPE_M48TXX_SYS_BUS "sysbus-m48txx"
-#define M48TXX_SYS_BUS_GET_CLASS(obj) \
- OBJECT_GET_CLASS(M48txxSysBusDeviceClass, (obj), TYPE_M48TXX_SYS_BUS)
-#define M48TXX_SYS_BUS_CLASS(klass) \
- OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS)
-#define M48TXX_SYS_BUS(obj) \
- OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS)
-
-#define TYPE_M48TXX_ISA "isa-m48txx"
-#define M48TXX_ISA_GET_CLASS(obj) \
- OBJECT_GET_CLASS(M48txxISADeviceClass, (obj), TYPE_M48TXX_ISA)
-#define M48TXX_ISA_CLASS(klass) \
- OBJECT_CLASS_CHECK(M48txxISADeviceClass, (klass), TYPE_M48TXX_ISA)
-#define M48TXX_ISA(obj) \
- OBJECT_CHECK(M48txxISAState, (obj), TYPE_M48TXX_ISA)
-
-/*
- * The M48T02, M48T08 and M48T59 chips are very similar. The newer '59 has
- * alarm and a watchdog timer and related control registers. In the
- * PPC platform there is also a nvram lock function.
- */
-
-typedef struct M48txxInfo {
- const char *isa_name;
- const char *sysbus_name;
- uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
- uint32_t size;
-} M48txxInfo;
-
-/*
- * Chipset docs:
- * http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf
- * http://www.st.com/stonline/products/literature/ds/2411/m48t08.pdf
- * http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf
- */
-
-typedef struct M48t59State {
- /* Hardware parameters */
- qemu_irq IRQ;
- MemoryRegion iomem;
- uint32_t size;
- int32_t base_year;
- /* RTC management */
- time_t time_offset;
- time_t stop_time;
- /* Alarm & watchdog */
- struct tm alarm;
- QEMUTimer *alrm_timer;
- QEMUTimer *wd_timer;
- /* NVRAM storage */
- uint8_t *buffer;
- /* Model parameters */
- uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
- /* NVRAM storage */
- uint16_t addr;
- uint8_t lock;
-} M48t59State;
-
-typedef struct M48txxISAState {
- ISADevice parent_obj;
- M48t59State state;
- uint32_t io_base;
- MemoryRegion io;
-} M48txxISAState;
-
-typedef struct M48txxISADeviceClass {
- ISADeviceClass parent_class;
- M48txxInfo info;
-} M48txxISADeviceClass;
-
-typedef struct M48txxSysBusState {
- SysBusDevice parent_obj;
- M48t59State state;
- MemoryRegion io;
-} M48txxSysBusState;
-
-typedef struct M48txxSysBusDeviceClass {
- SysBusDeviceClass parent_class;
- M48txxInfo info;
-} M48txxSysBusDeviceClass;
-
-static M48txxInfo m48txx_info[] = {
- {
- .sysbus_name = "sysbus-m48t02",
- .model = 2,
- .size = 0x800,
- },{
- .sysbus_name = "sysbus-m48t08",
- .model = 8,
- .size = 0x2000,
- },{
- .sysbus_name = "sysbus-m48t59",
- .model = 59,
- .size = 0x2000,
- },{
- .isa_name = "isa-m48t59",
- .model = 59,
- .size = 0x2000,
- }
-};
-
-
-/* Fake timer functions */
-
-/* Alarm management */
-static void alarm_cb (void *opaque)
-{
- struct tm tm;
- uint64_t next_time;
- M48t59State *NVRAM = opaque;
-
- qemu_set_irq(NVRAM->IRQ, 1);
- if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
- /* Repeat once a month */
- qemu_get_timedate(&tm, NVRAM->time_offset);
- tm.tm_mon++;
- if (tm.tm_mon == 13) {
- tm.tm_mon = 1;
- tm.tm_year++;
- }
- next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset;
- } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
- /* Repeat once a day */
- next_time = 24 * 60 * 60;
- } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
- (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
- /* Repeat once an hour */
- next_time = 60 * 60;
- } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
- (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
- /* Repeat once a minute */
- next_time = 60;
- } else {
- /* Repeat once a second */
- next_time = 1;
- }
- timer_mod(NVRAM->alrm_timer, qemu_clock_get_ns(rtc_clock) +
- next_time * 1000);
- qemu_set_irq(NVRAM->IRQ, 0);
-}
-
-static void set_alarm(M48t59State *NVRAM)
-{
- int diff;
- if (NVRAM->alrm_timer != NULL) {
- timer_del(NVRAM->alrm_timer);
- diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
- if (diff > 0)
- timer_mod(NVRAM->alrm_timer, diff * 1000);
- }
-}
-
-/* RTC management helpers */
-static inline void get_time(M48t59State *NVRAM, struct tm *tm)
-{
- qemu_get_timedate(tm, NVRAM->time_offset);
-}
-
-static void set_time(M48t59State *NVRAM, struct tm *tm)
-{
- NVRAM->time_offset = qemu_timedate_diff(tm);
- set_alarm(NVRAM);
-}
-
-/* Watchdog management */
-static void watchdog_cb (void *opaque)
-{
- M48t59State *NVRAM = opaque;
-
- NVRAM->buffer[0x1FF0] |= 0x80;
- if (NVRAM->buffer[0x1FF7] & 0x80) {
- NVRAM->buffer[0x1FF7] = 0x00;
- NVRAM->buffer[0x1FFC] &= ~0x40;
- /* May it be a hw CPU Reset instead ? */
- qemu_system_reset_request();
- } else {
- qemu_set_irq(NVRAM->IRQ, 1);
- qemu_set_irq(NVRAM->IRQ, 0);
- }
-}
-
-static void set_up_watchdog(M48t59State *NVRAM, uint8_t value)
-{
- uint64_t interval; /* in 1/16 seconds */
-
- NVRAM->buffer[0x1FF0] &= ~0x80;
- if (NVRAM->wd_timer != NULL) {
- timer_del(NVRAM->wd_timer);
- if (value != 0) {
- interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
- timer_mod(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
- ((interval * 1000) >> 4));
- }
- }
-}
-
-/* Direct access to NVRAM */
-static void m48t59_write(M48t59State *NVRAM, uint32_t addr, uint32_t val)
-{
- struct tm tm;
- int tmp;
-
- if (addr > 0x1FF8 && addr < 0x2000)
- NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
-
- /* check for NVRAM access */
- if ((NVRAM->model == 2 && addr < 0x7f8) ||
- (NVRAM->model == 8 && addr < 0x1ff8) ||
- (NVRAM->model == 59 && addr < 0x1ff0)) {
- goto do_write;
- }
-
- /* TOD access */
- switch (addr) {
- case 0x1FF0:
- /* flags register : read-only */
- break;
- case 0x1FF1:
- /* unused */
- break;
- case 0x1FF2:
- /* alarm seconds */
- tmp = from_bcd(val & 0x7F);
- if (tmp >= 0 && tmp <= 59) {
- NVRAM->alarm.tm_sec = tmp;
- NVRAM->buffer[0x1FF2] = val;
- set_alarm(NVRAM);
- }
- break;
- case 0x1FF3:
- /* alarm minutes */
- tmp = from_bcd(val & 0x7F);
- if (tmp >= 0 && tmp <= 59) {
- NVRAM->alarm.tm_min = tmp;
- NVRAM->buffer[0x1FF3] = val;
- set_alarm(NVRAM);
- }
- break;
- case 0x1FF4:
- /* alarm hours */
- tmp = from_bcd(val & 0x3F);
- if (tmp >= 0 && tmp <= 23) {
- NVRAM->alarm.tm_hour = tmp;
- NVRAM->buffer[0x1FF4] = val;
- set_alarm(NVRAM);
- }
- break;
- case 0x1FF5:
- /* alarm date */
- tmp = from_bcd(val & 0x3F);
- if (tmp != 0) {
- NVRAM->alarm.tm_mday = tmp;
- NVRAM->buffer[0x1FF5] = val;
- set_alarm(NVRAM);
- }
- break;
- case 0x1FF6:
- /* interrupts */
- NVRAM->buffer[0x1FF6] = val;
- break;
- case 0x1FF7:
- /* watchdog */
- NVRAM->buffer[0x1FF7] = val;
- set_up_watchdog(NVRAM, val);
- break;
- case 0x1FF8:
- case 0x07F8:
- /* control */
- NVRAM->buffer[addr] = (val & ~0xA0) | 0x90;
- break;
- case 0x1FF9:
- case 0x07F9:
- /* seconds (BCD) */
- tmp = from_bcd(val & 0x7F);
- if (tmp >= 0 && tmp <= 59) {
- get_time(NVRAM, &tm);
- tm.tm_sec = tmp;
- set_time(NVRAM, &tm);
- }
- if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
- if (val & 0x80) {
- NVRAM->stop_time = time(NULL);
- } else {
- NVRAM->time_offset += NVRAM->stop_time - time(NULL);
- NVRAM->stop_time = 0;
- }
- }
- NVRAM->buffer[addr] = val & 0x80;
- break;
- case 0x1FFA:
- case 0x07FA:
- /* minutes (BCD) */
- tmp = from_bcd(val & 0x7F);
- if (tmp >= 0 && tmp <= 59) {
- get_time(NVRAM, &tm);
- tm.tm_min = tmp;
- set_time(NVRAM, &tm);
- }
- break;
- case 0x1FFB:
- case 0x07FB:
- /* hours (BCD) */
- tmp = from_bcd(val & 0x3F);
- if (tmp >= 0 && tmp <= 23) {
- get_time(NVRAM, &tm);
- tm.tm_hour = tmp;
- set_time(NVRAM, &tm);
- }
- break;
- case 0x1FFC:
- case 0x07FC:
- /* day of the week / century */
- tmp = from_bcd(val & 0x07);
- get_time(NVRAM, &tm);
- tm.tm_wday = tmp;
- set_time(NVRAM, &tm);
- NVRAM->buffer[addr] = val & 0x40;
- break;
- case 0x1FFD:
- case 0x07FD:
- /* date (BCD) */
- tmp = from_bcd(val & 0x3F);
- if (tmp != 0) {
- get_time(NVRAM, &tm);
- tm.tm_mday = tmp;
- set_time(NVRAM, &tm);
- }
- break;
- case 0x1FFE:
- case 0x07FE:
- /* month */
- tmp = from_bcd(val & 0x1F);
- if (tmp >= 1 && tmp <= 12) {
- get_time(NVRAM, &tm);
- tm.tm_mon = tmp - 1;
- set_time(NVRAM, &tm);
- }
- break;
- case 0x1FFF:
- case 0x07FF:
- /* year */
- tmp = from_bcd(val);
- if (tmp >= 0 && tmp <= 99) {
- get_time(NVRAM, &tm);
- tm.tm_year = from_bcd(val) + NVRAM->base_year - 1900;
- set_time(NVRAM, &tm);
- }
- break;
- default:
- /* Check lock registers state */
- if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
- break;
- if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
- break;
- do_write:
- if (addr < NVRAM->size) {
- NVRAM->buffer[addr] = val & 0xFF;
- }
- break;
- }
-}
-
-static uint32_t m48t59_read(M48t59State *NVRAM, uint32_t addr)
-{
- struct tm tm;
- uint32_t retval = 0xFF;
-
- /* check for NVRAM access */
- if ((NVRAM->model == 2 && addr < 0x078f) ||
- (NVRAM->model == 8 && addr < 0x1ff8) ||
- (NVRAM->model == 59 && addr < 0x1ff0)) {
- goto do_read;
- }
-
- /* TOD access */
- switch (addr) {
- case 0x1FF0:
- /* flags register */
- goto do_read;
- case 0x1FF1:
- /* unused */
- retval = 0;
- break;
- case 0x1FF2:
- /* alarm seconds */
- goto do_read;
- case 0x1FF3:
- /* alarm minutes */
- goto do_read;
- case 0x1FF4:
- /* alarm hours */
- goto do_read;
- case 0x1FF5:
- /* alarm date */
- goto do_read;
- case 0x1FF6:
- /* interrupts */
- goto do_read;
- case 0x1FF7:
- /* A read resets the watchdog */
- set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
- goto do_read;
- case 0x1FF8:
- case 0x07F8:
- /* control */
- goto do_read;
- case 0x1FF9:
- case 0x07F9:
- /* seconds (BCD) */
- get_time(NVRAM, &tm);
- retval = (NVRAM->buffer[addr] & 0x80) | to_bcd(tm.tm_sec);
- break;
- case 0x1FFA:
- case 0x07FA:
- /* minutes (BCD) */
- get_time(NVRAM, &tm);
- retval = to_bcd(tm.tm_min);
- break;
- case 0x1FFB:
- case 0x07FB:
- /* hours (BCD) */
- get_time(NVRAM, &tm);
- retval = to_bcd(tm.tm_hour);
- break;
- case 0x1FFC:
- case 0x07FC:
- /* day of the week / century */
- get_time(NVRAM, &tm);
- retval = NVRAM->buffer[addr] | tm.tm_wday;
- break;
- case 0x1FFD:
- case 0x07FD:
- /* date */
- get_time(NVRAM, &tm);
- retval = to_bcd(tm.tm_mday);
- break;
- case 0x1FFE:
- case 0x07FE:
- /* month */
- get_time(NVRAM, &tm);
- retval = to_bcd(tm.tm_mon + 1);
- break;
- case 0x1FFF:
- case 0x07FF:
- /* year */
- get_time(NVRAM, &tm);
- retval = to_bcd((tm.tm_year + 1900 - NVRAM->base_year) % 100);
- break;
- default:
- /* Check lock registers state */
- if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
- break;
- if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
- break;
- do_read:
- if (addr < NVRAM->size) {
- retval = NVRAM->buffer[addr];
- }
- break;
- }
- if (addr > 0x1FF9 && addr < 0x2000)
- NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
-
- return retval;
-}
-
-static void m48t59_toggle_lock(M48t59State *NVRAM, int lock)
-{
- NVRAM->lock ^= 1 << lock;
-}
-
-/* IO access to NVRAM */
-static void NVRAM_writeb(void *opaque, hwaddr addr, uint64_t val,
- unsigned size)
-{
- M48t59State *NVRAM = opaque;
-
- NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
- switch (addr) {
- case 0:
- NVRAM->addr &= ~0x00FF;
- NVRAM->addr |= val;
- break;
- case 1:
- NVRAM->addr &= ~0xFF00;
- NVRAM->addr |= val << 8;
- break;
- case 3:
- m48t59_write(NVRAM, NVRAM->addr, val);
- NVRAM->addr = 0x0000;
- break;
- default:
- break;
- }
-}
-
-static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size)
-{
- M48t59State *NVRAM = opaque;
- uint32_t retval;
-
- switch (addr) {
- case 3:
- retval = m48t59_read(NVRAM, NVRAM->addr);
- break;
- default:
- retval = -1;
- break;
- }
- NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
-
- return retval;
-}
-
-static void nvram_writeb (void *opaque, hwaddr addr, uint32_t value)
-{
- M48t59State *NVRAM = opaque;
-
- m48t59_write(NVRAM, addr, value & 0xff);
-}
-
-static void nvram_writew (void *opaque, hwaddr addr, uint32_t value)
-{
- M48t59State *NVRAM = opaque;
-
- m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
- m48t59_write(NVRAM, addr + 1, value & 0xff);
-}
-
-static void nvram_writel (void *opaque, hwaddr addr, uint32_t value)
-{
- M48t59State *NVRAM = opaque;
-
- m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
- m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
- m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
- m48t59_write(NVRAM, addr + 3, value & 0xff);
-}
-
-static uint32_t nvram_readb (void *opaque, hwaddr addr)
-{
- M48t59State *NVRAM = opaque;
-
- return m48t59_read(NVRAM, addr);
-}
-
-static uint32_t nvram_readw (void *opaque, hwaddr addr)
-{
- M48t59State *NVRAM = opaque;
- uint32_t retval;
-
- retval = m48t59_read(NVRAM, addr) << 8;
- retval |= m48t59_read(NVRAM, addr + 1);
- return retval;
-}
-
-static uint32_t nvram_readl (void *opaque, hwaddr addr)
-{
- M48t59State *NVRAM = opaque;
- uint32_t retval;
-
- retval = m48t59_read(NVRAM, addr) << 24;
- retval |= m48t59_read(NVRAM, addr + 1) << 16;
- retval |= m48t59_read(NVRAM, addr + 2) << 8;
- retval |= m48t59_read(NVRAM, addr + 3);
- return retval;
-}
-
-static const MemoryRegionOps nvram_ops = {
- .old_mmio = {
- .read = { nvram_readb, nvram_readw, nvram_readl, },
- .write = { nvram_writeb, nvram_writew, nvram_writel, },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_m48t59 = {
- .name = "m48t59",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(lock, M48t59State),
- VMSTATE_UINT16(addr, M48t59State),
- VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, 0, size),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void m48t59_reset_common(M48t59State *NVRAM)
-{
- NVRAM->addr = 0;
- NVRAM->lock = 0;
- if (NVRAM->alrm_timer != NULL)
- timer_del(NVRAM->alrm_timer);
-
- if (NVRAM->wd_timer != NULL)
- timer_del(NVRAM->wd_timer);
-}
-
-static void m48t59_reset_isa(DeviceState *d)
-{
- M48txxISAState *isa = M48TXX_ISA(d);
- M48t59State *NVRAM = &isa->state;
-
- m48t59_reset_common(NVRAM);
-}
-
-static void m48t59_reset_sysbus(DeviceState *d)
-{
- M48txxSysBusState *sys = M48TXX_SYS_BUS(d);
- M48t59State *NVRAM = &sys->state;
-
- m48t59_reset_common(NVRAM);
-}
-
-static const MemoryRegionOps m48t59_io_ops = {
- .read = NVRAM_readb,
- .write = NVRAM_writeb,
- .impl = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-/* Initialisation routine */
-Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
- uint32_t io_base, uint16_t size, int base_year,
- int model)
-{
- DeviceState *dev;
- SysBusDevice *s;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
- if (!m48txx_info[i].sysbus_name ||
- m48txx_info[i].size != size ||
- m48txx_info[i].model != model) {
- continue;
- }
-
- dev = qdev_create(NULL, m48txx_info[i].sysbus_name);
- qdev_prop_set_int32(dev, "base-year", base_year);
- qdev_init_nofail(dev);
- s = SYS_BUS_DEVICE(dev);
- sysbus_connect_irq(s, 0, IRQ);
- if (io_base != 0) {
- memory_region_add_subregion(get_system_io(), io_base,
- sysbus_mmio_get_region(s, 1));
- }
- if (mem_base != 0) {
- sysbus_mmio_map(s, 0, mem_base);
- }
-
- return NVRAM(s);
- }
-
- assert(false);
- return NULL;
-}
-
-Nvram *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
- int base_year, int model)
-{
- DeviceState *dev;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
- if (!m48txx_info[i].isa_name ||
- m48txx_info[i].size != size ||
- m48txx_info[i].model != model) {
- continue;
- }
-
- dev = DEVICE(isa_create(bus, m48txx_info[i].isa_name));
- qdev_prop_set_uint32(dev, "iobase", io_base);
- qdev_prop_set_int32(dev, "base-year", base_year);
- qdev_init_nofail(dev);
- return NVRAM(dev);
- }
-
- assert(false);
- return NULL;
-}
-
-static void m48t59_realize_common(M48t59State *s, Error **errp)
-{
- s->buffer = g_malloc0(s->size);
- if (s->model == 59) {
- s->alrm_timer = timer_new_ns(rtc_clock, &alarm_cb, s);
- s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s);
- }
- qemu_get_timedate(&s->alarm, 0);
-
- vmstate_register(NULL, -1, &vmstate_m48t59, s);
-}
-
-static void m48t59_isa_realize(DeviceState *dev, Error **errp)
-{
- M48txxISADeviceClass *u = M48TXX_ISA_GET_CLASS(dev);
- ISADevice *isadev = ISA_DEVICE(dev);
- M48txxISAState *d = M48TXX_ISA(dev);
- M48t59State *s = &d->state;
-
- s->model = u->info.model;
- s->size = u->info.size;
- isa_init_irq(isadev, &s->IRQ, 8);
- m48t59_realize_common(s, errp);
- memory_region_init_io(&d->io, OBJECT(dev), &m48t59_io_ops, s, "m48t59", 4);
- if (d->io_base != 0) {
- isa_register_ioport(isadev, &d->io, d->io_base);
- }
-}
-
-static int m48t59_init1(SysBusDevice *dev)
-{
- M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_GET_CLASS(dev);
- M48txxSysBusState *d = M48TXX_SYS_BUS(dev);
- Object *o = OBJECT(dev);
- M48t59State *s = &d->state;
- Error *err = NULL;
-
- s->model = u->info.model;
- s->size = u->info.size;
- sysbus_init_irq(dev, &s->IRQ);
-
- memory_region_init_io(&s->iomem, o, &nvram_ops, s, "m48t59.nvram",
- s->size);
- memory_region_init_io(&d->io, o, &m48t59_io_ops, s, "m48t59", 4);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_mmio(dev, &d->io);
- m48t59_realize_common(s, &err);
- if (err != NULL) {
- error_free(err);
- return -1;
- }
-
- return 0;
-}
-
-static uint32_t m48txx_isa_read(Nvram *obj, uint32_t addr)
-{
- M48txxISAState *d = M48TXX_ISA(obj);
- return m48t59_read(&d->state, addr);
-}
-
-static void m48txx_isa_write(Nvram *obj, uint32_t addr, uint32_t val)
-{
- M48txxISAState *d = M48TXX_ISA(obj);
- m48t59_write(&d->state, addr, val);
-}
-
-static void m48txx_isa_toggle_lock(Nvram *obj, int lock)
-{
- M48txxISAState *d = M48TXX_ISA(obj);
- m48t59_toggle_lock(&d->state, lock);
-}
-
-static Property m48t59_isa_properties[] = {
- DEFINE_PROP_INT32("base-year", M48txxISAState, state.base_year, 0),
- DEFINE_PROP_UINT32("iobase", M48txxISAState, io_base, 0x74),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void m48txx_isa_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- NvramClass *nc = NVRAM_CLASS(klass);
-
- dc->realize = m48t59_isa_realize;
- dc->reset = m48t59_reset_isa;
- dc->props = m48t59_isa_properties;
- nc->read = m48txx_isa_read;
- nc->write = m48txx_isa_write;
- nc->toggle_lock = m48txx_isa_toggle_lock;
-}
-
-static void m48txx_isa_concrete_class_init(ObjectClass *klass, void *data)
-{
- M48txxISADeviceClass *u = M48TXX_ISA_CLASS(klass);
- M48txxInfo *info = data;
-
- u->info = *info;
-}
-
-static uint32_t m48txx_sysbus_read(Nvram *obj, uint32_t addr)
-{
- M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
- return m48t59_read(&d->state, addr);
-}
-
-static void m48txx_sysbus_write(Nvram *obj, uint32_t addr, uint32_t val)
-{
- M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
- m48t59_write(&d->state, addr, val);
-}
-
-static void m48txx_sysbus_toggle_lock(Nvram *obj, int lock)
-{
- M48txxSysBusState *d = M48TXX_SYS_BUS(obj);
- m48t59_toggle_lock(&d->state, lock);
-}
-
-static Property m48t59_sysbus_properties[] = {
- DEFINE_PROP_INT32("base-year", M48txxSysBusState, state.base_year, 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void m48txx_sysbus_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- NvramClass *nc = NVRAM_CLASS(klass);
-
- k->init = m48t59_init1;
- dc->reset = m48t59_reset_sysbus;
- dc->props = m48t59_sysbus_properties;
- nc->read = m48txx_sysbus_read;
- nc->write = m48txx_sysbus_write;
- nc->toggle_lock = m48txx_sysbus_toggle_lock;
-}
-
-static void m48txx_sysbus_concrete_class_init(ObjectClass *klass, void *data)
-{
- M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass);
- M48txxInfo *info = data;
-
- u->info = *info;
-}
-
-static const TypeInfo nvram_info = {
- .name = TYPE_NVRAM,
- .parent = TYPE_INTERFACE,
- .class_size = sizeof(NvramClass),
-};
-
-static const TypeInfo m48txx_sysbus_type_info = {
- .name = TYPE_M48TXX_SYS_BUS,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(M48txxSysBusState),
- .abstract = true,
- .class_init = m48txx_sysbus_class_init,
- .interfaces = (InterfaceInfo[]) {
- { TYPE_NVRAM },
- { }
- }
-};
-
-static const TypeInfo m48txx_isa_type_info = {
- .name = TYPE_M48TXX_ISA,
- .parent = TYPE_ISA_DEVICE,
- .instance_size = sizeof(M48txxISAState),
- .abstract = true,
- .class_init = m48txx_isa_class_init,
- .interfaces = (InterfaceInfo[]) {
- { TYPE_NVRAM },
- { }
- }
-};
-
-static void m48t59_register_types(void)
-{
- TypeInfo sysbus_type_info = {
- .parent = TYPE_M48TXX_SYS_BUS,
- .class_size = sizeof(M48txxSysBusDeviceClass),
- .class_init = m48txx_sysbus_concrete_class_init,
- };
- TypeInfo isa_type_info = {
- .parent = TYPE_M48TXX_ISA,
- .class_size = sizeof(M48txxISADeviceClass),
- .class_init = m48txx_isa_concrete_class_init,
- };
- int i;
-
- type_register_static(&nvram_info);
- type_register_static(&m48txx_sysbus_type_info);
- type_register_static(&m48txx_isa_type_info);
-
- for (i = 0; i < ARRAY_SIZE(m48txx_info); i++) {
- if (m48txx_info[i].sysbus_name) {
- sysbus_type_info.name = m48txx_info[i].sysbus_name;
- sysbus_type_info.class_data = &m48txx_info[i];
- type_register(&sysbus_type_info);
- }
-
- if (m48txx_info[i].isa_name) {
- isa_type_info.name = m48txx_info[i].isa_name;
- isa_type_info.class_data = &m48txx_info[i];
- type_register(&isa_type_info);
- }
- }
-}
-
-type_init(m48t59_register_types)
diff --git a/qemu/hw/timer/mc146818rtc.c b/qemu/hw/timer/mc146818rtc.c
deleted file mode 100644
index 2ac0fd3e4..000000000
--- a/qemu/hw/timer/mc146818rtc.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/*
- * QEMU MC146818 RTC emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * 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 "qemu/osdep.h"
-#include "config-target.h"
-#include "qemu/cutils.h"
-#include "qemu/bcd.h"
-#include "hw/hw.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "hw/timer/mc146818rtc.h"
-#include "qapi/visitor.h"
-#include "qapi-event.h"
-#include "qmp-commands.h"
-
-#ifdef TARGET_I386
-#include "hw/i386/apic.h"
-#endif
-
-//#define DEBUG_CMOS
-//#define DEBUG_COALESCED
-
-#ifdef DEBUG_CMOS
-# define CMOS_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
-#else
-# define CMOS_DPRINTF(format, ...) do { } while (0)
-#endif
-
-#ifdef DEBUG_COALESCED
-# define DPRINTF_C(format, ...) printf(format, ## __VA_ARGS__)
-#else
-# define DPRINTF_C(format, ...) do { } while (0)
-#endif
-
-#define SEC_PER_MIN 60
-#define MIN_PER_HOUR 60
-#define SEC_PER_HOUR 3600
-#define HOUR_PER_DAY 24
-#define SEC_PER_DAY 86400
-
-#define RTC_REINJECT_ON_ACK_COUNT 20
-#define RTC_CLOCK_RATE 32768
-#define UIP_HOLD_LENGTH (8 * NANOSECONDS_PER_SECOND / 32768)
-
-#define MC146818_RTC(obj) OBJECT_CHECK(RTCState, (obj), TYPE_MC146818_RTC)
-
-typedef struct RTCState {
- ISADevice parent_obj;
-
- MemoryRegion io;
- uint8_t cmos_data[128];
- uint8_t cmos_index;
- int32_t base_year;
- uint64_t base_rtc;
- uint64_t last_update;
- int64_t offset;
- qemu_irq irq;
- int it_shift;
- /* periodic timer */
- QEMUTimer *periodic_timer;
- int64_t next_periodic_time;
- /* update-ended timer */
- QEMUTimer *update_timer;
- uint64_t next_alarm_time;
- uint16_t irq_reinject_on_ack_count;
- uint32_t irq_coalesced;
- uint32_t period;
- QEMUTimer *coalesced_timer;
- Notifier clock_reset_notifier;
- LostTickPolicy lost_tick_policy;
- Notifier suspend_notifier;
- QLIST_ENTRY(RTCState) link;
-} RTCState;
-
-static void rtc_set_time(RTCState *s);
-static void rtc_update_time(RTCState *s);
-static void rtc_set_cmos(RTCState *s, const struct tm *tm);
-static inline int rtc_from_bcd(RTCState *s, int a);
-static uint64_t get_next_alarm(RTCState *s);
-
-static inline bool rtc_running(RTCState *s)
-{
- return (!(s->cmos_data[RTC_REG_B] & REG_B_SET) &&
- (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20);
-}
-
-static uint64_t get_guest_rtc_ns(RTCState *s)
-{
- uint64_t guest_rtc;
- uint64_t guest_clock = qemu_clock_get_ns(rtc_clock);
-
- guest_rtc = s->base_rtc * NANOSECONDS_PER_SECOND +
- guest_clock - s->last_update + s->offset;
- return guest_rtc;
-}
-
-#ifdef TARGET_I386
-static void rtc_coalesced_timer_update(RTCState *s)
-{
- if (s->irq_coalesced == 0) {
- timer_del(s->coalesced_timer);
- } else {
- /* divide each RTC interval to 2 - 8 smaller intervals */
- int c = MIN(s->irq_coalesced, 7) + 1;
- int64_t next_clock = qemu_clock_get_ns(rtc_clock) +
- muldiv64(s->period / c, NANOSECONDS_PER_SECOND, RTC_CLOCK_RATE);
- timer_mod(s->coalesced_timer, next_clock);
- }
-}
-
-static void rtc_coalesced_timer(void *opaque)
-{
- RTCState *s = opaque;
-
- if (s->irq_coalesced != 0) {
- apic_reset_irq_delivered();
- s->cmos_data[RTC_REG_C] |= 0xc0;
- DPRINTF_C("cmos: injecting from timer\n");
- qemu_irq_raise(s->irq);
- if (apic_get_irq_delivered()) {
- s->irq_coalesced--;
- DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
- s->irq_coalesced);
- }
- }
-
- rtc_coalesced_timer_update(s);
-}
-#endif
-
-/* handle periodic timer */
-static void periodic_timer_update(RTCState *s, int64_t current_time)
-{
- int period_code, period;
- int64_t cur_clock, next_irq_clock;
-
- period_code = s->cmos_data[RTC_REG_A] & 0x0f;
- if (period_code != 0
- && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
- if (period_code <= 2)
- period_code += 7;
- /* period in 32 Khz cycles */
- period = 1 << (period_code - 1);
-#ifdef TARGET_I386
- if (period != s->period) {
- s->irq_coalesced = (s->irq_coalesced * s->period) / period;
- DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
- }
- s->period = period;
-#endif
- /* compute 32 khz clock */
- cur_clock =
- muldiv64(current_time, RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
-
- next_irq_clock = (cur_clock & ~(period - 1)) + period;
- s->next_periodic_time = muldiv64(next_irq_clock, NANOSECONDS_PER_SECOND,
- RTC_CLOCK_RATE) + 1;
- timer_mod(s->periodic_timer, s->next_periodic_time);
- } else {
-#ifdef TARGET_I386
- s->irq_coalesced = 0;
-#endif
- timer_del(s->periodic_timer);
- }
-}
-
-static void rtc_periodic_timer(void *opaque)
-{
- RTCState *s = opaque;
-
- periodic_timer_update(s, s->next_periodic_time);
- s->cmos_data[RTC_REG_C] |= REG_C_PF;
- if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
- s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
-#ifdef TARGET_I386
- if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
- if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
- s->irq_reinject_on_ack_count = 0;
- apic_reset_irq_delivered();
- qemu_irq_raise(s->irq);
- if (!apic_get_irq_delivered()) {
- s->irq_coalesced++;
- rtc_coalesced_timer_update(s);
- DPRINTF_C("cmos: coalesced irqs increased to %d\n",
- s->irq_coalesced);
- }
- } else
-#endif
- qemu_irq_raise(s->irq);
- }
-}
-
-/* handle update-ended timer */
-static void check_update_timer(RTCState *s)
-{
- uint64_t next_update_time;
- uint64_t guest_nsec;
- int next_alarm_sec;
-
- /* From the data sheet: "Holding the dividers in reset prevents
- * interrupts from operating, while setting the SET bit allows"
- * them to occur. However, it will prevent an alarm interrupt
- * from occurring, because the time of day is not updated.
- */
- if ((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) {
- timer_del(s->update_timer);
- return;
- }
- if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
- (s->cmos_data[RTC_REG_B] & REG_B_SET)) {
- timer_del(s->update_timer);
- return;
- }
- if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
- (s->cmos_data[RTC_REG_C] & REG_C_AF)) {
- timer_del(s->update_timer);
- return;
- }
-
- guest_nsec = get_guest_rtc_ns(s) % NANOSECONDS_PER_SECOND;
- /* if UF is clear, reprogram to next second */
- next_update_time = qemu_clock_get_ns(rtc_clock)
- + NANOSECONDS_PER_SECOND - guest_nsec;
-
- /* Compute time of next alarm. One second is already accounted
- * for in next_update_time.
- */
- next_alarm_sec = get_next_alarm(s);
- s->next_alarm_time = next_update_time +
- (next_alarm_sec - 1) * NANOSECONDS_PER_SECOND;
-
- if (s->cmos_data[RTC_REG_C] & REG_C_UF) {
- /* UF is set, but AF is clear. Program the timer to target
- * the alarm time. */
- next_update_time = s->next_alarm_time;
- }
- if (next_update_time != timer_expire_time_ns(s->update_timer)) {
- timer_mod(s->update_timer, next_update_time);
- }
-}
-
-static inline uint8_t convert_hour(RTCState *s, uint8_t hour)
-{
- if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
- hour %= 12;
- if (s->cmos_data[RTC_HOURS] & 0x80) {
- hour += 12;
- }
- }
- return hour;
-}
-
-static uint64_t get_next_alarm(RTCState *s)
-{
- int32_t alarm_sec, alarm_min, alarm_hour, cur_hour, cur_min, cur_sec;
- int32_t hour, min, sec;
-
- rtc_update_time(s);
-
- alarm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]);
- alarm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]);
- alarm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]);
- alarm_hour = alarm_hour == -1 ? -1 : convert_hour(s, alarm_hour);
-
- cur_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
- cur_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
- cur_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS]);
- cur_hour = convert_hour(s, cur_hour);
-
- if (alarm_hour == -1) {
- alarm_hour = cur_hour;
- if (alarm_min == -1) {
- alarm_min = cur_min;
- if (alarm_sec == -1) {
- alarm_sec = cur_sec + 1;
- } else if (cur_sec > alarm_sec) {
- alarm_min++;
- }
- } else if (cur_min == alarm_min) {
- if (alarm_sec == -1) {
- alarm_sec = cur_sec + 1;
- } else {
- if (cur_sec > alarm_sec) {
- alarm_hour++;
- }
- }
- if (alarm_sec == SEC_PER_MIN) {
- /* wrap to next hour, minutes is not in don't care mode */
- alarm_sec = 0;
- alarm_hour++;
- }
- } else if (cur_min > alarm_min) {
- alarm_hour++;
- }
- } else if (cur_hour == alarm_hour) {
- if (alarm_min == -1) {
- alarm_min = cur_min;
- if (alarm_sec == -1) {
- alarm_sec = cur_sec + 1;
- } else if (cur_sec > alarm_sec) {
- alarm_min++;
- }
-
- if (alarm_sec == SEC_PER_MIN) {
- alarm_sec = 0;
- alarm_min++;
- }
- /* wrap to next day, hour is not in don't care mode */
- alarm_min %= MIN_PER_HOUR;
- } else if (cur_min == alarm_min) {
- if (alarm_sec == -1) {
- alarm_sec = cur_sec + 1;
- }
- /* wrap to next day, hours+minutes not in don't care mode */
- alarm_sec %= SEC_PER_MIN;
- }
- }
-
- /* values that are still don't care fire at the next min/sec */
- if (alarm_min == -1) {
- alarm_min = 0;
- }
- if (alarm_sec == -1) {
- alarm_sec = 0;
- }
-
- /* keep values in range */
- if (alarm_sec == SEC_PER_MIN) {
- alarm_sec = 0;
- alarm_min++;
- }
- if (alarm_min == MIN_PER_HOUR) {
- alarm_min = 0;
- alarm_hour++;
- }
- alarm_hour %= HOUR_PER_DAY;
-
- hour = alarm_hour - cur_hour;
- min = hour * MIN_PER_HOUR + alarm_min - cur_min;
- sec = min * SEC_PER_MIN + alarm_sec - cur_sec;
- return sec <= 0 ? sec + SEC_PER_DAY : sec;
-}
-
-static void rtc_update_timer(void *opaque)
-{
- RTCState *s = opaque;
- int32_t irqs = REG_C_UF;
- int32_t new_irqs;
-
- assert((s->cmos_data[RTC_REG_A] & 0x60) != 0x60);
-
- /* UIP might have been latched, update time and clear it. */
- rtc_update_time(s);
- s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
-
- if (qemu_clock_get_ns(rtc_clock) >= s->next_alarm_time) {
- irqs |= REG_C_AF;
- if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
- qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
- }
- }
-
- new_irqs = irqs & ~s->cmos_data[RTC_REG_C];
- s->cmos_data[RTC_REG_C] |= irqs;
- if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) {
- s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
- qemu_irq_raise(s->irq);
- }
- check_update_timer(s);
-}
-
-static void cmos_ioport_write(void *opaque, hwaddr addr,
- uint64_t data, unsigned size)
-{
- RTCState *s = opaque;
-
- if ((addr & 1) == 0) {
- s->cmos_index = data & 0x7f;
- } else {
- CMOS_DPRINTF("cmos: write index=0x%02x val=0x%02" PRIx64 "\n",
- s->cmos_index, data);
- switch(s->cmos_index) {
- case RTC_SECONDS_ALARM:
- case RTC_MINUTES_ALARM:
- case RTC_HOURS_ALARM:
- s->cmos_data[s->cmos_index] = data;
- check_update_timer(s);
- break;
- case RTC_IBM_PS2_CENTURY_BYTE:
- s->cmos_index = RTC_CENTURY;
- /* fall through */
- case RTC_CENTURY:
- case RTC_SECONDS:
- case RTC_MINUTES:
- case RTC_HOURS:
- case RTC_DAY_OF_WEEK:
- case RTC_DAY_OF_MONTH:
- case RTC_MONTH:
- case RTC_YEAR:
- s->cmos_data[s->cmos_index] = data;
- /* if in set mode, do not update the time */
- if (rtc_running(s)) {
- rtc_set_time(s);
- check_update_timer(s);
- }
- break;
- case RTC_REG_A:
- if ((data & 0x60) == 0x60) {
- if (rtc_running(s)) {
- rtc_update_time(s);
- }
- /* What happens to UIP when divider reset is enabled is
- * unclear from the datasheet. Shouldn't matter much
- * though.
- */
- s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
- } else if (((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) &&
- (data & 0x70) <= 0x20) {
- /* when the divider reset is removed, the first update cycle
- * begins one-half second later*/
- if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
- s->offset = 500000000;
- rtc_set_time(s);
- }
- s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
- }
- /* UIP bit is read only */
- s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
- (s->cmos_data[RTC_REG_A] & REG_A_UIP);
- periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
- check_update_timer(s);
- break;
- case RTC_REG_B:
- if (data & REG_B_SET) {
- /* update cmos to when the rtc was stopping */
- if (rtc_running(s)) {
- rtc_update_time(s);
- }
- /* set mode: reset UIP mode */
- s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
- data &= ~REG_B_UIE;
- } else {
- /* if disabling set mode, update the time */
- if ((s->cmos_data[RTC_REG_B] & REG_B_SET) &&
- (s->cmos_data[RTC_REG_A] & 0x70) <= 0x20) {
- s->offset = get_guest_rtc_ns(s) % NANOSECONDS_PER_SECOND;
- rtc_set_time(s);
- }
- }
- /* if an interrupt flag is already set when the interrupt
- * becomes enabled, raise an interrupt immediately. */
- if (data & s->cmos_data[RTC_REG_C] & REG_C_MASK) {
- s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
- qemu_irq_raise(s->irq);
- } else {
- s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF;
- qemu_irq_lower(s->irq);
- }
- s->cmos_data[RTC_REG_B] = data;
- periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
- check_update_timer(s);
- break;
- case RTC_REG_C:
- case RTC_REG_D:
- /* cannot write to them */
- break;
- default:
- s->cmos_data[s->cmos_index] = data;
- break;
- }
- }
-}
-
-static inline int rtc_to_bcd(RTCState *s, int a)
-{
- if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
- return a;
- } else {
- return ((a / 10) << 4) | (a % 10);
- }
-}
-
-static inline int rtc_from_bcd(RTCState *s, int a)
-{
- if ((a & 0xc0) == 0xc0) {
- return -1;
- }
- if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
- return a;
- } else {
- return ((a >> 4) * 10) + (a & 0x0f);
- }
-}
-
-static void rtc_get_time(RTCState *s, struct tm *tm)
-{
- tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
- tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
- tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
- if (!(s->cmos_data[RTC_REG_B] & REG_B_24H)) {
- tm->tm_hour %= 12;
- if (s->cmos_data[RTC_HOURS] & 0x80) {
- tm->tm_hour += 12;
- }
- }
- tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
- tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
- tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
- tm->tm_year =
- rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year +
- rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900;
-}
-
-static QLIST_HEAD(, RTCState) rtc_devices =
- QLIST_HEAD_INITIALIZER(rtc_devices);
-
-#ifdef TARGET_I386
-void qmp_rtc_reset_reinjection(Error **errp)
-{
- RTCState *s;
-
- QLIST_FOREACH(s, &rtc_devices, link) {
- s->irq_coalesced = 0;
- }
-}
-#endif
-
-static void rtc_set_time(RTCState *s)
-{
- struct tm tm;
-
- rtc_get_time(s, &tm);
- s->base_rtc = mktimegm(&tm);
- s->last_update = qemu_clock_get_ns(rtc_clock);
-
- qapi_event_send_rtc_change(qemu_timedate_diff(&tm), &error_abort);
-}
-
-static void rtc_set_cmos(RTCState *s, const struct tm *tm)
-{
- int year;
-
- s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
- s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
- if (s->cmos_data[RTC_REG_B] & REG_B_24H) {
- /* 24 hour format */
- s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
- } else {
- /* 12 hour format */
- int h = (tm->tm_hour % 12) ? tm->tm_hour % 12 : 12;
- s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, h);
- if (tm->tm_hour >= 12)
- s->cmos_data[RTC_HOURS] |= 0x80;
- }
- s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1);
- s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday);
- s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1);
- year = tm->tm_year + 1900 - s->base_year;
- s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year % 100);
- s->cmos_data[RTC_CENTURY] = rtc_to_bcd(s, year / 100);
-}
-
-static void rtc_update_time(RTCState *s)
-{
- struct tm ret;
- time_t guest_sec;
- int64_t guest_nsec;
-
- guest_nsec = get_guest_rtc_ns(s);
- guest_sec = guest_nsec / NANOSECONDS_PER_SECOND;
- gmtime_r(&guest_sec, &ret);
-
- /* Is SET flag of Register B disabled? */
- if ((s->cmos_data[RTC_REG_B] & REG_B_SET) == 0) {
- rtc_set_cmos(s, &ret);
- }
-}
-
-static int update_in_progress(RTCState *s)
-{
- int64_t guest_nsec;
-
- if (!rtc_running(s)) {
- return 0;
- }
- if (timer_pending(s->update_timer)) {
- int64_t next_update_time = timer_expire_time_ns(s->update_timer);
- /* Latch UIP until the timer expires. */
- if (qemu_clock_get_ns(rtc_clock) >=
- (next_update_time - UIP_HOLD_LENGTH)) {
- s->cmos_data[RTC_REG_A] |= REG_A_UIP;
- return 1;
- }
- }
-
- guest_nsec = get_guest_rtc_ns(s);
- /* UIP bit will be set at last 244us of every second. */
- if ((guest_nsec % NANOSECONDS_PER_SECOND) >=
- (NANOSECONDS_PER_SECOND - UIP_HOLD_LENGTH)) {
- return 1;
- }
- return 0;
-}
-
-static uint64_t cmos_ioport_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- RTCState *s = opaque;
- int ret;
- if ((addr & 1) == 0) {
- return 0xff;
- } else {
- switch(s->cmos_index) {
- case RTC_IBM_PS2_CENTURY_BYTE:
- s->cmos_index = RTC_CENTURY;
- /* fall through */
- case RTC_CENTURY:
- case RTC_SECONDS:
- case RTC_MINUTES:
- case RTC_HOURS:
- case RTC_DAY_OF_WEEK:
- case RTC_DAY_OF_MONTH:
- case RTC_MONTH:
- case RTC_YEAR:
- /* if not in set mode, calibrate cmos before
- * reading*/
- if (rtc_running(s)) {
- rtc_update_time(s);
- }
- ret = s->cmos_data[s->cmos_index];
- break;
- case RTC_REG_A:
- if (update_in_progress(s)) {
- s->cmos_data[s->cmos_index] |= REG_A_UIP;
- } else {
- s->cmos_data[s->cmos_index] &= ~REG_A_UIP;
- }
- ret = s->cmos_data[s->cmos_index];
- break;
- case RTC_REG_C:
- ret = s->cmos_data[s->cmos_index];
- qemu_irq_lower(s->irq);
- s->cmos_data[RTC_REG_C] = 0x00;
- if (ret & (REG_C_UF | REG_C_AF)) {
- check_update_timer(s);
- }
-#ifdef TARGET_I386
- if(s->irq_coalesced &&
- (s->cmos_data[RTC_REG_B] & REG_B_PIE) &&
- s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
- s->irq_reinject_on_ack_count++;
- s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF;
- apic_reset_irq_delivered();
- DPRINTF_C("cmos: injecting on ack\n");
- qemu_irq_raise(s->irq);
- if (apic_get_irq_delivered()) {
- s->irq_coalesced--;
- DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
- s->irq_coalesced);
- }
- }
-#endif
- break;
- default:
- ret = s->cmos_data[s->cmos_index];
- break;
- }
- CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n",
- s->cmos_index, ret);
- return ret;
- }
-}
-
-void rtc_set_memory(ISADevice *dev, int addr, int val)
-{
- RTCState *s = MC146818_RTC(dev);
- if (addr >= 0 && addr <= 127)
- s->cmos_data[addr] = val;
-}
-
-int rtc_get_memory(ISADevice *dev, int addr)
-{
- RTCState *s = MC146818_RTC(dev);
- assert(addr >= 0 && addr <= 127);
- return s->cmos_data[addr];
-}
-
-static void rtc_set_date_from_host(ISADevice *dev)
-{
- RTCState *s = MC146818_RTC(dev);
- struct tm tm;
-
- qemu_get_timedate(&tm, 0);
-
- s->base_rtc = mktimegm(&tm);
- s->last_update = qemu_clock_get_ns(rtc_clock);
- s->offset = 0;
-
- /* set the CMOS date */
- rtc_set_cmos(s, &tm);
-}
-
-static int rtc_post_load(void *opaque, int version_id)
-{
- RTCState *s = opaque;
-
- if (version_id <= 2) {
- rtc_set_time(s);
- s->offset = 0;
- check_update_timer(s);
- }
-
- uint64_t now = qemu_clock_get_ns(rtc_clock);
- if (now < s->next_periodic_time ||
- now > (s->next_periodic_time + get_max_clock_jump())) {
- periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
- }
-
-#ifdef TARGET_I386
- if (version_id >= 2) {
- if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
- rtc_coalesced_timer_update(s);
- }
- }
-#endif
- return 0;
-}
-
-static bool rtc_irq_reinject_on_ack_count_needed(void *opaque)
-{
- RTCState *s = (RTCState *)opaque;
- return s->irq_reinject_on_ack_count != 0;
-}
-
-static const VMStateDescription vmstate_rtc_irq_reinject_on_ack_count = {
- .name = "mc146818rtc/irq_reinject_on_ack_count",
- .version_id = 1,
- .minimum_version_id = 1,
- .needed = rtc_irq_reinject_on_ack_count_needed,
- .fields = (VMStateField[]) {
- VMSTATE_UINT16(irq_reinject_on_ack_count, RTCState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_rtc = {
- .name = "mc146818rtc",
- .version_id = 3,
- .minimum_version_id = 1,
- .post_load = rtc_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_BUFFER(cmos_data, RTCState),
- VMSTATE_UINT8(cmos_index, RTCState),
- VMSTATE_UNUSED(7*4),
- VMSTATE_TIMER_PTR(periodic_timer, RTCState),
- VMSTATE_INT64(next_periodic_time, RTCState),
- VMSTATE_UNUSED(3*8),
- VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
- VMSTATE_UINT32_V(period, RTCState, 2),
- VMSTATE_UINT64_V(base_rtc, RTCState, 3),
- VMSTATE_UINT64_V(last_update, RTCState, 3),
- VMSTATE_INT64_V(offset, RTCState, 3),
- VMSTATE_TIMER_PTR_V(update_timer, RTCState, 3),
- VMSTATE_UINT64_V(next_alarm_time, RTCState, 3),
- VMSTATE_END_OF_LIST()
- },
- .subsections = (const VMStateDescription*[]) {
- &vmstate_rtc_irq_reinject_on_ack_count,
- NULL
- }
-};
-
-static void rtc_notify_clock_reset(Notifier *notifier, void *data)
-{
- RTCState *s = container_of(notifier, RTCState, clock_reset_notifier);
- int64_t now = *(int64_t *)data;
-
- rtc_set_date_from_host(ISA_DEVICE(s));
- periodic_timer_update(s, now);
- check_update_timer(s);
-#ifdef TARGET_I386
- if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
- rtc_coalesced_timer_update(s);
- }
-#endif
-}
-
-/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
- BIOS will read it and start S3 resume at POST Entry */
-static void rtc_notify_suspend(Notifier *notifier, void *data)
-{
- RTCState *s = container_of(notifier, RTCState, suspend_notifier);
- rtc_set_memory(ISA_DEVICE(s), 0xF, 0xFE);
-}
-
-static void rtc_reset(void *opaque)
-{
- RTCState *s = opaque;
-
- s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
- s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
- check_update_timer(s);
-
- qemu_irq_lower(s->irq);
-
-#ifdef TARGET_I386
- if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {
- s->irq_coalesced = 0;
- s->irq_reinject_on_ack_count = 0;
- }
-#endif
-}
-
-static const MemoryRegionOps cmos_ops = {
- .read = cmos_ioport_read,
- .write = cmos_ioport_write,
- .impl = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void rtc_get_date(Object *obj, struct tm *current_tm, Error **errp)
-{
- RTCState *s = MC146818_RTC(obj);
-
- rtc_update_time(s);
- rtc_get_time(s, current_tm);
-}
-
-static void rtc_realizefn(DeviceState *dev, Error **errp)
-{
- ISADevice *isadev = ISA_DEVICE(dev);
- RTCState *s = MC146818_RTC(dev);
- int base = 0x70;
-
- s->cmos_data[RTC_REG_A] = 0x26;
- s->cmos_data[RTC_REG_B] = 0x02;
- s->cmos_data[RTC_REG_C] = 0x00;
- s->cmos_data[RTC_REG_D] = 0x80;
-
- /* This is for historical reasons. The default base year qdev property
- * was set to 2000 for most machine types before the century byte was
- * implemented.
- *
- * This if statement means that the century byte will be always 0
- * (at least until 2079...) for base_year = 1980, but will be set
- * correctly for base_year = 2000.
- */
- if (s->base_year == 2000) {
- s->base_year = 0;
- }
-
- rtc_set_date_from_host(isadev);
-
-#ifdef TARGET_I386
- switch (s->lost_tick_policy) {
- case LOST_TICK_POLICY_SLEW:
- s->coalesced_timer =
- timer_new_ns(rtc_clock, rtc_coalesced_timer, s);
- break;
- case LOST_TICK_POLICY_DISCARD:
- break;
- default:
- error_setg(errp, "Invalid lost tick policy.");
- return;
- }
-#endif
-
- s->periodic_timer = timer_new_ns(rtc_clock, rtc_periodic_timer, s);
- s->update_timer = timer_new_ns(rtc_clock, rtc_update_timer, s);
- check_update_timer(s);
-
- s->clock_reset_notifier.notify = rtc_notify_clock_reset;
- qemu_clock_register_reset_notifier(rtc_clock,
- &s->clock_reset_notifier);
-
- s->suspend_notifier.notify = rtc_notify_suspend;
- qemu_register_suspend_notifier(&s->suspend_notifier);
-
- memory_region_init_io(&s->io, OBJECT(s), &cmos_ops, s, "rtc", 2);
- isa_register_ioport(isadev, &s->io, base);
-
- qdev_set_legacy_instance_id(dev, base, 3);
- qemu_register_reset(rtc_reset, s);
-
- object_property_add_tm(OBJECT(s), "date", rtc_get_date, NULL);
-
- object_property_add_alias(qdev_get_machine(), "rtc-time",
- OBJECT(s), "date", NULL);
-}
-
-ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
-{
- DeviceState *dev;
- ISADevice *isadev;
- RTCState *s;
-
- isadev = isa_create(bus, TYPE_MC146818_RTC);
- dev = DEVICE(isadev);
- s = MC146818_RTC(isadev);
- qdev_prop_set_int32(dev, "base_year", base_year);
- qdev_init_nofail(dev);
- if (intercept_irq) {
- s->irq = intercept_irq;
- } else {
- isa_init_irq(isadev, &s->irq, RTC_ISA_IRQ);
- }
- QLIST_INSERT_HEAD(&rtc_devices, s, link);
-
- return isadev;
-}
-
-static Property mc146818rtc_properties[] = {
- DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
- DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", RTCState,
- lost_tick_policy, LOST_TICK_POLICY_DISCARD),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void rtc_class_initfn(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = rtc_realizefn;
- dc->vmsd = &vmstate_rtc;
- dc->props = mc146818rtc_properties;
- /* Reason: needs to be wired up by rtc_init() */
- dc->cannot_instantiate_with_device_add_yet = true;
-}
-
-static void rtc_finalize(Object *obj)
-{
- object_property_del(qdev_get_machine(), "rtc", NULL);
-}
-
-static const TypeInfo mc146818rtc_info = {
- .name = TYPE_MC146818_RTC,
- .parent = TYPE_ISA_DEVICE,
- .instance_size = sizeof(RTCState),
- .class_init = rtc_class_initfn,
- .instance_finalize = rtc_finalize,
-};
-
-static void mc146818rtc_register_types(void)
-{
- type_register_static(&mc146818rtc_info);
-}
-
-type_init(mc146818rtc_register_types)
diff --git a/qemu/hw/timer/milkymist-sysctl.c b/qemu/hw/timer/milkymist-sysctl.c
deleted file mode 100644
index 5f2948037..000000000
--- a/qemu/hw/timer/milkymist-sysctl.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * QEMU model of the Milkymist System Controller.
- *
- * Copyright (c) 2010-2012 Michael Walle <michael@walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- *
- * Specification available at:
- * http://www.milkymist.org/socdoc/sysctl.pdf
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "sysemu/sysemu.h"
-#include "trace.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "qemu/error-report.h"
-
-enum {
- CTRL_ENABLE = (1<<0),
- CTRL_AUTORESTART = (1<<1),
-};
-
-enum {
- ICAP_READY = (1<<0),
-};
-
-enum {
- R_GPIO_IN = 0,
- R_GPIO_OUT,
- R_GPIO_INTEN,
- R_TIMER0_CONTROL = 4,
- R_TIMER0_COMPARE,
- R_TIMER0_COUNTER,
- R_TIMER1_CONTROL = 8,
- R_TIMER1_COMPARE,
- R_TIMER1_COUNTER,
- R_ICAP = 16,
- R_DBG_SCRATCHPAD = 20,
- R_DBG_WRITE_LOCK,
- R_CLK_FREQUENCY = 29,
- R_CAPABILITIES,
- R_SYSTEM_ID,
- R_MAX
-};
-
-#define TYPE_MILKYMIST_SYSCTL "milkymist-sysctl"
-#define MILKYMIST_SYSCTL(obj) \
- OBJECT_CHECK(MilkymistSysctlState, (obj), TYPE_MILKYMIST_SYSCTL)
-
-struct MilkymistSysctlState {
- SysBusDevice parent_obj;
-
- MemoryRegion regs_region;
-
- QEMUBH *bh0;
- QEMUBH *bh1;
- ptimer_state *ptimer0;
- ptimer_state *ptimer1;
-
- uint32_t freq_hz;
- uint32_t capabilities;
- uint32_t systemid;
- uint32_t strappings;
-
- uint32_t regs[R_MAX];
-
- qemu_irq gpio_irq;
- qemu_irq timer0_irq;
- qemu_irq timer1_irq;
-};
-typedef struct MilkymistSysctlState MilkymistSysctlState;
-
-static void sysctl_icap_write(MilkymistSysctlState *s, uint32_t value)
-{
- trace_milkymist_sysctl_icap_write(value);
- switch (value & 0xffff) {
- case 0x000e:
- qemu_system_shutdown_request();
- break;
- }
-}
-
-static uint64_t sysctl_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- MilkymistSysctlState *s = opaque;
- uint32_t r = 0;
-
- addr >>= 2;
- switch (addr) {
- case R_TIMER0_COUNTER:
- r = (uint32_t)ptimer_get_count(s->ptimer0);
- /* milkymist timer counts up */
- r = s->regs[R_TIMER0_COMPARE] - r;
- break;
- case R_TIMER1_COUNTER:
- r = (uint32_t)ptimer_get_count(s->ptimer1);
- /* milkymist timer counts up */
- r = s->regs[R_TIMER1_COMPARE] - r;
- break;
- case R_GPIO_IN:
- case R_GPIO_OUT:
- case R_GPIO_INTEN:
- case R_TIMER0_CONTROL:
- case R_TIMER0_COMPARE:
- case R_TIMER1_CONTROL:
- case R_TIMER1_COMPARE:
- case R_ICAP:
- case R_DBG_SCRATCHPAD:
- case R_DBG_WRITE_LOCK:
- case R_CLK_FREQUENCY:
- case R_CAPABILITIES:
- case R_SYSTEM_ID:
- r = s->regs[addr];
- break;
-
- default:
- error_report("milkymist_sysctl: read access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- }
-
- trace_milkymist_sysctl_memory_read(addr << 2, r);
-
- return r;
-}
-
-static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
- unsigned size)
-{
- MilkymistSysctlState *s = opaque;
-
- trace_milkymist_sysctl_memory_write(addr, value);
-
- addr >>= 2;
- switch (addr) {
- case R_GPIO_OUT:
- case R_GPIO_INTEN:
- case R_TIMER0_COUNTER:
- case R_TIMER1_COUNTER:
- case R_DBG_SCRATCHPAD:
- s->regs[addr] = value;
- break;
- case R_TIMER0_COMPARE:
- ptimer_set_limit(s->ptimer0, value, 0);
- s->regs[addr] = value;
- break;
- case R_TIMER1_COMPARE:
- ptimer_set_limit(s->ptimer1, value, 0);
- s->regs[addr] = value;
- break;
- case R_TIMER0_CONTROL:
- s->regs[addr] = value;
- if (s->regs[R_TIMER0_CONTROL] & CTRL_ENABLE) {
- trace_milkymist_sysctl_start_timer0();
- ptimer_set_count(s->ptimer0,
- s->regs[R_TIMER0_COMPARE] - s->regs[R_TIMER0_COUNTER]);
- ptimer_run(s->ptimer0, 0);
- } else {
- trace_milkymist_sysctl_stop_timer0();
- ptimer_stop(s->ptimer0);
- }
- break;
- case R_TIMER1_CONTROL:
- s->regs[addr] = value;
- if (s->regs[R_TIMER1_CONTROL] & CTRL_ENABLE) {
- trace_milkymist_sysctl_start_timer1();
- ptimer_set_count(s->ptimer1,
- s->regs[R_TIMER1_COMPARE] - s->regs[R_TIMER1_COUNTER]);
- ptimer_run(s->ptimer1, 0);
- } else {
- trace_milkymist_sysctl_stop_timer1();
- ptimer_stop(s->ptimer1);
- }
- break;
- case R_ICAP:
- sysctl_icap_write(s, value);
- break;
- case R_DBG_WRITE_LOCK:
- s->regs[addr] = 1;
- break;
- case R_SYSTEM_ID:
- qemu_system_reset_request();
- break;
-
- case R_GPIO_IN:
- case R_CLK_FREQUENCY:
- case R_CAPABILITIES:
- error_report("milkymist_sysctl: write to read-only register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
-
- default:
- error_report("milkymist_sysctl: write access to unknown register 0x"
- TARGET_FMT_plx, addr << 2);
- break;
- }
-}
-
-static const MemoryRegionOps sysctl_mmio_ops = {
- .read = sysctl_read,
- .write = sysctl_write,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void timer0_hit(void *opaque)
-{
- MilkymistSysctlState *s = opaque;
-
- if (!(s->regs[R_TIMER0_CONTROL] & CTRL_AUTORESTART)) {
- s->regs[R_TIMER0_CONTROL] &= ~CTRL_ENABLE;
- trace_milkymist_sysctl_stop_timer0();
- ptimer_stop(s->ptimer0);
- }
-
- trace_milkymist_sysctl_pulse_irq_timer0();
- qemu_irq_pulse(s->timer0_irq);
-}
-
-static void timer1_hit(void *opaque)
-{
- MilkymistSysctlState *s = opaque;
-
- if (!(s->regs[R_TIMER1_CONTROL] & CTRL_AUTORESTART)) {
- s->regs[R_TIMER1_CONTROL] &= ~CTRL_ENABLE;
- trace_milkymist_sysctl_stop_timer1();
- ptimer_stop(s->ptimer1);
- }
-
- trace_milkymist_sysctl_pulse_irq_timer1();
- qemu_irq_pulse(s->timer1_irq);
-}
-
-static void milkymist_sysctl_reset(DeviceState *d)
-{
- MilkymistSysctlState *s = MILKYMIST_SYSCTL(d);
- int i;
-
- for (i = 0; i < R_MAX; i++) {
- s->regs[i] = 0;
- }
-
- ptimer_stop(s->ptimer0);
- ptimer_stop(s->ptimer1);
-
- /* defaults */
- s->regs[R_ICAP] = ICAP_READY;
- s->regs[R_SYSTEM_ID] = s->systemid;
- s->regs[R_CLK_FREQUENCY] = s->freq_hz;
- s->regs[R_CAPABILITIES] = s->capabilities;
- s->regs[R_GPIO_IN] = s->strappings;
-}
-
-static int milkymist_sysctl_init(SysBusDevice *dev)
-{
- MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev);
-
- sysbus_init_irq(dev, &s->gpio_irq);
- sysbus_init_irq(dev, &s->timer0_irq);
- sysbus_init_irq(dev, &s->timer1_irq);
-
- s->bh0 = qemu_bh_new(timer0_hit, s);
- s->bh1 = qemu_bh_new(timer1_hit, s);
- s->ptimer0 = ptimer_init(s->bh0);
- s->ptimer1 = ptimer_init(s->bh1);
- ptimer_set_freq(s->ptimer0, s->freq_hz);
- ptimer_set_freq(s->ptimer1, s->freq_hz);
-
- memory_region_init_io(&s->regs_region, OBJECT(s), &sysctl_mmio_ops, s,
- "milkymist-sysctl", R_MAX * 4);
- sysbus_init_mmio(dev, &s->regs_region);
-
- return 0;
-}
-
-static const VMStateDescription vmstate_milkymist_sysctl = {
- .name = "milkymist-sysctl",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32_ARRAY(regs, MilkymistSysctlState, R_MAX),
- VMSTATE_PTIMER(ptimer0, MilkymistSysctlState),
- VMSTATE_PTIMER(ptimer1, MilkymistSysctlState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static Property milkymist_sysctl_properties[] = {
- DEFINE_PROP_UINT32("frequency", MilkymistSysctlState,
- freq_hz, 80000000),
- DEFINE_PROP_UINT32("capabilities", MilkymistSysctlState,
- capabilities, 0x00000000),
- DEFINE_PROP_UINT32("systemid", MilkymistSysctlState,
- systemid, 0x10014d31),
- DEFINE_PROP_UINT32("gpio_strappings", MilkymistSysctlState,
- strappings, 0x00000001),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void milkymist_sysctl_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = milkymist_sysctl_init;
- dc->reset = milkymist_sysctl_reset;
- dc->vmsd = &vmstate_milkymist_sysctl;
- dc->props = milkymist_sysctl_properties;
-}
-
-static const TypeInfo milkymist_sysctl_info = {
- .name = TYPE_MILKYMIST_SYSCTL,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(MilkymistSysctlState),
- .class_init = milkymist_sysctl_class_init,
-};
-
-static void milkymist_sysctl_register_types(void)
-{
- type_register_static(&milkymist_sysctl_info);
-}
-
-type_init(milkymist_sysctl_register_types)
diff --git a/qemu/hw/timer/omap_gptimer.c b/qemu/hw/timer/omap_gptimer.c
deleted file mode 100644
index 3a4386304..000000000
--- a/qemu/hw/timer/omap_gptimer.c
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * TI OMAP2 general purpose timers emulation.
- *
- * Copyright (C) 2007-2008 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) any later version of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "qemu/timer.h"
-#include "hw/arm/omap.h"
-
-/* GP timers */
-struct omap_gp_timer_s {
- MemoryRegion iomem;
- qemu_irq irq;
- qemu_irq wkup;
- qemu_irq in;
- qemu_irq out;
- omap_clk clk;
- QEMUTimer *timer;
- QEMUTimer *match;
- struct omap_target_agent_s *ta;
-
- int in_val;
- int out_val;
- int64_t time;
- int64_t rate;
- int64_t ticks_per_sec;
-
- int16_t config;
- int status;
- int it_ena;
- int wu_ena;
- int enable;
- int inout;
- int capt2;
- int pt;
- enum {
- gpt_trigger_none, gpt_trigger_overflow, gpt_trigger_both
- } trigger;
- enum {
- gpt_capture_none, gpt_capture_rising,
- gpt_capture_falling, gpt_capture_both
- } capture;
- int scpwm;
- int ce;
- int pre;
- int ptv;
- int ar;
- int st;
- int posted;
- uint32_t val;
- uint32_t load_val;
- uint32_t capture_val[2];
- uint32_t match_val;
- int capt_num;
-
- uint16_t writeh; /* LSB */
- uint16_t readh; /* MSB */
-};
-
-#define GPT_TCAR_IT (1 << 2)
-#define GPT_OVF_IT (1 << 1)
-#define GPT_MAT_IT (1 << 0)
-
-static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it)
-{
- if (timer->it_ena & it) {
- if (!timer->status)
- qemu_irq_raise(timer->irq);
-
- timer->status |= it;
- /* Or are the status bits set even when masked?
- * i.e. is masking applied before or after the status register? */
- }
-
- if (timer->wu_ena & it)
- qemu_irq_pulse(timer->wkup);
-}
-
-static inline void omap_gp_timer_out(struct omap_gp_timer_s *timer, int level)
-{
- if (!timer->inout && timer->out_val != level) {
- timer->out_val = level;
- qemu_set_irq(timer->out, level);
- }
-}
-
-static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer)
-{
- uint64_t distance;
-
- if (timer->st && timer->rate) {
- distance = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - timer->time;
- distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
-
- if (distance >= 0xffffffff - timer->val)
- return 0xffffffff;
- else
- return timer->val + distance;
- } else
- return timer->val;
-}
-
-static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer)
-{
- if (timer->st) {
- timer->val = omap_gp_timer_read(timer);
- timer->time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- }
-}
-
-static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer)
-{
- int64_t expires, matches;
-
- if (timer->st && timer->rate) {
- expires = muldiv64(0x100000000ll - timer->val,
- timer->ticks_per_sec, timer->rate);
- timer_mod(timer->timer, timer->time + expires);
-
- if (timer->ce && timer->match_val >= timer->val) {
- matches = muldiv64(timer->match_val - timer->val,
- timer->ticks_per_sec, timer->rate);
- timer_mod(timer->match, timer->time + matches);
- } else
- timer_del(timer->match);
- } else {
- timer_del(timer->timer);
- timer_del(timer->match);
- omap_gp_timer_out(timer, timer->scpwm);
- }
-}
-
-static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer)
-{
- if (timer->pt)
- /* TODO in overflow-and-match mode if the first event to
- * occur is the match, don't toggle. */
- omap_gp_timer_out(timer, !timer->out_val);
- else
- /* TODO inverted pulse on timer->out_val == 1? */
- qemu_irq_pulse(timer->out);
-}
-
-static void omap_gp_timer_tick(void *opaque)
-{
- struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
-
- if (!timer->ar) {
- timer->st = 0;
- timer->val = 0;
- } else {
- timer->val = timer->load_val;
- timer->time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- }
-
- if (timer->trigger == gpt_trigger_overflow ||
- timer->trigger == gpt_trigger_both)
- omap_gp_timer_trigger(timer);
-
- omap_gp_timer_intr(timer, GPT_OVF_IT);
- omap_gp_timer_update(timer);
-}
-
-static void omap_gp_timer_match(void *opaque)
-{
- struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
-
- if (timer->trigger == gpt_trigger_both)
- omap_gp_timer_trigger(timer);
-
- omap_gp_timer_intr(timer, GPT_MAT_IT);
-}
-
-static void omap_gp_timer_input(void *opaque, int line, int on)
-{
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
- int trigger;
-
- switch (s->capture) {
- default:
- case gpt_capture_none:
- trigger = 0;
- break;
- case gpt_capture_rising:
- trigger = !s->in_val && on;
- break;
- case gpt_capture_falling:
- trigger = s->in_val && !on;
- break;
- case gpt_capture_both:
- trigger = (s->in_val == !on);
- break;
- }
- s->in_val = on;
-
- if (s->inout && trigger && s->capt_num < 2) {
- s->capture_val[s->capt_num] = omap_gp_timer_read(s);
-
- if (s->capt2 == s->capt_num ++)
- omap_gp_timer_intr(s, GPT_TCAR_IT);
- }
-}
-
-static void omap_gp_timer_clk_update(void *opaque, int line, int on)
-{
- struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
-
- omap_gp_timer_sync(timer);
- timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
- omap_gp_timer_update(timer);
-}
-
-static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer)
-{
- omap_clk_adduser(timer->clk,
- qemu_allocate_irq(omap_gp_timer_clk_update, timer, 0));
- timer->rate = omap_clk_getrate(timer->clk);
-}
-
-void omap_gp_timer_reset(struct omap_gp_timer_s *s)
-{
- s->config = 0x000;
- s->status = 0;
- s->it_ena = 0;
- s->wu_ena = 0;
- s->inout = 0;
- s->capt2 = 0;
- s->capt_num = 0;
- s->pt = 0;
- s->trigger = gpt_trigger_none;
- s->capture = gpt_capture_none;
- s->scpwm = 0;
- s->ce = 0;
- s->pre = 0;
- s->ptv = 0;
- s->ar = 0;
- s->st = 0;
- s->posted = 1;
- s->val = 0x00000000;
- s->load_val = 0x00000000;
- s->capture_val[0] = 0x00000000;
- s->capture_val[1] = 0x00000000;
- s->match_val = 0x00000000;
- omap_gp_timer_update(s);
-}
-
-static uint32_t omap_gp_timer_readw(void *opaque, hwaddr addr)
-{
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-
- switch (addr) {
- case 0x00: /* TIDR */
- return 0x21;
-
- case 0x10: /* TIOCP_CFG */
- return s->config;
-
- case 0x14: /* TISTAT */
- /* ??? When's this bit reset? */
- return 1; /* RESETDONE */
-
- case 0x18: /* TISR */
- return s->status;
-
- case 0x1c: /* TIER */
- return s->it_ena;
-
- case 0x20: /* TWER */
- return s->wu_ena;
-
- case 0x24: /* TCLR */
- return (s->inout << 14) |
- (s->capt2 << 13) |
- (s->pt << 12) |
- (s->trigger << 10) |
- (s->capture << 8) |
- (s->scpwm << 7) |
- (s->ce << 6) |
- (s->pre << 5) |
- (s->ptv << 2) |
- (s->ar << 1) |
- (s->st << 0);
-
- case 0x28: /* TCRR */
- return omap_gp_timer_read(s);
-
- case 0x2c: /* TLDR */
- return s->load_val;
-
- case 0x30: /* TTGR */
- return 0xffffffff;
-
- case 0x34: /* TWPS */
- return 0x00000000; /* No posted writes pending. */
-
- case 0x38: /* TMAR */
- return s->match_val;
-
- case 0x3c: /* TCAR1 */
- return s->capture_val[0];
-
- case 0x40: /* TSICR */
- return s->posted << 2;
-
- case 0x44: /* TCAR2 */
- return s->capture_val[1];
- }
-
- OMAP_BAD_REG(addr);
- return 0;
-}
-
-static uint32_t omap_gp_timer_readh(void *opaque, hwaddr addr)
-{
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
- uint32_t ret;
-
- if (addr & 2)
- return s->readh;
- else {
- ret = omap_gp_timer_readw(opaque, addr);
- s->readh = ret >> 16;
- return ret & 0xffff;
- }
-}
-
-static void omap_gp_timer_write(void *opaque, hwaddr addr,
- uint32_t value)
-{
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-
- switch (addr) {
- case 0x00: /* TIDR */
- case 0x14: /* TISTAT */
- case 0x34: /* TWPS */
- case 0x3c: /* TCAR1 */
- case 0x44: /* TCAR2 */
- OMAP_RO_REG(addr);
- break;
-
- case 0x10: /* TIOCP_CFG */
- s->config = value & 0x33d;
- if (((value >> 3) & 3) == 3) /* IDLEMODE */
- fprintf(stderr, "%s: illegal IDLEMODE value in TIOCP_CFG\n",
- __FUNCTION__);
- if (value & 2) /* SOFTRESET */
- omap_gp_timer_reset(s);
- break;
-
- case 0x18: /* TISR */
- if (value & GPT_TCAR_IT)
- s->capt_num = 0;
- if (s->status && !(s->status &= ~value))
- qemu_irq_lower(s->irq);
- break;
-
- case 0x1c: /* TIER */
- s->it_ena = value & 7;
- break;
-
- case 0x20: /* TWER */
- s->wu_ena = value & 7;
- break;
-
- case 0x24: /* TCLR */
- omap_gp_timer_sync(s);
- s->inout = (value >> 14) & 1;
- s->capt2 = (value >> 13) & 1;
- s->pt = (value >> 12) & 1;
- s->trigger = (value >> 10) & 3;
- if (s->capture == gpt_capture_none &&
- ((value >> 8) & 3) != gpt_capture_none)
- s->capt_num = 0;
- s->capture = (value >> 8) & 3;
- s->scpwm = (value >> 7) & 1;
- s->ce = (value >> 6) & 1;
- s->pre = (value >> 5) & 1;
- s->ptv = (value >> 2) & 7;
- s->ar = (value >> 1) & 1;
- s->st = (value >> 0) & 1;
- if (s->inout && s->trigger != gpt_trigger_none)
- fprintf(stderr, "%s: GP timer pin must be an output "
- "for this trigger mode\n", __FUNCTION__);
- if (!s->inout && s->capture != gpt_capture_none)
- fprintf(stderr, "%s: GP timer pin must be an input "
- "for this capture mode\n", __FUNCTION__);
- if (s->trigger == gpt_trigger_none)
- omap_gp_timer_out(s, s->scpwm);
- /* TODO: make sure this doesn't overflow 32-bits */
- s->ticks_per_sec = NANOSECONDS_PER_SECOND << (s->pre ? s->ptv + 1 : 0);
- omap_gp_timer_update(s);
- break;
-
- case 0x28: /* TCRR */
- s->time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- s->val = value;
- omap_gp_timer_update(s);
- break;
-
- case 0x2c: /* TLDR */
- s->load_val = value;
- break;
-
- case 0x30: /* TTGR */
- s->time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- s->val = s->load_val;
- omap_gp_timer_update(s);
- break;
-
- case 0x38: /* TMAR */
- omap_gp_timer_sync(s);
- s->match_val = value;
- omap_gp_timer_update(s);
- break;
-
- case 0x40: /* TSICR */
- s->posted = (value >> 2) & 1;
- if (value & 2) /* How much exactly are we supposed to reset? */
- omap_gp_timer_reset(s);
- break;
-
- default:
- OMAP_BAD_REG(addr);
- }
-}
-
-static void omap_gp_timer_writeh(void *opaque, hwaddr addr,
- uint32_t value)
-{
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
-
- if (addr & 2)
- omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);
- else
- s->writeh = (uint16_t) value;
-}
-
-static const MemoryRegionOps omap_gp_timer_ops = {
- .old_mmio = {
- .read = {
- omap_badwidth_read32,
- omap_gp_timer_readh,
- omap_gp_timer_readw,
- },
- .write = {
- omap_badwidth_write32,
- omap_gp_timer_writeh,
- omap_gp_timer_write,
- },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
- qemu_irq irq, omap_clk fclk, omap_clk iclk)
-{
- struct omap_gp_timer_s *s = g_new0(struct omap_gp_timer_s, 1);
-
- s->ta = ta;
- s->irq = irq;
- s->clk = fclk;
- s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_tick, s);
- s->match = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_match, s);
- s->in = qemu_allocate_irq(omap_gp_timer_input, s, 0);
- omap_gp_timer_reset(s);
- omap_gp_timer_clk_setup(s);
-
- memory_region_init_io(&s->iomem, NULL, &omap_gp_timer_ops, s, "omap.gptimer",
- omap_l4_region_size(ta, 0));
- omap_l4_attach(ta, 0, &s->iomem);
-
- return s;
-}
diff --git a/qemu/hw/timer/omap_synctimer.c b/qemu/hw/timer/omap_synctimer.c
deleted file mode 100644
index 9ee651979..000000000
--- a/qemu/hw/timer/omap_synctimer.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * TI OMAP2 32kHz sync timer emulation.
- *
- * Copyright (C) 2007-2008 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) any later version of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "qemu/timer.h"
-#include "hw/arm/omap.h"
-struct omap_synctimer_s {
- MemoryRegion iomem;
- uint32_t val;
- uint16_t readh;
-};
-
-/* 32-kHz Sync Timer of the OMAP2 */
-static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
- return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 0x8000,
- NANOSECONDS_PER_SECOND);
-}
-
-void omap_synctimer_reset(struct omap_synctimer_s *s)
-{
- s->val = omap_synctimer_read(s);
-}
-
-static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr)
-{
- struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
-
- switch (addr) {
- case 0x00: /* 32KSYNCNT_REV */
- return 0x21;
-
- case 0x10: /* CR */
- return omap_synctimer_read(s) - s->val;
- }
-
- OMAP_BAD_REG(addr);
- return 0;
-}
-
-static uint32_t omap_synctimer_readh(void *opaque, hwaddr addr)
-{
- struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
- uint32_t ret;
-
- if (addr & 2)
- return s->readh;
- else {
- ret = omap_synctimer_readw(opaque, addr);
- s->readh = ret >> 16;
- return ret & 0xffff;
- }
-}
-
-static void omap_synctimer_write(void *opaque, hwaddr addr,
- uint32_t value)
-{
- OMAP_BAD_REG(addr);
-}
-
-static const MemoryRegionOps omap_synctimer_ops = {
- .old_mmio = {
- .read = {
- omap_badwidth_read32,
- omap_synctimer_readh,
- omap_synctimer_readw,
- },
- .write = {
- omap_badwidth_write32,
- omap_synctimer_write,
- omap_synctimer_write,
- },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta,
- struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
-{
- struct omap_synctimer_s *s = g_malloc0(sizeof(*s));
-
- omap_synctimer_reset(s);
- memory_region_init_io(&s->iomem, NULL, &omap_synctimer_ops, s, "omap.synctimer",
- omap_l4_region_size(ta, 0));
- omap_l4_attach(ta, 0, &s->iomem);
-
- return s;
-}
diff --git a/qemu/hw/timer/pl031.c b/qemu/hw/timer/pl031.c
deleted file mode 100644
index 38e0cb5ad..000000000
--- a/qemu/hw/timer/pl031.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * ARM AMBA PrimeCell PL031 RTC
- *
- * Copyright (c) 2007 CodeSourcery
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "qemu/cutils.h"
-
-//#define DEBUG_PL031
-
-#ifdef DEBUG_PL031
-#define DPRINTF(fmt, ...) \
-do { printf("pl031: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
-
-#define RTC_DR 0x00 /* Data read register */
-#define RTC_MR 0x04 /* Match register */
-#define RTC_LR 0x08 /* Data load register */
-#define RTC_CR 0x0c /* Control register */
-#define RTC_IMSC 0x10 /* Interrupt mask and set register */
-#define RTC_RIS 0x14 /* Raw interrupt status register */
-#define RTC_MIS 0x18 /* Masked interrupt status register */
-#define RTC_ICR 0x1c /* Interrupt clear register */
-
-#define TYPE_PL031 "pl031"
-#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
-
-typedef struct PL031State {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- QEMUTimer *timer;
- qemu_irq irq;
-
- /* Needed to preserve the tick_count across migration, even if the
- * absolute value of the rtc_clock is different on the source and
- * destination.
- */
- uint32_t tick_offset_vmstate;
- uint32_t tick_offset;
-
- uint32_t mr;
- uint32_t lr;
- uint32_t cr;
- uint32_t im;
- uint32_t is;
-} PL031State;
-
-static const unsigned char pl031_id[] = {
- 0x31, 0x10, 0x14, 0x00, /* Device ID */
- 0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
-};
-
-static void pl031_update(PL031State *s)
-{
- qemu_set_irq(s->irq, s->is & s->im);
-}
-
-static void pl031_interrupt(void * opaque)
-{
- PL031State *s = (PL031State *)opaque;
-
- s->is = 1;
- DPRINTF("Alarm raised\n");
- pl031_update(s);
-}
-
-static uint32_t pl031_get_count(PL031State *s)
-{
- int64_t now = qemu_clock_get_ns(rtc_clock);
- return s->tick_offset + now / NANOSECONDS_PER_SECOND;
-}
-
-static void pl031_set_alarm(PL031State *s)
-{
- uint32_t ticks;
-
- /* The timer wraps around. This subtraction also wraps in the same way,
- and gives correct results when alarm < now_ticks. */
- ticks = s->mr - pl031_get_count(s);
- DPRINTF("Alarm set in %ud ticks\n", ticks);
- if (ticks == 0) {
- timer_del(s->timer);
- pl031_interrupt(s);
- } else {
- int64_t now = qemu_clock_get_ns(rtc_clock);
- timer_mod(s->timer, now + (int64_t)ticks * NANOSECONDS_PER_SECOND);
- }
-}
-
-static uint64_t pl031_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- PL031State *s = (PL031State *)opaque;
-
- if (offset >= 0xfe0 && offset < 0x1000)
- return pl031_id[(offset - 0xfe0) >> 2];
-
- switch (offset) {
- case RTC_DR:
- return pl031_get_count(s);
- case RTC_MR:
- return s->mr;
- case RTC_IMSC:
- return s->im;
- case RTC_RIS:
- return s->is;
- case RTC_LR:
- return s->lr;
- case RTC_CR:
- /* RTC is permanently enabled. */
- return 1;
- case RTC_MIS:
- return s->is & s->im;
- case RTC_ICR:
- qemu_log_mask(LOG_GUEST_ERROR,
- "pl031: read of write-only register at offset 0x%x\n",
- (int)offset);
- break;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "pl031_read: Bad offset 0x%x\n", (int)offset);
- break;
- }
-
- return 0;
-}
-
-static void pl031_write(void * opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- PL031State *s = (PL031State *)opaque;
-
-
- switch (offset) {
- case RTC_LR:
- s->tick_offset += value - pl031_get_count(s);
- pl031_set_alarm(s);
- break;
- case RTC_MR:
- s->mr = value;
- pl031_set_alarm(s);
- break;
- case RTC_IMSC:
- s->im = value & 1;
- DPRINTF("Interrupt mask %d\n", s->im);
- pl031_update(s);
- break;
- case RTC_ICR:
- /* The PL031 documentation (DDI0224B) states that the interrupt is
- cleared when bit 0 of the written value is set. However the
- arm926e documentation (DDI0287B) states that the interrupt is
- cleared when any value is written. */
- DPRINTF("Interrupt cleared");
- s->is = 0;
- pl031_update(s);
- break;
- case RTC_CR:
- /* Written value is ignored. */
- break;
-
- case RTC_DR:
- case RTC_MIS:
- case RTC_RIS:
- qemu_log_mask(LOG_GUEST_ERROR,
- "pl031: write to read-only register at offset 0x%x\n",
- (int)offset);
- break;
-
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "pl031_write: Bad offset 0x%x\n", (int)offset);
- break;
- }
-}
-
-static const MemoryRegionOps pl031_ops = {
- .read = pl031_read,
- .write = pl031_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void pl031_init(Object *obj)
-{
- PL031State *s = PL031(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- struct tm tm;
-
- memory_region_init_io(&s->iomem, obj, &pl031_ops, s, "pl031", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
-
- sysbus_init_irq(dev, &s->irq);
- qemu_get_timedate(&tm, 0);
- s->tick_offset = mktimegm(&tm) -
- qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
-
- s->timer = timer_new_ns(rtc_clock, pl031_interrupt, s);
-}
-
-static void pl031_pre_save(void *opaque)
-{
- PL031State *s = opaque;
-
- /* tick_offset is base_time - rtc_clock base time. Instead, we want to
- * store the base time relative to the QEMU_CLOCK_VIRTUAL for backwards-compatibility. */
- int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- s->tick_offset_vmstate = s->tick_offset + delta / NANOSECONDS_PER_SECOND;
-}
-
-static int pl031_post_load(void *opaque, int version_id)
-{
- PL031State *s = opaque;
-
- int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- s->tick_offset = s->tick_offset_vmstate - delta / NANOSECONDS_PER_SECOND;
- pl031_set_alarm(s);
- return 0;
-}
-
-static const VMStateDescription vmstate_pl031 = {
- .name = "pl031",
- .version_id = 1,
- .minimum_version_id = 1,
- .pre_save = pl031_pre_save,
- .post_load = pl031_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(tick_offset_vmstate, PL031State),
- VMSTATE_UINT32(mr, PL031State),
- VMSTATE_UINT32(lr, PL031State),
- VMSTATE_UINT32(cr, PL031State),
- VMSTATE_UINT32(im, PL031State),
- VMSTATE_UINT32(is, PL031State),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void pl031_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->vmsd = &vmstate_pl031;
-}
-
-static const TypeInfo pl031_info = {
- .name = TYPE_PL031,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(PL031State),
- .instance_init = pl031_init,
- .class_init = pl031_class_init,
-};
-
-static void pl031_register_types(void)
-{
- type_register_static(&pl031_info);
-}
-
-type_init(pl031_register_types)
diff --git a/qemu/hw/timer/puv3_ost.c b/qemu/hw/timer/puv3_ost.c
deleted file mode 100644
index 93650b799..000000000
--- a/qemu/hw/timer/puv3_ost.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * OSTimer device simulation in PKUnity SoC
- *
- * Copyright (C) 2010-2012 Guan Xuetao
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation, or any later version.
- * See the COPYING file in the top-level directory.
- */
-#include "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "hw/ptimer.h"
-#include "qemu/main-loop.h"
-
-#undef DEBUG_PUV3
-#include "hw/unicore32/puv3.h"
-
-#define TYPE_PUV3_OST "puv3_ost"
-#define PUV3_OST(obj) OBJECT_CHECK(PUV3OSTState, (obj), TYPE_PUV3_OST)
-
-/* puv3 ostimer implementation. */
-typedef struct PUV3OSTState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- QEMUBH *bh;
- qemu_irq irq;
- ptimer_state *ptimer;
-
- uint32_t reg_OSMR0;
- uint32_t reg_OSCR;
- uint32_t reg_OSSR;
- uint32_t reg_OIER;
-} PUV3OSTState;
-
-static uint64_t puv3_ost_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- PUV3OSTState *s = opaque;
- uint32_t ret = 0;
-
- switch (offset) {
- case 0x10: /* Counter Register */
- ret = s->reg_OSMR0 - (uint32_t)ptimer_get_count(s->ptimer);
- break;
- case 0x14: /* Status Register */
- ret = s->reg_OSSR;
- break;
- case 0x1c: /* Interrupt Enable Register */
- ret = s->reg_OIER;
- break;
- default:
- DPRINTF("Bad offset %x\n", (int)offset);
- }
- DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
- return ret;
-}
-
-static void puv3_ost_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- PUV3OSTState *s = opaque;
-
- DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
- switch (offset) {
- case 0x00: /* Match Register 0 */
- s->reg_OSMR0 = value;
- if (s->reg_OSMR0 > s->reg_OSCR) {
- ptimer_set_count(s->ptimer, s->reg_OSMR0 - s->reg_OSCR);
- } else {
- ptimer_set_count(s->ptimer, s->reg_OSMR0 +
- (0xffffffff - s->reg_OSCR));
- }
- ptimer_run(s->ptimer, 2);
- break;
- case 0x14: /* Status Register */
- assert(value == 0);
- if (s->reg_OSSR) {
- s->reg_OSSR = value;
- qemu_irq_lower(s->irq);
- }
- break;
- case 0x1c: /* Interrupt Enable Register */
- s->reg_OIER = value;
- break;
- default:
- DPRINTF("Bad offset %x\n", (int)offset);
- }
-}
-
-static const MemoryRegionOps puv3_ost_ops = {
- .read = puv3_ost_read,
- .write = puv3_ost_write,
- .impl = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void puv3_ost_tick(void *opaque)
-{
- PUV3OSTState *s = opaque;
-
- DPRINTF("ost hit when ptimer counter from 0x%x to 0x%x!\n",
- s->reg_OSCR, s->reg_OSMR0);
-
- s->reg_OSCR = s->reg_OSMR0;
- if (s->reg_OIER) {
- s->reg_OSSR = 1;
- qemu_irq_raise(s->irq);
- }
-}
-
-static int puv3_ost_init(SysBusDevice *dev)
-{
- PUV3OSTState *s = PUV3_OST(dev);
-
- s->reg_OIER = 0;
- s->reg_OSSR = 0;
- s->reg_OSMR0 = 0;
- s->reg_OSCR = 0;
-
- sysbus_init_irq(dev, &s->irq);
-
- s->bh = qemu_bh_new(puv3_ost_tick, s);
- s->ptimer = ptimer_init(s->bh);
- ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
-
- memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
- PUV3_REGS_OFFSET);
- sysbus_init_mmio(dev, &s->iomem);
-
- return 0;
-}
-
-static void puv3_ost_class_init(ObjectClass *klass, void *data)
-{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
- sdc->init = puv3_ost_init;
-}
-
-static const TypeInfo puv3_ost_info = {
- .name = TYPE_PUV3_OST,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(PUV3OSTState),
- .class_init = puv3_ost_class_init,
-};
-
-static void puv3_ost_register_type(void)
-{
- type_register_static(&puv3_ost_info);
-}
-
-type_init(puv3_ost_register_type)
diff --git a/qemu/hw/timer/pxa2xx_timer.c b/qemu/hw/timer/pxa2xx_timer.c
deleted file mode 100644
index 59002b407..000000000
--- a/qemu/hw/timer/pxa2xx_timer.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * Intel XScale PXA255/270 OS Timers.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Copyright (c) 2006 Thorsten Zitterell
- *
- * This code is licensed under the GPL.
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "qemu/timer.h"
-#include "sysemu/sysemu.h"
-#include "hw/arm/pxa.h"
-#include "hw/sysbus.h"
-
-#define OSMR0 0x00
-#define OSMR1 0x04
-#define OSMR2 0x08
-#define OSMR3 0x0c
-#define OSMR4 0x80
-#define OSMR5 0x84
-#define OSMR6 0x88
-#define OSMR7 0x8c
-#define OSMR8 0x90
-#define OSMR9 0x94
-#define OSMR10 0x98
-#define OSMR11 0x9c
-#define OSCR 0x10 /* OS Timer Count */
-#define OSCR4 0x40
-#define OSCR5 0x44
-#define OSCR6 0x48
-#define OSCR7 0x4c
-#define OSCR8 0x50
-#define OSCR9 0x54
-#define OSCR10 0x58
-#define OSCR11 0x5c
-#define OSSR 0x14 /* Timer status register */
-#define OWER 0x18
-#define OIER 0x1c /* Interrupt enable register 3-0 to E3-E0 */
-#define OMCR4 0xc0 /* OS Match Control registers */
-#define OMCR5 0xc4
-#define OMCR6 0xc8
-#define OMCR7 0xcc
-#define OMCR8 0xd0
-#define OMCR9 0xd4
-#define OMCR10 0xd8
-#define OMCR11 0xdc
-#define OSNR 0x20
-
-#define PXA25X_FREQ 3686400 /* 3.6864 MHz */
-#define PXA27X_FREQ 3250000 /* 3.25 MHz */
-
-static int pxa2xx_timer4_freq[8] = {
- [0] = 0,
- [1] = 32768,
- [2] = 1000,
- [3] = 1,
- [4] = 1000000,
- /* [5] is the "Externally supplied clock". Assign if necessary. */
- [5 ... 7] = 0,
-};
-
-#define TYPE_PXA2XX_TIMER "pxa2xx-timer"
-#define PXA2XX_TIMER(obj) \
- OBJECT_CHECK(PXA2xxTimerInfo, (obj), TYPE_PXA2XX_TIMER)
-
-typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
-
-typedef struct {
- uint32_t value;
- qemu_irq irq;
- QEMUTimer *qtimer;
- int num;
- PXA2xxTimerInfo *info;
-} PXA2xxTimer0;
-
-typedef struct {
- PXA2xxTimer0 tm;
- int32_t oldclock;
- int32_t clock;
- uint64_t lastload;
- uint32_t freq;
- uint32_t control;
-} PXA2xxTimer4;
-
-struct PXA2xxTimerInfo {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- uint32_t flags;
-
- int32_t clock;
- int32_t oldclock;
- uint64_t lastload;
- uint32_t freq;
- PXA2xxTimer0 timer[4];
- uint32_t events;
- uint32_t irq_enabled;
- uint32_t reset3;
- uint32_t snapshot;
-
- qemu_irq irq4;
- PXA2xxTimer4 tm4[8];
-};
-
-#define PXA2XX_TIMER_HAVE_TM4 0
-
-static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s)
-{
- return s->flags & (1 << PXA2XX_TIMER_HAVE_TM4);
-}
-
-static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
-{
- PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
- int i;
- uint32_t now_vm;
- uint64_t new_qemu;
-
- now_vm = s->clock +
- muldiv64(now_qemu - s->lastload, s->freq, NANOSECONDS_PER_SECOND);
-
- for (i = 0; i < 4; i ++) {
- new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
- NANOSECONDS_PER_SECOND, s->freq);
- timer_mod(s->timer[i].qtimer, new_qemu);
- }
-}
-
-static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
-{
- PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
- uint32_t now_vm;
- uint64_t new_qemu;
- static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
- int counter;
-
- if (s->tm4[n].control & (1 << 7))
- counter = n;
- else
- counter = counters[n];
-
- if (!s->tm4[counter].freq) {
- timer_del(s->tm4[n].tm.qtimer);
- return;
- }
-
- now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
- s->tm4[counter].lastload,
- s->tm4[counter].freq, NANOSECONDS_PER_SECOND);
-
- new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
- NANOSECONDS_PER_SECOND, s->tm4[counter].freq);
- timer_mod(s->tm4[n].tm.qtimer, new_qemu);
-}
-
-static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
- int tm = 0;
-
- switch (offset) {
- case OSMR3: tm ++;
- /* fall through */
- case OSMR2: tm ++;
- /* fall through */
- case OSMR1: tm ++;
- /* fall through */
- case OSMR0:
- return s->timer[tm].value;
- case OSMR11: tm ++;
- /* fall through */
- case OSMR10: tm ++;
- /* fall through */
- case OSMR9: tm ++;
- /* fall through */
- case OSMR8: tm ++;
- /* fall through */
- case OSMR7: tm ++;
- /* fall through */
- case OSMR6: tm ++;
- /* fall through */
- case OSMR5: tm ++;
- /* fall through */
- case OSMR4:
- if (!pxa2xx_timer_has_tm4(s))
- goto badreg;
- return s->tm4[tm].tm.value;
- case OSCR:
- return s->clock + muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
- s->lastload, s->freq, NANOSECONDS_PER_SECOND);
- case OSCR11: tm ++;
- /* fall through */
- case OSCR10: tm ++;
- /* fall through */
- case OSCR9: tm ++;
- /* fall through */
- case OSCR8: tm ++;
- /* fall through */
- case OSCR7: tm ++;
- /* fall through */
- case OSCR6: tm ++;
- /* fall through */
- case OSCR5: tm ++;
- /* fall through */
- case OSCR4:
- if (!pxa2xx_timer_has_tm4(s))
- goto badreg;
-
- if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
- if (s->tm4[tm - 1].freq)
- s->snapshot = s->tm4[tm - 1].clock + muldiv64(
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
- s->tm4[tm - 1].lastload,
- s->tm4[tm - 1].freq, NANOSECONDS_PER_SECOND);
- else
- s->snapshot = s->tm4[tm - 1].clock;
- }
-
- if (!s->tm4[tm].freq)
- return s->tm4[tm].clock;
- return s->tm4[tm].clock +
- muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
- s->tm4[tm].lastload, s->tm4[tm].freq,
- NANOSECONDS_PER_SECOND);
- case OIER:
- return s->irq_enabled;
- case OSSR: /* Status register */
- return s->events;
- case OWER:
- return s->reset3;
- case OMCR11: tm ++;
- /* fall through */
- case OMCR10: tm ++;
- /* fall through */
- case OMCR9: tm ++;
- /* fall through */
- case OMCR8: tm ++;
- /* fall through */
- case OMCR7: tm ++;
- /* fall through */
- case OMCR6: tm ++;
- /* fall through */
- case OMCR5: tm ++;
- /* fall through */
- case OMCR4:
- if (!pxa2xx_timer_has_tm4(s))
- goto badreg;
- return s->tm4[tm].control;
- case OSNR:
- return s->snapshot;
- default:
- badreg:
- hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
- }
-
- return 0;
-}
-
-static void pxa2xx_timer_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- int i, tm = 0;
- PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
-
- switch (offset) {
- case OSMR3: tm ++;
- /* fall through */
- case OSMR2: tm ++;
- /* fall through */
- case OSMR1: tm ++;
- /* fall through */
- case OSMR0:
- s->timer[tm].value = value;
- pxa2xx_timer_update(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
- break;
- case OSMR11: tm ++;
- /* fall through */
- case OSMR10: tm ++;
- /* fall through */
- case OSMR9: tm ++;
- /* fall through */
- case OSMR8: tm ++;
- /* fall through */
- case OSMR7: tm ++;
- /* fall through */
- case OSMR6: tm ++;
- /* fall through */
- case OSMR5: tm ++;
- /* fall through */
- case OSMR4:
- if (!pxa2xx_timer_has_tm4(s))
- goto badreg;
- s->tm4[tm].tm.value = value;
- pxa2xx_timer_update4(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tm);
- break;
- case OSCR:
- s->oldclock = s->clock;
- s->lastload = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- s->clock = value;
- pxa2xx_timer_update(s, s->lastload);
- break;
- case OSCR11: tm ++;
- /* fall through */
- case OSCR10: tm ++;
- /* fall through */
- case OSCR9: tm ++;
- /* fall through */
- case OSCR8: tm ++;
- /* fall through */
- case OSCR7: tm ++;
- /* fall through */
- case OSCR6: tm ++;
- /* fall through */
- case OSCR5: tm ++;
- /* fall through */
- case OSCR4:
- if (!pxa2xx_timer_has_tm4(s))
- goto badreg;
- s->tm4[tm].oldclock = s->tm4[tm].clock;
- s->tm4[tm].lastload = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- s->tm4[tm].clock = value;
- pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
- break;
- case OIER:
- s->irq_enabled = value & 0xfff;
- break;
- case OSSR: /* Status register */
- value &= s->events;
- s->events &= ~value;
- for (i = 0; i < 4; i ++, value >>= 1)
- if (value & 1)
- qemu_irq_lower(s->timer[i].irq);
- if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value)
- qemu_irq_lower(s->irq4);
- break;
- case OWER: /* XXX: Reset on OSMR3 match? */
- s->reset3 = value;
- break;
- case OMCR7: tm ++;
- /* fall through */
- case OMCR6: tm ++;
- /* fall through */
- case OMCR5: tm ++;
- /* fall through */
- case OMCR4:
- if (!pxa2xx_timer_has_tm4(s))
- goto badreg;
- s->tm4[tm].control = value & 0x0ff;
- /* XXX Stop if running (shouldn't happen) */
- if ((value & (1 << 7)) || tm == 0)
- s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
- else {
- s->tm4[tm].freq = 0;
- pxa2xx_timer_update4(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tm);
- }
- break;
- case OMCR11: tm ++;
- /* fall through */
- case OMCR10: tm ++;
- /* fall through */
- case OMCR9: tm ++;
- /* fall through */
- case OMCR8: tm += 4;
- if (!pxa2xx_timer_has_tm4(s))
- goto badreg;
- s->tm4[tm].control = value & 0x3ff;
- /* XXX Stop if running (shouldn't happen) */
- if ((value & (1 << 7)) || !(tm & 1))
- s->tm4[tm].freq =
- pxa2xx_timer4_freq[(value & (1 << 8)) ? 0 : (value & 7)];
- else {
- s->tm4[tm].freq = 0;
- pxa2xx_timer_update4(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tm);
- }
- break;
- default:
- badreg:
- hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
- }
-}
-
-static const MemoryRegionOps pxa2xx_timer_ops = {
- .read = pxa2xx_timer_read,
- .write = pxa2xx_timer_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void pxa2xx_timer_tick(void *opaque)
-{
- PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
- PXA2xxTimerInfo *i = t->info;
-
- if (i->irq_enabled & (1 << t->num)) {
- i->events |= 1 << t->num;
- qemu_irq_raise(t->irq);
- }
-
- if (t->num == 3)
- if (i->reset3 & 1) {
- i->reset3 = 0;
- qemu_system_reset_request();
- }
-}
-
-static void pxa2xx_timer_tick4(void *opaque)
-{
- PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
- PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
-
- pxa2xx_timer_tick(&t->tm);
- if (t->control & (1 << 3))
- t->clock = 0;
- if (t->control & (1 << 6))
- pxa2xx_timer_update4(i, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), t->tm.num - 4);
- if (i->events & 0xff0)
- qemu_irq_raise(i->irq4);
-}
-
-static int pxa25x_timer_post_load(void *opaque, int version_id)
-{
- PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
- int64_t now;
- int i;
-
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- pxa2xx_timer_update(s, now);
-
- if (pxa2xx_timer_has_tm4(s))
- for (i = 0; i < 8; i ++)
- pxa2xx_timer_update4(s, now, i);
-
- return 0;
-}
-
-static void pxa2xx_timer_init(Object *obj)
-{
- PXA2xxTimerInfo *s = PXA2XX_TIMER(obj);
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-
- s->irq_enabled = 0;
- s->oldclock = 0;
- s->clock = 0;
- s->lastload = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- s->reset3 = 0;
-
- memory_region_init_io(&s->iomem, obj, &pxa2xx_timer_ops, s,
- "pxa2xx-timer", 0x00001000);
- sysbus_init_mmio(dev, &s->iomem);
-}
-
-static void pxa2xx_timer_realize(DeviceState *dev, Error **errp)
-{
- PXA2xxTimerInfo *s = PXA2XX_TIMER(dev);
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- int i;
-
- for (i = 0; i < 4; i ++) {
- s->timer[i].value = 0;
- sysbus_init_irq(sbd, &s->timer[i].irq);
- s->timer[i].info = s;
- s->timer[i].num = i;
- s->timer[i].qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- pxa2xx_timer_tick, &s->timer[i]);
- }
-
- if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
- sysbus_init_irq(sbd, &s->irq4);
-
- for (i = 0; i < 8; i ++) {
- s->tm4[i].tm.value = 0;
- s->tm4[i].tm.info = s;
- s->tm4[i].tm.num = i + 4;
- s->tm4[i].freq = 0;
- s->tm4[i].control = 0x0;
- s->tm4[i].tm.qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- pxa2xx_timer_tick4, &s->tm4[i]);
- }
- }
-}
-
-static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
- .name = "pxa2xx_timer0",
- .version_id = 2,
- .minimum_version_id = 2,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(value, PXA2xxTimer0),
- VMSTATE_END_OF_LIST(),
- },
-};
-
-static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
- .name = "pxa2xx_timer4",
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
- vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
- VMSTATE_INT32(oldclock, PXA2xxTimer4),
- VMSTATE_INT32(clock, PXA2xxTimer4),
- VMSTATE_UINT64(lastload, PXA2xxTimer4),
- VMSTATE_UINT32(freq, PXA2xxTimer4),
- VMSTATE_UINT32(control, PXA2xxTimer4),
- VMSTATE_END_OF_LIST(),
- },
-};
-
-static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
-{
- return pxa2xx_timer_has_tm4(opaque);
-}
-
-static const VMStateDescription vmstate_pxa2xx_timer_regs = {
- .name = "pxa2xx_timer",
- .version_id = 1,
- .minimum_version_id = 1,
- .post_load = pxa25x_timer_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(clock, PXA2xxTimerInfo),
- VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
- VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
- VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
- vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
- VMSTATE_UINT32(events, PXA2xxTimerInfo),
- VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
- VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
- VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
- VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
- pxa2xx_timer_has_tm4_test, 0,
- vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
- VMSTATE_END_OF_LIST(),
- }
-};
-
-static Property pxa25x_timer_dev_properties[] = {
- DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
- DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
- PXA2XX_TIMER_HAVE_TM4, false),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->desc = "PXA25x timer";
- dc->props = pxa25x_timer_dev_properties;
-}
-
-static const TypeInfo pxa25x_timer_dev_info = {
- .name = "pxa25x-timer",
- .parent = TYPE_PXA2XX_TIMER,
- .instance_size = sizeof(PXA2xxTimerInfo),
- .class_init = pxa25x_timer_dev_class_init,
-};
-
-static Property pxa27x_timer_dev_properties[] = {
- DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
- DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
- PXA2XX_TIMER_HAVE_TM4, true),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->desc = "PXA27x timer";
- dc->props = pxa27x_timer_dev_properties;
-}
-
-static const TypeInfo pxa27x_timer_dev_info = {
- .name = "pxa27x-timer",
- .parent = TYPE_PXA2XX_TIMER,
- .instance_size = sizeof(PXA2xxTimerInfo),
- .class_init = pxa27x_timer_dev_class_init,
-};
-
-static void pxa2xx_timer_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- dc->realize = pxa2xx_timer_realize;
- dc->vmsd = &vmstate_pxa2xx_timer_regs;
-}
-
-static const TypeInfo pxa2xx_timer_type_info = {
- .name = TYPE_PXA2XX_TIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(PXA2xxTimerInfo),
- .instance_init = pxa2xx_timer_init,
- .abstract = true,
- .class_init = pxa2xx_timer_class_init,
-};
-
-static void pxa2xx_timer_register_types(void)
-{
- type_register_static(&pxa2xx_timer_type_info);
- type_register_static(&pxa25x_timer_dev_info);
- type_register_static(&pxa27x_timer_dev_info);
-}
-
-type_init(pxa2xx_timer_register_types)
diff --git a/qemu/hw/timer/sh_timer.c b/qemu/hw/timer/sh_timer.c
deleted file mode 100644
index 255b2fc91..000000000
--- a/qemu/hw/timer/sh_timer.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * SuperH Timer modules.
- *
- * Copyright (c) 2007 Magnus Damm
- * Based on arm_timer.c by Paul Brook
- * Copyright (c) 2005-2006 CodeSourcery.
- *
- * This code is licensed under the GPL.
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/sh4/sh.h"
-#include "qemu/timer.h"
-#include "qemu/main-loop.h"
-#include "exec/address-spaces.h"
-#include "hw/ptimer.h"
-
-//#define DEBUG_TIMER
-
-#define TIMER_TCR_TPSC (7 << 0)
-#define TIMER_TCR_CKEG (3 << 3)
-#define TIMER_TCR_UNIE (1 << 5)
-#define TIMER_TCR_ICPE (3 << 6)
-#define TIMER_TCR_UNF (1 << 8)
-#define TIMER_TCR_ICPF (1 << 9)
-#define TIMER_TCR_RESERVED (0x3f << 10)
-
-#define TIMER_FEAT_CAPT (1 << 0)
-#define TIMER_FEAT_EXTCLK (1 << 1)
-
-#define OFFSET_TCOR 0
-#define OFFSET_TCNT 1
-#define OFFSET_TCR 2
-#define OFFSET_TCPR 3
-
-typedef struct {
- ptimer_state *timer;
- uint32_t tcnt;
- uint32_t tcor;
- uint32_t tcr;
- uint32_t tcpr;
- int freq;
- int int_level;
- int old_level;
- int feat;
- int enabled;
- qemu_irq irq;
-} sh_timer_state;
-
-/* Check all active timers, and schedule the next timer interrupt. */
-
-static void sh_timer_update(sh_timer_state *s)
-{
- int new_level = s->int_level && (s->tcr & TIMER_TCR_UNIE);
-
- if (new_level != s->old_level)
- qemu_set_irq (s->irq, new_level);
-
- s->old_level = s->int_level;
- s->int_level = new_level;
-}
-
-static uint32_t sh_timer_read(void *opaque, hwaddr offset)
-{
- sh_timer_state *s = (sh_timer_state *)opaque;
-
- switch (offset >> 2) {
- case OFFSET_TCOR:
- return s->tcor;
- case OFFSET_TCNT:
- return ptimer_get_count(s->timer);
- case OFFSET_TCR:
- return s->tcr | (s->int_level ? TIMER_TCR_UNF : 0);
- case OFFSET_TCPR:
- if (s->feat & TIMER_FEAT_CAPT)
- return s->tcpr;
- default:
- hw_error("sh_timer_read: Bad offset %x\n", (int)offset);
- return 0;
- }
-}
-
-static void sh_timer_write(void *opaque, hwaddr offset,
- uint32_t value)
-{
- sh_timer_state *s = (sh_timer_state *)opaque;
- int freq;
-
- switch (offset >> 2) {
- case OFFSET_TCOR:
- s->tcor = value;
- ptimer_set_limit(s->timer, s->tcor, 0);
- break;
- case OFFSET_TCNT:
- s->tcnt = value;
- ptimer_set_count(s->timer, s->tcnt);
- break;
- case OFFSET_TCR:
- if (s->enabled) {
- /* Pause the timer if it is running. This may cause some
- inaccuracy dure to rounding, but avoids a whole lot of other
- messyness. */
- ptimer_stop(s->timer);
- }
- freq = s->freq;
- /* ??? Need to recalculate expiry time after changing divisor. */
- switch (value & TIMER_TCR_TPSC) {
- case 0: freq >>= 2; break;
- case 1: freq >>= 4; break;
- case 2: freq >>= 6; break;
- case 3: freq >>= 8; break;
- case 4: freq >>= 10; break;
- case 6:
- case 7: if (s->feat & TIMER_FEAT_EXTCLK) break;
- default: hw_error("sh_timer_write: Reserved TPSC value\n"); break;
- }
- switch ((value & TIMER_TCR_CKEG) >> 3) {
- case 0: break;
- case 1:
- case 2:
- case 3: if (s->feat & TIMER_FEAT_EXTCLK) break;
- default: hw_error("sh_timer_write: Reserved CKEG value\n"); break;
- }
- switch ((value & TIMER_TCR_ICPE) >> 6) {
- case 0: break;
- case 2:
- case 3: if (s->feat & TIMER_FEAT_CAPT) break;
- default: hw_error("sh_timer_write: Reserved ICPE value\n"); break;
- }
- if ((value & TIMER_TCR_UNF) == 0)
- s->int_level = 0;
-
- value &= ~TIMER_TCR_UNF;
-
- if ((value & TIMER_TCR_ICPF) && (!(s->feat & TIMER_FEAT_CAPT)))
- hw_error("sh_timer_write: Reserved ICPF value\n");
-
- value &= ~TIMER_TCR_ICPF; /* capture not supported */
-
- if (value & TIMER_TCR_RESERVED)
- hw_error("sh_timer_write: Reserved TCR bits set\n");
- s->tcr = value;
- ptimer_set_limit(s->timer, s->tcor, 0);
- ptimer_set_freq(s->timer, freq);
- if (s->enabled) {
- /* Restart the timer if still enabled. */
- ptimer_run(s->timer, 0);
- }
- break;
- case OFFSET_TCPR:
- if (s->feat & TIMER_FEAT_CAPT) {
- s->tcpr = value;
- break;
- }
- default:
- hw_error("sh_timer_write: Bad offset %x\n", (int)offset);
- }
- sh_timer_update(s);
-}
-
-static void sh_timer_start_stop(void *opaque, int enable)
-{
- sh_timer_state *s = (sh_timer_state *)opaque;
-
-#ifdef DEBUG_TIMER
- printf("sh_timer_start_stop %d (%d)\n", enable, s->enabled);
-#endif
-
- if (s->enabled && !enable) {
- ptimer_stop(s->timer);
- }
- if (!s->enabled && enable) {
- ptimer_run(s->timer, 0);
- }
- s->enabled = !!enable;
-
-#ifdef DEBUG_TIMER
- printf("sh_timer_start_stop done %d\n", s->enabled);
-#endif
-}
-
-static void sh_timer_tick(void *opaque)
-{
- sh_timer_state *s = (sh_timer_state *)opaque;
- s->int_level = s->enabled;
- sh_timer_update(s);
-}
-
-static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
-{
- sh_timer_state *s;
- QEMUBH *bh;
-
- s = (sh_timer_state *)g_malloc0(sizeof(sh_timer_state));
- s->freq = freq;
- s->feat = feat;
- s->tcor = 0xffffffff;
- s->tcnt = 0xffffffff;
- s->tcpr = 0xdeadbeef;
- s->tcr = 0;
- s->enabled = 0;
- s->irq = irq;
-
- bh = qemu_bh_new(sh_timer_tick, s);
- s->timer = ptimer_init(bh);
-
- sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor);
- sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt);
- sh_timer_write(s, OFFSET_TCPR >> 2, s->tcpr);
- sh_timer_write(s, OFFSET_TCR >> 2, s->tcpr);
- /* ??? Save/restore. */
- return s;
-}
-
-typedef struct {
- MemoryRegion iomem;
- MemoryRegion iomem_p4;
- MemoryRegion iomem_a7;
- void *timer[3];
- int level[3];
- uint32_t tocr;
- uint32_t tstr;
- int feat;
-} tmu012_state;
-
-static uint64_t tmu012_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- tmu012_state *s = (tmu012_state *)opaque;
-
-#ifdef DEBUG_TIMER
- printf("tmu012_read 0x%lx\n", (unsigned long) offset);
-#endif
-
- if (offset >= 0x20) {
- if (!(s->feat & TMU012_FEAT_3CHAN))
- hw_error("tmu012_write: Bad channel offset %x\n", (int)offset);
- return sh_timer_read(s->timer[2], offset - 0x20);
- }
-
- if (offset >= 0x14)
- return sh_timer_read(s->timer[1], offset - 0x14);
-
- if (offset >= 0x08)
- return sh_timer_read(s->timer[0], offset - 0x08);
-
- if (offset == 4)
- return s->tstr;
-
- if ((s->feat & TMU012_FEAT_TOCR) && offset == 0)
- return s->tocr;
-
- hw_error("tmu012_write: Bad offset %x\n", (int)offset);
- return 0;
-}
-
-static void tmu012_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
-{
- tmu012_state *s = (tmu012_state *)opaque;
-
-#ifdef DEBUG_TIMER
- printf("tmu012_write 0x%lx 0x%08x\n", (unsigned long) offset, value);
-#endif
-
- if (offset >= 0x20) {
- if (!(s->feat & TMU012_FEAT_3CHAN))
- hw_error("tmu012_write: Bad channel offset %x\n", (int)offset);
- sh_timer_write(s->timer[2], offset - 0x20, value);
- return;
- }
-
- if (offset >= 0x14) {
- sh_timer_write(s->timer[1], offset - 0x14, value);
- return;
- }
-
- if (offset >= 0x08) {
- sh_timer_write(s->timer[0], offset - 0x08, value);
- return;
- }
-
- if (offset == 4) {
- sh_timer_start_stop(s->timer[0], value & (1 << 0));
- sh_timer_start_stop(s->timer[1], value & (1 << 1));
- if (s->feat & TMU012_FEAT_3CHAN)
- sh_timer_start_stop(s->timer[2], value & (1 << 2));
- else
- if (value & (1 << 2))
- hw_error("tmu012_write: Bad channel\n");
-
- s->tstr = value;
- return;
- }
-
- if ((s->feat & TMU012_FEAT_TOCR) && offset == 0) {
- s->tocr = value & (1 << 0);
- }
-}
-
-static const MemoryRegionOps tmu012_ops = {
- .read = tmu012_read,
- .write = tmu012_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-void tmu012_init(MemoryRegion *sysmem, hwaddr base,
- int feat, uint32_t freq,
- qemu_irq ch0_irq, qemu_irq ch1_irq,
- qemu_irq ch2_irq0, qemu_irq ch2_irq1)
-{
- tmu012_state *s;
- int timer_feat = (feat & TMU012_FEAT_EXTCLK) ? TIMER_FEAT_EXTCLK : 0;
-
- s = (tmu012_state *)g_malloc0(sizeof(tmu012_state));
- s->feat = feat;
- s->timer[0] = sh_timer_init(freq, timer_feat, ch0_irq);
- s->timer[1] = sh_timer_init(freq, timer_feat, ch1_irq);
- if (feat & TMU012_FEAT_3CHAN)
- s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT,
- ch2_irq0); /* ch2_irq1 not supported */
-
- memory_region_init_io(&s->iomem, NULL, &tmu012_ops, s,
- "timer", 0x100000000ULL);
-
- memory_region_init_alias(&s->iomem_p4, NULL, "timer-p4",
- &s->iomem, 0, 0x1000);
- memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
-
- memory_region_init_alias(&s->iomem_a7, NULL, "timer-a7",
- &s->iomem, 0, 0x1000);
- memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
- /* ??? Save/restore. */
-}
diff --git a/qemu/hw/timer/slavio_timer.c b/qemu/hw/timer/slavio_timer.c
deleted file mode 100644
index fb3e08bed..000000000
--- a/qemu/hw/timer/slavio_timer.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * QEMU Sparc SLAVIO timer controller emulation
- *
- * Copyright (c) 2003-2005 Fabrice Bellard
- *
- * 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 "qemu/osdep.h"
-#include "hw/sparc/sun4m.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "qemu/main-loop.h"
-
-/*
- * Registers of hardware timer in sun4m.
- *
- * This is the timer/counter part of chip STP2001 (Slave I/O), also
- * produced as NCR89C105. See
- * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
- *
- * The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
- * are zero. Bit 31 is 1 when count has been reached.
- *
- * Per-CPU timers interrupt local CPU, system timer uses normal
- * interrupt routing.
- *
- */
-
-#define MAX_CPUS 16
-
-typedef struct CPUTimerState {
- qemu_irq irq;
- ptimer_state *timer;
- uint32_t count, counthigh, reached;
- /* processor only */
- uint32_t run;
- uint64_t limit;
-} CPUTimerState;
-
-#define TYPE_SLAVIO_TIMER "slavio_timer"
-#define SLAVIO_TIMER(obj) \
- OBJECT_CHECK(SLAVIO_TIMERState, (obj), TYPE_SLAVIO_TIMER)
-
-typedef struct SLAVIO_TIMERState {
- SysBusDevice parent_obj;
-
- uint32_t num_cpus;
- uint32_t cputimer_mode;
- CPUTimerState cputimer[MAX_CPUS + 1];
-} SLAVIO_TIMERState;
-
-typedef struct TimerContext {
- MemoryRegion iomem;
- SLAVIO_TIMERState *s;
- unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
-} TimerContext;
-
-#define SYS_TIMER_SIZE 0x14
-#define CPU_TIMER_SIZE 0x10
-
-#define TIMER_LIMIT 0
-#define TIMER_COUNTER 1
-#define TIMER_COUNTER_NORST 2
-#define TIMER_STATUS 3
-#define TIMER_MODE 4
-
-#define TIMER_COUNT_MASK32 0xfffffe00
-#define TIMER_LIMIT_MASK32 0x7fffffff
-#define TIMER_MAX_COUNT64 0x7ffffffffffffe00ULL
-#define TIMER_MAX_COUNT32 0x7ffffe00ULL
-#define TIMER_REACHED 0x80000000
-#define TIMER_PERIOD 500ULL // 500ns
-#define LIMIT_TO_PERIODS(l) (((l) >> 9) - 1)
-#define PERIODS_TO_LIMIT(l) (((l) + 1) << 9)
-
-static int slavio_timer_is_user(TimerContext *tc)
-{
- SLAVIO_TIMERState *s = tc->s;
- unsigned int timer_index = tc->timer_index;
-
- return timer_index != 0 && (s->cputimer_mode & (1 << (timer_index - 1)));
-}
-
-// Update count, set irq, update expire_time
-// Convert from ptimer countdown units
-static void slavio_timer_get_out(CPUTimerState *t)
-{
- uint64_t count, limit;
-
- if (t->limit == 0) { /* free-run system or processor counter */
- limit = TIMER_MAX_COUNT32;
- } else {
- limit = t->limit;
- }
- count = limit - PERIODS_TO_LIMIT(ptimer_get_count(t->timer));
-
- trace_slavio_timer_get_out(t->limit, t->counthigh, t->count);
- t->count = count & TIMER_COUNT_MASK32;
- t->counthigh = count >> 32;
-}
-
-// timer callback
-static void slavio_timer_irq(void *opaque)
-{
- TimerContext *tc = opaque;
- SLAVIO_TIMERState *s = tc->s;
- CPUTimerState *t = &s->cputimer[tc->timer_index];
-
- slavio_timer_get_out(t);
- trace_slavio_timer_irq(t->counthigh, t->count);
- /* if limit is 0 (free-run), there will be no match */
- if (t->limit != 0) {
- t->reached = TIMER_REACHED;
- }
- /* there is no interrupt if user timer or free-run */
- if (!slavio_timer_is_user(tc) && t->limit != 0) {
- qemu_irq_raise(t->irq);
- }
-}
-
-static uint64_t slavio_timer_mem_readl(void *opaque, hwaddr addr,
- unsigned size)
-{
- TimerContext *tc = opaque;
- SLAVIO_TIMERState *s = tc->s;
- uint32_t saddr, ret;
- unsigned int timer_index = tc->timer_index;
- CPUTimerState *t = &s->cputimer[timer_index];
-
- saddr = addr >> 2;
- switch (saddr) {
- case TIMER_LIMIT:
- // read limit (system counter mode) or read most signifying
- // part of counter (user mode)
- if (slavio_timer_is_user(tc)) {
- // read user timer MSW
- slavio_timer_get_out(t);
- ret = t->counthigh | t->reached;
- } else {
- // read limit
- // clear irq
- qemu_irq_lower(t->irq);
- t->reached = 0;
- ret = t->limit & TIMER_LIMIT_MASK32;
- }
- break;
- case TIMER_COUNTER:
- // read counter and reached bit (system mode) or read lsbits
- // of counter (user mode)
- slavio_timer_get_out(t);
- if (slavio_timer_is_user(tc)) { // read user timer LSW
- ret = t->count & TIMER_MAX_COUNT64;
- } else { // read limit
- ret = (t->count & TIMER_MAX_COUNT32) |
- t->reached;
- }
- break;
- case TIMER_STATUS:
- // only available in processor counter/timer
- // read start/stop status
- if (timer_index > 0) {
- ret = t->run;
- } else {
- ret = 0;
- }
- break;
- case TIMER_MODE:
- // only available in system counter
- // read user/system mode
- ret = s->cputimer_mode;
- break;
- default:
- trace_slavio_timer_mem_readl_invalid(addr);
- ret = 0;
- break;
- }
- trace_slavio_timer_mem_readl(addr, ret);
- return ret;
-}
-
-static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
-{
- TimerContext *tc = opaque;
- SLAVIO_TIMERState *s = tc->s;
- uint32_t saddr;
- unsigned int timer_index = tc->timer_index;
- CPUTimerState *t = &s->cputimer[timer_index];
-
- trace_slavio_timer_mem_writel(addr, val);
- saddr = addr >> 2;
- switch (saddr) {
- case TIMER_LIMIT:
- if (slavio_timer_is_user(tc)) {
- uint64_t count;
-
- // set user counter MSW, reset counter
- t->limit = TIMER_MAX_COUNT64;
- t->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
- t->reached = 0;
- count = ((uint64_t)t->counthigh << 32) | t->count;
- trace_slavio_timer_mem_writel_limit(timer_index, count);
- ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
- } else {
- // set limit, reset counter
- qemu_irq_lower(t->irq);
- t->limit = val & TIMER_MAX_COUNT32;
- if (t->timer) {
- if (t->limit == 0) { /* free-run */
- ptimer_set_limit(t->timer,
- LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
- } else {
- ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 1);
- }
- }
- }
- break;
- case TIMER_COUNTER:
- if (slavio_timer_is_user(tc)) {
- uint64_t count;
-
- // set user counter LSW, reset counter
- t->limit = TIMER_MAX_COUNT64;
- t->count = val & TIMER_MAX_COUNT64;
- t->reached = 0;
- count = ((uint64_t)t->counthigh) << 32 | t->count;
- trace_slavio_timer_mem_writel_limit(timer_index, count);
- ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
- } else {
- trace_slavio_timer_mem_writel_counter_invalid();
- }
- break;
- case TIMER_COUNTER_NORST:
- // set limit without resetting counter
- t->limit = val & TIMER_MAX_COUNT32;
- if (t->limit == 0) { /* free-run */
- ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
- } else {
- ptimer_set_limit(t->timer, LIMIT_TO_PERIODS(t->limit), 0);
- }
- break;
- case TIMER_STATUS:
- if (slavio_timer_is_user(tc)) {
- // start/stop user counter
- if (val & 1) {
- trace_slavio_timer_mem_writel_status_start(timer_index);
- ptimer_run(t->timer, 0);
- } else {
- trace_slavio_timer_mem_writel_status_stop(timer_index);
- ptimer_stop(t->timer);
- }
- }
- t->run = val & 1;
- break;
- case TIMER_MODE:
- if (timer_index == 0) {
- unsigned int i;
-
- for (i = 0; i < s->num_cpus; i++) {
- unsigned int processor = 1 << i;
- CPUTimerState *curr_timer = &s->cputimer[i + 1];
-
- // check for a change in timer mode for this processor
- if ((val & processor) != (s->cputimer_mode & processor)) {
- if (val & processor) { // counter -> user timer
- qemu_irq_lower(curr_timer->irq);
- // counters are always running
- if (!curr_timer->run) {
- ptimer_stop(curr_timer->timer);
- }
- // user timer limit is always the same
- curr_timer->limit = TIMER_MAX_COUNT64;
- ptimer_set_limit(curr_timer->timer,
- LIMIT_TO_PERIODS(curr_timer->limit),
- 1);
- // set this processors user timer bit in config
- // register
- s->cputimer_mode |= processor;
- trace_slavio_timer_mem_writel_mode_user(timer_index);
- } else { // user timer -> counter
- // start the counter
- ptimer_run(curr_timer->timer, 0);
- // clear this processors user timer bit in config
- // register
- s->cputimer_mode &= ~processor;
- trace_slavio_timer_mem_writel_mode_counter(timer_index);
- }
- }
- }
- } else {
- trace_slavio_timer_mem_writel_mode_invalid();
- }
- break;
- default:
- trace_slavio_timer_mem_writel_invalid(addr);
- break;
- }
-}
-
-static const MemoryRegionOps slavio_timer_mem_ops = {
- .read = slavio_timer_mem_readl,
- .write = slavio_timer_mem_writel,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4,
- },
-};
-
-static const VMStateDescription vmstate_timer = {
- .name ="timer",
- .version_id = 3,
- .minimum_version_id = 3,
- .fields = (VMStateField[]) {
- VMSTATE_UINT64(limit, CPUTimerState),
- VMSTATE_UINT32(count, CPUTimerState),
- VMSTATE_UINT32(counthigh, CPUTimerState),
- VMSTATE_UINT32(reached, CPUTimerState),
- VMSTATE_UINT32(run , CPUTimerState),
- VMSTATE_PTIMER(timer, CPUTimerState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static const VMStateDescription vmstate_slavio_timer = {
- .name ="slavio_timer",
- .version_id = 3,
- .minimum_version_id = 3,
- .fields = (VMStateField[]) {
- VMSTATE_STRUCT_ARRAY(cputimer, SLAVIO_TIMERState, MAX_CPUS + 1, 3,
- vmstate_timer, CPUTimerState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void slavio_timer_reset(DeviceState *d)
-{
- SLAVIO_TIMERState *s = SLAVIO_TIMER(d);
- unsigned int i;
- CPUTimerState *curr_timer;
-
- for (i = 0; i <= MAX_CPUS; i++) {
- curr_timer = &s->cputimer[i];
- curr_timer->limit = 0;
- curr_timer->count = 0;
- curr_timer->reached = 0;
- if (i <= s->num_cpus) {
- ptimer_set_limit(curr_timer->timer,
- LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
- ptimer_run(curr_timer->timer, 0);
- curr_timer->run = 1;
- }
- }
- s->cputimer_mode = 0;
-}
-
-static int slavio_timer_init1(SysBusDevice *dev)
-{
- SLAVIO_TIMERState *s = SLAVIO_TIMER(dev);
- QEMUBH *bh;
- unsigned int i;
- TimerContext *tc;
-
- for (i = 0; i <= MAX_CPUS; i++) {
- uint64_t size;
- char timer_name[20];
-
- tc = g_malloc0(sizeof(TimerContext));
- tc->s = s;
- tc->timer_index = i;
-
- bh = qemu_bh_new(slavio_timer_irq, tc);
- s->cputimer[i].timer = ptimer_init(bh);
- ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
-
- size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
- snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
- memory_region_init_io(&tc->iomem, OBJECT(s), &slavio_timer_mem_ops, tc,
- timer_name, size);
- sysbus_init_mmio(dev, &tc->iomem);
-
- sysbus_init_irq(dev, &s->cputimer[i].irq);
- }
-
- return 0;
-}
-
-static Property slavio_timer_properties[] = {
- DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void slavio_timer_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = slavio_timer_init1;
- dc->reset = slavio_timer_reset;
- dc->vmsd = &vmstate_slavio_timer;
- dc->props = slavio_timer_properties;
-}
-
-static const TypeInfo slavio_timer_info = {
- .name = TYPE_SLAVIO_TIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(SLAVIO_TIMERState),
- .class_init = slavio_timer_class_init,
-};
-
-static void slavio_timer_register_types(void)
-{
- type_register_static(&slavio_timer_info);
-}
-
-type_init(slavio_timer_register_types)
diff --git a/qemu/hw/timer/stm32f2xx_timer.c b/qemu/hw/timer/stm32f2xx_timer.c
deleted file mode 100644
index 55dacbbe3..000000000
--- a/qemu/hw/timer/stm32f2xx_timer.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * STM32F2XX Timer
- *
- * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
- *
- * 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 "qemu/osdep.h"
-#include "hw/timer/stm32f2xx_timer.h"
-
-#ifndef STM_TIMER_ERR_DEBUG
-#define STM_TIMER_ERR_DEBUG 0
-#endif
-
-#define DB_PRINT_L(lvl, fmt, args...) do { \
- if (STM_TIMER_ERR_DEBUG >= lvl) { \
- qemu_log("%s: " fmt, __func__, ## args); \
- } \
-} while (0);
-
-#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
-
-static void stm32f2xx_timer_set_alarm(STM32F2XXTimerState *s, int64_t now);
-
-static void stm32f2xx_timer_interrupt(void *opaque)
-{
- STM32F2XXTimerState *s = opaque;
-
- DB_PRINT("Interrupt\n");
-
- if (s->tim_dier & TIM_DIER_UIE && s->tim_cr1 & TIM_CR1_CEN) {
- s->tim_sr |= 1;
- qemu_irq_pulse(s->irq);
- stm32f2xx_timer_set_alarm(s, s->hit_time);
- }
-}
-
-static inline int64_t stm32f2xx_ns_to_ticks(STM32F2XXTimerState *s, int64_t t)
-{
- return muldiv64(t, s->freq_hz, 1000000000ULL) / (s->tim_psc + 1);
-}
-
-static void stm32f2xx_timer_set_alarm(STM32F2XXTimerState *s, int64_t now)
-{
- uint64_t ticks;
- int64_t now_ticks;
-
- if (s->tim_arr == 0) {
- return;
- }
-
- DB_PRINT("Alarm set at: 0x%x\n", s->tim_cr1);
-
- now_ticks = stm32f2xx_ns_to_ticks(s, now);
- ticks = s->tim_arr - (now_ticks - s->tick_offset);
-
- DB_PRINT("Alarm set in %d ticks\n", (int) ticks);
-
- s->hit_time = muldiv64((ticks + (uint64_t) now_ticks) * (s->tim_psc + 1),
- 1000000000ULL, s->freq_hz);
-
- timer_mod(s->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->hit_time);
- DB_PRINT("Wait Time: %" PRId64 " ticks\n", s->hit_time);
-}
-
-static void stm32f2xx_timer_reset(DeviceState *dev)
-{
- STM32F2XXTimerState *s = STM32F2XXTIMER(dev);
- int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
- s->tim_cr1 = 0;
- s->tim_cr2 = 0;
- s->tim_smcr = 0;
- s->tim_dier = 0;
- s->tim_sr = 0;
- s->tim_egr = 0;
- s->tim_ccmr1 = 0;
- s->tim_ccmr2 = 0;
- s->tim_ccer = 0;
- s->tim_psc = 0;
- s->tim_arr = 0;
- s->tim_ccr1 = 0;
- s->tim_ccr2 = 0;
- s->tim_ccr3 = 0;
- s->tim_ccr4 = 0;
- s->tim_dcr = 0;
- s->tim_dmar = 0;
- s->tim_or = 0;
-
- s->tick_offset = stm32f2xx_ns_to_ticks(s, now);
-}
-
-static uint64_t stm32f2xx_timer_read(void *opaque, hwaddr offset,
- unsigned size)
-{
- STM32F2XXTimerState *s = opaque;
-
- DB_PRINT("Read 0x%"HWADDR_PRIx"\n", offset);
-
- switch (offset) {
- case TIM_CR1:
- return s->tim_cr1;
- case TIM_CR2:
- return s->tim_cr2;
- case TIM_SMCR:
- return s->tim_smcr;
- case TIM_DIER:
- return s->tim_dier;
- case TIM_SR:
- return s->tim_sr;
- case TIM_EGR:
- return s->tim_egr;
- case TIM_CCMR1:
- return s->tim_ccmr1;
- case TIM_CCMR2:
- return s->tim_ccmr2;
- case TIM_CCER:
- return s->tim_ccer;
- case TIM_CNT:
- return stm32f2xx_ns_to_ticks(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) -
- s->tick_offset;
- case TIM_PSC:
- return s->tim_psc;
- case TIM_ARR:
- return s->tim_arr;
- case TIM_CCR1:
- return s->tim_ccr1;
- case TIM_CCR2:
- return s->tim_ccr2;
- case TIM_CCR3:
- return s->tim_ccr3;
- case TIM_CCR4:
- return s->tim_ccr4;
- case TIM_DCR:
- return s->tim_dcr;
- case TIM_DMAR:
- return s->tim_dmar;
- case TIM_OR:
- return s->tim_or;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, offset);
- }
-
- return 0;
-}
-
-static void stm32f2xx_timer_write(void *opaque, hwaddr offset,
- uint64_t val64, unsigned size)
-{
- STM32F2XXTimerState *s = opaque;
- uint32_t value = val64;
- int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- uint32_t timer_val = 0;
-
- DB_PRINT("Write 0x%x, 0x%"HWADDR_PRIx"\n", value, offset);
-
- switch (offset) {
- case TIM_CR1:
- s->tim_cr1 = value;
- return;
- case TIM_CR2:
- s->tim_cr2 = value;
- return;
- case TIM_SMCR:
- s->tim_smcr = value;
- return;
- case TIM_DIER:
- s->tim_dier = value;
- return;
- case TIM_SR:
- /* This is set by hardware and cleared by software */
- s->tim_sr &= value;
- return;
- case TIM_EGR:
- s->tim_egr = value;
- if (s->tim_egr & TIM_EGR_UG) {
- timer_val = 0;
- break;
- }
- return;
- case TIM_CCMR1:
- s->tim_ccmr1 = value;
- return;
- case TIM_CCMR2:
- s->tim_ccmr2 = value;
- return;
- case TIM_CCER:
- s->tim_ccer = value;
- return;
- case TIM_PSC:
- timer_val = stm32f2xx_ns_to_ticks(s, now) - s->tick_offset;
- s->tim_psc = value;
- value = timer_val;
- break;
- case TIM_CNT:
- timer_val = value;
- break;
- case TIM_ARR:
- s->tim_arr = value;
- stm32f2xx_timer_set_alarm(s, now);
- return;
- case TIM_CCR1:
- s->tim_ccr1 = value;
- return;
- case TIM_CCR2:
- s->tim_ccr2 = value;
- return;
- case TIM_CCR3:
- s->tim_ccr3 = value;
- return;
- case TIM_CCR4:
- s->tim_ccr4 = value;
- return;
- case TIM_DCR:
- s->tim_dcr = value;
- return;
- case TIM_DMAR:
- s->tim_dmar = value;
- return;
- case TIM_OR:
- s->tim_or = value;
- return;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, offset);
- return;
- }
-
- /* This means that a register write has affected the timer in a way that
- * requires a refresh of both tick_offset and the alarm.
- */
- s->tick_offset = stm32f2xx_ns_to_ticks(s, now) - timer_val;
- stm32f2xx_timer_set_alarm(s, now);
-}
-
-static const MemoryRegionOps stm32f2xx_timer_ops = {
- .read = stm32f2xx_timer_read,
- .write = stm32f2xx_timer_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_stm32f2xx_timer = {
- .name = TYPE_STM32F2XX_TIMER,
- .version_id = 1,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_INT64(tick_offset, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_cr1, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_cr2, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_smcr, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_dier, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_sr, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_egr, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_ccmr1, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_ccmr2, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_ccer, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_psc, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_arr, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_ccr1, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_ccr2, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_ccr3, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_ccr4, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_dcr, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_dmar, STM32F2XXTimerState),
- VMSTATE_UINT32(tim_or, STM32F2XXTimerState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static Property stm32f2xx_timer_properties[] = {
- DEFINE_PROP_UINT64("clock-frequency", struct STM32F2XXTimerState,
- freq_hz, 1000000000),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void stm32f2xx_timer_init(Object *obj)
-{
- STM32F2XXTimerState *s = STM32F2XXTIMER(obj);
-
- sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
-
- memory_region_init_io(&s->iomem, obj, &stm32f2xx_timer_ops, s,
- "stm32f2xx_timer", 0x4000);
- sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
-
- s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, stm32f2xx_timer_interrupt, s);
-}
-
-static void stm32f2xx_timer_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->reset = stm32f2xx_timer_reset;
- dc->props = stm32f2xx_timer_properties;
- dc->vmsd = &vmstate_stm32f2xx_timer;
-}
-
-static const TypeInfo stm32f2xx_timer_info = {
- .name = TYPE_STM32F2XX_TIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(STM32F2XXTimerState),
- .instance_init = stm32f2xx_timer_init,
- .class_init = stm32f2xx_timer_class_init,
-};
-
-static void stm32f2xx_timer_register_types(void)
-{
- type_register_static(&stm32f2xx_timer_info);
-}
-
-type_init(stm32f2xx_timer_register_types)
diff --git a/qemu/hw/timer/twl92230.c b/qemu/hw/timer/twl92230.c
deleted file mode 100644
index 7ba4e9a7c..000000000
--- a/qemu/hw/timer/twl92230.c
+++ /dev/null
@@ -1,889 +0,0 @@
-/*
- * TI TWL92230C energy-management companion device for the OMAP24xx.
- * Aka. Menelaus (N4200 MENELAUS1_V2.2)
- *
- * Copyright (C) 2008 Nokia Corporation
- * Written by Andrzej Zaborowski <andrew@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "qemu/timer.h"
-#include "hw/i2c/i2c.h"
-#include "sysemu/sysemu.h"
-#include "ui/console.h"
-#include "qemu/bcd.h"
-
-#define VERBOSE 1
-
-#define TYPE_TWL92230 "twl92230"
-#define TWL92230(obj) OBJECT_CHECK(MenelausState, (obj), TYPE_TWL92230)
-
-typedef struct MenelausState {
- I2CSlave parent_obj;
-
- int firstbyte;
- uint8_t reg;
-
- uint8_t vcore[5];
- uint8_t dcdc[3];
- uint8_t ldo[8];
- uint8_t sleep[2];
- uint8_t osc;
- uint8_t detect;
- uint16_t mask;
- uint16_t status;
- uint8_t dir;
- uint8_t inputs;
- uint8_t outputs;
- uint8_t bbsms;
- uint8_t pull[4];
- uint8_t mmc_ctrl[3];
- uint8_t mmc_debounce;
- struct {
- uint8_t ctrl;
- uint16_t comp;
- QEMUTimer *hz_tm;
- int64_t next;
- struct tm tm;
- struct tm new;
- struct tm alm;
- int sec_offset;
- int alm_sec;
- int next_comp;
- } rtc;
- uint16_t rtc_next_vmstate;
- qemu_irq out[4];
- uint8_t pwrbtn_state;
-} MenelausState;
-
-static inline void menelaus_update(MenelausState *s)
-{
- qemu_set_irq(s->out[3], s->status & ~s->mask);
-}
-
-static inline void menelaus_rtc_start(MenelausState *s)
-{
- s->rtc.next += qemu_clock_get_ms(rtc_clock);
- timer_mod(s->rtc.hz_tm, s->rtc.next);
-}
-
-static inline void menelaus_rtc_stop(MenelausState *s)
-{
- timer_del(s->rtc.hz_tm);
- s->rtc.next -= qemu_clock_get_ms(rtc_clock);
- if (s->rtc.next < 1)
- s->rtc.next = 1;
-}
-
-static void menelaus_rtc_update(MenelausState *s)
-{
- qemu_get_timedate(&s->rtc.tm, s->rtc.sec_offset);
-}
-
-static void menelaus_alm_update(MenelausState *s)
-{
- if ((s->rtc.ctrl & 3) == 3)
- s->rtc.alm_sec = qemu_timedate_diff(&s->rtc.alm) - s->rtc.sec_offset;
-}
-
-static void menelaus_rtc_hz(void *opaque)
-{
- MenelausState *s = (MenelausState *) opaque;
-
- s->rtc.next_comp --;
- s->rtc.alm_sec --;
- s->rtc.next += 1000;
- timer_mod(s->rtc.hz_tm, s->rtc.next);
- if ((s->rtc.ctrl >> 3) & 3) { /* EVERY */
- menelaus_rtc_update(s);
- if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec)
- s->status |= 1 << 8; /* RTCTMR */
- else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min)
- s->status |= 1 << 8; /* RTCTMR */
- else if (!s->rtc.tm.tm_hour)
- s->status |= 1 << 8; /* RTCTMR */
- } else
- s->status |= 1 << 8; /* RTCTMR */
- if ((s->rtc.ctrl >> 1) & 1) { /* RTC_AL_EN */
- if (s->rtc.alm_sec == 0)
- s->status |= 1 << 9; /* RTCALM */
- /* TODO: wake-up */
- }
- if (s->rtc.next_comp <= 0) {
- s->rtc.next -= muldiv64((int16_t) s->rtc.comp, 1000, 0x8000);
- s->rtc.next_comp = 3600;
- }
- menelaus_update(s);
-}
-
-static void menelaus_reset(I2CSlave *i2c)
-{
- MenelausState *s = TWL92230(i2c);
-
- s->reg = 0x00;
-
- s->vcore[0] = 0x0c; /* XXX: X-loader needs 0x8c? check! */
- s->vcore[1] = 0x05;
- s->vcore[2] = 0x02;
- s->vcore[3] = 0x0c;
- s->vcore[4] = 0x03;
- s->dcdc[0] = 0x33; /* Depends on wiring */
- s->dcdc[1] = 0x03;
- s->dcdc[2] = 0x00;
- s->ldo[0] = 0x95;
- s->ldo[1] = 0x7e;
- s->ldo[2] = 0x00;
- s->ldo[3] = 0x00; /* Depends on wiring */
- s->ldo[4] = 0x03; /* Depends on wiring */
- s->ldo[5] = 0x00;
- s->ldo[6] = 0x00;
- s->ldo[7] = 0x00;
- s->sleep[0] = 0x00;
- s->sleep[1] = 0x00;
- s->osc = 0x01;
- s->detect = 0x09;
- s->mask = 0x0fff;
- s->status = 0;
- s->dir = 0x07;
- s->outputs = 0x00;
- s->bbsms = 0x00;
- s->pull[0] = 0x00;
- s->pull[1] = 0x00;
- s->pull[2] = 0x00;
- s->pull[3] = 0x00;
- s->mmc_ctrl[0] = 0x03;
- s->mmc_ctrl[1] = 0xc0;
- s->mmc_ctrl[2] = 0x00;
- s->mmc_debounce = 0x05;
-
- if (s->rtc.ctrl & 1)
- menelaus_rtc_stop(s);
- s->rtc.ctrl = 0x00;
- s->rtc.comp = 0x0000;
- s->rtc.next = 1000;
- s->rtc.sec_offset = 0;
- s->rtc.next_comp = 1800;
- s->rtc.alm_sec = 1800;
- s->rtc.alm.tm_sec = 0x00;
- s->rtc.alm.tm_min = 0x00;
- s->rtc.alm.tm_hour = 0x00;
- s->rtc.alm.tm_mday = 0x01;
- s->rtc.alm.tm_mon = 0x00;
- s->rtc.alm.tm_year = 2004;
- menelaus_update(s);
-}
-
-static void menelaus_gpio_set(void *opaque, int line, int level)
-{
- MenelausState *s = (MenelausState *) opaque;
-
- if (line < 3) {
- /* No interrupt generated */
- s->inputs &= ~(1 << line);
- s->inputs |= level << line;
- return;
- }
-
- if (!s->pwrbtn_state && level) {
- s->status |= 1 << 11; /* PSHBTN */
- menelaus_update(s);
- }
- s->pwrbtn_state = level;
-}
-
-#define MENELAUS_REV 0x01
-#define MENELAUS_VCORE_CTRL1 0x02
-#define MENELAUS_VCORE_CTRL2 0x03
-#define MENELAUS_VCORE_CTRL3 0x04
-#define MENELAUS_VCORE_CTRL4 0x05
-#define MENELAUS_VCORE_CTRL5 0x06
-#define MENELAUS_DCDC_CTRL1 0x07
-#define MENELAUS_DCDC_CTRL2 0x08
-#define MENELAUS_DCDC_CTRL3 0x09
-#define MENELAUS_LDO_CTRL1 0x0a
-#define MENELAUS_LDO_CTRL2 0x0b
-#define MENELAUS_LDO_CTRL3 0x0c
-#define MENELAUS_LDO_CTRL4 0x0d
-#define MENELAUS_LDO_CTRL5 0x0e
-#define MENELAUS_LDO_CTRL6 0x0f
-#define MENELAUS_LDO_CTRL7 0x10
-#define MENELAUS_LDO_CTRL8 0x11
-#define MENELAUS_SLEEP_CTRL1 0x12
-#define MENELAUS_SLEEP_CTRL2 0x13
-#define MENELAUS_DEVICE_OFF 0x14
-#define MENELAUS_OSC_CTRL 0x15
-#define MENELAUS_DETECT_CTRL 0x16
-#define MENELAUS_INT_MASK1 0x17
-#define MENELAUS_INT_MASK2 0x18
-#define MENELAUS_INT_STATUS1 0x19
-#define MENELAUS_INT_STATUS2 0x1a
-#define MENELAUS_INT_ACK1 0x1b
-#define MENELAUS_INT_ACK2 0x1c
-#define MENELAUS_GPIO_CTRL 0x1d
-#define MENELAUS_GPIO_IN 0x1e
-#define MENELAUS_GPIO_OUT 0x1f
-#define MENELAUS_BBSMS 0x20
-#define MENELAUS_RTC_CTRL 0x21
-#define MENELAUS_RTC_UPDATE 0x22
-#define MENELAUS_RTC_SEC 0x23
-#define MENELAUS_RTC_MIN 0x24
-#define MENELAUS_RTC_HR 0x25
-#define MENELAUS_RTC_DAY 0x26
-#define MENELAUS_RTC_MON 0x27
-#define MENELAUS_RTC_YR 0x28
-#define MENELAUS_RTC_WKDAY 0x29
-#define MENELAUS_RTC_AL_SEC 0x2a
-#define MENELAUS_RTC_AL_MIN 0x2b
-#define MENELAUS_RTC_AL_HR 0x2c
-#define MENELAUS_RTC_AL_DAY 0x2d
-#define MENELAUS_RTC_AL_MON 0x2e
-#define MENELAUS_RTC_AL_YR 0x2f
-#define MENELAUS_RTC_COMP_MSB 0x30
-#define MENELAUS_RTC_COMP_LSB 0x31
-#define MENELAUS_S1_PULL_EN 0x32
-#define MENELAUS_S1_PULL_DIR 0x33
-#define MENELAUS_S2_PULL_EN 0x34
-#define MENELAUS_S2_PULL_DIR 0x35
-#define MENELAUS_MCT_CTRL1 0x36
-#define MENELAUS_MCT_CTRL2 0x37
-#define MENELAUS_MCT_CTRL3 0x38
-#define MENELAUS_MCT_PIN_ST 0x39
-#define MENELAUS_DEBOUNCE1 0x3a
-
-static uint8_t menelaus_read(void *opaque, uint8_t addr)
-{
- MenelausState *s = (MenelausState *) opaque;
- int reg = 0;
-
- switch (addr) {
- case MENELAUS_REV:
- return 0x22;
-
- case MENELAUS_VCORE_CTRL5: reg ++;
- case MENELAUS_VCORE_CTRL4: reg ++;
- case MENELAUS_VCORE_CTRL3: reg ++;
- case MENELAUS_VCORE_CTRL2: reg ++;
- case MENELAUS_VCORE_CTRL1:
- return s->vcore[reg];
-
- case MENELAUS_DCDC_CTRL3: reg ++;
- case MENELAUS_DCDC_CTRL2: reg ++;
- case MENELAUS_DCDC_CTRL1:
- return s->dcdc[reg];
-
- case MENELAUS_LDO_CTRL8: reg ++;
- case MENELAUS_LDO_CTRL7: reg ++;
- case MENELAUS_LDO_CTRL6: reg ++;
- case MENELAUS_LDO_CTRL5: reg ++;
- case MENELAUS_LDO_CTRL4: reg ++;
- case MENELAUS_LDO_CTRL3: reg ++;
- case MENELAUS_LDO_CTRL2: reg ++;
- case MENELAUS_LDO_CTRL1:
- return s->ldo[reg];
-
- case MENELAUS_SLEEP_CTRL2: reg ++;
- case MENELAUS_SLEEP_CTRL1:
- return s->sleep[reg];
-
- case MENELAUS_DEVICE_OFF:
- return 0;
-
- case MENELAUS_OSC_CTRL:
- return s->osc | (1 << 7); /* CLK32K_GOOD */
-
- case MENELAUS_DETECT_CTRL:
- return s->detect;
-
- case MENELAUS_INT_MASK1:
- return (s->mask >> 0) & 0xff;
- case MENELAUS_INT_MASK2:
- return (s->mask >> 8) & 0xff;
-
- case MENELAUS_INT_STATUS1:
- return (s->status >> 0) & 0xff;
- case MENELAUS_INT_STATUS2:
- return (s->status >> 8) & 0xff;
-
- case MENELAUS_INT_ACK1:
- case MENELAUS_INT_ACK2:
- return 0;
-
- case MENELAUS_GPIO_CTRL:
- return s->dir;
- case MENELAUS_GPIO_IN:
- return s->inputs | (~s->dir & s->outputs);
- case MENELAUS_GPIO_OUT:
- return s->outputs;
-
- case MENELAUS_BBSMS:
- return s->bbsms;
-
- case MENELAUS_RTC_CTRL:
- return s->rtc.ctrl;
- case MENELAUS_RTC_UPDATE:
- return 0x00;
- case MENELAUS_RTC_SEC:
- menelaus_rtc_update(s);
- return to_bcd(s->rtc.tm.tm_sec);
- case MENELAUS_RTC_MIN:
- menelaus_rtc_update(s);
- return to_bcd(s->rtc.tm.tm_min);
- case MENELAUS_RTC_HR:
- menelaus_rtc_update(s);
- if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */
- return to_bcd((s->rtc.tm.tm_hour % 12) + 1) |
- (!!(s->rtc.tm.tm_hour >= 12) << 7); /* PM_nAM */
- else
- return to_bcd(s->rtc.tm.tm_hour);
- case MENELAUS_RTC_DAY:
- menelaus_rtc_update(s);
- return to_bcd(s->rtc.tm.tm_mday);
- case MENELAUS_RTC_MON:
- menelaus_rtc_update(s);
- return to_bcd(s->rtc.tm.tm_mon + 1);
- case MENELAUS_RTC_YR:
- menelaus_rtc_update(s);
- return to_bcd(s->rtc.tm.tm_year - 2000);
- case MENELAUS_RTC_WKDAY:
- menelaus_rtc_update(s);
- return to_bcd(s->rtc.tm.tm_wday);
- case MENELAUS_RTC_AL_SEC:
- return to_bcd(s->rtc.alm.tm_sec);
- case MENELAUS_RTC_AL_MIN:
- return to_bcd(s->rtc.alm.tm_min);
- case MENELAUS_RTC_AL_HR:
- if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */
- return to_bcd((s->rtc.alm.tm_hour % 12) + 1) |
- (!!(s->rtc.alm.tm_hour >= 12) << 7);/* AL_PM_nAM */
- else
- return to_bcd(s->rtc.alm.tm_hour);
- case MENELAUS_RTC_AL_DAY:
- return to_bcd(s->rtc.alm.tm_mday);
- case MENELAUS_RTC_AL_MON:
- return to_bcd(s->rtc.alm.tm_mon + 1);
- case MENELAUS_RTC_AL_YR:
- return to_bcd(s->rtc.alm.tm_year - 2000);
- case MENELAUS_RTC_COMP_MSB:
- return (s->rtc.comp >> 8) & 0xff;
- case MENELAUS_RTC_COMP_LSB:
- return (s->rtc.comp >> 0) & 0xff;
-
- case MENELAUS_S1_PULL_EN:
- return s->pull[0];
- case MENELAUS_S1_PULL_DIR:
- return s->pull[1];
- case MENELAUS_S2_PULL_EN:
- return s->pull[2];
- case MENELAUS_S2_PULL_DIR:
- return s->pull[3];
-
- case MENELAUS_MCT_CTRL3: reg ++;
- case MENELAUS_MCT_CTRL2: reg ++;
- case MENELAUS_MCT_CTRL1:
- return s->mmc_ctrl[reg];
- case MENELAUS_MCT_PIN_ST:
- /* TODO: return the real Card Detect */
- return 0;
- case MENELAUS_DEBOUNCE1:
- return s->mmc_debounce;
-
- default:
-#ifdef VERBOSE
- printf("%s: unknown register %02x\n", __FUNCTION__, addr);
-#endif
- break;
- }
- return 0;
-}
-
-static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
-{
- MenelausState *s = (MenelausState *) opaque;
- int line;
- int reg = 0;
- struct tm tm;
-
- switch (addr) {
- case MENELAUS_VCORE_CTRL1:
- s->vcore[0] = (value & 0xe) | MIN(value & 0x1f, 0x12);
- break;
- case MENELAUS_VCORE_CTRL2:
- s->vcore[1] = value;
- break;
- case MENELAUS_VCORE_CTRL3:
- s->vcore[2] = MIN(value & 0x1f, 0x12);
- break;
- case MENELAUS_VCORE_CTRL4:
- s->vcore[3] = MIN(value & 0x1f, 0x12);
- break;
- case MENELAUS_VCORE_CTRL5:
- s->vcore[4] = value & 3;
- /* XXX
- * auto set to 3 on M_Active, nRESWARM
- * auto set to 0 on M_WaitOn, M_Backup
- */
- break;
-
- case MENELAUS_DCDC_CTRL1:
- s->dcdc[0] = value & 0x3f;
- break;
- case MENELAUS_DCDC_CTRL2:
- s->dcdc[1] = value & 0x07;
- /* XXX
- * auto set to 3 on M_Active, nRESWARM
- * auto set to 0 on M_WaitOn, M_Backup
- */
- break;
- case MENELAUS_DCDC_CTRL3:
- s->dcdc[2] = value & 0x07;
- break;
-
- case MENELAUS_LDO_CTRL1:
- s->ldo[0] = value;
- break;
- case MENELAUS_LDO_CTRL2:
- s->ldo[1] = value & 0x7f;
- /* XXX
- * auto set to 0x7e on M_WaitOn, M_Backup
- */
- break;
- case MENELAUS_LDO_CTRL3:
- s->ldo[2] = value & 3;
- /* XXX
- * auto set to 3 on M_Active, nRESWARM
- * auto set to 0 on M_WaitOn, M_Backup
- */
- break;
- case MENELAUS_LDO_CTRL4:
- s->ldo[3] = value & 3;
- /* XXX
- * auto set to 3 on M_Active, nRESWARM
- * auto set to 0 on M_WaitOn, M_Backup
- */
- break;
- case MENELAUS_LDO_CTRL5:
- s->ldo[4] = value & 3;
- /* XXX
- * auto set to 3 on M_Active, nRESWARM
- * auto set to 0 on M_WaitOn, M_Backup
- */
- break;
- case MENELAUS_LDO_CTRL6:
- s->ldo[5] = value & 3;
- break;
- case MENELAUS_LDO_CTRL7:
- s->ldo[6] = value & 3;
- break;
- case MENELAUS_LDO_CTRL8:
- s->ldo[7] = value & 3;
- break;
-
- case MENELAUS_SLEEP_CTRL2: reg ++;
- case MENELAUS_SLEEP_CTRL1:
- s->sleep[reg] = value;
- break;
-
- case MENELAUS_DEVICE_OFF:
- if (value & 1) {
- menelaus_reset(I2C_SLAVE(s));
- }
- break;
-
- case MENELAUS_OSC_CTRL:
- s->osc = value & 7;
- break;
-
- case MENELAUS_DETECT_CTRL:
- s->detect = value & 0x7f;
- break;
-
- case MENELAUS_INT_MASK1:
- s->mask &= 0xf00;
- s->mask |= value << 0;
- menelaus_update(s);
- break;
- case MENELAUS_INT_MASK2:
- s->mask &= 0x0ff;
- s->mask |= value << 8;
- menelaus_update(s);
- break;
-
- case MENELAUS_INT_ACK1:
- s->status &= ~(((uint16_t) value) << 0);
- menelaus_update(s);
- break;
- case MENELAUS_INT_ACK2:
- s->status &= ~(((uint16_t) value) << 8);
- menelaus_update(s);
- break;
-
- case MENELAUS_GPIO_CTRL:
- for (line = 0; line < 3; line ++) {
- if (((s->dir ^ value) >> line) & 1) {
- qemu_set_irq(s->out[line],
- ((s->outputs & ~s->dir) >> line) & 1);
- }
- }
- s->dir = value & 0x67;
- break;
- case MENELAUS_GPIO_OUT:
- for (line = 0; line < 3; line ++) {
- if ((((s->outputs ^ value) & ~s->dir) >> line) & 1) {
- qemu_set_irq(s->out[line], (s->outputs >> line) & 1);
- }
- }
- s->outputs = value & 0x07;
- break;
-
- case MENELAUS_BBSMS:
- s->bbsms = 0x0d;
- break;
-
- case MENELAUS_RTC_CTRL:
- if ((s->rtc.ctrl ^ value) & 1) { /* RTC_EN */
- if (value & 1)
- menelaus_rtc_start(s);
- else
- menelaus_rtc_stop(s);
- }
- s->rtc.ctrl = value & 0x1f;
- menelaus_alm_update(s);
- break;
- case MENELAUS_RTC_UPDATE:
- menelaus_rtc_update(s);
- memcpy(&tm, &s->rtc.tm, sizeof(tm));
- switch (value & 0xf) {
- case 0:
- break;
- case 1:
- tm.tm_sec = s->rtc.new.tm_sec;
- break;
- case 2:
- tm.tm_min = s->rtc.new.tm_min;
- break;
- case 3:
- if (s->rtc.new.tm_hour > 23)
- goto rtc_badness;
- tm.tm_hour = s->rtc.new.tm_hour;
- break;
- case 4:
- if (s->rtc.new.tm_mday < 1)
- goto rtc_badness;
- /* TODO check range */
- tm.tm_mday = s->rtc.new.tm_mday;
- break;
- case 5:
- if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
- goto rtc_badness;
- tm.tm_mon = s->rtc.new.tm_mon;
- break;
- case 6:
- tm.tm_year = s->rtc.new.tm_year;
- break;
- case 7:
- /* TODO set .tm_mday instead */
- tm.tm_wday = s->rtc.new.tm_wday;
- break;
- case 8:
- if (s->rtc.new.tm_hour > 23)
- goto rtc_badness;
- if (s->rtc.new.tm_mday < 1)
- goto rtc_badness;
- if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
- goto rtc_badness;
- tm.tm_sec = s->rtc.new.tm_sec;
- tm.tm_min = s->rtc.new.tm_min;
- tm.tm_hour = s->rtc.new.tm_hour;
- tm.tm_mday = s->rtc.new.tm_mday;
- tm.tm_mon = s->rtc.new.tm_mon;
- tm.tm_year = s->rtc.new.tm_year;
- break;
- rtc_badness:
- default:
- fprintf(stderr, "%s: bad RTC_UPDATE value %02x\n",
- __FUNCTION__, value);
- s->status |= 1 << 10; /* RTCERR */
- menelaus_update(s);
- }
- s->rtc.sec_offset = qemu_timedate_diff(&tm);
- break;
- case MENELAUS_RTC_SEC:
- s->rtc.tm.tm_sec = from_bcd(value & 0x7f);
- break;
- case MENELAUS_RTC_MIN:
- s->rtc.tm.tm_min = from_bcd(value & 0x7f);
- break;
- case MENELAUS_RTC_HR:
- s->rtc.tm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */
- MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
- from_bcd(value & 0x3f);
- break;
- case MENELAUS_RTC_DAY:
- s->rtc.tm.tm_mday = from_bcd(value);
- break;
- case MENELAUS_RTC_MON:
- s->rtc.tm.tm_mon = MAX(1, from_bcd(value)) - 1;
- break;
- case MENELAUS_RTC_YR:
- s->rtc.tm.tm_year = 2000 + from_bcd(value);
- break;
- case MENELAUS_RTC_WKDAY:
- s->rtc.tm.tm_mday = from_bcd(value);
- break;
- case MENELAUS_RTC_AL_SEC:
- s->rtc.alm.tm_sec = from_bcd(value & 0x7f);
- menelaus_alm_update(s);
- break;
- case MENELAUS_RTC_AL_MIN:
- s->rtc.alm.tm_min = from_bcd(value & 0x7f);
- menelaus_alm_update(s);
- break;
- case MENELAUS_RTC_AL_HR:
- s->rtc.alm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */
- MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
- from_bcd(value & 0x3f);
- menelaus_alm_update(s);
- break;
- case MENELAUS_RTC_AL_DAY:
- s->rtc.alm.tm_mday = from_bcd(value);
- menelaus_alm_update(s);
- break;
- case MENELAUS_RTC_AL_MON:
- s->rtc.alm.tm_mon = MAX(1, from_bcd(value)) - 1;
- menelaus_alm_update(s);
- break;
- case MENELAUS_RTC_AL_YR:
- s->rtc.alm.tm_year = 2000 + from_bcd(value);
- menelaus_alm_update(s);
- break;
- case MENELAUS_RTC_COMP_MSB:
- s->rtc.comp &= 0xff;
- s->rtc.comp |= value << 8;
- break;
- case MENELAUS_RTC_COMP_LSB:
- s->rtc.comp &= 0xff << 8;
- s->rtc.comp |= value;
- break;
-
- case MENELAUS_S1_PULL_EN:
- s->pull[0] = value;
- break;
- case MENELAUS_S1_PULL_DIR:
- s->pull[1] = value & 0x1f;
- break;
- case MENELAUS_S2_PULL_EN:
- s->pull[2] = value;
- break;
- case MENELAUS_S2_PULL_DIR:
- s->pull[3] = value & 0x1f;
- break;
-
- case MENELAUS_MCT_CTRL1:
- s->mmc_ctrl[0] = value & 0x7f;
- break;
- case MENELAUS_MCT_CTRL2:
- s->mmc_ctrl[1] = value;
- /* TODO update Card Detect interrupts */
- break;
- case MENELAUS_MCT_CTRL3:
- s->mmc_ctrl[2] = value & 0xf;
- break;
- case MENELAUS_DEBOUNCE1:
- s->mmc_debounce = value & 0x3f;
- break;
-
- default:
-#ifdef VERBOSE
- printf("%s: unknown register %02x\n", __FUNCTION__, addr);
-#endif
- }
-}
-
-static void menelaus_event(I2CSlave *i2c, enum i2c_event event)
-{
- MenelausState *s = TWL92230(i2c);
-
- if (event == I2C_START_SEND)
- s->firstbyte = 1;
-}
-
-static int menelaus_tx(I2CSlave *i2c, uint8_t data)
-{
- MenelausState *s = TWL92230(i2c);
-
- /* Interpret register address byte */
- if (s->firstbyte) {
- s->reg = data;
- s->firstbyte = 0;
- } else
- menelaus_write(s, s->reg ++, data);
-
- return 0;
-}
-
-static int menelaus_rx(I2CSlave *i2c)
-{
- MenelausState *s = TWL92230(i2c);
-
- return menelaus_read(s, s->reg ++);
-}
-
-/* Save restore 32 bit int as uint16_t
- This is a Big hack, but it is how the old state did it.
- Or we broke compatibility in the state, or we can't use struct tm
- */
-
-static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
-{
- int *v = pv;
- *v = qemu_get_be16(f);
- return 0;
-}
-
-static void put_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
-{
- int *v = pv;
- qemu_put_be16(f, *v);
-}
-
-static const VMStateInfo vmstate_hack_int32_as_uint16 = {
- .name = "int32_as_uint16",
- .get = get_int32_as_uint16,
- .put = put_int32_as_uint16,
-};
-
-#define VMSTATE_UINT16_HACK(_f, _s) \
- VMSTATE_SINGLE(_f, _s, 0, vmstate_hack_int32_as_uint16, int32_t)
-
-
-static const VMStateDescription vmstate_menelaus_tm = {
- .name = "menelaus_tm",
- .version_id = 0,
- .minimum_version_id = 0,
- .fields = (VMStateField[]) {
- VMSTATE_UINT16_HACK(tm_sec, struct tm),
- VMSTATE_UINT16_HACK(tm_min, struct tm),
- VMSTATE_UINT16_HACK(tm_hour, struct tm),
- VMSTATE_UINT16_HACK(tm_mday, struct tm),
- VMSTATE_UINT16_HACK(tm_min, struct tm),
- VMSTATE_UINT16_HACK(tm_year, struct tm),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static void menelaus_pre_save(void *opaque)
-{
- MenelausState *s = opaque;
- /* Should be <= 1000 */
- s->rtc_next_vmstate = s->rtc.next - qemu_clock_get_ms(rtc_clock);
-}
-
-static int menelaus_post_load(void *opaque, int version_id)
-{
- MenelausState *s = opaque;
-
- if (s->rtc.ctrl & 1) /* RTC_EN */
- menelaus_rtc_stop(s);
-
- s->rtc.next = s->rtc_next_vmstate;
-
- menelaus_alm_update(s);
- menelaus_update(s);
- if (s->rtc.ctrl & 1) /* RTC_EN */
- menelaus_rtc_start(s);
- return 0;
-}
-
-static const VMStateDescription vmstate_menelaus = {
- .name = "menelaus",
- .version_id = 0,
- .minimum_version_id = 0,
- .pre_save = menelaus_pre_save,
- .post_load = menelaus_post_load,
- .fields = (VMStateField[]) {
- VMSTATE_INT32(firstbyte, MenelausState),
- VMSTATE_UINT8(reg, MenelausState),
- VMSTATE_UINT8_ARRAY(vcore, MenelausState, 5),
- VMSTATE_UINT8_ARRAY(dcdc, MenelausState, 3),
- VMSTATE_UINT8_ARRAY(ldo, MenelausState, 8),
- VMSTATE_UINT8_ARRAY(sleep, MenelausState, 2),
- VMSTATE_UINT8(osc, MenelausState),
- VMSTATE_UINT8(detect, MenelausState),
- VMSTATE_UINT16(mask, MenelausState),
- VMSTATE_UINT16(status, MenelausState),
- VMSTATE_UINT8(dir, MenelausState),
- VMSTATE_UINT8(inputs, MenelausState),
- VMSTATE_UINT8(outputs, MenelausState),
- VMSTATE_UINT8(bbsms, MenelausState),
- VMSTATE_UINT8_ARRAY(pull, MenelausState, 4),
- VMSTATE_UINT8_ARRAY(mmc_ctrl, MenelausState, 3),
- VMSTATE_UINT8(mmc_debounce, MenelausState),
- VMSTATE_UINT8(rtc.ctrl, MenelausState),
- VMSTATE_UINT16(rtc.comp, MenelausState),
- VMSTATE_UINT16(rtc_next_vmstate, MenelausState),
- VMSTATE_STRUCT(rtc.new, MenelausState, 0, vmstate_menelaus_tm,
- struct tm),
- VMSTATE_STRUCT(rtc.alm, MenelausState, 0, vmstate_menelaus_tm,
- struct tm),
- VMSTATE_UINT8(pwrbtn_state, MenelausState),
- VMSTATE_I2C_SLAVE(parent_obj, MenelausState),
- VMSTATE_END_OF_LIST()
- }
-};
-
-static int twl92230_init(I2CSlave *i2c)
-{
- DeviceState *dev = DEVICE(i2c);
- MenelausState *s = TWL92230(i2c);
-
- s->rtc.hz_tm = timer_new_ms(rtc_clock, menelaus_rtc_hz, s);
- /* Three output pins plus one interrupt pin. */
- qdev_init_gpio_out(dev, s->out, 4);
-
- /* Three input pins plus one power-button pin. */
- qdev_init_gpio_in(dev, menelaus_gpio_set, 4);
-
- menelaus_reset(i2c);
-
- return 0;
-}
-
-static void twl92230_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
-
- sc->init = twl92230_init;
- sc->event = menelaus_event;
- sc->recv = menelaus_rx;
- sc->send = menelaus_tx;
- dc->vmsd = &vmstate_menelaus;
-}
-
-static const TypeInfo twl92230_info = {
- .name = TYPE_TWL92230,
- .parent = TYPE_I2C_SLAVE,
- .instance_size = sizeof(MenelausState),
- .class_init = twl92230_class_init,
-};
-
-static void twl92230_register_types(void)
-{
- type_register_static(&twl92230_info);
-}
-
-type_init(twl92230_register_types)
diff --git a/qemu/hw/timer/xilinx_timer.c b/qemu/hw/timer/xilinx_timer.c
deleted file mode 100644
index 2ea970dc9..000000000
--- a/qemu/hw/timer/xilinx_timer.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * QEMU model of the Xilinx timer block.
- *
- * Copyright (c) 2009 Edgar E. Iglesias.
- *
- * 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 "qemu/osdep.h"
-#include "hw/sysbus.h"
-#include "hw/ptimer.h"
-#include "qemu/log.h"
-#include "qemu/main-loop.h"
-
-#define D(x)
-
-#define R_TCSR 0
-#define R_TLR 1
-#define R_TCR 2
-#define R_MAX 4
-
-#define TCSR_MDT (1<<0)
-#define TCSR_UDT (1<<1)
-#define TCSR_GENT (1<<2)
-#define TCSR_CAPT (1<<3)
-#define TCSR_ARHT (1<<4)
-#define TCSR_LOAD (1<<5)
-#define TCSR_ENIT (1<<6)
-#define TCSR_ENT (1<<7)
-#define TCSR_TINT (1<<8)
-#define TCSR_PWMA (1<<9)
-#define TCSR_ENALL (1<<10)
-
-struct xlx_timer
-{
- QEMUBH *bh;
- ptimer_state *ptimer;
- void *parent;
- int nr; /* for debug. */
-
- unsigned long timer_div;
-
- uint32_t regs[R_MAX];
-};
-
-#define TYPE_XILINX_TIMER "xlnx.xps-timer"
-#define XILINX_TIMER(obj) \
- OBJECT_CHECK(struct timerblock, (obj), TYPE_XILINX_TIMER)
-
-struct timerblock
-{
- SysBusDevice parent_obj;
-
- MemoryRegion mmio;
- qemu_irq irq;
- uint8_t one_timer_only;
- uint32_t freq_hz;
- struct xlx_timer *timers;
-};
-
-static inline unsigned int num_timers(struct timerblock *t)
-{
- return 2 - t->one_timer_only;
-}
-
-static inline unsigned int timer_from_addr(hwaddr addr)
-{
- /* Timers get a 4x32bit control reg area each. */
- return addr >> 2;
-}
-
-static void timer_update_irq(struct timerblock *t)
-{
- unsigned int i, irq = 0;
- uint32_t csr;
-
- for (i = 0; i < num_timers(t); i++) {
- csr = t->timers[i].regs[R_TCSR];
- irq |= (csr & TCSR_TINT) && (csr & TCSR_ENIT);
- }
-
- /* All timers within the same slave share a single IRQ line. */
- qemu_set_irq(t->irq, !!irq);
-}
-
-static uint64_t
-timer_read(void *opaque, hwaddr addr, unsigned int size)
-{
- struct timerblock *t = opaque;
- struct xlx_timer *xt;
- uint32_t r = 0;
- unsigned int timer;
-
- addr >>= 2;
- timer = timer_from_addr(addr);
- xt = &t->timers[timer];
- /* Further decoding to address a specific timers reg. */
- addr &= 0x3;
- switch (addr)
- {
- case R_TCR:
- r = ptimer_get_count(xt->ptimer);
- if (!(xt->regs[R_TCSR] & TCSR_UDT))
- r = ~r;
- D(qemu_log("xlx_timer t=%d read counter=%x udt=%d\n",
- timer, r, xt->regs[R_TCSR] & TCSR_UDT));
- break;
- default:
- if (addr < ARRAY_SIZE(xt->regs))
- r = xt->regs[addr];
- break;
-
- }
- D(fprintf(stderr, "%s timer=%d %x=%x\n", __func__, timer, addr * 4, r));
- return r;
-}
-
-static void timer_enable(struct xlx_timer *xt)
-{
- uint64_t count;
-
- D(fprintf(stderr, "%s timer=%d down=%d\n", __func__,
- xt->nr, xt->regs[R_TCSR] & TCSR_UDT));
-
- ptimer_stop(xt->ptimer);
-
- if (xt->regs[R_TCSR] & TCSR_UDT)
- count = xt->regs[R_TLR];
- else
- count = ~0 - xt->regs[R_TLR];
- ptimer_set_limit(xt->ptimer, count, 1);
- ptimer_run(xt->ptimer, 1);
-}
-
-static void
-timer_write(void *opaque, hwaddr addr,
- uint64_t val64, unsigned int size)
-{
- struct timerblock *t = opaque;
- struct xlx_timer *xt;
- unsigned int timer;
- uint32_t value = val64;
-
- addr >>= 2;
- timer = timer_from_addr(addr);
- xt = &t->timers[timer];
- D(fprintf(stderr, "%s addr=%x val=%x (timer=%d off=%d)\n",
- __func__, addr * 4, value, timer, addr & 3));
- /* Further decoding to address a specific timers reg. */
- addr &= 3;
- switch (addr)
- {
- case R_TCSR:
- if (value & TCSR_TINT)
- value &= ~TCSR_TINT;
-
- xt->regs[addr] = value & 0x7ff;
- if (value & TCSR_ENT)
- timer_enable(xt);
- break;
-
- default:
- if (addr < ARRAY_SIZE(xt->regs))
- xt->regs[addr] = value;
- break;
- }
- timer_update_irq(t);
-}
-
-static const MemoryRegionOps timer_ops = {
- .read = timer_read,
- .write = timer_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 4,
- .max_access_size = 4
- }
-};
-
-static void timer_hit(void *opaque)
-{
- struct xlx_timer *xt = opaque;
- struct timerblock *t = xt->parent;
- D(fprintf(stderr, "%s %d\n", __func__, xt->nr));
- xt->regs[R_TCSR] |= TCSR_TINT;
-
- if (xt->regs[R_TCSR] & TCSR_ARHT)
- timer_enable(xt);
- timer_update_irq(t);
-}
-
-static void xilinx_timer_realize(DeviceState *dev, Error **errp)
-{
- struct timerblock *t = XILINX_TIMER(dev);
- unsigned int i;
-
- /* Init all the ptimers. */
- t->timers = g_malloc0(sizeof t->timers[0] * num_timers(t));
- for (i = 0; i < num_timers(t); i++) {
- struct xlx_timer *xt = &t->timers[i];
-
- xt->parent = t;
- xt->nr = i;
- xt->bh = qemu_bh_new(timer_hit, xt);
- xt->ptimer = ptimer_init(xt->bh);
- ptimer_set_freq(xt->ptimer, t->freq_hz);
- }
-
- memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",
- R_MAX * 4 * num_timers(t));
- sysbus_init_mmio(SYS_BUS_DEVICE(dev), &t->mmio);
-}
-
-static void xilinx_timer_init(Object *obj)
-{
- struct timerblock *t = XILINX_TIMER(obj);
-
- /* All timers share a single irq line. */
- sysbus_init_irq(SYS_BUS_DEVICE(obj), &t->irq);
-}
-
-static Property xilinx_timer_properties[] = {
- DEFINE_PROP_UINT32("clock-frequency", struct timerblock, freq_hz,
- 62 * 1000000),
- DEFINE_PROP_UINT8("one-timer-only", struct timerblock, one_timer_only, 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static void xilinx_timer_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = xilinx_timer_realize;
- dc->props = xilinx_timer_properties;
-}
-
-static const TypeInfo xilinx_timer_info = {
- .name = TYPE_XILINX_TIMER,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(struct timerblock),
- .instance_init = xilinx_timer_init,
- .class_init = xilinx_timer_class_init,
-};
-
-static void xilinx_timer_register_types(void)
-{
- type_register_static(&xilinx_timer_info);
-}
-
-type_init(xilinx_timer_register_types)