]> Git Repo - qemu.git/blob - hw/armv7m.c
Get rid of _t suffix
[qemu.git] / hw / armv7m.c
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
10 #include "sysbus.h"
11 #include "arm-misc.h"
12 #include "sysemu.h"
13 #include "loader.h"
14 #include "elf.h"
15
16 /* Bitbanded IO.  Each word corresponds to a single bit.  */
17
18 /* Get the byte address of the real memory for a bitband acess.  */
19 static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
20 {
21     uint32_t res;
22
23     res = *(uint32_t *)opaque;
24     res |= (addr & 0x1ffffff) >> 5;
25     return res;
26
27 }
28
29 static uint32_t bitband_readb(void *opaque, a_target_phys_addr offset)
30 {
31     uint8_t v;
32     cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
33     return (v & (1 << ((offset >> 2) & 7))) != 0;
34 }
35
36 static void bitband_writeb(void *opaque, a_target_phys_addr offset,
37                            uint32_t value)
38 {
39     uint32_t addr;
40     uint8_t mask;
41     uint8_t v;
42     addr = bitband_addr(opaque, offset);
43     mask = (1 << ((offset >> 2) & 7));
44     cpu_physical_memory_read(addr, &v, 1);
45     if (value & 1)
46         v |= mask;
47     else
48         v &= ~mask;
49     cpu_physical_memory_write(addr, &v, 1);
50 }
51
52 static uint32_t bitband_readw(void *opaque, a_target_phys_addr offset)
53 {
54     uint32_t addr;
55     uint16_t mask;
56     uint16_t v;
57     addr = bitband_addr(opaque, offset) & ~1;
58     mask = (1 << ((offset >> 2) & 15));
59     mask = tswap16(mask);
60     cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
61     return (v & mask) != 0;
62 }
63
64 static void bitband_writew(void *opaque, a_target_phys_addr offset,
65                            uint32_t value)
66 {
67     uint32_t addr;
68     uint16_t mask;
69     uint16_t v;
70     addr = bitband_addr(opaque, offset) & ~1;
71     mask = (1 << ((offset >> 2) & 15));
72     mask = tswap16(mask);
73     cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
74     if (value & 1)
75         v |= mask;
76     else
77         v &= ~mask;
78     cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
79 }
80
81 static uint32_t bitband_readl(void *opaque, a_target_phys_addr offset)
82 {
83     uint32_t addr;
84     uint32_t mask;
85     uint32_t v;
86     addr = bitband_addr(opaque, offset) & ~3;
87     mask = (1 << ((offset >> 2) & 31));
88     mask = tswap32(mask);
89     cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
90     return (v & mask) != 0;
91 }
92
93 static void bitband_writel(void *opaque, a_target_phys_addr offset,
94                            uint32_t value)
95 {
96     uint32_t addr;
97     uint32_t mask;
98     uint32_t v;
99     addr = bitband_addr(opaque, offset) & ~3;
100     mask = (1 << ((offset >> 2) & 31));
101     mask = tswap32(mask);
102     cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
103     if (value & 1)
104         v |= mask;
105     else
106         v &= ~mask;
107     cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
108 }
109
110 static CPUReadMemoryFunc * const bitband_readfn[] = {
111    bitband_readb,
112    bitband_readw,
113    bitband_readl
114 };
115
116 static CPUWriteMemoryFunc * const bitband_writefn[] = {
117    bitband_writeb,
118    bitband_writew,
119    bitband_writel
120 };
121
122 typedef struct {
123     SysBusDevice busdev;
124     uint32_t base;
125 } BitBandState;
126
127 static int bitband_init(SysBusDevice *dev)
128 {
129     BitBandState *s = FROM_SYSBUS(BitBandState, dev);
130     int iomemtype;
131
132     iomemtype = cpu_register_io_memory(bitband_readfn, bitband_writefn,
133                                        &s->base);
134     sysbus_init_mmio(dev, 0x02000000, iomemtype);
135     return 0;
136 }
137
138 static void armv7m_bitband_init(void)
139 {
140     DeviceState *dev;
141
142     dev = qdev_create(NULL, "ARM,bitband-memory");
143     qdev_prop_set_uint32(dev, "base", 0x20000000);
144     qdev_init(dev);
145     sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x22000000);
146
147     dev = qdev_create(NULL, "ARM,bitband-memory");
148     qdev_prop_set_uint32(dev, "base", 0x40000000);
149     qdev_init(dev);
150     sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x42000000);
151 }
152
153 /* Board init.  */
154 /* Init CPU and memory for a v7-M based board.
155    flash_size and sram_size are in kb.
156    Returns the NVIC array.  */
157
158 qemu_irq *armv7m_init(int flash_size, int sram_size,
159                       const char *kernel_filename, const char *cpu_model)
160 {
161     CPUState *env;
162     DeviceState *nvic;
163     /* FIXME: make this local state.  */
164     static qemu_irq pic[64];
165     qemu_irq *cpu_pic;
166     uint32_t pc;
167     int image_size;
168     uint64_t entry;
169     uint64_t lowaddr;
170     int i;
171     int big_endian;
172
173     flash_size *= 1024;
174     sram_size *= 1024;
175
176     if (!cpu_model)
177         cpu_model = "cortex-m3";
178     env = cpu_init(cpu_model);
179     if (!env) {
180         fprintf(stderr, "Unable to find CPU definition\n");
181         exit(1);
182     }
183
184 #if 0
185     /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
186        We don't have proper commandline options, so allocate half of memory
187        as SRAM, up to a maximum of 32Mb, and the rest as code.  */
188     if (ram_size > (512 + 32) * 1024 * 1024)
189         ram_size = (512 + 32) * 1024 * 1024;
190     sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
191     if (sram_size > 32 * 1024 * 1024)
192         sram_size = 32 * 1024 * 1024;
193     code_size = ram_size - sram_size;
194 #endif
195
196     /* Flash programming is done via the SCU, so pretend it is ROM.  */
197     cpu_register_physical_memory(0, flash_size,
198                                  qemu_ram_alloc(flash_size) | IO_MEM_ROM);
199     cpu_register_physical_memory(0x20000000, sram_size,
200                                  qemu_ram_alloc(sram_size) | IO_MEM_RAM);
201     armv7m_bitband_init();
202
203     nvic = qdev_create(NULL, "armv7m_nvic");
204     env->v7m.nvic = nvic;
205     qdev_init(nvic);
206     cpu_pic = arm_pic_init_cpu(env);
207     sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
208     for (i = 0; i < 64; i++) {
209         pic[i] = qdev_get_gpio_in(nvic, i);
210     }
211
212 #ifdef TARGET_WORDS_BIGENDIAN
213     big_endian = 1;
214 #else
215     big_endian = 0;
216 #endif
217
218     image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL,
219                           big_endian, ELF_MACHINE, 1);
220     if (image_size < 0) {
221         image_size = load_image_targphys(kernel_filename, 0, flash_size);
222         lowaddr = 0;
223     }
224     if (image_size < 0) {
225         fprintf(stderr, "qemu: could not load kernel '%s'\n",
226                 kernel_filename);
227         exit(1);
228     }
229
230     /* If the image was loaded at address zero then assume it is a
231        regular ROM image and perform the normal CPU reset sequence.
232        Otherwise jump directly to the entry point.  */
233     if (lowaddr == 0) {
234         env->regs[13] = ldl_phys(0);
235         pc = ldl_phys(4);
236     } else {
237         pc = entry;
238     }
239     env->thumb = pc & 1;
240     env->regs[15] = pc & ~1;
241
242     /* Hack to map an additional page of ram at the top of the address
243        space.  This stops qemu complaining about executing code outside RAM
244        when returning from an exception.  */
245     cpu_register_physical_memory(0xfffff000, 0x1000,
246                                  qemu_ram_alloc(0x1000) | IO_MEM_RAM);
247
248     return pic;
249 }
250
251 static SysBusDeviceInfo bitband_info = {
252     .init = bitband_init,
253     .qdev.name  = "ARM,bitband-memory",
254     .qdev.size  = sizeof(BitBandState),
255     .qdev.props = (Property[]) {
256         DEFINE_PROP_UINT32("base", BitBandState, base, 0),
257         DEFINE_PROP_END_OF_LIST(),
258     }
259 };
260
261 static void armv7m_register_devices(void)
262 {
263     sysbus_register_withprop(&bitband_info);
264 }
265
266 device_init(armv7m_register_devices)
This page took 0.036601 seconds and 4 git commands to generate.