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