summaryrefslogtreecommitdiff
path: root/recipes-bsp/u-boot-mainline/files/0008-MLK-16087-imx8qm-qxp-Disable-kernel-FDT-nodes-for-th.patch
blob: 919a777c2d34055c0436fe6522cafb2d7421910a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
From db6acd1b9a0c4ee3819c5546d033be4710233084 Mon Sep 17 00:00:00 2001
From: Ye Li <ye.li@nxp.com>
Date: Mon, 16 Apr 2018 00:05:24 -0700
Subject: [PATCH 08/15] MLK-16087 imx8qm/qxp: Disable kernel FDT nodes for the
 resources are not owned

Before starting the kernel, need to check if the enabled nodes (resources) in FDT
are owned by current partition.  If it is not owned, need to disable it because A core
can't access it.
We use the node's power-domain property to get the PD node which has the SCFW resource
id in its reg property. Then we can check it with SCFW.

Signed-off-by: Ye Li <ye.li@nxp.com>
(cherry picked from downstream commit 358372674b29685788a4007b0944ab03b7fafc13)
---
 arch/arm/mach-imx/imx8/cpu.c | 115 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 115 insertions(+)

diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c
index 72404d9eb6..7f2dd2166b 100644
--- a/arch/arm/mach-imx/imx8/cpu.c
+++ b/arch/arm/mach-imx/imx8/cpu.c
@@ -11,6 +11,8 @@
 #include <dm/lists.h>
 #include <dm/uclass.h>
 #include <errno.h>
+#include <fdt_support.h>
+#include <fdtdec.h>
 #include <thermal.h>
 #include <asm/arch/sci/sci.h>
 #include <asm/arch/sid.h>
@@ -193,6 +195,119 @@ int mmc_get_env_dev(void)
 }
 #endif
 
+#ifdef CONFIG_OF_SYSTEM_SETUP
+static bool check_owned_resource(sc_rsrc_t rsrc_id)
+{
+	sc_ipc_t ipcHndl = 0;
+	bool owned;
+
+	ipcHndl = -1;
+
+	owned = sc_rm_is_resource_owned(ipcHndl, rsrc_id);
+
+	return owned;
+}
+
+static int disable_fdt_node(void *blob, int nodeoffset)
+{
+	int rc, ret;
+	const char *status = "disabled";
+
+	do {
+		rc = fdt_setprop(blob, nodeoffset, "status", status, strlen(status) + 1);
+		if (rc) {
+			if (rc == -FDT_ERR_NOSPACE) {
+				ret = fdt_increase_size(blob, 512);
+				if (ret)
+					return ret;
+			}
+		}
+	} while (rc == -FDT_ERR_NOSPACE);
+
+	return rc;
+}
+
+static void update_fdt_with_owned_resources(void *blob)
+{
+	/* Traverses the fdt nodes,
+	  * check its power domain and use the resource id in the power domain
+	  * for checking whether it is owned by current partition
+	  */
+
+	int offset = 0, next_off, addr;
+	int depth, 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;
+		 offset = fdt_next_node(blob, offset, &depth)) {
+
+		debug("Node name: %s, depth %d\n", fdt_get_name(blob, offset, NULL), depth);
+
+		if (!fdtdec_get_is_enabled(blob, offset)) {
+			debug("   - ignoring disabled device\n");
+			continue;
+		}
+
+		if (!fdt_node_check_compatible(blob, offset, "nxp,imx8-pd")) {
+			/* Skip to next depth=1 node*/
+			next_off = offset;
+			next_depth = depth;
+			do {
+				offset = next_off;
+				depth = next_depth;
+				next_off = fdt_next_node(blob, offset, &next_depth);
+				if (next_off < 0 || next_depth < 1)
+					break;
+
+				debug("PD name: %s, offset %d, depth %d\n",
+					fdt_get_name(blob, next_off, NULL), next_off, next_depth);
+			} while (next_depth > 1);
+
+			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));
+			}
+		}
+	}
+}
+
+int ft_system_setup(void *blob, bd_t *bd)
+{
+	update_fdt_with_owned_resources(blob);
+
+	return 0;
+}
+#endif
+
 #define MEMSTART_ALIGNMENT  SZ_2M /* Align the memory start with 2MB */
 
 static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start,
-- 
2.13.6