]> git.proxmox.com Git - mirror_qemu.git/blame_incremental - hw/arm/armv7m.c
hw/char: QOM'ify cadence_uart model
[mirror_qemu.git] / hw / arm / armv7m.c
... / ...
CommitLineData
1/*
2 * ARMV7M System emulation.
3 *
4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
6 *
7 * This code is licensed under the GPL.
8 */
9
10#include "qemu/osdep.h"
11#include "qapi/error.h"
12#include "qemu-common.h"
13#include "cpu.h"
14#include "hw/sysbus.h"
15#include "hw/arm/arm.h"
16#include "hw/loader.h"
17#include "elf.h"
18#include "sysemu/qtest.h"
19#include "qemu/error-report.h"
20
21/* Bitbanded IO. Each word corresponds to a single bit. */
22
23/* Get the byte address of the real memory for a bitband access. */
24static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
25{
26 uint32_t res;
27
28 res = *(uint32_t *)opaque;
29 res |= (addr & 0x1ffffff) >> 5;
30 return res;
31
32}
33
34static uint32_t bitband_readb(void *opaque, hwaddr offset)
35{
36 uint8_t v;
37 cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
38 return (v & (1 << ((offset >> 2) & 7))) != 0;
39}
40
41static void bitband_writeb(void *opaque, hwaddr offset,
42 uint32_t value)
43{
44 uint32_t addr;
45 uint8_t mask;
46 uint8_t v;
47 addr = bitband_addr(opaque, offset);
48 mask = (1 << ((offset >> 2) & 7));
49 cpu_physical_memory_read(addr, &v, 1);
50 if (value & 1)
51 v |= mask;
52 else
53 v &= ~mask;
54 cpu_physical_memory_write(addr, &v, 1);
55}
56
57static uint32_t bitband_readw(void *opaque, hwaddr offset)
58{
59 uint32_t addr;
60 uint16_t mask;
61 uint16_t v;
62 addr = bitband_addr(opaque, offset) & ~1;
63 mask = (1 << ((offset >> 2) & 15));
64 mask = tswap16(mask);
65 cpu_physical_memory_read(addr, &v, 2);
66 return (v & mask) != 0;
67}
68
69static void bitband_writew(void *opaque, hwaddr offset,
70 uint32_t value)
71{
72 uint32_t addr;
73 uint16_t mask;
74 uint16_t v;
75 addr = bitband_addr(opaque, offset) & ~1;
76 mask = (1 << ((offset >> 2) & 15));
77 mask = tswap16(mask);
78 cpu_physical_memory_read(addr, &v, 2);
79 if (value & 1)
80 v |= mask;
81 else
82 v &= ~mask;
83 cpu_physical_memory_write(addr, &v, 2);
84}
85
86static uint32_t bitband_readl(void *opaque, hwaddr offset)
87{
88 uint32_t addr;
89 uint32_t mask;
90 uint32_t v;
91 addr = bitband_addr(opaque, offset) & ~3;
92 mask = (1 << ((offset >> 2) & 31));
93 mask = tswap32(mask);
94 cpu_physical_memory_read(addr, &v, 4);
95 return (v & mask) != 0;
96}
97
98static void bitband_writel(void *opaque, hwaddr offset,
99 uint32_t value)
100{
101 uint32_t addr;
102 uint32_t mask;
103 uint32_t v;
104 addr = bitband_addr(opaque, offset) & ~3;
105 mask = (1 << ((offset >> 2) & 31));
106 mask = tswap32(mask);
107 cpu_physical_memory_read(addr, &v, 4);
108 if (value & 1)
109 v |= mask;
110 else
111 v &= ~mask;
112 cpu_physical_memory_write(addr, &v, 4);
113}
114
115static const MemoryRegionOps bitband_ops = {
116 .old_mmio = {
117 .read = { bitband_readb, bitband_readw, bitband_readl, },
118 .write = { bitband_writeb, bitband_writew, bitband_writel, },
119 },
120 .endianness = DEVICE_NATIVE_ENDIAN,
121};
122
123#define TYPE_BITBAND "ARM,bitband-memory"
124#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
125
126typedef struct {
127 /*< private >*/
128 SysBusDevice parent_obj;
129 /*< public >*/
130
131 MemoryRegion iomem;
132 uint32_t base;
133} BitBandState;
134
135static void bitband_init(Object *obj)
136{
137 BitBandState *s = BITBAND(obj);
138 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
139
140 memory_region_init_io(&s->iomem, obj, &bitband_ops, &s->base,
141 "bitband", 0x02000000);
142 sysbus_init_mmio(dev, &s->iomem);
143}
144
145static void armv7m_bitband_init(void)
146{
147 DeviceState *dev;
148
149 dev = qdev_create(NULL, TYPE_BITBAND);
150 qdev_prop_set_uint32(dev, "base", 0x20000000);
151 qdev_init_nofail(dev);
152 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
153
154 dev = qdev_create(NULL, TYPE_BITBAND);
155 qdev_prop_set_uint32(dev, "base", 0x40000000);
156 qdev_init_nofail(dev);
157 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
158}
159
160/* Board init. */
161
162static void armv7m_reset(void *opaque)
163{
164 ARMCPU *cpu = opaque;
165
166 cpu_reset(CPU(cpu));
167}
168
169/* Init CPU and memory for a v7-M based board.
170 mem_size is in bytes.
171 Returns the NVIC array. */
172
173DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
174 const char *kernel_filename, const char *cpu_model)
175{
176 ARMCPU *cpu;
177 CPUARMState *env;
178 DeviceState *nvic;
179 int image_size;
180 uint64_t entry;
181 uint64_t lowaddr;
182 int big_endian;
183 MemoryRegion *hack = g_new(MemoryRegion, 1);
184
185 if (cpu_model == NULL) {
186 cpu_model = "cortex-m3";
187 }
188 cpu = cpu_arm_init(cpu_model);
189 if (cpu == NULL) {
190 fprintf(stderr, "Unable to find CPU definition\n");
191 exit(1);
192 }
193 env = &cpu->env;
194
195 armv7m_bitband_init();
196
197 nvic = qdev_create(NULL, "armv7m_nvic");
198 qdev_prop_set_uint32(nvic, "num-irq", num_irq);
199 env->nvic = nvic;
200 qdev_init_nofail(nvic);
201 sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
202 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
203
204#ifdef TARGET_WORDS_BIGENDIAN
205 big_endian = 1;
206#else
207 big_endian = 0;
208#endif
209
210 if (!kernel_filename && !qtest_enabled()) {
211 fprintf(stderr, "Guest image must be specified (using -kernel)\n");
212 exit(1);
213 }
214
215 if (kernel_filename) {
216 image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
217 NULL, big_endian, EM_ARM, 1, 0);
218 if (image_size < 0) {
219 image_size = load_image_targphys(kernel_filename, 0, mem_size);
220 lowaddr = 0;
221 }
222 if (image_size < 0) {
223 error_report("Could not load kernel '%s'", kernel_filename);
224 exit(1);
225 }
226 }
227
228 /* Hack to map an additional page of ram at the top of the address
229 space. This stops qemu complaining about executing code outside RAM
230 when returning from an exception. */
231 memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000, &error_fatal);
232 vmstate_register_ram_global(hack);
233 memory_region_add_subregion(system_memory, 0xfffff000, hack);
234
235 qemu_register_reset(armv7m_reset, cpu);
236 return nvic;
237}
238
239static Property bitband_properties[] = {
240 DEFINE_PROP_UINT32("base", BitBandState, base, 0),
241 DEFINE_PROP_END_OF_LIST(),
242};
243
244static void bitband_class_init(ObjectClass *klass, void *data)
245{
246 DeviceClass *dc = DEVICE_CLASS(klass);
247
248 dc->props = bitband_properties;
249}
250
251static const TypeInfo bitband_info = {
252 .name = TYPE_BITBAND,
253 .parent = TYPE_SYS_BUS_DEVICE,
254 .instance_size = sizeof(BitBandState),
255 .instance_init = bitband_init,
256 .class_init = bitband_class_init,
257};
258
259static void armv7m_register_types(void)
260{
261 type_register_static(&bitband_info);
262}
263
264type_init(armv7m_register_types)