2 * Shakti C-class SoC emulation
4 * Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
20 #include "hw/boards.h"
21 #include "hw/riscv/shakti_c.h"
22 #include "qapi/error.h"
23 #include "hw/intc/sifive_plic.h"
24 #include "hw/intc/riscv_aclint.h"
25 #include "sysemu/sysemu.h"
26 #include "hw/qdev-properties.h"
27 #include "exec/address-spaces.h"
28 #include "hw/riscv/boot.h"
31 static const struct MemmapEntry
{
34 } shakti_c_memmap
[] = {
35 [SHAKTI_C_ROM
] = { 0x00001000, 0x2000 },
36 [SHAKTI_C_RAM
] = { 0x80000000, 0x0 },
37 [SHAKTI_C_UART
] = { 0x00011300, 0x00040 },
38 [SHAKTI_C_GPIO
] = { 0x020d0000, 0x00100 },
39 [SHAKTI_C_PLIC
] = { 0x0c000000, 0x20000 },
40 [SHAKTI_C_CLINT
] = { 0x02000000, 0xc0000 },
41 [SHAKTI_C_I2C
] = { 0x20c00000, 0x00100 },
44 static void shakti_c_machine_state_init(MachineState
*mstate
)
46 ShaktiCMachineState
*sms
= RISCV_SHAKTI_MACHINE(mstate
);
47 MemoryRegion
*system_memory
= get_system_memory();
48 MemoryRegion
*main_mem
= g_new(MemoryRegion
, 1);
50 /* Allow only Shakti C CPU for this platform */
51 if (strcmp(mstate
->cpu_type
, TYPE_RISCV_CPU_SHAKTI_C
) != 0) {
52 error_report("This board can only be used with Shakti C CPU");
57 object_initialize_child(OBJECT(mstate
), "soc", &sms
->soc
,
58 TYPE_RISCV_SHAKTI_SOC
);
59 qdev_realize(DEVICE(&sms
->soc
), NULL
, &error_abort
);
62 memory_region_init_ram(main_mem
, NULL
, "riscv.shakti.c.ram",
63 mstate
->ram_size
, &error_fatal
);
64 memory_region_add_subregion(system_memory
,
65 shakti_c_memmap
[SHAKTI_C_RAM
].base
,
68 /* ROM reset vector */
69 riscv_setup_rom_reset_vec(mstate
, &sms
->soc
.cpus
,
70 shakti_c_memmap
[SHAKTI_C_RAM
].base
,
71 shakti_c_memmap
[SHAKTI_C_ROM
].base
,
72 shakti_c_memmap
[SHAKTI_C_ROM
].size
, 0, 0,
74 if (mstate
->firmware
) {
75 riscv_load_firmware(mstate
->firmware
,
76 shakti_c_memmap
[SHAKTI_C_RAM
].base
,
81 static void shakti_c_machine_instance_init(Object
*obj
)
85 static void shakti_c_machine_class_init(ObjectClass
*klass
, void *data
)
87 MachineClass
*mc
= MACHINE_CLASS(klass
);
88 mc
->desc
= "RISC-V Board compatible with Shakti SDK";
89 mc
->init
= shakti_c_machine_state_init
;
90 mc
->default_cpu_type
= TYPE_RISCV_CPU_SHAKTI_C
;
93 static const TypeInfo shakti_c_machine_type_info
= {
94 .name
= TYPE_RISCV_SHAKTI_MACHINE
,
95 .parent
= TYPE_MACHINE
,
96 .class_init
= shakti_c_machine_class_init
,
97 .instance_init
= shakti_c_machine_instance_init
,
98 .instance_size
= sizeof(ShaktiCMachineState
),
101 static void shakti_c_machine_type_info_register(void)
103 type_register_static(&shakti_c_machine_type_info
);
105 type_init(shakti_c_machine_type_info_register
)
107 static void shakti_c_soc_state_realize(DeviceState
*dev
, Error
**errp
)
109 MachineState
*ms
= MACHINE(qdev_get_machine());
110 ShaktiCSoCState
*sss
= RISCV_SHAKTI_SOC(dev
);
111 MemoryRegion
*system_memory
= get_system_memory();
113 sysbus_realize(SYS_BUS_DEVICE(&sss
->cpus
), &error_abort
);
115 sss
->plic
= sifive_plic_create(shakti_c_memmap
[SHAKTI_C_PLIC
].base
,
116 (char *)SHAKTI_C_PLIC_HART_CONFIG
, ms
->smp
.cpus
, 0,
117 SHAKTI_C_PLIC_NUM_SOURCES
,
118 SHAKTI_C_PLIC_NUM_PRIORITIES
,
119 SHAKTI_C_PLIC_PRIORITY_BASE
,
120 SHAKTI_C_PLIC_PENDING_BASE
,
121 SHAKTI_C_PLIC_ENABLE_BASE
,
122 SHAKTI_C_PLIC_ENABLE_STRIDE
,
123 SHAKTI_C_PLIC_CONTEXT_BASE
,
124 SHAKTI_C_PLIC_CONTEXT_STRIDE
,
125 shakti_c_memmap
[SHAKTI_C_PLIC
].size
);
127 riscv_aclint_swi_create(shakti_c_memmap
[SHAKTI_C_CLINT
].base
,
129 riscv_aclint_mtimer_create(shakti_c_memmap
[SHAKTI_C_CLINT
].base
+
130 RISCV_ACLINT_SWI_SIZE
,
131 RISCV_ACLINT_DEFAULT_MTIMER_SIZE
, 0, 1,
132 RISCV_ACLINT_DEFAULT_MTIMECMP
, RISCV_ACLINT_DEFAULT_MTIME
,
133 RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ
, false);
135 qdev_prop_set_chr(DEVICE(&(sss
->uart
)), "chardev", serial_hd(0));
136 if (!sysbus_realize(SYS_BUS_DEVICE(&sss
->uart
), errp
)) {
139 sysbus_mmio_map(SYS_BUS_DEVICE(&sss
->uart
), 0,
140 shakti_c_memmap
[SHAKTI_C_UART
].base
);
143 memory_region_init_rom(&sss
->rom
, OBJECT(dev
), "riscv.shakti.c.rom",
144 shakti_c_memmap
[SHAKTI_C_ROM
].size
, &error_fatal
);
145 memory_region_add_subregion(system_memory
,
146 shakti_c_memmap
[SHAKTI_C_ROM
].base
, &sss
->rom
);
149 static void shakti_c_soc_class_init(ObjectClass
*klass
, void *data
)
151 DeviceClass
*dc
= DEVICE_CLASS(klass
);
152 dc
->realize
= shakti_c_soc_state_realize
;
155 static void shakti_c_soc_instance_init(Object
*obj
)
157 ShaktiCSoCState
*sss
= RISCV_SHAKTI_SOC(obj
);
159 object_initialize_child(obj
, "cpus", &sss
->cpus
, TYPE_RISCV_HART_ARRAY
);
160 object_initialize_child(obj
, "uart", &sss
->uart
, TYPE_SHAKTI_UART
);
163 * CPU type is fixed and we are not supporting passing from commandline yet.
164 * So let it be in instance_init. When supported should use ms->cpu_type
165 * instead of TYPE_RISCV_CPU_SHAKTI_C
167 object_property_set_str(OBJECT(&sss
->cpus
), "cpu-type",
168 TYPE_RISCV_CPU_SHAKTI_C
, &error_abort
);
169 object_property_set_int(OBJECT(&sss
->cpus
), "num-harts", 1,
173 static const TypeInfo shakti_c_type_info
= {
174 .name
= TYPE_RISCV_SHAKTI_SOC
,
175 .parent
= TYPE_DEVICE
,
176 .class_init
= shakti_c_soc_class_init
,
177 .instance_init
= shakti_c_soc_instance_init
,
178 .instance_size
= sizeof(ShaktiCSoCState
),
181 static void shakti_c_type_info_register(void)
183 type_register_static(&shakti_c_type_info
);
185 type_init(shakti_c_type_info_register
)