MLK-20794-1 imx8: Change kernel FDT updating for fused parts
authorYe Li <ye.li@nxp.com>
Thu, 24 Jan 2019 07:42:57 +0000 (23:42 -0800)
committerYe Li <ye.li@nxp.com>
Fri, 24 May 2019 11:28:14 +0000 (04:28 -0700)
Before booting kernel, we check all nodes in kernel FDT whether they
are owned in our partition. If it is not owned, we will disable it in FDT.

For fused iMX8X 17x17 parts, like DC0 is disabled, SCFW only disable SC_R_DC_0,
other sub-modules in DC0 SS are still assign to our partition. Since DC0 is fused,
we actually can't access these sub-modules.

This patch changes the algorithm to check resources along the power domain tree to the
top node of that SS power domain. If any resource in the PD tree is not owned, we will
disable the peripheral node.
For example, the i2c0_mipi_lvds1 peripheral node, according to power domain tree,
we checks resources: SC_R_MIPI_1_I2C_0  -->  SC_R_MIPI_1  --> SC_R_DC_0. When SC_R_DC_0
is not owned, we will disable the i2c0_mipi_lvds1 peripheral node from FDT.

Signed-off-by: Ye Li <ye.li@nxp.com>
(cherry picked from commit da636e4b8eda4698be6e2e53767cc1a598aadb0b)

arch/arm/mach-imx/imx8/cpu.c

index 1d97d58..162efca 100644 (file)
@@ -605,6 +605,44 @@ static bool check_owned_resource(sc_rsrc_t rsrc_id)
        return owned;
 }
 
+static bool check_owned_resources_in_pd_tree(void *blob, int nodeoff,
+       unsigned int *unowned_rsrc)
+{
+       unsigned int rsrc_id;
+       const fdt32_t *php;
+
+       /* Search the ancestors nodes in current SS power-domain tree,
+       *   if all ancestors' resources are owned,  we can enable the node,
+       *   otherwise any ancestor is not owned, we should disable the node.
+       */
+
+       do {
+               php = fdt_getprop(blob, nodeoff, "power-domains", NULL);
+               if (!php) {
+                       debug("   - ignoring no power-domains\n");
+                       break;
+               }
+               nodeoff = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*php));
+
+               rsrc_id = fdtdec_get_uint(blob, nodeoff, "reg", 0);
+               if (rsrc_id == SC_R_LAST) {
+                       debug("%s's power domain use SC_R_LAST\n",
+                               fdt_get_name(blob, nodeoff, NULL));
+                       break;
+               }
+
+               debug("power-domains node 0x%x, resource id %u\n", nodeoff, rsrc_id);
+
+               if (!check_owned_resource(rsrc_id)) {
+                       if (unowned_rsrc != NULL)
+                               *unowned_rsrc = rsrc_id;
+                       return false;
+               }
+       } while (fdt_node_check_compatible(blob, nodeoff, "nxp,imx8-pd"));
+
+       return true;
+}
+
 static int disable_fdt_node(void *blob, int nodeoffset)
 {
        int rc, ret;
@@ -865,11 +903,9 @@ static void update_fdt_with_owned_resources(void *blob)
          * for checking whether it is owned by current partition
          */
 
-       int offset = 0, next_off, addr;
+       int offset = 0, next_off;
        int depth = 0, next_depth;
        unsigned int rsrc_id;
-       const fdt32_t *php;
-       const char *name;
        int rc;
 
        for (offset = fdt_next_node(blob, offset, &depth); offset > 0;
@@ -900,34 +936,17 @@ static void update_fdt_with_owned_resources(void *blob)
                        continue;
                }
 
-               php = fdt_getprop(blob, offset, "power-domains", NULL);
-               if (!php) {
-                       debug("   - ignoring no power-domains\n");
-               } else {
-                       addr = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*php));
-                       rsrc_id = fdtdec_get_uint(blob, addr, "reg", 0);
-
-                       if (rsrc_id == SC_R_LAST) {
-                               name = fdt_get_name(blob, offset, NULL);
-                               printf("%s's power domain use SC_R_LAST\n", name);
-                               continue;
-                       }
-
-                       debug("power-domains phandle 0x%x, addr 0x%x, resource id %u\n",
-                               fdt32_to_cpu(*php), addr, rsrc_id);
-
-                       if (!check_owned_resource(rsrc_id)) {
-
-                               /* If the resource is not owned, disable it in FDT */
-                               rc = disable_fdt_node(blob, offset);
-                               if (!rc)
-                                       printf("Disable %s, resource id %u, pd phandle 0x%x\n",
-                                               fdt_get_name(blob, offset, NULL), rsrc_id, fdt32_to_cpu(*php));
-                               else
-                                       printf("Unable to disable %s, err=%s\n",
-                                               fdt_get_name(blob, offset, NULL), fdt_strerror(rc));
-                       }
+               if (!check_owned_resources_in_pd_tree(blob, offset, &rsrc_id)) {
+                       /* If the resource is not owned, disable it in FDT */
+                       rc = disable_fdt_node(blob, offset);
+                       if (!rc)
+                               printf("Disable %s, resource id %u not owned\n",
+                                       fdt_get_name(blob, offset, NULL), rsrc_id);
+                       else
+                               printf("Unable to disable %s, err=%s\n",
+                                       fdt_get_name(blob, offset, NULL), fdt_strerror(rc));
                }
+
        }
 }