@@ -1524,6 +1524,74 @@ static int dt_disable_missing_devs(const char *adt_prefix, const char *dt_prefix
15241524 return ret ;
15251525}
15261526
1527+ static int dt_transfer_virtios (void )
1528+ {
1529+ int path [3 ];
1530+ path [0 ] = adt_path_offset (adt , "/arm-io/" );
1531+ if (path [0 ] < 0 )
1532+ bail ("ADT: /arm-io not found\n" );
1533+
1534+ int aic = fdt_node_offset_by_compatible (dt , -1 , "apple,aic" );
1535+ if (aic == - FDT_ERR_NOTFOUND )
1536+ aic = fdt_node_offset_by_compatible (dt , -1 , "apple,aic2" );
1537+ if (aic < 0 )
1538+ bail ("FDT: failed to find AIC node\n" );
1539+
1540+ u32 aic_phandle = fdt_get_phandle (dt , aic );
1541+ const fdt32_t * ic_prop = fdt_getprop (dt , aic , "#interrupt-cells" , NULL );
1542+ u32 intcells = 0 ;
1543+ if (ic_prop )
1544+ intcells = fdt32_ld (ic_prop );
1545+ if (intcells < 3 || intcells > 4 )
1546+ bail ("FDT: bad '#interrupt-cells' on AIC node (%d)\n" , intcells );
1547+
1548+ for (u32 i = 0 ; i < 16 ; i ++ ) {
1549+ char name [16 ], fullname [32 ];
1550+ snprintf (name , sizeof (name ) - 1 , "virtio%d" , i );
1551+
1552+ path [1 ] = adt_subnode_offset (adt , path [0 ], name );
1553+ if (path [1 ] < 0 )
1554+ break ;
1555+ path [2 ] = 0 ;
1556+
1557+ u64 addr , size ;
1558+ if (adt_get_reg (adt , path , "reg" , 0 , & addr , & size ) < 0 )
1559+ bail ("ADT: error getting /arm-io/%s regs\n" , name );
1560+
1561+ u32 irq ;
1562+ ADT_GETPROP (adt , path [1 ], "interrupts" , & irq );
1563+
1564+ snprintf (fullname , sizeof (fullname ) - 1 , "virtio@%lx" , addr );
1565+ printf ("FDT: Adding %s found in ADT\n" , name );
1566+
1567+ int fnode = fdt_add_subnode (dt , 0 , fullname );
1568+ if (fnode < 0 )
1569+ bail ("FDT: failed to create %s\n" , fullname );
1570+
1571+ if (fdt_setprop_string (dt , fnode , "compatible" , "virtio,mmio" ))
1572+ bail ("FDT: couldn't set %s.compatible\n" , fullname );
1573+
1574+ fdt64_t reg [2 ];
1575+ fdt64_st (reg + 0 , addr );
1576+ fdt64_st (reg + 1 , size );
1577+ if (fdt_setprop (dt , fnode , "reg" , reg , sizeof (reg )))
1578+ bail ("FDT: couldn't set %s.reg\n" , fullname );
1579+
1580+ if (fdt_setprop_u32 (dt , fnode , "interrupt-parent" , aic_phandle ))
1581+ bail ("FDT: couldn't set %s.interrupt-parent\n" , fullname );
1582+
1583+ fdt32_t intprop [4 ];
1584+ fdt32_st (intprop + 0 , 0 ); // AIC_IRQ
1585+ fdt32_st (intprop + 1 , 0 );
1586+ fdt32_st (intprop + intcells - 2 , irq );
1587+ fdt32_st (intprop + intcells - 1 , 4 ); // IRQ_TYPE_LEVEL_HIGH
1588+ if (fdt_setprop (dt , fnode , "interrupts" , intprop , 4 * intcells ))
1589+ bail ("FDT: couldn't set %s.interrupts\n" , fullname );
1590+ }
1591+
1592+ return 0 ;
1593+ }
1594+
15271595void kboot_set_initrd (void * start , size_t size )
15281596{
15291597 initrd_start = start ;
@@ -1610,6 +1678,10 @@ int kboot_prepare_dt(void *fdt)
16101678 return -1 ;
16111679 if (dt_disable_missing_devs ("i2c" , "i2c@" , 8 ))
16121680 return -1 ;
1681+ #ifndef RELEASE
1682+ if (dt_transfer_virtios ())
1683+ return 1 ;
1684+ #endif
16131685
16141686 if (fdt_pack (dt ))
16151687 bail ("FDT: fdt_pack() failed\n" );
0 commit comments