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 "qemu/error-report.h"
24 #include "hw/intc/sifive_plic.h"
25 #include "hw/intc/riscv_aclint.h"
26 #include "sysemu/sysemu.h"
27 #include "hw/qdev-properties.h"
28 #include "exec/address-spaces.h"
29 #include "hw/riscv/boot.h"
32 static const struct MemmapEntry
{
35 } shakti_c_memmap
[] = {
36 [SHAKTI_C_ROM
] = { 0x00001000, 0x2000 },
37 [SHAKTI_C_RAM
] = { 0x80000000, 0x0 },
38 [SHAKTI_C_UART
] = { 0x00011300, 0x00040 },
39 [SHAKTI_C_GPIO
] = { 0x020d0000, 0x00100 },
40 [SHAKTI_C_PLIC
] = { 0x0c000000, 0x20000 },
41 [SHAKTI_C_CLINT
] = { 0x02000000, 0xc0000 },
42 [SHAKTI_C_I2C
] = { 0x20c00000, 0x00100 },
45 static void shakti_c_machine_state_init(MachineState
*mstate
)
47 ShaktiCMachineState
*sms
= RISCV_SHAKTI_MACHINE(mstate
);
48 MemoryRegion
*system_memory
= get_system_memory();
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_add_subregion(system_memory
,
63 shakti_c_memmap
[SHAKTI_C_RAM
].base
,
66 /* ROM reset vector */
67 riscv_setup_rom_reset_vec(mstate
, &sms
->soc
.cpus
,
68 shakti_c_memmap
[SHAKTI_C_RAM
].base
,
69 shakti_c_memmap
[SHAKTI_C_ROM
].base
,
70 shakti_c_memmap
[SHAKTI_C_ROM
].size
, 0, 0);
71 if (mstate
->firmware
) {
72 riscv_load_firmware(mstate
->firmware
,
73 shakti_c_memmap
[SHAKTI_C_RAM
].base
,
78 static void shakti_c_machine_instance_init(Object
*obj
)
82 static void shakti_c_machine_class_init(ObjectClass
*klass
, void *data
)
84 MachineClass
*mc
= MACHINE_CLASS(klass
);
85 mc
->desc
= "RISC-V Board compatible with Shakti SDK";
86 mc
->init
= shakti_c_machine_state_init
;
87 mc
->default_cpu_type
= TYPE_RISCV_CPU_SHAKTI_C
;
88 mc
->default_ram_id
= "riscv.shakti.c.ram";
91 static const TypeInfo shakti_c_machine_type_info
= {
92 .name
= TYPE_RISCV_SHAKTI_MACHINE
,
93 .parent
= TYPE_MACHINE
,
94 .class_init
= shakti_c_machine_class_init
,
95 .instance_init
= shakti_c_machine_instance_init
,
96 .instance_size
= sizeof(ShaktiCMachineState
),
99 static void shakti_c_machine_type_info_register(void)
101 type_register_static(&shakti_c_machine_type_info
);
103 type_init(shakti_c_machine_type_info_register
)
105 static void shakti_c_soc_state_realize(DeviceState
*dev
, Error
**errp
)
107 MachineState
*ms
= MACHINE(qdev_get_machine());
108 ShaktiCSoCState
*sss
= RISCV_SHAKTI_SOC(dev
);
109 MemoryRegion
*system_memory
= get_system_memory();
111 sysbus_realize(SYS_BUS_DEVICE(&sss
->cpus
), &error_abort
);
113 sss
->plic
= sifive_plic_create(shakti_c_memmap
[SHAKTI_C_PLIC
].base
,
114 (char *)SHAKTI_C_PLIC_HART_CONFIG
, ms
->smp
.cpus
, 0,
115 SHAKTI_C_PLIC_NUM_SOURCES
,
116 SHAKTI_C_PLIC_NUM_PRIORITIES
,
117 SHAKTI_C_PLIC_PRIORITY_BASE
,
118 SHAKTI_C_PLIC_PENDING_BASE
,
119 SHAKTI_C_PLIC_ENABLE_BASE
,
120 SHAKTI_C_PLIC_ENABLE_STRIDE
,
121 SHAKTI_C_PLIC_CONTEXT_BASE
,
122 SHAKTI_C_PLIC_CONTEXT_STRIDE
,
123 shakti_c_memmap
[SHAKTI_C_PLIC
].size
);
125 riscv_aclint_swi_create(shakti_c_memmap
[SHAKTI_C_CLINT
].base
,
127 riscv_aclint_mtimer_create(shakti_c_memmap
[SHAKTI_C_CLINT
].base
+
128 RISCV_ACLINT_SWI_SIZE
,
129 RISCV_ACLINT_DEFAULT_MTIMER_SIZE
, 0, 1,
130 RISCV_ACLINT_DEFAULT_MTIMECMP
, RISCV_ACLINT_DEFAULT_MTIME
,
131 RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ
, false);
133 qdev_prop_set_chr(DEVICE(&(sss
->uart
)), "chardev", serial_hd(0));
134 if (!sysbus_realize(SYS_BUS_DEVICE(&sss
->uart
), errp
)) {
137 sysbus_mmio_map(SYS_BUS_DEVICE(&sss
->uart
), 0,
138 shakti_c_memmap
[SHAKTI_C_UART
].base
);
141 memory_region_init_rom(&sss
->rom
, OBJECT(dev
), "riscv.shakti.c.rom",
142 shakti_c_memmap
[SHAKTI_C_ROM
].size
, &error_fatal
);
143 memory_region_add_subregion(system_memory
,
144 shakti_c_memmap
[SHAKTI_C_ROM
].base
, &sss
->rom
);
147 static void shakti_c_soc_class_init(ObjectClass
*klass
, void *data
)
149 DeviceClass
*dc
= DEVICE_CLASS(klass
);
150 dc
->realize
= shakti_c_soc_state_realize
;
153 * - Creates CPUS in riscv_hart_realize(), and can create unintended
155 * - Uses serial_hds in realize function, thus can't be used twice
157 dc
->user_creatable
= false;
160 static void shakti_c_soc_instance_init(Object
*obj
)
162 ShaktiCSoCState
*sss
= RISCV_SHAKTI_SOC(obj
);
164 object_initialize_child(obj
, "cpus", &sss
->cpus
, TYPE_RISCV_HART_ARRAY
);
165 object_initialize_child(obj
, "uart", &sss
->uart
, TYPE_SHAKTI_UART
);
168 * CPU type is fixed and we are not supporting passing from commandline yet.
169 * So let it be in instance_init. When supported should use ms->cpu_type
170 * instead of TYPE_RISCV_CPU_SHAKTI_C
172 object_property_set_str(OBJECT(&sss
->cpus
), "cpu-type",
173 TYPE_RISCV_CPU_SHAKTI_C
, &error_abort
);
174 object_property_set_int(OBJECT(&sss
->cpus
), "num-harts", 1,
178 static const TypeInfo shakti_c_type_info
= {
179 .name
= TYPE_RISCV_SHAKTI_SOC
,
180 .parent
= TYPE_DEVICE
,
181 .class_init
= shakti_c_soc_class_init
,
182 .instance_init
= shakti_c_soc_instance_init
,
183 .instance_size
= sizeof(ShaktiCSoCState
),
186 static void shakti_c_type_info_register(void)
188 type_register_static(&shakti_c_type_info
);
190 type_init(shakti_c_type_info_register
)