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:
zbb 2017-06-08 16:51:46 +00:00
parent 553d3e55f3
commit 1326a8a13d

View File

@ -2379,13 +2379,60 @@ win_cpu_from_dt(void)
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", &reg, sizeof(reg)) <= 0)
return (EINVAL);
if (addr_cells <= 2)
base = fdt_data_get(&reg[0], addr_cells);
else
base = fdt_data_get(&reg[addr_cells - 2], 2);
size = fdt_data_get(&reg[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);
}
}
/*