]> git.proxmox.com Git - mirror_qemu.git/blame - hw/armv7m.c
sysbus: rename sysbus_init_mmio_region() to sysbus_init_mmio()
[mirror_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 *
2167f7bc 7 * This code is licensed under the GPL.
9ee6e8bb
PB
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
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
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
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);
40905a6a
PB
140 sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x22000000);
141
142 dev = qdev_create(NULL, "ARM,bitband-memory");
ee6847d1 143 qdev_prop_set_uint32(dev, "base", 0x40000000);
e23a1b33 144 qdev_init_nofail(dev);
40905a6a 145 sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x42000000);
9ee6e8bb
PB
146}
147
148/* Board init. */
983fe826
PB
149
150static void armv7m_reset(void *opaque)
151{
152 cpu_reset((CPUState *)opaque);
153}
154
9ee6e8bb
PB
155/* Init CPU and memory for a v7-M based board.
156 flash_size and sram_size are in kb.
157 Returns the NVIC array. */
158
7d6f78cf
AK
159qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
160 int flash_size, int sram_size,
9ee6e8bb
PB
161 const char *kernel_filename, const char *cpu_model)
162{
163 CPUState *env;
fe7e8758
PB
164 DeviceState *nvic;
165 /* FIXME: make this local state. */
166 static qemu_irq pic[64];
167 qemu_irq *cpu_pic;
9ee6e8bb
PB
168 int image_size;
169 uint64_t entry;
170 uint64_t lowaddr;
fe7e8758 171 int i;
ca20cf32 172 int big_endian;
7d6f78cf
AK
173 MemoryRegion *sram = g_new(MemoryRegion, 1);
174 MemoryRegion *flash = g_new(MemoryRegion, 1);
175 MemoryRegion *hack = g_new(MemoryRegion, 1);
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. */
7d6f78cf
AK
201 memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size);
202 memory_region_set_readonly(flash, true);
203 memory_region_add_subregion(address_space_mem, 0, flash);
204 memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size);
205 memory_region_add_subregion(address_space_mem, 0x20000000, sram);
9ee6e8bb
PB
206 armv7m_bitband_init();
207
fe7e8758 208 nvic = qdev_create(NULL, "armv7m_nvic");
983fe826 209 env->nvic = nvic;
e23a1b33 210 qdev_init_nofail(nvic);
fe7e8758
PB
211 cpu_pic = arm_pic_init_cpu(env);
212 sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
213 for (i = 0; i < 64; i++) {
067a3ddc 214 pic[i] = qdev_get_gpio_in(nvic, i);
fe7e8758 215 }
9ee6e8bb 216
ca20cf32
BS
217#ifdef TARGET_WORDS_BIGENDIAN
218 big_endian = 1;
219#else
220 big_endian = 0;
221#endif
222
409dbce5
AJ
223 image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
224 NULL, big_endian, ELF_MACHINE, 1);
9ee6e8bb 225 if (image_size < 0) {
dcac9679 226 image_size = load_image_targphys(kernel_filename, 0, flash_size);
9ee6e8bb
PB
227 lowaddr = 0;
228 }
229 if (image_size < 0) {
230 fprintf(stderr, "qemu: could not load kernel '%s'\n",
231 kernel_filename);
232 exit(1);
233 }
234
9ee6e8bb
PB
235 /* Hack to map an additional page of ram at the top of the address
236 space. This stops qemu complaining about executing code outside RAM
237 when returning from an exception. */
7d6f78cf
AK
238 memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000);
239 memory_region_add_subregion(address_space_mem, 0xfffff000, hack);
9ee6e8bb 240
983fe826 241 qemu_register_reset(armv7m_reset, env);
9ee6e8bb
PB
242 return pic;
243}
40905a6a 244
ee6847d1
GH
245static SysBusDeviceInfo bitband_info = {
246 .init = bitband_init,
247 .qdev.name = "ARM,bitband-memory",
248 .qdev.size = sizeof(BitBandState),
249 .qdev.props = (Property[]) {
1832efa2
GH
250 DEFINE_PROP_UINT32("base", BitBandState, base, 0),
251 DEFINE_PROP_END_OF_LIST(),
ee6847d1
GH
252 }
253};
254
40905a6a
PB
255static void armv7m_register_devices(void)
256{
ee6847d1 257 sysbus_register_withprop(&bitband_info);
40905a6a
PB
258}
259
260device_init(armv7m_register_devices)