]> git.proxmox.com Git - qemu.git/blame - hw/armv7m.c
Remove unused sysemu.h include directives
[qemu.git] / hw / armv7m.c
CommitLineData
9ee6e8bb
PB
1/*
2 * ARMV7M System emulation.
3 *
4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
6 *
7 * This code is licenced under the GPL.
8 */
9
fe7e8758 10#include "sysbus.h"
87ecb68b 11#include "arm-misc.h"
ca20cf32
BS
12#include "loader.h"
13#include "elf.h"
9ee6e8bb
PB
14
15/* Bitbanded IO. Each word corresponds to a single bit. */
16
17/* Get the byte address of the real memory for a bitband acess. */
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
c227f099 28static uint32_t bitband_readb(void *opaque, target_phys_addr_t 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
c227f099 35static void bitband_writeb(void *opaque, target_phys_addr_t 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
c227f099 51static uint32_t bitband_readw(void *opaque, target_phys_addr_t 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
c227f099 63static void bitband_writew(void *opaque, target_phys_addr_t 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
c227f099 80static uint32_t bitband_readl(void *opaque, target_phys_addr_t 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
c227f099 92static void bitband_writel(void *opaque, target_phys_addr_t 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
d60efc6b 109static CPUReadMemoryFunc * const bitband_readfn[] = {
9ee6e8bb
PB
110 bitband_readb,
111 bitband_readw,
112 bitband_readl
113};
114
d60efc6b 115static CPUWriteMemoryFunc * const bitband_writefn[] = {
9ee6e8bb
PB
116 bitband_writeb,
117 bitband_writew,
118 bitband_writel
119};
120
40905a6a
PB
121typedef struct {
122 SysBusDevice busdev;
123 uint32_t base;
124} BitBandState;
125
81a322d4 126static int bitband_init(SysBusDevice *dev)
9ee6e8bb 127{
40905a6a 128 BitBandState *s = FROM_SYSBUS(BitBandState, dev);
9ee6e8bb
PB
129 int iomemtype;
130
1eed09cb 131 iomemtype = cpu_register_io_memory(bitband_readfn, bitband_writefn,
2507c12a 132 &s->base, DEVICE_NATIVE_ENDIAN);
40905a6a 133 sysbus_init_mmio(dev, 0x02000000, iomemtype);
81a322d4 134 return 0;
40905a6a
PB
135}
136
137static void armv7m_bitband_init(void)
138{
139 DeviceState *dev;
140
141 dev = qdev_create(NULL, "ARM,bitband-memory");
ee6847d1 142 qdev_prop_set_uint32(dev, "base", 0x20000000);
e23a1b33 143 qdev_init_nofail(dev);
40905a6a
PB
144 sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x22000000);
145
146 dev = qdev_create(NULL, "ARM,bitband-memory");
ee6847d1 147 qdev_prop_set_uint32(dev, "base", 0x40000000);
e23a1b33 148 qdev_init_nofail(dev);
40905a6a 149 sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x42000000);
9ee6e8bb
PB
150}
151
152/* Board init. */
983fe826
PB
153
154static void armv7m_reset(void *opaque)
155{
156 cpu_reset((CPUState *)opaque);
157}
158
9ee6e8bb
PB
159/* Init CPU and memory for a v7-M based board.
160 flash_size and sram_size are in kb.
161 Returns the NVIC array. */
162
163qemu_irq *armv7m_init(int flash_size, int sram_size,
164 const char *kernel_filename, const char *cpu_model)
165{
166 CPUState *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;
9ee6e8bb
PB
176
177 flash_size *= 1024;
178 sram_size *= 1024;
179
180 if (!cpu_model)
181 cpu_model = "cortex-m3";
182 env = cpu_init(cpu_model);
183 if (!env) {
184 fprintf(stderr, "Unable to find CPU definition\n");
185 exit(1);
186 }
187
188#if 0
189 /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
190 We don't have proper commandline options, so allocate half of memory
191 as SRAM, up to a maximum of 32Mb, and the rest as code. */
192 if (ram_size > (512 + 32) * 1024 * 1024)
193 ram_size = (512 + 32) * 1024 * 1024;
194 sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
195 if (sram_size > 32 * 1024 * 1024)
196 sram_size = 32 * 1024 * 1024;
197 code_size = ram_size - sram_size;
198#endif
199
200 /* Flash programming is done via the SCU, so pretend it is ROM. */
dcac9679 201 cpu_register_physical_memory(0, flash_size,
1724f049
AW
202 qemu_ram_alloc(NULL, "armv7m.flash",
203 flash_size) | IO_MEM_ROM);
9ee6e8bb 204 cpu_register_physical_memory(0x20000000, sram_size,
1724f049
AW
205 qemu_ram_alloc(NULL, "armv7m.sram",
206 sram_size) | IO_MEM_RAM);
9ee6e8bb
PB
207 armv7m_bitband_init();
208
fe7e8758 209 nvic = qdev_create(NULL, "armv7m_nvic");
983fe826 210 env->nvic = nvic;
e23a1b33 211 qdev_init_nofail(nvic);
fe7e8758
PB
212 cpu_pic = arm_pic_init_cpu(env);
213 sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
214 for (i = 0; i < 64; i++) {
067a3ddc 215 pic[i] = qdev_get_gpio_in(nvic, i);
fe7e8758 216 }
9ee6e8bb 217
ca20cf32
BS
218#ifdef TARGET_WORDS_BIGENDIAN
219 big_endian = 1;
220#else
221 big_endian = 0;
222#endif
223
409dbce5
AJ
224 image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
225 NULL, big_endian, ELF_MACHINE, 1);
9ee6e8bb 226 if (image_size < 0) {
dcac9679 227 image_size = load_image_targphys(kernel_filename, 0, flash_size);
9ee6e8bb
PB
228 lowaddr = 0;
229 }
230 if (image_size < 0) {
231 fprintf(stderr, "qemu: could not load kernel '%s'\n",
232 kernel_filename);
233 exit(1);
234 }
235
9ee6e8bb
PB
236 /* Hack to map an additional page of ram at the top of the address
237 space. This stops qemu complaining about executing code outside RAM
238 when returning from an exception. */
dcac9679 239 cpu_register_physical_memory(0xfffff000, 0x1000,
1724f049
AW
240 qemu_ram_alloc(NULL, "armv7m.hack",
241 0x1000) | IO_MEM_RAM);
9ee6e8bb 242
983fe826 243 qemu_register_reset(armv7m_reset, env);
9ee6e8bb
PB
244 return pic;
245}
40905a6a 246
ee6847d1
GH
247static SysBusDeviceInfo bitband_info = {
248 .init = bitband_init,
249 .qdev.name = "ARM,bitband-memory",
250 .qdev.size = sizeof(BitBandState),
251 .qdev.props = (Property[]) {
1832efa2
GH
252 DEFINE_PROP_UINT32("base", BitBandState, base, 0),
253 DEFINE_PROP_END_OF_LIST(),
ee6847d1
GH
254 }
255};
256
40905a6a
PB
257static void armv7m_register_devices(void)
258{
ee6847d1 259 sysbus_register_withprop(&bitband_info);
40905a6a
PB
260}
261
262device_init(armv7m_register_devices)