]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/timer/etraxfs_timer.c
hw/timer/slavio_timer: Allow 64-bit accesses
[mirror_qemu.git] / hw / timer / etraxfs_timer.c
index 6dd107209203f87c2327739d04c7bbb1ae4b21e0..48f2e3ade2f060ddc3ba0430bd1ed32b843d9cfc 100644 (file)
  * 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 "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "qemu/module.h"
 #include "qemu/timer.h"
+#include "hw/irq.h"
 #include "hw/ptimer.h"
+#include "qom/object.h"
 
 #define D(x)
 
 #define R_INTR        0x50
 #define R_MASKED_INTR 0x54
 
-struct etrax_timer {
-    SysBusDevice busdev;
+#define TYPE_ETRAX_FS_TIMER "etraxfs,timer"
+typedef struct ETRAXTimerState ETRAXTimerState;
+DECLARE_INSTANCE_CHECKER(ETRAXTimerState, ETRAX_TIMER,
+                         TYPE_ETRAX_FS_TIMER)
+
+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;
@@ -77,7 +86,7 @@ struct etrax_timer {
 static uint64_t
 timer_read(void *opaque, hwaddr addr, unsigned int size)
 {
-    struct etrax_timer *t = opaque;
+    ETRAXTimerState *t = opaque;
     uint32_t r = 0;
 
     switch (addr) {
@@ -88,7 +97,7 @@ timer_read(void *opaque, hwaddr addr, unsigned int size)
         r = ptimer_get_count(t->ptimer_t1);
         break;
     case R_TIME:
-        r = qemu_get_clock_ns(vm_clock) / 10;
+        r = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 10;
         break;
     case RW_INTR_MASK:
         r = t->rw_intr_mask;
@@ -103,7 +112,7 @@ timer_read(void *opaque, hwaddr addr, unsigned int size)
     return r;
 }
 
-static void update_ctrl(struct etrax_timer *t, int tnum)
+static void update_ctrl(ETRAXTimerState *t, int tnum)
 {
     unsigned int op;
     unsigned int freq;
@@ -144,6 +153,7 @@ static void update_ctrl(struct etrax_timer *t, int tnum)
     }
 
     D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
+    ptimer_transaction_begin(timer);
     ptimer_set_freq(timer, freq_hz);
     ptimer_set_limit(timer, div, 0);
 
@@ -165,9 +175,10 @@ static void update_ctrl(struct etrax_timer *t, int tnum)
             abort();
             break;
     }
+    ptimer_transaction_commit(timer);
 }
 
-static void timer_update_irq(struct etrax_timer *t)
+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;
@@ -178,21 +189,21 @@ static void timer_update_irq(struct etrax_timer *t)
 
 static void timer0_hit(void *opaque)
 {
-    struct etrax_timer *t = opaque;
+    ETRAXTimerState *t = opaque;
     t->r_intr |= 1;
     timer_update_irq(t);
 }
 
 static void timer1_hit(void *opaque)
 {
-    struct etrax_timer *t = opaque;
+    ETRAXTimerState *t = opaque;
     t->r_intr |= 2;
     timer_update_irq(t);
 }
 
 static void watchdog_hit(void *opaque)
 {
-    struct etrax_timer *t = 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.  */
@@ -201,12 +212,12 @@ static void watchdog_hit(void *opaque)
         qemu_irq_raise(t->nmi);
     }
     else
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
 
     t->wd_hits++;
 }
 
-static inline void timer_watchdog_update(struct etrax_timer *t, uint32_t value)
+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;
@@ -229,6 +240,7 @@ static inline void timer_watchdog_update(struct etrax_timer *t, uint32_t value)
 
     t->wd_hits = 0;
 
+    ptimer_transaction_begin(t->ptimer_wd);
     ptimer_set_freq(t->ptimer_wd, 760);
     if (wd_cnt == 0)
         wd_cnt = 256;
@@ -239,13 +251,14 @@ static inline void timer_watchdog_update(struct etrax_timer *t, uint32_t value)
         ptimer_stop(t->ptimer_wd);
 
     t->rw_wd_ctrl = value;
+    ptimer_transaction_commit(t->ptimer_wd);
 }
 
 static void
 timer_write(void *opaque, hwaddr addr,
             uint64_t val64, unsigned int size)
 {
-    struct etrax_timer *t = opaque;
+    ETRAXTimerState *t = opaque;
     uint32_t value = val64;
 
     switch (addr)
@@ -298,49 +311,52 @@ static const MemoryRegionOps timer_ops = {
 
 static void etraxfs_timer_reset(void *opaque)
 {
-    struct etrax_timer *t = opaque;
+    ETRAXTimerState *t = opaque;
 
+    ptimer_transaction_begin(t->ptimer_t0);
     ptimer_stop(t->ptimer_t0);
+    ptimer_transaction_commit(t->ptimer_t0);
+    ptimer_transaction_begin(t->ptimer_t1);
     ptimer_stop(t->ptimer_t1);
+    ptimer_transaction_commit(t->ptimer_t1);
+    ptimer_transaction_begin(t->ptimer_wd);
     ptimer_stop(t->ptimer_wd);
+    ptimer_transaction_commit(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)
+static void etraxfs_timer_realize(DeviceState *dev, Error **errp)
 {
-    struct etrax_timer *t = FROM_SYSBUS(typeof (*t), dev);
+    ETRAXTimerState *t = ETRAX_TIMER(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(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);
+    t->ptimer_t0 = ptimer_init(timer0_hit, t, PTIMER_POLICY_DEFAULT);
+    t->ptimer_t1 = ptimer_init(timer1_hit, t, PTIMER_POLICY_DEFAULT);
+    t->ptimer_wd = ptimer_init(watchdog_hit, t, PTIMER_POLICY_DEFAULT);
 
-    sysbus_init_irq(dev, &t->irq);
-    sysbus_init_irq(dev, &t->nmi);
+    sysbus_init_irq(sbd, &t->irq);
+    sysbus_init_irq(sbd, &t->nmi);
 
     memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
                           "etraxfs-timer", 0x5c);
-    sysbus_init_mmio(dev, &t->mmio);
+    sysbus_init_mmio(sbd, &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);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
-    sdc->init = etraxfs_timer_init;
+    dc->realize = etraxfs_timer_realize;
 }
 
 static const TypeInfo etraxfs_timer_info = {
-    .name          = "etraxfs,timer",
+    .name          = TYPE_ETRAX_FS_TIMER,
     .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof (struct etrax_timer),
+    .instance_size = sizeof(ETRAXTimerState),
     .class_init    = etraxfs_timer_class_init,
 };