@@ -49,6 +49,15 @@ typedef struct BostonState BostonState;
49
49
DECLARE_INSTANCE_CHECKER (BostonState , BOSTON ,
50
50
TYPE_BOSTON )
51
51
52
+ #define FDT_IRQ_TYPE_NONE 0
53
+ #define FDT_IRQ_TYPE_LEVEL_HIGH 4
54
+ #define FDT_GIC_SHARED 0
55
+ #define FDT_GIC_LOCAL 1
56
+ #define FDT_BOSTON_CLK_SYS 1
57
+ #define FDT_BOSTON_CLK_CPU 2
58
+ #define FDT_PCI_IRQ_MAP_PINS 4
59
+ #define FDT_PCI_IRQ_MAP_DESCS 6
60
+
52
61
struct BostonState {
53
62
SysBusDevice parent_obj ;
54
63
@@ -437,6 +446,222 @@ xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr,
437
446
return XILINX_PCIE_HOST (dev );
438
447
}
439
448
449
+
450
+ static void fdt_create_pcie (void * fdt , int gic_ph , int irq , hwaddr reg_base ,
451
+ hwaddr reg_size , hwaddr mmio_base , hwaddr mmio_size )
452
+ {
453
+ int i ;
454
+ char * name , * intc_name ;
455
+ uint32_t intc_ph ;
456
+ uint32_t interrupt_map [FDT_PCI_IRQ_MAP_PINS ][FDT_PCI_IRQ_MAP_DESCS ];
457
+
458
+ intc_ph = qemu_fdt_alloc_phandle (fdt );
459
+ name = g_strdup_printf ("/soc/pci@%" HWADDR_PRIx , reg_base );
460
+ qemu_fdt_add_subnode (fdt , name );
461
+ qemu_fdt_setprop_string (fdt , name , "compatible" ,
462
+ "xlnx,axi-pcie-host-1.00.a" );
463
+ qemu_fdt_setprop_string (fdt , name , "device_type" , "pci" );
464
+ qemu_fdt_setprop_cells (fdt , name , "reg" , reg_base , reg_size );
465
+
466
+ qemu_fdt_setprop_cell (fdt , name , "#address-cells" , 3 );
467
+ qemu_fdt_setprop_cell (fdt , name , "#size-cells" , 2 );
468
+ qemu_fdt_setprop_cell (fdt , name , "#interrupt-cells" , 1 );
469
+
470
+ qemu_fdt_setprop_cell (fdt , name , "interrupt-parent" , gic_ph );
471
+ qemu_fdt_setprop_cells (fdt , name , "interrupts" , FDT_GIC_SHARED , irq ,
472
+ FDT_IRQ_TYPE_LEVEL_HIGH );
473
+
474
+ qemu_fdt_setprop_cells (fdt , name , "ranges" , 0x02000000 , 0 , mmio_base ,
475
+ mmio_base , 0 , mmio_size );
476
+ qemu_fdt_setprop_cells (fdt , name , "bus-range" , 0x00 , 0xff );
477
+
478
+
479
+
480
+ intc_name = g_strdup_printf ("%s/interrupt-controller" , name );
481
+ qemu_fdt_add_subnode (fdt , intc_name );
482
+ qemu_fdt_setprop (fdt , intc_name , "interrupt-controller" , NULL , 0 );
483
+ qemu_fdt_setprop_cell (fdt , intc_name , "#address-cells" , 0 );
484
+ qemu_fdt_setprop_cell (fdt , intc_name , "#interrupt-cells" , 1 );
485
+ qemu_fdt_setprop_cell (fdt , intc_name , "phandle" , intc_ph );
486
+
487
+ qemu_fdt_setprop_cells (fdt , name , "interrupt-map-mask" , 0 , 0 , 0 , 7 );
488
+ for (i = 0 ; i < FDT_PCI_IRQ_MAP_PINS ; i ++ ) {
489
+ uint32_t * irqmap = interrupt_map [i ];
490
+
491
+ irqmap [0 ] = cpu_to_be32 (0 );
492
+ irqmap [1 ] = cpu_to_be32 (0 );
493
+ irqmap [2 ] = cpu_to_be32 (0 );
494
+ irqmap [3 ] = cpu_to_be32 (i + 1 );
495
+ irqmap [4 ] = cpu_to_be32 (intc_ph );
496
+ irqmap [5 ] = cpu_to_be32 (i + 1 );
497
+ }
498
+ qemu_fdt_setprop (fdt , name , "interrupt-map" ,
499
+ & interrupt_map , sizeof (interrupt_map ));
500
+
501
+ g_free (intc_name );
502
+ g_free (name );
503
+ }
504
+
505
+ static const void * create_fdt (BostonState * s ,
506
+ const MemMapEntry * memmap , int * dt_size )
507
+ {
508
+ void * fdt ;
509
+ int cpu ;
510
+ MachineState * mc = s -> mach ;
511
+ uint32_t platreg_ph , gic_ph , clk_ph ;
512
+ char * name , * gic_name , * platreg_name , * stdout_name ;
513
+ static const char * const syscon_compat [2 ] = {
514
+ "img,boston-platform-regs" , "syscon"
515
+ };
516
+
517
+ fdt = create_device_tree (dt_size );
518
+ if (!fdt ) {
519
+ error_report ("create_device_tree() failed" );
520
+ exit (1 );
521
+ }
522
+
523
+ platreg_ph = qemu_fdt_alloc_phandle (fdt );
524
+ gic_ph = qemu_fdt_alloc_phandle (fdt );
525
+ clk_ph = qemu_fdt_alloc_phandle (fdt );
526
+
527
+ qemu_fdt_setprop_string (fdt , "/" , "model" , "img,boston" );
528
+ qemu_fdt_setprop_string (fdt , "/" , "compatible" , "img,boston" );
529
+ qemu_fdt_setprop_cell (fdt , "/" , "#size-cells" , 0x1 );
530
+ qemu_fdt_setprop_cell (fdt , "/" , "#address-cells" , 0x1 );
531
+
532
+
533
+ qemu_fdt_add_subnode (fdt , "/cpus" );
534
+ qemu_fdt_setprop_cell (fdt , "/cpus" , "#size-cells" , 0x0 );
535
+ qemu_fdt_setprop_cell (fdt , "/cpus" , "#address-cells" , 0x1 );
536
+
537
+ for (cpu = 0 ; cpu < mc -> smp .cpus ; cpu ++ ) {
538
+ name = g_strdup_printf ("/cpus/cpu@%d" , cpu );
539
+ qemu_fdt_add_subnode (fdt , name );
540
+ qemu_fdt_setprop_string (fdt , name , "compatible" , "img,mips" );
541
+ qemu_fdt_setprop_string (fdt , name , "status" , "okay" );
542
+ qemu_fdt_setprop_cell (fdt , name , "reg" , cpu );
543
+ qemu_fdt_setprop_string (fdt , name , "device_type" , "cpu" );
544
+ qemu_fdt_setprop_cells (fdt , name , "clocks" , clk_ph , FDT_BOSTON_CLK_CPU );
545
+ g_free (name );
546
+ }
547
+
548
+ qemu_fdt_add_subnode (fdt , "/soc" );
549
+ qemu_fdt_setprop (fdt , "/soc" , "ranges" , NULL , 0 );
550
+ qemu_fdt_setprop_string (fdt , "/soc" , "compatible" , "simple-bus" );
551
+ qemu_fdt_setprop_cell (fdt , "/soc" , "#size-cells" , 0x1 );
552
+ qemu_fdt_setprop_cell (fdt , "/soc" , "#address-cells" , 0x1 );
553
+
554
+ fdt_create_pcie (fdt , gic_ph , 2 ,
555
+ memmap [BOSTON_PCIE0 ].base , memmap [BOSTON_PCIE0 ].size ,
556
+ memmap [BOSTON_PCIE0_MMIO ].base , memmap [BOSTON_PCIE0_MMIO ].size );
557
+
558
+ fdt_create_pcie (fdt , gic_ph , 1 ,
559
+ memmap [BOSTON_PCIE1 ].base , memmap [BOSTON_PCIE1 ].size ,
560
+ memmap [BOSTON_PCIE1_MMIO ].base , memmap [BOSTON_PCIE1_MMIO ].size );
561
+
562
+ fdt_create_pcie (fdt , gic_ph , 0 ,
563
+ memmap [BOSTON_PCIE2 ].base , memmap [BOSTON_PCIE2 ].size ,
564
+ memmap [BOSTON_PCIE2_MMIO ].base , memmap [BOSTON_PCIE2_MMIO ].size );
565
+
566
+ /* GIC with it's timer node */
567
+ gic_name = g_strdup_printf ("/soc/interrupt-controller@%" HWADDR_PRIx ,
568
+ memmap [BOSTON_GIC ].base );
569
+ qemu_fdt_add_subnode (fdt , gic_name );
570
+ qemu_fdt_setprop_string (fdt , gic_name , "compatible" , "mti,gic" );
571
+ qemu_fdt_setprop_cells (fdt , gic_name , "reg" , memmap [BOSTON_GIC ].base ,
572
+ memmap [BOSTON_GIC ].size );
573
+ qemu_fdt_setprop (fdt , gic_name , "interrupt-controller" , NULL , 0 );
574
+ qemu_fdt_setprop_cell (fdt , gic_name , "#interrupt-cells" , 3 );
575
+ qemu_fdt_setprop_cell (fdt , gic_name , "phandle" , gic_ph );
576
+
577
+ name = g_strdup_printf ("%s/timer" , gic_name );
578
+ qemu_fdt_add_subnode (fdt , name );
579
+ qemu_fdt_setprop_string (fdt , name , "compatible" , "mti,gic-timer" );
580
+ qemu_fdt_setprop_cells (fdt , name , "interrupts" , FDT_GIC_LOCAL , 1 ,
581
+ FDT_IRQ_TYPE_NONE );
582
+ qemu_fdt_setprop_cells (fdt , name , "clocks" , clk_ph , FDT_BOSTON_CLK_CPU );
583
+ g_free (name );
584
+ g_free (gic_name );
585
+
586
+ /* CDMM node */
587
+ name = g_strdup_printf ("/soc/cdmm@%" HWADDR_PRIx , memmap [BOSTON_CDMM ].base );
588
+ qemu_fdt_add_subnode (fdt , name );
589
+ qemu_fdt_setprop_string (fdt , name , "compatible" , "mti,mips-cdmm" );
590
+ qemu_fdt_setprop_cells (fdt , name , "reg" , memmap [BOSTON_CDMM ].base ,
591
+ memmap [BOSTON_CDMM ].size );
592
+ g_free (name );
593
+
594
+ /* CPC node */
595
+ name = g_strdup_printf ("/soc/cpc@%" HWADDR_PRIx , memmap [BOSTON_CPC ].base );
596
+ qemu_fdt_add_subnode (fdt , name );
597
+ qemu_fdt_setprop_string (fdt , name , "compatible" , "mti,mips-cpc" );
598
+ qemu_fdt_setprop_cells (fdt , name , "reg" , memmap [BOSTON_CPC ].base ,
599
+ memmap [BOSTON_CPC ].size );
600
+ g_free (name );
601
+
602
+ /* platreg and it's clk node */
603
+ platreg_name = g_strdup_printf ("/soc/system-controller@%" HWADDR_PRIx ,
604
+ memmap [BOSTON_PLATREG ].base );
605
+ qemu_fdt_add_subnode (fdt , platreg_name );
606
+ qemu_fdt_setprop_string_array (fdt , platreg_name , "compatible" ,
607
+ (char * * )& syscon_compat ,
608
+ ARRAY_SIZE (syscon_compat ));
609
+ qemu_fdt_setprop_cells (fdt , platreg_name , "reg" ,
610
+ memmap [BOSTON_PLATREG ].base ,
611
+ memmap [BOSTON_PLATREG ].size );
612
+ qemu_fdt_setprop_cell (fdt , platreg_name , "phandle" , platreg_ph );
613
+
614
+ name = g_strdup_printf ("%s/clock" , platreg_name );
615
+ qemu_fdt_add_subnode (fdt , name );
616
+ qemu_fdt_setprop_string (fdt , name , "compatible" , "img,boston-clock" );
617
+ qemu_fdt_setprop_cell (fdt , name , "#clock-cells" , 1 );
618
+ qemu_fdt_setprop_cell (fdt , name , "phandle" , clk_ph );
619
+ g_free (name );
620
+ g_free (platreg_name );
621
+
622
+ /* reboot node */
623
+ name = g_strdup_printf ("/soc/reboot" );
624
+ qemu_fdt_add_subnode (fdt , name );
625
+ qemu_fdt_setprop_string (fdt , name , "compatible" , "syscon-reboot" );
626
+ qemu_fdt_setprop_cell (fdt , name , "regmap" , platreg_ph );
627
+ qemu_fdt_setprop_cell (fdt , name , "offset" , 0x10 );
628
+ qemu_fdt_setprop_cell (fdt , name , "mask" , 0x10 );
629
+ g_free (name );
630
+
631
+ /* uart node */
632
+ name = g_strdup_printf ("/soc/uart@%" HWADDR_PRIx , memmap [BOSTON_UART ].base );
633
+ qemu_fdt_add_subnode (fdt , name );
634
+ qemu_fdt_setprop_string (fdt , name , "compatible" , "ns16550a" );
635
+ qemu_fdt_setprop_cells (fdt , name , "reg" , memmap [BOSTON_UART ].base ,
636
+ memmap [BOSTON_UART ].size );
637
+ qemu_fdt_setprop_cell (fdt , name , "reg-shift" , 0x2 );
638
+ qemu_fdt_setprop_cell (fdt , name , "interrupt-parent" , gic_ph );
639
+ qemu_fdt_setprop_cells (fdt , name , "interrupts" , FDT_GIC_SHARED , 3 ,
640
+ FDT_IRQ_TYPE_LEVEL_HIGH );
641
+ qemu_fdt_setprop_cells (fdt , name , "clocks" , clk_ph , FDT_BOSTON_CLK_SYS );
642
+
643
+ qemu_fdt_add_subnode (fdt , "/chosen" );
644
+ stdout_name = g_strdup_printf ("%s:115200" , name );
645
+ qemu_fdt_setprop_string (fdt , "/chosen" , "stdout-path" , stdout_name );
646
+ g_free (stdout_name );
647
+ g_free (name );
648
+
649
+ /* lcd node */
650
+ name = g_strdup_printf ("/soc/lcd@%" HWADDR_PRIx , memmap [BOSTON_LCD ].base );
651
+ qemu_fdt_add_subnode (fdt , name );
652
+ qemu_fdt_setprop_string (fdt , name , "compatible" , "img,boston-lcd" );
653
+ qemu_fdt_setprop_cells (fdt , name , "reg" , memmap [BOSTON_LCD ].base ,
654
+ memmap [BOSTON_LCD ].size );
655
+ g_free (name );
656
+
657
+ name = g_strdup_printf ("/memory@0" );
658
+ qemu_fdt_add_subnode (fdt , name );
659
+ qemu_fdt_setprop_string (fdt , name , "device_type" , "memory" );
660
+ g_free (name );
661
+
662
+ return fdt ;
663
+ }
664
+
440
665
static void boston_mach_init (MachineState * machine )
441
666
{
442
667
DeviceState * dev ;
@@ -560,22 +785,24 @@ static void boston_mach_init(MachineState *machine)
560
785
NULL , 0 , EM_MIPS , 1 , 0 );
561
786
562
787
if (kernel_size ) {
788
+ int dt_size ;
789
+ g_autofree const void * dtb_file_data , * dtb_load_data ;
563
790
hwaddr dtb_paddr = QEMU_ALIGN_UP (kernel_high , 64 * KiB );
564
791
hwaddr dtb_vaddr = cpu_mips_phys_to_kseg0 (NULL , dtb_paddr );
565
792
566
793
s -> kernel_entry = kernel_entry ;
567
794
if (machine -> dtb ) {
568
- int dt_size ;
569
- g_autofree const void * dtb_file_data , * dtb_load_data ;
570
-
571
795
dtb_file_data = load_device_tree (machine -> dtb , & dt_size );
572
- dtb_load_data = boston_fdt_filter (s , dtb_file_data ,
573
- NULL , & dtb_vaddr );
574
-
575
- /* Calculate real fdt size after filter */
576
- dt_size = fdt_totalsize (dtb_load_data );
577
- rom_add_blob_fixed ("dtb" , dtb_load_data , dt_size , dtb_paddr );
796
+ } else {
797
+ dtb_file_data = create_fdt (s , boston_memmap , & dt_size );
578
798
}
799
+
800
+ dtb_load_data = boston_fdt_filter (s , dtb_file_data ,
801
+ NULL , & dtb_vaddr );
802
+
803
+ /* Calculate real fdt size after filter */
804
+ dt_size = fdt_totalsize (dtb_load_data );
805
+ rom_add_blob_fixed ("dtb" , dtb_load_data , dt_size , dtb_paddr );
579
806
} else {
580
807
/* Try to load file as FIT */
581
808
fit_err = load_fit (& boston_fit_loader , machine -> kernel_filename , s );
0 commit comments