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"
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();
50 object_initialize_child(OBJECT(mstate
), "soc", &sms
->soc
,
51 TYPE_RISCV_SHAKTI_SOC
);
52 qdev_realize(DEVICE(&sms
->soc
), NULL
, &error_abort
);
55 memory_region_add_subregion(system_memory
,
56 shakti_c_memmap
[SHAKTI_C_RAM
].base
,
59 /* ROM reset vector */
60 riscv_setup_rom_reset_vec(mstate
, &sms
->soc
.cpus
,
61 shakti_c_memmap
[SHAKTI_C_RAM
].base
,
62 shakti_c_memmap
[SHAKTI_C_ROM
].base
,
63 shakti_c_memmap
[SHAKTI_C_ROM
].size
, 0, 0);
64 if (mstate
->firmware
) {
65 riscv_load_firmware(mstate
->firmware
,
66 shakti_c_memmap
[SHAKTI_C_RAM
].base
,
71 static void shakti_c_machine_instance_init(Object
*obj
)
75 static void shakti_c_machine_class_init(ObjectClass
*klass
, void *data
)
77 MachineClass
*mc
= MACHINE_CLASS(klass
);
78 static const char * const valid_cpu_types
[] = {
79 RISCV_CPU_TYPE_NAME("shakti-c"),
83 mc
->desc
= "RISC-V Board compatible with Shakti SDK";
84 mc
->init
= shakti_c_machine_state_init
;
85 mc
->default_cpu_type
= TYPE_RISCV_CPU_SHAKTI_C
;
86 mc
->valid_cpu_types
= valid_cpu_types
;
87 mc
->default_ram_id
= "riscv.shakti.c.ram";
90 static const TypeInfo shakti_c_machine_type_info
= {
91 .name
= TYPE_RISCV_SHAKTI_MACHINE
,
92 .parent
= TYPE_MACHINE
,
93 .class_init
= shakti_c_machine_class_init
,
94 .instance_init
= shakti_c_machine_instance_init
,
95 .instance_size
= sizeof(ShaktiCMachineState
),
98 static void shakti_c_machine_type_info_register(void)
100 type_register_static(&shakti_c_machine_type_info
);
102 type_init(shakti_c_machine_type_info_register
)
104 static void shakti_c_soc_state_realize(DeviceState
*dev
, Error
**errp
)
106 MachineState
*ms
= MACHINE(qdev_get_machine());
107 ShaktiCSoCState
*sss
= RISCV_SHAKTI_SOC(dev
);
108 MemoryRegion
*system_memory
= get_system_memory();
110 sysbus_realize(SYS_BUS_DEVICE(&sss
->cpus
), &error_abort
);
112 sss
->plic
= sifive_plic_create(shakti_c_memmap
[SHAKTI_C_PLIC
].base
,
113 (char *)SHAKTI_C_PLIC_HART_CONFIG
, ms
->smp
.cpus
, 0,
114 SHAKTI_C_PLIC_NUM_SOURCES
,
115 SHAKTI_C_PLIC_NUM_PRIORITIES
,
116 SHAKTI_C_PLIC_PRIORITY_BASE
,
117 SHAKTI_C_PLIC_PENDING_BASE
,
118 SHAKTI_C_PLIC_ENABLE_BASE
,
119 SHAKTI_C_PLIC_ENABLE_STRIDE
,
120 SHAKTI_C_PLIC_CONTEXT_BASE
,
121 SHAKTI_C_PLIC_CONTEXT_STRIDE
,
122 shakti_c_memmap
[SHAKTI_C_PLIC
].size
);
124 riscv_aclint_swi_create(shakti_c_memmap
[SHAKTI_C_CLINT
].base
,
126 riscv_aclint_mtimer_create(shakti_c_memmap
[SHAKTI_C_CLINT
].base
+
127 RISCV_ACLINT_SWI_SIZE
,
128 RISCV_ACLINT_DEFAULT_MTIMER_SIZE
, 0, 1,
129 RISCV_ACLINT_DEFAULT_MTIMECMP
, RISCV_ACLINT_DEFAULT_MTIME
,
130 RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ
, false);
132 qdev_prop_set_chr(DEVICE(&(sss
->uart
)), "chardev", serial_hd(0));
133 if (!sysbus_realize(SYS_BUS_DEVICE(&sss
->uart
), errp
)) {
136 sysbus_mmio_map(SYS_BUS_DEVICE(&sss
->uart
), 0,
137 shakti_c_memmap
[SHAKTI_C_UART
].base
);
140 memory_region_init_rom(&sss
->rom
, OBJECT(dev
), "riscv.shakti.c.rom",
141 shakti_c_memmap
[SHAKTI_C_ROM
].size
, &error_fatal
);
142 memory_region_add_subregion(system_memory
,
143 shakti_c_memmap
[SHAKTI_C_ROM
].base
, &sss
->rom
);
146 static void shakti_c_soc_class_init(ObjectClass
*klass
, void *data
)
148 DeviceClass
*dc
= DEVICE_CLASS(klass
);
149 dc
->realize
= shakti_c_soc_state_realize
;
152 * - Creates CPUS in riscv_hart_realize(), and can create unintended
154 * - Uses serial_hds in realize function, thus can't be used twice
156 dc
->user_creatable
= false;
159 static void shakti_c_soc_instance_init(Object
*obj
)
161 ShaktiCSoCState
*sss
= RISCV_SHAKTI_SOC(obj
);
163 object_initialize_child(obj
, "cpus", &sss
->cpus
, TYPE_RISCV_HART_ARRAY
);
164 object_initialize_child(obj
, "uart", &sss
->uart
, TYPE_SHAKTI_UART
);
167 * CPU type is fixed and we are not supporting passing from commandline yet.
168 * So let it be in instance_init. When supported should use ms->cpu_type
169 * instead of TYPE_RISCV_CPU_SHAKTI_C
171 object_property_set_str(OBJECT(&sss
->cpus
), "cpu-type",
172 TYPE_RISCV_CPU_SHAKTI_C
, &error_abort
);
173 object_property_set_int(OBJECT(&sss
->cpus
), "num-harts", 1,
177 static const TypeInfo shakti_c_type_info
= {
178 .name
= TYPE_RISCV_SHAKTI_SOC
,
179 .parent
= TYPE_DEVICE
,
180 .class_init
= shakti_c_soc_class_init
,
181 .instance_init
= shakti_c_soc_instance_init
,
182 .instance_size
= sizeof(ShaktiCSoCState
),
185 static void shakti_c_type_info_register(void)
187 type_register_static(&shakti_c_type_info
);
189 type_init(shakti_c_type_info_register
)