summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Krummenacher <max.krummenacher@toradex.com>2020-12-03 19:49:17 +0100
committerMax Krummenacher <max.krummenacher@toradex.com>2020-12-03 22:20:34 +0100
commita3e4437c592a4d7087331533b497bda8fe04a8e4 (patch)
treedf0c03760e319b66ad226e1fc3cf5f550d78b4b3
parent28f08c4f0e71a899e05136a9029cc77a05492719 (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.c61
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;
}