diff options
author | Max Krummenacher <max.krummenacher@toradex.com> | 2020-12-03 19:49:17 +0100 |
---|---|---|
committer | Max Krummenacher <max.krummenacher@toradex.com> | 2020-12-03 22:20:34 +0100 |
commit | a3e4437c592a4d7087331533b497bda8fe04a8e4 (patch) | |
tree | df0c03760e319b66ad226e1fc3cf5f550d78b4b3 | |
parent | 28f08c4f0e71a899e05136a9029cc77a05492719 (diff) |
imx8m/soc.c: deleting phandles pointing to deleted cpus
For i.MX8M Mini with less than 4 CPU cores the code patches the device
tree to reflect that and deletes the nodes representing the not existing
cores.
The deleted nodes are referenced by phandles in the following two properties:
/thermal-zones/cpu-thermal/cooling-maps/map0/cooling-device
/pmu/interrupt-affinity
Modify these properties to no longer contain the phandles to no longer
existing nodes.
Fixes the thermal subsystem which otherwise bails out with:
[ 0.102895] OF: /thermal-zones/cpu-thermal/cooling-maps/map0: could not find phandle
[ 0.102922] thermal_sys: failed to build thermal zone cpu-thermal: -22
[ 1.377046] i.mx8mm_thermal 30260000.tmu: failed to register thermal zone sensor[0]: 0
[ 3.013718] i.mx8mm_thermal 30260000.tmu: failed to register thermal zone sensor[0]: 0
...
Related-to: ELB-3292
Signed-off-by: Max Krummenacher <max.krummenacher@toradex.com>
-rw-r--r-- | arch/arm/mach-imx/imx8m/soc.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 0ead9925a4..9f11ae42c5 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -844,6 +844,16 @@ int disable_dsp_nodes(void *blob) return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp)); } +static int fdt_setprop_array_u32(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + int i; + int *a_array = (int *)val; + for (i = 0; i < (len); i++) + a_array[i] = cpu_to_fdt32(a_array[i]); + return fdt_setprop(fdt, nodeoffset, name, val, len * 4); +} + static int disable_cpu_nodes(void *blob, u32 disabled_cores) { const char *nodes_path[] = { @@ -851,10 +861,15 @@ static int disable_cpu_nodes(void *blob, u32 disabled_cores) "/cpus/cpu@2", "/cpus/cpu@3", }; - - u32 i = 0; + const char *cooling_phandles = + "/thermal-zones/cpu-thermal/cooling-maps/map0"; + const char *pmu_phandles = "/pmu"; int rc; int nodeoff; + u32 i, k, n, num_elements; + u32 del_phandles[3] = {0,0,0}; + /* assume a maximum of 16 entries in the cooling devices property */ + u32 a_property[3 * 16]; if (disabled_cores > 3) return -EINVAL; @@ -866,6 +881,8 @@ static int disable_cpu_nodes(void *blob, u32 disabled_cores) if (nodeoff < 0) continue; /* Not found, skip it */ + del_phandles[i] = fdt_get_phandle(blob, nodeoff); + rc = fdt_del_node(blob, nodeoff); if (rc < 0) { printf("Unable to delete node %s, err=%s\n", @@ -875,6 +892,46 @@ static int disable_cpu_nodes(void *blob, u32 disabled_cores) } } + /* We delete CPU nodes above, but phandles to these nodes are still in the fdt */ + /* Delete tho phandles in the cooling-device property */ + nodeoff = fdt_path_offset(blob, cooling_phandles); + if (nodeoff >= 0) { + num_elements = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", + a_property, ARRAY_SIZE(a_property)); + for (i = 0; i < 3; i++) { + for (k = num_elements; k > 0; ) { + k -= 3; + if (del_phandles[i] == a_property[k]) { + for (n = k; n < (num_elements - 1); n++) + a_property[n] = a_property[n + 3]; + num_elements -= 3; + debug("deleting cpu[%i] reference\n", i+1); + } + } + } + debug("cooling-device property has now %i elements\n", num_elements); + fdt_setprop_array_u32(blob, nodeoff, "cooling-device", a_property, num_elements); } + + /* Delete tho phandles in the interrupt-affinity property */ + nodeoff = fdt_path_offset(blob, pmu_phandles); + if (nodeoff >= 0) { + num_elements = fdtdec_get_int_array_count(blob, nodeoff, "interrupt-affinity", + a_property, ARRAY_SIZE(a_property)); + for (i = 0; i < 3; i++) { + for (k = num_elements; k > 0; ) { + k--; + if (del_phandles[i] == a_property[k]) { + for (n = k; n < (num_elements - 1); n++) + a_property[n] = a_property[n + 1]; + num_elements--; + debug("deleting cpu[%i] reference\n", i+1); + } + } + } + debug("interrupt-affinity property has now %i elements\n", num_elements); + fdt_setprop_array_u32(blob, nodeoff, "interrupt-affinity", a_property, num_elements); + } + return 0; } |