2 * OpenRISC simulator for use as an IIS.
4 * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5 * Feng Gao <gf91597@gmail.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
22 #include "qemu/error-report.h"
23 #include "qapi/error.h"
26 #include "hw/boards.h"
27 #include "hw/char/serial.h"
29 #include "hw/openrisc/boot.h"
30 #include "hw/qdev-properties.h"
31 #include "exec/address-spaces.h"
32 #include "sysemu/device_tree.h"
33 #include "sysemu/sysemu.h"
34 #include "hw/sysbus.h"
35 #include "sysemu/qtest.h"
36 #include "sysemu/reset.h"
37 #include "hw/core/split-irq.h"
41 #define KERNEL_LOAD_ADDR 0x100
43 #define OR1KSIM_CPUS_MAX 4
44 #define OR1KSIM_CLK_MHZ 20000000
46 #define TYPE_OR1KSIM_MACHINE MACHINE_TYPE_NAME("or1k-sim")
47 #define OR1KSIM_MACHINE(obj) \
48 OBJECT_CHECK(Or1ksimState, (obj), TYPE_OR1KSIM_MACHINE)
50 typedef struct Or1ksimState
{
52 MachineState parent_obj
;
68 OR1KSIM_OMPIC_IRQ
= 1,
70 OR1KSIM_ETHOC_IRQ
= 4,
74 OR1KSIM_UART_COUNT
= 4
77 static const struct MemmapEntry
{
80 } or1ksim_memmap
[] = {
81 [OR1KSIM_DRAM
] = { 0x00000000, 0 },
82 [OR1KSIM_UART
] = { 0x90000000, 0x100 },
83 [OR1KSIM_ETHOC
] = { 0x92000000, 0x800 },
84 [OR1KSIM_OMPIC
] = { 0x98000000, OR1KSIM_CPUS_MAX
* 8 },
87 static struct openrisc_boot_info
{
88 uint32_t bootstrap_pc
;
92 static void main_cpu_reset(void *opaque
)
94 OpenRISCCPU
*cpu
= opaque
;
95 CPUState
*cs
= CPU(cpu
);
99 cpu_set_pc(cs
, boot_info
.bootstrap_pc
);
100 cpu_set_gpr(&cpu
->env
, 3, boot_info
.fdt_addr
);
103 static qemu_irq
get_cpu_irq(OpenRISCCPU
*cpus
[], int cpunum
, int irq_pin
)
105 return qdev_get_gpio_in_named(DEVICE(cpus
[cpunum
]), "IRQ", irq_pin
);
108 static void openrisc_create_fdt(Or1ksimState
*state
,
109 const struct MemmapEntry
*memmap
,
110 int num_cpus
, uint64_t mem_size
,
118 fdt
= state
->fdt
= create_device_tree(&state
->fdt_size
);
120 error_report("create_device_tree() failed");
124 qemu_fdt_setprop_string(fdt
, "/", "compatible", "opencores,or1ksim");
125 qemu_fdt_setprop_cell(fdt
, "/", "#address-cells", 0x1);
126 qemu_fdt_setprop_cell(fdt
, "/", "#size-cells", 0x1);
128 nodename
= g_strdup_printf("/memory@%" HWADDR_PRIx
,
129 memmap
[OR1KSIM_DRAM
].base
);
130 qemu_fdt_add_subnode(fdt
, nodename
);
131 qemu_fdt_setprop_cells(fdt
, nodename
, "reg",
132 memmap
[OR1KSIM_DRAM
].base
, mem_size
);
133 qemu_fdt_setprop_string(fdt
, nodename
, "device_type", "memory");
136 qemu_fdt_add_subnode(fdt
, "/cpus");
137 qemu_fdt_setprop_cell(fdt
, "/cpus", "#size-cells", 0x0);
138 qemu_fdt_setprop_cell(fdt
, "/cpus", "#address-cells", 0x1);
140 for (cpu
= 0; cpu
< num_cpus
; cpu
++) {
141 nodename
= g_strdup_printf("/cpus/cpu@%d", cpu
);
142 qemu_fdt_add_subnode(fdt
, nodename
);
143 qemu_fdt_setprop_string(fdt
, nodename
, "compatible",
144 "opencores,or1200-rtlsvn481");
145 qemu_fdt_setprop_cell(fdt
, nodename
, "reg", cpu
);
146 qemu_fdt_setprop_cell(fdt
, nodename
, "clock-frequency",
151 nodename
= (char *)"/pic";
152 qemu_fdt_add_subnode(fdt
, nodename
);
153 pic_ph
= qemu_fdt_alloc_phandle(fdt
);
154 qemu_fdt_setprop_string(fdt
, nodename
, "compatible",
155 "opencores,or1k-pic-level");
156 qemu_fdt_setprop_cell(fdt
, nodename
, "#interrupt-cells", 1);
157 qemu_fdt_setprop(fdt
, nodename
, "interrupt-controller", NULL
, 0);
158 qemu_fdt_setprop_cell(fdt
, nodename
, "phandle", pic_ph
);
160 qemu_fdt_setprop_cell(fdt
, "/", "interrupt-parent", pic_ph
);
162 qemu_fdt_add_subnode(fdt
, "/chosen");
164 qemu_fdt_setprop_string(fdt
, "/chosen", "bootargs", cmdline
);
167 /* Create aliases node for use by devices. */
168 qemu_fdt_add_subnode(fdt
, "/aliases");
171 static void openrisc_sim_net_init(Or1ksimState
*state
, hwaddr base
, hwaddr size
,
172 int num_cpus
, OpenRISCCPU
*cpus
[],
173 int irq_pin
, NICInfo
*nd
)
175 void *fdt
= state
->fdt
;
181 dev
= qdev_new("open_eth");
182 qdev_set_nic_properties(dev
, nd
);
184 s
= SYS_BUS_DEVICE(dev
);
185 sysbus_realize_and_unref(s
, &error_fatal
);
187 DeviceState
*splitter
= qdev_new(TYPE_SPLIT_IRQ
);
188 qdev_prop_set_uint32(splitter
, "num-lines", num_cpus
);
189 qdev_realize_and_unref(splitter
, NULL
, &error_fatal
);
190 for (i
= 0; i
< num_cpus
; i
++) {
191 qdev_connect_gpio_out(splitter
, i
, get_cpu_irq(cpus
, i
, irq_pin
));
193 sysbus_connect_irq(s
, 0, qdev_get_gpio_in(splitter
, 0));
195 sysbus_connect_irq(s
, 0, get_cpu_irq(cpus
, 0, irq_pin
));
197 sysbus_mmio_map(s
, 0, base
);
198 sysbus_mmio_map(s
, 1, base
+ 0x400);
200 /* Init device tree node for ethoc. */
201 nodename
= g_strdup_printf("/ethoc@%" HWADDR_PRIx
, base
);
202 qemu_fdt_add_subnode(fdt
, nodename
);
203 qemu_fdt_setprop_string(fdt
, nodename
, "compatible", "opencores,ethoc");
204 qemu_fdt_setprop_cells(fdt
, nodename
, "reg", base
, size
);
205 qemu_fdt_setprop_cell(fdt
, nodename
, "interrupts", irq_pin
);
206 qemu_fdt_setprop(fdt
, nodename
, "big-endian", NULL
, 0);
208 qemu_fdt_setprop_string(fdt
, "/aliases", "enet0", nodename
);
212 static void openrisc_sim_ompic_init(Or1ksimState
*state
, hwaddr base
,
213 hwaddr size
, int num_cpus
,
214 OpenRISCCPU
*cpus
[], int irq_pin
)
216 void *fdt
= state
->fdt
;
222 dev
= qdev_new("or1k-ompic");
223 qdev_prop_set_uint32(dev
, "num-cpus", num_cpus
);
225 s
= SYS_BUS_DEVICE(dev
);
226 sysbus_realize_and_unref(s
, &error_fatal
);
227 for (i
= 0; i
< num_cpus
; i
++) {
228 sysbus_connect_irq(s
, i
, get_cpu_irq(cpus
, i
, irq_pin
));
230 sysbus_mmio_map(s
, 0, base
);
232 /* Add device tree node for ompic. */
233 nodename
= g_strdup_printf("/ompic@%" HWADDR_PRIx
, base
);
234 qemu_fdt_add_subnode(fdt
, nodename
);
235 qemu_fdt_setprop_string(fdt
, nodename
, "compatible", "openrisc,ompic");
236 qemu_fdt_setprop_cells(fdt
, nodename
, "reg", base
, size
);
237 qemu_fdt_setprop(fdt
, nodename
, "interrupt-controller", NULL
, 0);
238 qemu_fdt_setprop_cell(fdt
, nodename
, "#interrupt-cells", 0);
239 qemu_fdt_setprop_cell(fdt
, nodename
, "interrupts", irq_pin
);
243 static void openrisc_sim_serial_init(Or1ksimState
*state
, hwaddr base
,
244 hwaddr size
, int num_cpus
,
245 OpenRISCCPU
*cpus
[], int irq_pin
,
248 void *fdt
= state
->fdt
;
251 char alias
[sizeof("uart0")];
255 DeviceState
*splitter
= qdev_new(TYPE_SPLIT_IRQ
);
256 qdev_prop_set_uint32(splitter
, "num-lines", num_cpus
);
257 qdev_realize_and_unref(splitter
, NULL
, &error_fatal
);
258 for (i
= 0; i
< num_cpus
; i
++) {
259 qdev_connect_gpio_out(splitter
, i
, get_cpu_irq(cpus
, i
, irq_pin
));
261 serial_irq
= qdev_get_gpio_in(splitter
, 0);
263 serial_irq
= get_cpu_irq(cpus
, 0, irq_pin
);
265 serial_mm_init(get_system_memory(), base
, 0, serial_irq
, 115200,
266 serial_hd(OR1KSIM_UART_COUNT
- uart_idx
- 1),
267 DEVICE_NATIVE_ENDIAN
);
269 /* Add device tree node for serial. */
270 nodename
= g_strdup_printf("/serial@%" HWADDR_PRIx
, base
);
271 qemu_fdt_add_subnode(fdt
, nodename
);
272 qemu_fdt_setprop_string(fdt
, nodename
, "compatible", "ns16550a");
273 qemu_fdt_setprop_cells(fdt
, nodename
, "reg", base
, size
);
274 qemu_fdt_setprop_cell(fdt
, nodename
, "interrupts", irq_pin
);
275 qemu_fdt_setprop_cell(fdt
, nodename
, "clock-frequency", OR1KSIM_CLK_MHZ
);
276 qemu_fdt_setprop(fdt
, nodename
, "big-endian", NULL
, 0);
278 /* The /chosen node is created during fdt creation. */
279 qemu_fdt_setprop_string(fdt
, "/chosen", "stdout-path", nodename
);
280 snprintf(alias
, sizeof(alias
), "uart%d", uart_idx
);
281 qemu_fdt_setprop_string(fdt
, "/aliases", alias
, nodename
);
285 static void openrisc_sim_init(MachineState
*machine
)
287 ram_addr_t ram_size
= machine
->ram_size
;
288 const char *kernel_filename
= machine
->kernel_filename
;
289 OpenRISCCPU
*cpus
[OR1KSIM_CPUS_MAX
] = {};
290 Or1ksimState
*state
= OR1KSIM_MACHINE(machine
);
294 unsigned int smp_cpus
= machine
->smp
.cpus
;
296 assert(smp_cpus
>= 1 && smp_cpus
<= OR1KSIM_CPUS_MAX
);
297 for (n
= 0; n
< smp_cpus
; n
++) {
298 cpus
[n
] = OPENRISC_CPU(cpu_create(machine
->cpu_type
));
299 if (cpus
[n
] == NULL
) {
300 fprintf(stderr
, "Unable to find CPU definition!\n");
304 cpu_openrisc_clock_init(cpus
[n
]);
306 qemu_register_reset(main_cpu_reset
, cpus
[n
]);
309 ram
= g_malloc(sizeof(*ram
));
310 memory_region_init_ram(ram
, NULL
, "openrisc.ram", ram_size
, &error_fatal
);
311 memory_region_add_subregion(get_system_memory(), 0, ram
);
313 openrisc_create_fdt(state
, or1ksim_memmap
, smp_cpus
, machine
->ram_size
,
314 machine
->kernel_cmdline
);
316 if (nd_table
[0].used
) {
317 openrisc_sim_net_init(state
, or1ksim_memmap
[OR1KSIM_ETHOC
].base
,
318 or1ksim_memmap
[OR1KSIM_ETHOC
].size
,
320 OR1KSIM_ETHOC_IRQ
, nd_table
);
324 openrisc_sim_ompic_init(state
, or1ksim_memmap
[OR1KSIM_OMPIC
].base
,
325 or1ksim_memmap
[OR1KSIM_OMPIC
].size
,
326 smp_cpus
, cpus
, OR1KSIM_OMPIC_IRQ
);
329 for (n
= 0; n
< OR1KSIM_UART_COUNT
; ++n
)
330 openrisc_sim_serial_init(state
, or1ksim_memmap
[OR1KSIM_UART
].base
+
331 or1ksim_memmap
[OR1KSIM_UART
].size
* n
,
332 or1ksim_memmap
[OR1KSIM_UART
].size
,
333 smp_cpus
, cpus
, OR1KSIM_UART_IRQ
, n
);
335 load_addr
= openrisc_load_kernel(ram_size
, kernel_filename
,
336 &boot_info
.bootstrap_pc
);
338 if (machine
->initrd_filename
) {
339 load_addr
= openrisc_load_initrd(state
->fdt
,
340 machine
->initrd_filename
,
341 load_addr
, machine
->ram_size
);
343 boot_info
.fdt_addr
= openrisc_load_fdt(state
->fdt
, load_addr
,
348 static void openrisc_sim_machine_init(ObjectClass
*oc
, void *data
)
350 MachineClass
*mc
= MACHINE_CLASS(oc
);
352 mc
->desc
= "or1k simulation";
353 mc
->init
= openrisc_sim_init
;
354 mc
->max_cpus
= OR1KSIM_CPUS_MAX
;
355 mc
->is_default
= true;
356 mc
->default_cpu_type
= OPENRISC_CPU_TYPE_NAME("or1200");
359 static const TypeInfo or1ksim_machine_typeinfo
= {
360 .name
= TYPE_OR1KSIM_MACHINE
,
361 .parent
= TYPE_MACHINE
,
362 .class_init
= openrisc_sim_machine_init
,
363 .instance_size
= sizeof(Or1ksimState
),
366 static void or1ksim_machine_init_register_types(void)
368 type_register_static(&or1ksim_machine_typeinfo
);
371 type_init(or1ksim_machine_init_register_types
)