1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2 /*
3 * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved
4 */
5
6 #define LOG_CATEGORY LOGC_ARCH
7
8 #include <fdtdec.h>
9 #include <fdt_support.h>
10 #include <log.h>
11 #include <tee.h>
12 #include <mach/stm32.h>
13 #include <asm/arch/sys_proto.h>
14 #include <dt-bindings/pinctrl/stm32-pinfunc.h>
15 #include <linux/io.h>
16
17 #define STM32MP13_FDCAN_BASE 0x4400F000
18 #define STM32MP13_ADC1_BASE 0x48003000
19 #define STM32MP13_TSC_BASE 0x5000B000
20 #define STM32MP13_CRYP_BASE 0x54002000
21 #define STM32MP13_ETH2_BASE 0x5800E000
22 #define STM32MP13_DCMIPP_BASE 0x5A000000
23 #define STM32MP13_LTDC_BASE 0x5A010000
24
25 #define STM32MP15_FDCAN_BASE 0x4400e000
26 #define STM32MP15_CRYP2_BASE 0x4c005000
27 #define STM32MP15_CRYP1_BASE 0x54001000
28 #define STM32MP15_GPU_BASE 0x59000000
29 #define STM32MP15_DSI_BASE 0x5a000000
30
31 /* fdt helper */
fdt_disable_subnode_by_address(void * fdt,int offset,u32 addr)32 static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr)
33 {
34 int node;
35 fdt_addr_t regs;
36
37 for (node = fdt_first_subnode(fdt, offset);
38 node >= 0;
39 node = fdt_next_subnode(fdt, node)) {
40 regs = fdtdec_get_addr(fdt, node, "reg");
41 if (addr == regs) {
42 if (fdtdec_get_is_enabled(fdt, node)) {
43 fdt_status_disabled(fdt, node);
44
45 return true;
46 }
47 return false;
48 }
49 }
50
51 return false;
52 }
53
54 /* deactivate all the cpu except core 0 */
stm32_fdt_fixup_cpu(void * blob,char * name)55 static void stm32_fdt_fixup_cpu(void *blob, char *name)
56 {
57 int off;
58 u32 reg;
59
60 off = fdt_path_offset(blob, "/cpus");
61 if (off < 0) {
62 log_warning("%s: couldn't find /cpus node\n", __func__);
63 return;
64 }
65
66 off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
67 while (off != -FDT_ERR_NOTFOUND) {
68 reg = fdtdec_get_addr(blob, off, "reg");
69 if (reg != 0) {
70 fdt_del_node(blob, off);
71 log_notice("FDT: cpu %d node remove for %s\n",
72 reg, name);
73 /* after delete we can't trust the offsets anymore */
74 off = -1;
75 }
76 off = fdt_node_offset_by_prop_value(blob, off,
77 "device_type", "cpu", 4);
78 }
79 }
80
stm32_fdt_disable(void * fdt,int offset,u32 addr,const char * string,const char * name)81 static void stm32_fdt_disable(void *fdt, int offset, u32 addr,
82 const char *string, const char *name)
83 {
84 if (fdt_disable_subnode_by_address(fdt, offset, addr))
85 log_notice("FDT: %s@%08x node disabled for %s\n",
86 string, addr, name);
87 }
88
stm32_fdt_disable_optee(void * blob)89 static void stm32_fdt_disable_optee(void *blob)
90 {
91 int off, node;
92
93 /* Delete "optee" firmware node */
94 off = fdt_node_offset_by_compatible(blob, -1, "linaro,optee-tz");
95 if (off >= 0 && fdtdec_get_is_enabled(blob, off))
96 fdt_del_node(blob, off);
97
98 /* Delete "optee@..." reserved-memory node */
99 off = fdt_path_offset(blob, "/reserved-memory/");
100 if (off < 0)
101 return;
102 for (node = fdt_first_subnode(blob, off);
103 node >= 0;
104 node = fdt_next_subnode(blob, node)) {
105 if (strncmp(fdt_get_name(blob, node, NULL), "optee@", 6))
106 continue;
107
108 if (fdt_del_node(blob, node))
109 printf("Failed to remove optee reserved-memory node\n");
110 }
111 }
112
stm32mp13_fdt_fixup(void * blob,int soc,u32 cpu,char * name)113 static void stm32mp13_fdt_fixup(void *blob, int soc, u32 cpu, char *name)
114 {
115 switch (cpu) {
116 case CPU_STM32MP131Fxx:
117 case CPU_STM32MP131Dxx:
118 case CPU_STM32MP131Cxx:
119 case CPU_STM32MP131Axx:
120 stm32_fdt_disable(blob, soc, STM32MP13_FDCAN_BASE, "can", name);
121 stm32_fdt_disable(blob, soc, STM32MP13_ADC1_BASE, "adc", name);
122 fallthrough;
123 case CPU_STM32MP133Fxx:
124 case CPU_STM32MP133Dxx:
125 case CPU_STM32MP133Cxx:
126 case CPU_STM32MP133Axx:
127 stm32_fdt_disable(blob, soc, STM32MP13_LTDC_BASE, "ltdc", name);
128 stm32_fdt_disable(blob, soc, STM32MP13_DCMIPP_BASE, "dcmipp",
129 name);
130 stm32_fdt_disable(blob, soc, STM32MP13_TSC_BASE, "tsc", name);
131 break;
132 default:
133 break;
134 }
135
136 switch (cpu) {
137 case CPU_STM32MP135Dxx:
138 case CPU_STM32MP135Axx:
139 case CPU_STM32MP133Dxx:
140 case CPU_STM32MP133Axx:
141 case CPU_STM32MP131Dxx:
142 case CPU_STM32MP131Axx:
143 stm32_fdt_disable(blob, soc, STM32MP13_CRYP_BASE, "cryp", name);
144 break;
145 default:
146 break;
147 }
148 }
149
stm32mp15_fdt_fixup(void * blob,int soc,u32 cpu,char * name)150 static void stm32mp15_fdt_fixup(void *blob, int soc, u32 cpu, char *name)
151 {
152 u32 pkg;
153
154 switch (cpu) {
155 case CPU_STM32MP151Fxx:
156 case CPU_STM32MP151Dxx:
157 case CPU_STM32MP151Cxx:
158 case CPU_STM32MP151Axx:
159 stm32_fdt_fixup_cpu(blob, name);
160 /* after cpu delete we can't trust the soc offsets anymore */
161 soc = fdt_path_offset(blob, "/soc");
162 stm32_fdt_disable(blob, soc, STM32MP15_FDCAN_BASE, "can", name);
163 fallthrough;
164 case CPU_STM32MP153Fxx:
165 case CPU_STM32MP153Dxx:
166 case CPU_STM32MP153Cxx:
167 case CPU_STM32MP153Axx:
168 stm32_fdt_disable(blob, soc, STM32MP15_GPU_BASE, "gpu", name);
169 stm32_fdt_disable(blob, soc, STM32MP15_DSI_BASE, "dsi", name);
170 break;
171 default:
172 break;
173 }
174 switch (cpu) {
175 case CPU_STM32MP157Dxx:
176 case CPU_STM32MP157Axx:
177 case CPU_STM32MP153Dxx:
178 case CPU_STM32MP153Axx:
179 case CPU_STM32MP151Dxx:
180 case CPU_STM32MP151Axx:
181 stm32_fdt_disable(blob, soc, STM32MP15_CRYP1_BASE, "cryp",
182 name);
183 stm32_fdt_disable(blob, soc, STM32MP15_CRYP2_BASE, "cryp",
184 name);
185 break;
186 default:
187 break;
188 }
189 switch (get_cpu_package()) {
190 case STM32MP15_PKG_AA_LBGA448:
191 pkg = STM32MP_PKG_AA;
192 break;
193 case STM32MP15_PKG_AB_LBGA354:
194 pkg = STM32MP_PKG_AB;
195 break;
196 case STM32MP15_PKG_AC_TFBGA361:
197 pkg = STM32MP_PKG_AC;
198 break;
199 case STM32MP15_PKG_AD_TFBGA257:
200 pkg = STM32MP_PKG_AD;
201 break;
202 default:
203 pkg = 0;
204 break;
205 }
206 if (pkg) {
207 do_fixup_by_compat_u32(blob, "st,stm32mp157-pinctrl",
208 "st,package", pkg, false);
209 do_fixup_by_compat_u32(blob, "st,stm32mp157-z-pinctrl",
210 "st,package", pkg, false);
211 }
212 }
213
214 /*
215 * This function is called right before the kernel is booted. "blob" is the
216 * device tree that will be passed to the kernel.
217 */
ft_system_setup(void * blob,struct bd_info * bd)218 int ft_system_setup(void *blob, struct bd_info *bd)
219 {
220 int ret = 0;
221 int soc;
222 u32 cpu;
223 char name[SOC_NAME_SIZE];
224
225 soc = fdt_path_offset(blob, "/soc");
226 /* when absent, nothing to do */
227 if (soc == -FDT_ERR_NOTFOUND)
228 return 0;
229 if (soc < 0)
230 return soc;
231
232 /* MPUs Part Numbers and name*/
233 cpu = get_cpu_type();
234 get_soc_name(name);
235
236 if (IS_ENABLED(CONFIG_STM32MP13X))
237 stm32mp13_fdt_fixup(blob, soc, cpu, name);
238
239 if (IS_ENABLED(CONFIG_STM32MP15X)) {
240 stm32mp15_fdt_fixup(blob, soc, cpu, name);
241
242 /*
243 * TEMP: remove OP-TEE nodes in kernel device tree
244 * copied from U-Boot device tree by optee_copy_fdt_nodes
245 * when OP-TEE is not detected (probe failed)
246 * these OP-TEE nodes are present in <board>-u-boot.dtsi
247 * under CONFIG_STM32MP15x_STM32IMAGE only for compatibility
248 * when FIP is not used by TF-A
249 */
250 if (IS_ENABLED(CONFIG_STM32MP15X_STM32IMAGE) &&
251 !tee_find_device(NULL, NULL, NULL, NULL))
252 stm32_fdt_disable_optee(blob);
253 }
254
255 return ret;
256 }
257