]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
imx8m: disable nodes before kernel/mfgtool boot for fused part
authorPeng Fan <peng.fan@nxp.com>
Thu, 9 Jul 2020 06:06:49 +0000 (14:06 +0800)
committerPeng Fan <peng.fan@nxp.com>
Tue, 14 Jul 2020 07:23:47 +0000 (15:23 +0800)
To fused part, we need to disable nodes of dtb to let kernel boot.

To mfgtool, USB issue when using super-speed for mfgtool, temporally
work around the problem to use high-speed only.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
arch/arm/mach-imx/imx8m/soc.c

index 9517a7cfcf1503af84f6f02e5ee019126f80f06b..bb2f112af697bf29a6d028c9769c0c7c00c2d425 100644 (file)
@@ -428,12 +428,298 @@ bool is_usb_boot(void)
 }
 
 #ifdef CONFIG_OF_SYSTEM_SETUP
+bool check_fdt_new_path(void *blob)
+{
+       const char *soc_path = "/soc@0";
+       int nodeoff;
+
+       nodeoff = fdt_path_offset(blob, soc_path);
+       if (nodeoff < 0)
+               return false;
+
+       return true;
+}
+
+static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
+{
+       int i = 0;
+       int rc;
+       int nodeoff;
+       const char *status = "disabled";
+
+       for (i = 0; i < size_array; i++) {
+               nodeoff = fdt_path_offset(blob, nodes_path[i]);
+               if (nodeoff < 0)
+                       continue; /* Not found, skip it */
+
+               printf("Found %s node\n", nodes_path[i]);
+
+add_status:
+               rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
+               if (rc) {
+                       if (rc == -FDT_ERR_NOSPACE) {
+                               rc = fdt_increase_size(blob, 512);
+                               if (!rc)
+                                       goto add_status;
+                       }
+                       printf("Unable to update property %s:%s, err=%s\n",
+                              nodes_path[i], "status", fdt_strerror(rc));
+               } else {
+                       printf("Modify %s:%s disabled\n",
+                              nodes_path[i], "status");
+               }
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_IMX8MQ
+bool check_dcss_fused(void)
+{
+       struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+       struct fuse_bank *bank = &ocotp->bank[1];
+       struct fuse_bank1_regs *fuse =
+               (struct fuse_bank1_regs *)bank->fuse_regs;
+       u32 value = readl(&fuse->tester4);
+
+       if (value & 0x4000000)
+               return true;
+
+       return false;
+}
+
+static int disable_mipi_dsi_nodes(void *blob)
+{
+       static const char * const nodes_path[] = {
+               "/mipi_dsi@30A00000",
+               "/mipi_dsi_bridge@30A00000",
+               "/dsi_phy@30A00300",
+               "/soc@0/bus@30800000/mipi_dsi@30a00000",
+               "/soc@0/bus@30800000/dphy@30a00300"
+       };
+
+       return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
+}
+
+static int disable_dcss_nodes(void *blob)
+{
+       static const char * const nodes_path[] = {
+               "/dcss@0x32e00000",
+               "/dcss@32e00000",
+               "/hdmi@32c00000",
+               "/hdmi_cec@32c33800",
+               "/hdmi_drm@32c00000",
+               "/display-subsystem",
+               "/sound-hdmi",
+               "/sound-hdmi-arc",
+               "/soc@0/bus@32c00000/display-controller@32e00000",
+               "/soc@0/bus@32c00000/hdmi@32c00000",
+       };
+
+       return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
+}
+
+static int check_mipi_dsi_nodes(void *blob)
+{
+       static const char * const lcdif_path[] = {
+               "/lcdif@30320000",
+               "/soc@0/bus@30000000/lcdif@30320000"
+       };
+       static const char * const mipi_dsi_path[] = {
+               "/mipi_dsi@30A00000",
+               "/soc@0/bus@30800000/mipi_dsi@30a00000"
+       };
+       static const char * const lcdif_ep_path[] = {
+               "/lcdif@30320000/port@0/mipi-dsi-endpoint",
+               "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint"
+       };
+       static const char * const mipi_dsi_ep_path[] = {
+               "/mipi_dsi@30A00000/port@1/endpoint",
+               "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint"
+       };
+
+       int lookup_node;
+       int nodeoff;
+       bool new_path = check_fdt_new_path(blob);
+       int i = new_path ? 1 : 0;
+
+       nodeoff = fdt_path_offset(blob, lcdif_path[i]);
+       if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
+               /*
+                * If can't find lcdif node or lcdif node is disabled,
+                * then disable all mipi dsi, since they only can input
+                * from DCSS
+                */
+               return disable_mipi_dsi_nodes(blob);
+       }
+
+       nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
+       if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
+               return 0;
+
+       nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
+       if (nodeoff < 0) {
+               /*
+                * If can't find lcdif endpoint, then disable all mipi dsi,
+                * since they only can input from DCSS
+                */
+               return disable_mipi_dsi_nodes(blob);
+       }
+
+       lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
+       nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
+
+       if (nodeoff > 0 && nodeoff == lookup_node)
+               return 0;
+
+       return disable_mipi_dsi_nodes(blob);
+}
+#endif
+
+int disable_vpu_nodes(void *blob)
+{
+       static const char * const nodes_path_8mq[] = {
+               "/vpu@38300000",
+               "/soc@0/vpu@38300000"
+       };
+
+       static const char * const nodes_path_8mm[] = {
+               "/vpu_g1@38300000",
+               "/vpu_g2@38310000",
+               "/vpu_h1@38320000"
+       };
+
+       static const char * const nodes_path_8mp[] = {
+               "/vpu_g1@38300000",
+               "/vpu_g2@38310000",
+               "/vpu_vc8000e@38320000"
+       };
+
+       if (is_imx8mq())
+               return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
+       else if (is_imx8mm())
+               return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
+       else if (is_imx8mp())
+               return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
+       else
+               return -EPERM;
+}
+
+int disable_gpu_nodes(void *blob)
+{
+       static const char * const nodes_path_8mn[] = {
+               "/gpu@38000000"
+       };
+
+       return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
+}
+
+int disable_npu_nodes(void *blob)
+{
+       static const char * const nodes_path_8mp[] = {
+               "/vipsi@38500000"
+       };
+
+       return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
+}
+
+int disable_isp_nodes(void *blob)
+{
+       static const char * const nodes_path_8mp[] = {
+               "/soc@0/bus@32c00000/camera/isp@32e10000",
+               "/soc@0/bus@32c00000/camera/isp@32e20000"
+       };
+
+       return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
+}
+
+int disable_dsp_nodes(void *blob)
+{
+       static const char * const nodes_path_8mp[] = {
+               "/dsp@3b6e8000"
+       };
+
+       return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
+}
+
+static int disable_cpu_nodes(void *blob, u32 disabled_cores)
+{
+       static const char * const nodes_path[] = {
+               "/cpus/cpu@1",
+               "/cpus/cpu@2",
+               "/cpus/cpu@3",
+       };
+       u32 i = 0;
+       int rc;
+       int nodeoff;
+
+       if (disabled_cores > 3)
+               return -EINVAL;
+
+       i = 3 - disabled_cores;
+
+       for (; i < 3; i++) {
+               nodeoff = fdt_path_offset(blob, nodes_path[i]);
+               if (nodeoff < 0)
+                       continue; /* Not found, skip it */
+
+               debug("Found %s node\n", nodes_path[i]);
+
+               rc = fdt_del_node(blob, nodeoff);
+               if (rc < 0) {
+                       printf("Unable to delete node %s, err=%s\n",
+                              nodes_path[i], fdt_strerror(rc));
+               } else {
+                       printf("Delete node %s\n", nodes_path[i]);
+               }
+       }
+
+       return 0;
+}
+
 int ft_system_setup(void *blob, bd_t *bd)
 {
+#ifdef CONFIG_IMX8MQ
        int i = 0;
        int rc;
        int nodeoff;
 
+       if (get_boot_device() == USB_BOOT) {
+               disable_dcss_nodes(blob);
+
+               bool new_path = check_fdt_new_path(blob);
+               int v = new_path ? 1 : 0;
+               static const char * const usb_dwc3_path[] = {
+                       "/usb@38100000/dwc3",
+                       "/soc@0/usb@38100000"
+               };
+
+               nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
+               if (nodeoff >= 0) {
+                       const char *speed = "high-speed";
+
+                       printf("Found %s node\n", usb_dwc3_path[v]);
+
+usb_modify_speed:
+
+                       rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
+                       if (rc) {
+                               if (rc == -FDT_ERR_NOSPACE) {
+                                       rc = fdt_increase_size(blob, 512);
+                                       if (!rc)
+                                               goto usb_modify_speed;
+                               }
+                               printf("Unable to set property %s:%s, err=%s\n",
+                                      usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
+                       } else {
+                               printf("Modify %s:%s = %s\n",
+                                      usb_dwc3_path[v], "maximum-speed", speed);
+                       }
+               } else {
+                       printf("Can't found %s node\n", usb_dwc3_path[v]);
+               }
+       }
+
        /* Disable the CPU idle for A0 chip since the HW does not support it */
        if (is_soc_rev(CHIP_REV_1_0)) {
                static const char * const nodes_path[] = {
@@ -464,6 +750,53 @@ int ft_system_setup(void *blob, bd_t *bd)
                }
        }
 
+       if (is_imx8mql()) {
+               disable_vpu_nodes(blob);
+               if (check_dcss_fused()) {
+                       printf("DCSS is fused\n");
+                       disable_dcss_nodes(blob);
+                       check_mipi_dsi_nodes(blob);
+               }
+       }
+
+       if (is_imx8md())
+               disable_cpu_nodes(blob, 2);
+
+#elif defined(CONFIG_IMX8MM)
+       if (is_imx8mml() || is_imx8mmdl() ||  is_imx8mmsl())
+               disable_vpu_nodes(blob);
+
+       if (is_imx8mmd() || is_imx8mmdl())
+               disable_cpu_nodes(blob, 2);
+       else if (is_imx8mms() || is_imx8mmsl())
+               disable_cpu_nodes(blob, 3);
+
+#elif defined(CONFIG_IMX8MN)
+       if (is_imx8mnl() || is_imx8mndl() ||  is_imx8mnsl())
+               disable_gpu_nodes(blob);
+
+       if (is_imx8mnd() || is_imx8mndl())
+               disable_cpu_nodes(blob, 2);
+       else if (is_imx8mns() || is_imx8mnsl())
+               disable_cpu_nodes(blob, 3);
+
+#elif defined(CONFIG_IMX8MP)
+       if (is_imx8mpl() || is_imx8mp7())
+               disable_vpu_nodes(blob);
+
+       if (is_imx8mpl() || is_imx8mp6() || is_imx8mp5())
+               disable_npu_nodes(blob);
+
+       if (is_imx8mpl() || is_imx8mp5())
+               disable_isp_nodes(blob);
+
+       if (is_imx8mpl() || is_imx8mp7() || is_imx8mp6() || is_imx8mp5())
+               disable_dsp_nodes(blob);
+
+       if (is_imx8mpd())
+               disable_cpu_nodes(blob, 2);
+#endif
+
        return 0;
 }
 #endif