Extend the imx6 gpc->gic interrupt controller fixup of fdt data at runtime

to work with the pmu and tempmon nodes as well as the soc node.  This allows
interrupts to work on the pmu and tempmon devices even though we don't have
a driver for the low-power gpc interrupt controller (which is not a problem
because we also don't have support for entering deep power-down modes where
it gets used).
This commit is contained in:
Ian Lepore 2020-11-25 20:05:05 +00:00
parent 0ffeeb414f
commit 2814e68675
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=368030

View File

@ -78,6 +78,10 @@ static platform_cpu_reset_t imx6_cpu_reset;
* node to refer to GIC instead of GPC. This will get us by until we write our
* own GPC driver (or until linux changes its mind and the FDT data again).
*
* 2020/11/25: The tempmon and pmu nodes are siblings (not children) of the soc
* node, so for them to use interrupts we need to apply the same fix as we do
* for the soc node.
*
* We validate that we have data that looks like we expect before changing it:
* - SOC node exists and has GPC as its interrupt parent.
* - GPC node exists and has GIC as its interrupt parent.
@ -95,22 +99,30 @@ static platform_cpu_reset_t imx6_cpu_reset;
* nodes by string matching we now have to search for both flavors of each node
* name involved.
*/
static void
fix_node_iparent(const char* nodepath, phandle_t gpcxref, phandle_t gicxref)
{
static const char *propname = "interrupt-parent";
phandle_t node, iparent;
if ((node = OF_finddevice(nodepath)) == -1)
return;
if (OF_getencprop(node, propname, &iparent, sizeof(iparent)) <= 0)
return;
if (iparent != gpcxref)
return;
OF_setprop(node, propname, &gicxref, sizeof(gicxref));
}
static void
fix_fdt_interrupt_data(void)
{
phandle_t gicipar, gicnode, gicxref;
phandle_t gpcipar, gpcnode, gpcxref;
phandle_t socipar, socnode;
int result;
socnode = OF_finddevice("/soc");
if (socnode == -1)
return;
result = OF_getencprop(socnode, "interrupt-parent", &socipar,
sizeof(socipar));
if (result <= 0)
return;
/* GIC node may be child of soc node, or appear directly at root. */
gicnode = OF_finddevice("/soc/interrupt-controller@00a01000");
if (gicnode == -1)
@ -143,11 +155,13 @@ fix_fdt_interrupt_data(void)
return;
gpcxref = OF_xref_from_node(gpcnode);
if (socipar != gpcxref || gpcipar != gicxref || gicipar != gicxref)
if (gpcipar != gicxref || gicipar != gicxref)
return;
gicxref = cpu_to_fdt32(gicxref);
OF_setprop(socnode, "interrupt-parent", &gicxref, sizeof(gicxref));
fix_node_iparent("/soc", gpcxref, gicxref);
fix_node_iparent("/pmu", gpcxref, gicxref);
fix_node_iparent("/tempmon", gpcxref, gicxref);
}
static void