Skip to content

Commit 7db6917

Browse files
povikmarcan
authored andcommitted
kboot: Transfer virtio nodes from ADT to FDT
Signed-off-by: Martin Povišer <[email protected]>
1 parent c760e02 commit 7db6917

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

src/kboot.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
15271595
void 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

Comments
 (0)