mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 16:22:46 -04:00
Fix PCIe window decoding on Armada 38x
Original PCIe nodes for Marvell SoCs consists of ports' nodes under main controller node. In order to properly parse this kind of representation in DT a mechanism for traversing through the tree required an update. Moreover, processing FDT data consisting of more than 2 cells had to be fixed, because the 'reg' property of mrvl,pcie node have additional parameter in front of 64-bit address. It should be skipped by default. This commit works properly with old mrvl,pcie representation for Kirkwood and ArmadaXP SoCs. Submitted by: Wojciech Macek <wma@semihalf.com> Michal Mazur <mkm@semihalf.com> Obtained from: Semihalf Sponsored by: Stormshield, Netgate Differential revision: https://reviews.freebsd.org/D10905
This commit is contained in:
parent
dc3b75aeef
commit
73e48bc6d6
1 changed files with 63 additions and 24 deletions
|
|
@ -2379,13 +2379,60 @@ moveon:
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fdt_win_process(phandle_t child)
|
||||
{
|
||||
int i;
|
||||
struct soc_node_spec *soc_node;
|
||||
int addr_cells, size_cells;
|
||||
pcell_t reg[8];
|
||||
u_long size, base;
|
||||
|
||||
for (i = 0; soc_nodes[i].compat != NULL; i++) {
|
||||
|
||||
soc_node = &soc_nodes[i];
|
||||
|
||||
/* Setup only for enabled devices */
|
||||
if (ofw_bus_node_status_okay(child) == 0)
|
||||
continue;
|
||||
|
||||
if (!ofw_bus_node_is_compatible(child, soc_node->compat))
|
||||
continue;
|
||||
|
||||
if (fdt_addrsize_cells(OF_parent(child), &addr_cells,
|
||||
&size_cells))
|
||||
return (ENXIO);
|
||||
|
||||
if ((sizeof(pcell_t) * (addr_cells + size_cells)) > sizeof(reg))
|
||||
return (ENOMEM);
|
||||
|
||||
if (OF_getprop(child, "reg", ®, sizeof(reg)) <= 0)
|
||||
return (EINVAL);
|
||||
|
||||
if (addr_cells <= 2)
|
||||
base = fdt_data_get(®[0], addr_cells);
|
||||
else
|
||||
base = fdt_data_get(®[addr_cells - 2], 2);
|
||||
size = fdt_data_get(®[addr_cells], size_cells);
|
||||
|
||||
base = (base & 0x000fffff) | fdt_immr_va;
|
||||
if (soc_node->decode_handler != NULL)
|
||||
soc_node->decode_handler(base);
|
||||
else
|
||||
return (ENXIO);
|
||||
|
||||
if (MV_DUMP_WIN && (soc_node->dump_handler != NULL))
|
||||
soc_node->dump_handler(base);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
static int
|
||||
fdt_win_setup(void)
|
||||
{
|
||||
phandle_t node, child, sb;
|
||||
struct soc_node_spec *soc_node;
|
||||
u_long size, base;
|
||||
int err, i;
|
||||
phandle_t child_pci;
|
||||
int err;
|
||||
|
||||
sb = 0;
|
||||
node = OF_finddevice("/");
|
||||
|
|
@ -2398,29 +2445,21 @@ fdt_win_setup(void)
|
|||
*/
|
||||
child = OF_child(node);
|
||||
while (child != 0) {
|
||||
for (i = 0; soc_nodes[i].compat != NULL; i++) {
|
||||
/* Lookup for callback and run */
|
||||
err = fdt_win_process(child);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
soc_node = &soc_nodes[i];
|
||||
/* Process Marvell Armada-XP/38x PCIe controllers */
|
||||
if (ofw_bus_node_is_compatible(child, "marvell,armada-370-pcie")) {
|
||||
child_pci = OF_child(child);
|
||||
while (child_pci != 0) {
|
||||
err = fdt_win_process(child_pci);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
/* Setup only for enabled devices */
|
||||
if (ofw_bus_node_status_okay(child) == 0)
|
||||
continue;
|
||||
|
||||
if (!ofw_bus_node_is_compatible(child,soc_node->compat))
|
||||
continue;
|
||||
|
||||
err = fdt_regsize(child, &base, &size);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
base = (base & 0x000fffff) | fdt_immr_va;
|
||||
if (soc_node->decode_handler != NULL)
|
||||
soc_node->decode_handler(base);
|
||||
else
|
||||
return (ENXIO);
|
||||
|
||||
if (MV_DUMP_WIN && (soc_node->dump_handler != NULL))
|
||||
soc_node->dump_handler(base);
|
||||
child_pci = OF_peer(child_pci);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue