]> git.proxmox.com Git - mirror_qemu.git/blame - hw/arm/armv7m.c
hw: move headers to include/
[mirror_qemu.git] / hw / arm / armv7m.c
CommitLineData
9ee6e8bb
PB
1/*
2 * ARMV7M System emulation.
3 *
4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
6 *
2167f7bc 7 * This code is licensed under the GPL.
9ee6e8bb
PB
8 */
9
83c9f4ca 10#include "hw/sysbus.h"
0d09e41a 11#include "hw/arm.h"
83c9f4ca 12#include "hw/loader.h"
ca20cf32 13#include "elf.h"
9ee6e8bb
PB
14
15/* Bitbanded IO. Each word corresponds to a single bit. */
16
2167f7bc 17/* Get the byte address of the real memory for a bitband access. */
8da3ff18 18static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
9ee6e8bb
PB
19{
20 uint32_t res;
21
8da3ff18 22 res = *(uint32_t *)opaque;
9ee6e8bb
PB
23 res |= (addr & 0x1ffffff) >> 5;
24 return res;
25
26}
27
a8170e5e 28static uint32_t bitband_readb(void *opaque, hwaddr offset)
9ee6e8bb
PB
29{
30 uint8_t v;
8da3ff18 31 cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
9ee6e8bb
PB
32 return (v & (1 << ((offset >> 2) & 7))) != 0;
33}
34
a8170e5e 35static void bitband_writeb(void *opaque, hwaddr offset,
9ee6e8bb
PB
36 uint32_t value)
37{
38 uint32_t addr;
39 uint8_t mask;
40 uint8_t v;
8da3ff18 41 addr = bitband_addr(opaque, offset);
9ee6e8bb
PB
42 mask = (1 << ((offset >> 2) & 7));
43 cpu_physical_memory_read(addr, &v, 1);
44 if (value & 1)
45 v |= mask;
46 else
47 v &= ~mask;
48 cpu_physical_memory_write(addr, &v, 1);
49}
50
a8170e5e 51static uint32_t bitband_readw(void *opaque, hwaddr offset)
9ee6e8bb
PB
52{
53 uint32_t addr;
54 uint16_t mask;
55 uint16_t v;
8da3ff18 56 addr = bitband_addr(opaque, offset) & ~1;
9ee6e8bb
PB
57 mask = (1 << ((offset >> 2) & 15));
58 mask = tswap16(mask);
59 cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
60 return (v & mask) != 0;
61}
62
a8170e5e 63static void bitband_writew(void *opaque, hwaddr offset,
9ee6e8bb
PB
64 uint32_t value)
65{
66 uint32_t addr;
67 uint16_t mask;
68 uint16_t v;
8da3ff18 69 addr = bitband_addr(opaque, offset) & ~1;
9ee6e8bb
PB
70 mask = (1 << ((offset >> 2) & 15));
71 mask = tswap16(mask);
72 cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
73 if (value & 1)
74 v |= mask;
75 else
76 v &= ~mask;
77 cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
78}
79
a8170e5e 80static uint32_t bitband_readl(void *opaque, hwaddr offset)
9ee6e8bb
PB
81{
82 uint32_t addr;
83 uint32_t mask;
84 uint32_t v;
8da3ff18 85 addr = bitband_addr(opaque, offset) & ~3;
9ee6e8bb
PB
86 mask = (1 << ((offset >> 2) & 31));
87 mask = tswap32(mask);
88 cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
89 return (v & mask) != 0;
90}
91
a8170e5e 92static void bitband_writel(void *opaque, hwaddr offset,
9ee6e8bb
PB
93 uint32_t value)
94{
95 uint32_t addr;
96 uint32_t mask;
97 uint32_t v;
8da3ff18 98 addr = bitband_addr(opaque, offset) & ~3;
9ee6e8bb
PB
99 mask = (1 << ((offset >> 2) & 31));
100 mask = tswap32(mask);
101 cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
102 if (value & 1)
103 v |= mask;
104 else
105 v &= ~mask;
106 cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
107}
108
f69bf9d4
AK
109static const MemoryRegionOps bitband_ops = {
110 .old_mmio = {
111 .read = { bitband_readb, bitband_readw, bitband_readl, },
112 .write = { bitband_writeb, bitband_writew, bitband_writel, },
113 },
114 .endianness = DEVICE_NATIVE_ENDIAN,
9ee6e8bb
PB
115};
116
40905a6a
PB
117typedef struct {
118 SysBusDevice busdev;
f69bf9d4 119 MemoryRegion iomem;
40905a6a
PB
120 uint32_t base;
121} BitBandState;
122
81a322d4 123static int bitband_init(SysBusDevice *dev)
9ee6e8bb 124{
40905a6a 125 BitBandState *s = FROM_SYSBUS(BitBandState, dev);
9ee6e8bb 126
f69bf9d4
AK
127 memory_region_init_io(&s->iomem, &bitband_ops, &s->base, "bitband",
128 0x02000000);
750ecd44 129 sysbus_init_mmio(dev, &s->iomem);
81a322d4 130 return 0;
40905a6a
PB
131}
132
133static void armv7m_bitband_init(void)
134{
135 DeviceState *dev;
136
137 dev = qdev_create(NULL, "ARM,bitband-memory");
ee6847d1 138 qdev_prop_set_uint32(dev, "base", 0x20000000);
e23a1b33 139 qdev_init_nofail(dev);
1356b98d 140 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
40905a6a
PB
141
142 dev = qdev_create(NULL, "ARM,bitband-memory");
ee6847d1 143 qdev_prop_set_uint32(dev, "base", 0x40000000);
e23a1b33 144 qdev_init_nofail(dev);
1356b98d 145 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
9ee6e8bb
PB
146}
147
148/* Board init. */
983fe826
PB
149
150static void armv7m_reset(void *opaque)
151{
31363f12
AF
152 ARMCPU *cpu = opaque;
153
154 cpu_reset(CPU(cpu));
983fe826
PB
155}
156
9ee6e8bb
PB
157/* Init CPU and memory for a v7-M based board.
158 flash_size and sram_size are in kb.
159 Returns the NVIC array. */
160
7d6f78cf
AK
161qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
162 int flash_size, int sram_size,
9ee6e8bb
PB
163 const char *kernel_filename, const char *cpu_model)
164{
0f37c99b 165 ARMCPU *cpu;
5ae93306 166 CPUARMState *env;
fe7e8758
PB
167 DeviceState *nvic;
168 /* FIXME: make this local state. */
169 static qemu_irq pic[64];
170 qemu_irq *cpu_pic;
9ee6e8bb
PB
171 int image_size;
172 uint64_t entry;
173 uint64_t lowaddr;
fe7e8758 174 int i;
ca20cf32 175 int big_endian;
7d6f78cf
AK
176 MemoryRegion *sram = g_new(MemoryRegion, 1);
177 MemoryRegion *flash = g_new(MemoryRegion, 1);
178 MemoryRegion *hack = g_new(MemoryRegion, 1);
9ee6e8bb
PB
179
180 flash_size *= 1024;
181 sram_size *= 1024;
182
0f37c99b 183 if (cpu_model == NULL) {
9ee6e8bb 184 cpu_model = "cortex-m3";
0f37c99b
AF
185 }
186 cpu = cpu_arm_init(cpu_model);
187 if (cpu == NULL) {
9ee6e8bb
PB
188 fprintf(stderr, "Unable to find CPU definition\n");
189 exit(1);
190 }
0f37c99b 191 env = &cpu->env;
9ee6e8bb
PB
192
193#if 0
194 /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
195 We don't have proper commandline options, so allocate half of memory
196 as SRAM, up to a maximum of 32Mb, and the rest as code. */
197 if (ram_size > (512 + 32) * 1024 * 1024)
198 ram_size = (512 + 32) * 1024 * 1024;
199 sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
200 if (sram_size > 32 * 1024 * 1024)
201 sram_size = 32 * 1024 * 1024;
202 code_size = ram_size - sram_size;
203#endif
204
205 /* Flash programming is done via the SCU, so pretend it is ROM. */
c5705a77
AK
206 memory_region_init_ram(flash, "armv7m.flash", flash_size);
207 vmstate_register_ram_global(flash);
7d6f78cf
AK
208 memory_region_set_readonly(flash, true);
209 memory_region_add_subregion(address_space_mem, 0, flash);
c5705a77
AK
210 memory_region_init_ram(sram, "armv7m.sram", sram_size);
211 vmstate_register_ram_global(sram);
7d6f78cf 212 memory_region_add_subregion(address_space_mem, 0x20000000, sram);
9ee6e8bb
PB
213 armv7m_bitband_init();
214
fe7e8758 215 nvic = qdev_create(NULL, "armv7m_nvic");
983fe826 216 env->nvic = nvic;
e23a1b33 217 qdev_init_nofail(nvic);
4bd74661 218 cpu_pic = arm_pic_init_cpu(cpu);
1356b98d 219 sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
fe7e8758 220 for (i = 0; i < 64; i++) {
067a3ddc 221 pic[i] = qdev_get_gpio_in(nvic, i);
fe7e8758 222 }
9ee6e8bb 223
ca20cf32
BS
224#ifdef TARGET_WORDS_BIGENDIAN
225 big_endian = 1;
226#else
227 big_endian = 0;
228#endif
229
01fd41ab
PC
230 if (!kernel_filename) {
231 fprintf(stderr, "Guest image must be specified (using -kernel)\n");
232 exit(1);
233 }
234
409dbce5
AJ
235 image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
236 NULL, big_endian, ELF_MACHINE, 1);
9ee6e8bb 237 if (image_size < 0) {
dcac9679 238 image_size = load_image_targphys(kernel_filename, 0, flash_size);
9ee6e8bb
PB
239 lowaddr = 0;
240 }
241 if (image_size < 0) {
242 fprintf(stderr, "qemu: could not load kernel '%s'\n",
243 kernel_filename);
244 exit(1);
245 }
246
9ee6e8bb
PB
247 /* Hack to map an additional page of ram at the top of the address
248 space. This stops qemu complaining about executing code outside RAM
249 when returning from an exception. */
c5705a77
AK
250 memory_region_init_ram(hack, "armv7m.hack", 0x1000);
251 vmstate_register_ram_global(hack);
7d6f78cf 252 memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
9ee6e8bb 253
31363f12 254 qemu_register_reset(armv7m_reset, cpu);
9ee6e8bb
PB
255 return pic;
256}
40905a6a 257
999e12bb
AL
258static Property bitband_properties[] = {
259 DEFINE_PROP_UINT32("base", BitBandState, base, 0),
260 DEFINE_PROP_END_OF_LIST(),
261};
262
263static void bitband_class_init(ObjectClass *klass, void *data)
264{
39bffca2 265 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb
AL
266 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
267
268 k->init = bitband_init;
39bffca2 269 dc->props = bitband_properties;
999e12bb
AL
270}
271
8c43a6f0 272static const TypeInfo bitband_info = {
39bffca2
AL
273 .name = "ARM,bitband-memory",
274 .parent = TYPE_SYS_BUS_DEVICE,
275 .instance_size = sizeof(BitBandState),
276 .class_init = bitband_class_init,
ee6847d1
GH
277};
278
83f7d43a 279static void armv7m_register_types(void)
40905a6a 280{
39bffca2 281 type_register_static(&bitband_info);
40905a6a
PB
282}
283
83f7d43a 284type_init(armv7m_register_types)