44
44
45
45
#include <libfdt.h>
46
46
47
+ /* Each UART is given 0x100 bytes of memory map despite not needing nearly
48
+ * that much. Despite that, the existing memory map still supports up to
49
+ * 16 uarts, which is probably plenty.
50
+ */
51
+ #define MAX_UARTS 16
52
+
47
53
static const struct MemmapEntry {
48
54
hwaddr base ;
49
55
hwaddr size ;
@@ -59,7 +65,7 @@ static const struct MemmapEntry {
59
65
};
60
66
61
67
static void * create_fdt (RISCVVirtState * s , const struct MemmapEntry * memmap ,
62
- uint64_t mem_size , const char * cmdline )
68
+ uint64_t mem_size , const char * cmdline , uint32_t * out_plic_handle )
63
69
{
64
70
void * fdt ;
65
71
int cpu ;
@@ -200,28 +206,52 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
200
206
qemu_fdt_setprop_cells (fdt , nodename , "reg" ,
201
207
0x0 , memmap [VIRT_TEST ].base ,
202
208
0x0 , memmap [VIRT_TEST ].size );
209
+ g_free (nodename );
203
210
204
- nodename = g_strdup_printf ("/uart@%lx" ,
205
- (long )memmap [VIRT_UART0 ].base );
206
- qemu_fdt_add_subnode (fdt , nodename );
207
- qemu_fdt_setprop_string (fdt , nodename , "compatible" , "ns16550a" );
208
- qemu_fdt_setprop_cells (fdt , nodename , "reg" ,
209
- 0x0 , memmap [VIRT_UART0 ].base ,
210
- 0x0 , memmap [VIRT_UART0 ].size );
211
- qemu_fdt_setprop_cell (fdt , nodename , "clock-frequency" , 3686400 );
212
- qemu_fdt_setprop_cells (fdt , nodename , "interrupt-parent" , plic_phandle );
213
- qemu_fdt_setprop_cells (fdt , nodename , "interrupts" , UART0_IRQ );
214
-
211
+ /* Install UART0 as /chosen/stdout-path */
212
+ nodename = g_strdup_printf ("/uart@%lx" , (long )memmap [VIRT_UART0 ].base );
215
213
qemu_fdt_add_subnode (fdt , "/chosen" );
216
214
qemu_fdt_setprop_string (fdt , "/chosen" , "stdout-path" , nodename );
215
+ g_free (nodename );
217
216
if (cmdline ) {
218
217
qemu_fdt_setprop_string (fdt , "/chosen" , "bootargs" , cmdline );
219
218
}
220
- g_free (nodename );
219
+
220
+ if (out_plic_handle ) {
221
+ * out_plic_handle = plic_phandle ;
222
+ }
221
223
222
224
return fdt ;
223
225
}
224
226
227
+ static void
228
+ riscv_virt_serial_init (RISCVVirtState * s , const struct MemmapEntry * memmap ,
229
+ MemoryRegion * system_memory , void * fdt ,
230
+ uint32_t plic_phandle , int hdix , int uix )
231
+ {
232
+ hwaddr addr ;
233
+ char * nodename ;
234
+
235
+ addr = memmap [VIRT_UART0 ].base + uix * memmap [VIRT_UART0 ].size ;
236
+
237
+ /* Wire to memory */
238
+ serial_mm_init (system_memory , addr , 0 ,
239
+ qdev_get_gpio_in (DEVICE (s -> plic ), UART0_IRQ + uix ), 399193 ,
240
+ serial_hd (hdix ), DEVICE_LITTLE_ENDIAN );
241
+
242
+ /* Register with FDT */
243
+ nodename = g_strdup_printf ("/uart@%lx" , (long )addr );
244
+ qemu_fdt_add_subnode (fdt , nodename );
245
+ qemu_fdt_setprop_string (fdt , nodename , "compatible" , "ns16550a" );
246
+ qemu_fdt_setprop_cells (fdt , nodename , "reg" ,
247
+ 0x0 , addr ,
248
+ 0x0 , memmap [VIRT_UART0 ].size );
249
+ qemu_fdt_setprop_cell (fdt , nodename , "clock-frequency" , 3686400 );
250
+ qemu_fdt_setprop_cells (fdt , nodename , "interrupt-parent" , plic_phandle );
251
+ qemu_fdt_setprop_cells (fdt , nodename , "interrupts" , UART0_IRQ + uix );
252
+ g_free (nodename );
253
+ }
254
+
225
255
static void riscv_virt_board_init (MachineState * machine )
226
256
{
227
257
const struct MemmapEntry * memmap = virt_memmap ;
@@ -232,8 +262,9 @@ static void riscv_virt_board_init(MachineState *machine)
232
262
MemoryRegion * mask_rom = g_new (MemoryRegion , 1 );
233
263
char * plic_hart_config ;
234
264
size_t plic_hart_config_len ;
235
- int i ;
265
+ int i , j ;
236
266
void * fdt ;
267
+ uint32_t plic_phandle ;
237
268
hwaddr firmware_entry ;
238
269
239
270
/* Initialize SOC */
@@ -253,7 +284,44 @@ static void riscv_virt_board_init(MachineState *machine)
253
284
main_mem );
254
285
255
286
/* create device tree */
256
- fdt = create_fdt (s , memmap , machine -> ram_size , machine -> kernel_cmdline );
287
+ fdt = create_fdt (s , memmap , machine -> ram_size , machine -> kernel_cmdline ,
288
+ & plic_phandle );
289
+
290
+ /* create PLIC hart topology configuration string */
291
+ plic_hart_config_len = (strlen (VIRT_PLIC_HART_CONFIG ) + 1 ) * smp_cpus ;
292
+ plic_hart_config = g_malloc0 (plic_hart_config_len );
293
+ for (i = 0 ; i < smp_cpus ; i ++ ) {
294
+ if (i != 0 ) {
295
+ strncat (plic_hart_config , "," , plic_hart_config_len );
296
+ }
297
+ strncat (plic_hart_config , VIRT_PLIC_HART_CONFIG , plic_hart_config_len );
298
+ plic_hart_config_len -= (strlen (VIRT_PLIC_HART_CONFIG ) + 1 );
299
+ }
300
+
301
+ /* create PLIC */
302
+ s -> plic = sifive_plic_create (memmap [VIRT_PLIC ].base ,
303
+ plic_hart_config ,
304
+ VIRT_PLIC_NUM_SOURCES ,
305
+ VIRT_PLIC_NUM_PRIORITIES ,
306
+ VIRT_PLIC_PRIORITY_BASE ,
307
+ VIRT_PLIC_PENDING_BASE ,
308
+ VIRT_PLIC_ENABLE_BASE ,
309
+ VIRT_PLIC_ENABLE_STRIDE ,
310
+ VIRT_PLIC_CONTEXT_BASE ,
311
+ VIRT_PLIC_CONTEXT_STRIDE ,
312
+ memmap [VIRT_PLIC ].size );
313
+
314
+ /* Attach UARTs */
315
+ for (i = 1 , j = 1 ; (i < serial_max_hds ()) && (j < MAX_UARTS ); i ++ ) {
316
+ if (serial_hd (i ) == NULL ) {
317
+ continue ;
318
+ }
319
+ riscv_virt_serial_init (s , memmap , system_memory , fdt , plic_phandle ,
320
+ i , j );
321
+ j ++ ;
322
+ }
323
+ /* Attach the debug UART last, so BBL finds it first */
324
+ riscv_virt_serial_init (s , memmap , system_memory , fdt , plic_phandle , 0 , 0 );
257
325
258
326
/* boot rom */
259
327
memory_region_init_rom (mask_rom , NULL , "riscv_virt_board.mrom" ,
@@ -303,29 +371,7 @@ static void riscv_virt_board_init(MachineState *machine)
303
371
memmap [VIRT_MROM ].base + sizeof (reset_vec ),
304
372
& address_space_memory );
305
373
306
- /* create PLIC hart topology configuration string */
307
- plic_hart_config_len = (strlen (VIRT_PLIC_HART_CONFIG ) + 1 ) * smp_cpus ;
308
- plic_hart_config = g_malloc0 (plic_hart_config_len );
309
- for (i = 0 ; i < smp_cpus ; i ++ ) {
310
- if (i != 0 ) {
311
- strncat (plic_hart_config , "," , plic_hart_config_len );
312
- }
313
- strncat (plic_hart_config , VIRT_PLIC_HART_CONFIG , plic_hart_config_len );
314
- plic_hart_config_len -= (strlen (VIRT_PLIC_HART_CONFIG ) + 1 );
315
- }
316
-
317
- /* MMIO */
318
- s -> plic = sifive_plic_create (memmap [VIRT_PLIC ].base ,
319
- plic_hart_config ,
320
- VIRT_PLIC_NUM_SOURCES ,
321
- VIRT_PLIC_NUM_PRIORITIES ,
322
- VIRT_PLIC_PRIORITY_BASE ,
323
- VIRT_PLIC_PENDING_BASE ,
324
- VIRT_PLIC_ENABLE_BASE ,
325
- VIRT_PLIC_ENABLE_STRIDE ,
326
- VIRT_PLIC_CONTEXT_BASE ,
327
- VIRT_PLIC_CONTEXT_STRIDE ,
328
- memmap [VIRT_PLIC ].size );
374
+ /* Other MMIO: CLINT, TEST */
329
375
sifive_clint_create (memmap [VIRT_CLINT ].base ,
330
376
memmap [VIRT_CLINT ].size , smp_cpus ,
331
377
SIFIVE_SIP_BASE , SIFIVE_TIMECMP_BASE , SIFIVE_TIME_BASE );
@@ -337,10 +383,6 @@ static void riscv_virt_board_init(MachineState *machine)
337
383
qdev_get_gpio_in (DEVICE (s -> plic ), VIRTIO_IRQ + i ));
338
384
}
339
385
340
- serial_mm_init (system_memory , memmap [VIRT_UART0 ].base ,
341
- 0 , qdev_get_gpio_in (DEVICE (s -> plic ), UART0_IRQ ), 399193 ,
342
- serial_hd (0 ), DEVICE_LITTLE_ENDIAN );
343
-
344
386
g_free (plic_hart_config );
345
387
}
346
388
0 commit comments