root / hw / timer / puv3_ost.c @ 6a1751b7
History | View | Annotate | Download (3.8 kB)
1 | 56d07a90 | Guan Xuetao | /*
|
---|---|---|---|
2 | 56d07a90 | Guan Xuetao | * OSTimer device simulation in PKUnity SoC
|
3 | 56d07a90 | Guan Xuetao | *
|
4 | 56d07a90 | Guan Xuetao | * Copyright (C) 2010-2012 Guan Xuetao
|
5 | 56d07a90 | Guan Xuetao | *
|
6 | 56d07a90 | Guan Xuetao | * This program is free software; you can redistribute it and/or modify
|
7 | 56d07a90 | Guan Xuetao | * it under the terms of the GNU General Public License version 2 as
|
8 | 56d07a90 | Guan Xuetao | * published by the Free Software Foundation, or any later version.
|
9 | 56d07a90 | Guan Xuetao | * See the COPYING file in the top-level directory.
|
10 | 56d07a90 | Guan Xuetao | */
|
11 | 83c9f4ca | Paolo Bonzini | #include "hw/sysbus.h" |
12 | 83c9f4ca | Paolo Bonzini | #include "hw/ptimer.h" |
13 | 6a1751b7 | Alex Bligh | #include "qemu/main-loop.h" |
14 | 56d07a90 | Guan Xuetao | |
15 | 56d07a90 | Guan Xuetao | #undef DEBUG_PUV3
|
16 | 0d09e41a | Paolo Bonzini | #include "hw/unicore32/puv3.h" |
17 | 56d07a90 | Guan Xuetao | |
18 | 9c9610b8 | Andreas Färber | #define TYPE_PUV3_OST "puv3_ost" |
19 | 9c9610b8 | Andreas Färber | #define PUV3_OST(obj) OBJECT_CHECK(PUV3OSTState, (obj), TYPE_PUV3_OST)
|
20 | 9c9610b8 | Andreas Färber | |
21 | 56d07a90 | Guan Xuetao | /* puv3 ostimer implementation. */
|
22 | 9c9610b8 | Andreas Färber | typedef struct PUV3OSTState { |
23 | 9c9610b8 | Andreas Färber | SysBusDevice parent_obj; |
24 | 9c9610b8 | Andreas Färber | |
25 | 56d07a90 | Guan Xuetao | MemoryRegion iomem; |
26 | 56d07a90 | Guan Xuetao | QEMUBH *bh; |
27 | 56d07a90 | Guan Xuetao | qemu_irq irq; |
28 | 56d07a90 | Guan Xuetao | ptimer_state *ptimer; |
29 | 56d07a90 | Guan Xuetao | |
30 | 56d07a90 | Guan Xuetao | uint32_t reg_OSMR0; |
31 | 56d07a90 | Guan Xuetao | uint32_t reg_OSCR; |
32 | 56d07a90 | Guan Xuetao | uint32_t reg_OSSR; |
33 | 56d07a90 | Guan Xuetao | uint32_t reg_OIER; |
34 | 56d07a90 | Guan Xuetao | } PUV3OSTState; |
35 | 56d07a90 | Guan Xuetao | |
36 | a8170e5e | Avi Kivity | static uint64_t puv3_ost_read(void *opaque, hwaddr offset, |
37 | 56d07a90 | Guan Xuetao | unsigned size)
|
38 | 56d07a90 | Guan Xuetao | { |
39 | 56d07a90 | Guan Xuetao | PUV3OSTState *s = opaque; |
40 | 56d07a90 | Guan Xuetao | uint32_t ret = 0;
|
41 | 56d07a90 | Guan Xuetao | |
42 | 56d07a90 | Guan Xuetao | switch (offset) {
|
43 | 56d07a90 | Guan Xuetao | case 0x10: /* Counter Register */ |
44 | 56d07a90 | Guan Xuetao | ret = s->reg_OSMR0 - (uint32_t)ptimer_get_count(s->ptimer); |
45 | 56d07a90 | Guan Xuetao | break;
|
46 | 56d07a90 | Guan Xuetao | case 0x14: /* Status Register */ |
47 | 56d07a90 | Guan Xuetao | ret = s->reg_OSSR; |
48 | 56d07a90 | Guan Xuetao | break;
|
49 | 56d07a90 | Guan Xuetao | case 0x1c: /* Interrupt Enable Register */ |
50 | 56d07a90 | Guan Xuetao | ret = s->reg_OIER; |
51 | 56d07a90 | Guan Xuetao | break;
|
52 | 56d07a90 | Guan Xuetao | default:
|
53 | 56d07a90 | Guan Xuetao | DPRINTF("Bad offset %x\n", (int)offset); |
54 | 56d07a90 | Guan Xuetao | } |
55 | 56d07a90 | Guan Xuetao | DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
|
56 | 56d07a90 | Guan Xuetao | return ret;
|
57 | 56d07a90 | Guan Xuetao | } |
58 | 56d07a90 | Guan Xuetao | |
59 | a8170e5e | Avi Kivity | static void puv3_ost_write(void *opaque, hwaddr offset, |
60 | 56d07a90 | Guan Xuetao | uint64_t value, unsigned size)
|
61 | 56d07a90 | Guan Xuetao | { |
62 | 56d07a90 | Guan Xuetao | PUV3OSTState *s = opaque; |
63 | 56d07a90 | Guan Xuetao | |
64 | 56d07a90 | Guan Xuetao | DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
|
65 | 56d07a90 | Guan Xuetao | switch (offset) {
|
66 | 56d07a90 | Guan Xuetao | case 0x00: /* Match Register 0 */ |
67 | 56d07a90 | Guan Xuetao | s->reg_OSMR0 = value; |
68 | 56d07a90 | Guan Xuetao | if (s->reg_OSMR0 > s->reg_OSCR) {
|
69 | 56d07a90 | Guan Xuetao | ptimer_set_count(s->ptimer, s->reg_OSMR0 - s->reg_OSCR); |
70 | 56d07a90 | Guan Xuetao | } else {
|
71 | 56d07a90 | Guan Xuetao | ptimer_set_count(s->ptimer, s->reg_OSMR0 + |
72 | 56d07a90 | Guan Xuetao | (0xffffffff - s->reg_OSCR));
|
73 | 56d07a90 | Guan Xuetao | } |
74 | 56d07a90 | Guan Xuetao | ptimer_run(s->ptimer, 2);
|
75 | 56d07a90 | Guan Xuetao | break;
|
76 | 56d07a90 | Guan Xuetao | case 0x14: /* Status Register */ |
77 | 56d07a90 | Guan Xuetao | assert(value == 0);
|
78 | 56d07a90 | Guan Xuetao | if (s->reg_OSSR) {
|
79 | 56d07a90 | Guan Xuetao | s->reg_OSSR = value; |
80 | 56d07a90 | Guan Xuetao | qemu_irq_lower(s->irq); |
81 | 56d07a90 | Guan Xuetao | } |
82 | 56d07a90 | Guan Xuetao | break;
|
83 | 56d07a90 | Guan Xuetao | case 0x1c: /* Interrupt Enable Register */ |
84 | 56d07a90 | Guan Xuetao | s->reg_OIER = value; |
85 | 56d07a90 | Guan Xuetao | break;
|
86 | 56d07a90 | Guan Xuetao | default:
|
87 | 56d07a90 | Guan Xuetao | DPRINTF("Bad offset %x\n", (int)offset); |
88 | 56d07a90 | Guan Xuetao | } |
89 | 56d07a90 | Guan Xuetao | } |
90 | 56d07a90 | Guan Xuetao | |
91 | 56d07a90 | Guan Xuetao | static const MemoryRegionOps puv3_ost_ops = { |
92 | 56d07a90 | Guan Xuetao | .read = puv3_ost_read, |
93 | 56d07a90 | Guan Xuetao | .write = puv3_ost_write, |
94 | 56d07a90 | Guan Xuetao | .impl = { |
95 | 56d07a90 | Guan Xuetao | .min_access_size = 4,
|
96 | 56d07a90 | Guan Xuetao | .max_access_size = 4,
|
97 | 56d07a90 | Guan Xuetao | }, |
98 | 56d07a90 | Guan Xuetao | .endianness = DEVICE_NATIVE_ENDIAN, |
99 | 56d07a90 | Guan Xuetao | }; |
100 | 56d07a90 | Guan Xuetao | |
101 | 56d07a90 | Guan Xuetao | static void puv3_ost_tick(void *opaque) |
102 | 56d07a90 | Guan Xuetao | { |
103 | 56d07a90 | Guan Xuetao | PUV3OSTState *s = opaque; |
104 | 56d07a90 | Guan Xuetao | |
105 | 56d07a90 | Guan Xuetao | DPRINTF("ost hit when ptimer counter from 0x%x to 0x%x!\n",
|
106 | 56d07a90 | Guan Xuetao | s->reg_OSCR, s->reg_OSMR0); |
107 | 56d07a90 | Guan Xuetao | |
108 | 56d07a90 | Guan Xuetao | s->reg_OSCR = s->reg_OSMR0; |
109 | 56d07a90 | Guan Xuetao | if (s->reg_OIER) {
|
110 | 56d07a90 | Guan Xuetao | s->reg_OSSR = 1;
|
111 | 56d07a90 | Guan Xuetao | qemu_irq_raise(s->irq); |
112 | 56d07a90 | Guan Xuetao | } |
113 | 56d07a90 | Guan Xuetao | } |
114 | 56d07a90 | Guan Xuetao | |
115 | 56d07a90 | Guan Xuetao | static int puv3_ost_init(SysBusDevice *dev) |
116 | 56d07a90 | Guan Xuetao | { |
117 | 9c9610b8 | Andreas Färber | PUV3OSTState *s = PUV3_OST(dev); |
118 | 56d07a90 | Guan Xuetao | |
119 | 56d07a90 | Guan Xuetao | s->reg_OIER = 0;
|
120 | 56d07a90 | Guan Xuetao | s->reg_OSSR = 0;
|
121 | 56d07a90 | Guan Xuetao | s->reg_OSMR0 = 0;
|
122 | 56d07a90 | Guan Xuetao | s->reg_OSCR = 0;
|
123 | 56d07a90 | Guan Xuetao | |
124 | 56d07a90 | Guan Xuetao | sysbus_init_irq(dev, &s->irq); |
125 | 56d07a90 | Guan Xuetao | |
126 | 56d07a90 | Guan Xuetao | s->bh = qemu_bh_new(puv3_ost_tick, s); |
127 | 56d07a90 | Guan Xuetao | s->ptimer = ptimer_init(s->bh); |
128 | 56d07a90 | Guan Xuetao | ptimer_set_freq(s->ptimer, 50 * 1000 * 1000); |
129 | 56d07a90 | Guan Xuetao | |
130 | 853dca12 | Paolo Bonzini | memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
|
131 | 56d07a90 | Guan Xuetao | PUV3_REGS_OFFSET); |
132 | 56d07a90 | Guan Xuetao | sysbus_init_mmio(dev, &s->iomem); |
133 | 56d07a90 | Guan Xuetao | |
134 | 56d07a90 | Guan Xuetao | return 0; |
135 | 56d07a90 | Guan Xuetao | } |
136 | 56d07a90 | Guan Xuetao | |
137 | 56d07a90 | Guan Xuetao | static void puv3_ost_class_init(ObjectClass *klass, void *data) |
138 | 56d07a90 | Guan Xuetao | { |
139 | 56d07a90 | Guan Xuetao | SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); |
140 | 56d07a90 | Guan Xuetao | |
141 | 56d07a90 | Guan Xuetao | sdc->init = puv3_ost_init; |
142 | 56d07a90 | Guan Xuetao | } |
143 | 56d07a90 | Guan Xuetao | |
144 | 56d07a90 | Guan Xuetao | static const TypeInfo puv3_ost_info = { |
145 | 9c9610b8 | Andreas Färber | .name = TYPE_PUV3_OST, |
146 | 56d07a90 | Guan Xuetao | .parent = TYPE_SYS_BUS_DEVICE, |
147 | 56d07a90 | Guan Xuetao | .instance_size = sizeof(PUV3OSTState),
|
148 | 56d07a90 | Guan Xuetao | .class_init = puv3_ost_class_init, |
149 | 56d07a90 | Guan Xuetao | }; |
150 | 56d07a90 | Guan Xuetao | |
151 | 56d07a90 | Guan Xuetao | static void puv3_ost_register_type(void) |
152 | 56d07a90 | Guan Xuetao | { |
153 | 56d07a90 | Guan Xuetao | type_register_static(&puv3_ost_info); |
154 | 56d07a90 | Guan Xuetao | } |
155 | 56d07a90 | Guan Xuetao | |
156 | 56d07a90 | Guan Xuetao | type_init(puv3_ost_register_type) |