Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
| 2 | /* |
Etienne Carriere | e634113 | 2020-06-05 09:24:29 +0200 | [diff] [blame] | 3 | * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 4 | */ |
| 5 | |
Patrick Delaunay | ba77940 | 2020-11-06 19:01:29 +0100 | [diff] [blame] | 6 | #define LOG_CATEGORY LOGC_ARCH |
| 7 | |
Simon Glass | 3ba929a | 2020-10-30 21:38:53 -0600 | [diff] [blame] | 8 | #include <fdtdec.h> |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 9 | #include <fdt_support.h> |
Simon Glass | 0f2af88 | 2020-05-10 11:40:05 -0600 | [diff] [blame] | 10 | #include <log.h> |
Patrick Delaunay | 472407a | 2020-03-18 09:22:49 +0100 | [diff] [blame] | 11 | #include <tee.h> |
Tom Rini | dec7ea0 | 2024-05-20 13:35:03 -0600 | [diff] [blame] | 12 | #include <mach/stm32.h> |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 13 | #include <asm/arch/sys_proto.h> |
| 14 | #include <dt-bindings/pinctrl/stm32-pinfunc.h> |
Patrick Delaunay | 43f214c | 2019-07-05 17:20:15 +0200 | [diff] [blame] | 15 | #include <linux/io.h> |
| 16 | |
Patrick Delaunay | cf47195 | 2022-05-09 17:13:22 +0200 | [diff] [blame] | 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 | |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 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 |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 30 | |
Patrick Delaunay | 43f214c | 2019-07-05 17:20:15 +0200 | [diff] [blame] | 31 | /* fdt helper */ |
| 32 | static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr) |
| 33 | { |
| 34 | int node; |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 35 | fdt_addr_t regs; |
Patrick Delaunay | 43f214c | 2019-07-05 17:20:15 +0200 | [diff] [blame] | 36 | |
| 37 | for (node = fdt_first_subnode(fdt, offset); |
| 38 | node >= 0; |
| 39 | node = fdt_next_subnode(fdt, node)) { |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 40 | regs = fdtdec_get_addr(fdt, node, "reg"); |
| 41 | if (addr == regs) { |
Patrick Delaunay | 43f214c | 2019-07-05 17:20:15 +0200 | [diff] [blame] | 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 | |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 54 | /* deactivate all the cpu except core 0 */ |
| 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) { |
Patrick Delaunay | ba77940 | 2020-11-06 19:01:29 +0100 | [diff] [blame] | 62 | log_warning("%s: couldn't find /cpus node\n", __func__); |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 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); |
Patrick Delaunay | ba77940 | 2020-11-06 19:01:29 +0100 | [diff] [blame] | 71 | log_notice("FDT: cpu %d node remove for %s\n", |
| 72 | reg, name); |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 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 | |
| 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)) |
Patrick Delaunay | ba77940 | 2020-11-06 19:01:29 +0100 | [diff] [blame] | 85 | log_notice("FDT: %s@%08x node disabled for %s\n", |
| 86 | string, addr, name); |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 87 | } |
| 88 | |
Patrick Delaunay | d1633b3 | 2020-03-18 09:22:48 +0100 | [diff] [blame] | 89 | static void stm32_fdt_disable_optee(void *blob) |
| 90 | { |
| 91 | int off, node; |
| 92 | |
Etienne Carriere | e634113 | 2020-06-05 09:24:29 +0200 | [diff] [blame] | 93 | /* Delete "optee" firmware node */ |
Patrick Delaunay | d1633b3 | 2020-03-18 09:22:48 +0100 | [diff] [blame] | 94 | off = fdt_node_offset_by_compatible(blob, -1, "linaro,optee-tz"); |
| 95 | if (off >= 0 && fdtdec_get_is_enabled(blob, off)) |
Etienne Carriere | e634113 | 2020-06-05 09:24:29 +0200 | [diff] [blame] | 96 | fdt_del_node(blob, off); |
Patrick Delaunay | d1633b3 | 2020-03-18 09:22:48 +0100 | [diff] [blame] | 97 | |
Etienne Carriere | e634113 | 2020-06-05 09:24:29 +0200 | [diff] [blame] | 98 | /* Delete "optee@..." reserved-memory node */ |
Patrick Delaunay | d1633b3 | 2020-03-18 09:22:48 +0100 | [diff] [blame] | 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)) { |
Etienne Carriere | e634113 | 2020-06-05 09:24:29 +0200 | [diff] [blame] | 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"); |
Patrick Delaunay | d1633b3 | 2020-03-18 09:22:48 +0100 | [diff] [blame] | 110 | } |
| 111 | } |
| 112 | |
Patrick Delaunay | cf47195 | 2022-05-09 17:13:22 +0200 | [diff] [blame] | 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 | |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 150 | static void stm32mp15_fdt_fixup(void *blob, int soc, u32 cpu, char *name) |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 151 | { |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 152 | u32 pkg; |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 153 | |
| 154 | switch (cpu) { |
Patrick Delaunay | db33b0e | 2020-02-26 11:26:43 +0100 | [diff] [blame] | 155 | case CPU_STM32MP151Fxx: |
| 156 | case CPU_STM32MP151Dxx: |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 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"); |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 162 | stm32_fdt_disable(blob, soc, STM32MP15_FDCAN_BASE, "can", name); |
| 163 | fallthrough; |
Patrick Delaunay | db33b0e | 2020-02-26 11:26:43 +0100 | [diff] [blame] | 164 | case CPU_STM32MP153Fxx: |
| 165 | case CPU_STM32MP153Dxx: |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 166 | case CPU_STM32MP153Cxx: |
| 167 | case CPU_STM32MP153Axx: |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 168 | stm32_fdt_disable(blob, soc, STM32MP15_GPU_BASE, "gpu", name); |
| 169 | stm32_fdt_disable(blob, soc, STM32MP15_DSI_BASE, "dsi", name); |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 170 | break; |
| 171 | default: |
| 172 | break; |
| 173 | } |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 174 | switch (cpu) { |
Patrick Delaunay | db33b0e | 2020-02-26 11:26:43 +0100 | [diff] [blame] | 175 | case CPU_STM32MP157Dxx: |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 176 | case CPU_STM32MP157Axx: |
Patrick Delaunay | db33b0e | 2020-02-26 11:26:43 +0100 | [diff] [blame] | 177 | case CPU_STM32MP153Dxx: |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 178 | case CPU_STM32MP153Axx: |
Patrick Delaunay | db33b0e | 2020-02-26 11:26:43 +0100 | [diff] [blame] | 179 | case CPU_STM32MP151Dxx: |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 180 | case CPU_STM32MP151Axx: |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 181 | stm32_fdt_disable(blob, soc, STM32MP15_CRYP1_BASE, "cryp", |
| 182 | name); |
| 183 | stm32_fdt_disable(blob, soc, STM32MP15_CRYP2_BASE, "cryp", |
| 184 | name); |
Patrick Delaunay | fac5ba8 | 2020-02-12 19:37:44 +0100 | [diff] [blame] | 185 | break; |
| 186 | default: |
| 187 | break; |
| 188 | } |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 189 | switch (get_cpu_package()) { |
Patrick Delaunay | e4bdd54 | 2022-05-20 18:24:42 +0200 | [diff] [blame] | 190 | case STM32MP15_PKG_AA_LBGA448: |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 191 | pkg = STM32MP_PKG_AA; |
| 192 | break; |
Patrick Delaunay | e4bdd54 | 2022-05-20 18:24:42 +0200 | [diff] [blame] | 193 | case STM32MP15_PKG_AB_LBGA354: |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 194 | pkg = STM32MP_PKG_AB; |
| 195 | break; |
Patrick Delaunay | e4bdd54 | 2022-05-20 18:24:42 +0200 | [diff] [blame] | 196 | case STM32MP15_PKG_AC_TFBGA361: |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 197 | pkg = STM32MP_PKG_AC; |
| 198 | break; |
Patrick Delaunay | e4bdd54 | 2022-05-20 18:24:42 +0200 | [diff] [blame] | 199 | case STM32MP15_PKG_AD_TFBGA257: |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 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 | } |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 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 | */ |
| 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 | |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 232 | /* MPUs Part Numbers and name*/ |
| 233 | cpu = get_cpu_type(); |
| 234 | get_soc_name(name); |
| 235 | |
Patrick Delaunay | 990e057 | 2024-01-15 15:05:56 +0100 | [diff] [blame] | 236 | if (IS_ENABLED(CONFIG_STM32MP13X)) |
Patrick Delaunay | cf47195 | 2022-05-09 17:13:22 +0200 | [diff] [blame] | 237 | stm32mp13_fdt_fixup(blob, soc, cpu, name); |
| 238 | |
Patrick Delaunay | 4c6fcbc | 2024-01-15 15:05:57 +0100 | [diff] [blame] | 239 | if (IS_ENABLED(CONFIG_STM32MP15X)) { |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 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 | */ |
Patrick Delaunay | 4c6fcbc | 2024-01-15 15:05:57 +0100 | [diff] [blame] | 250 | if (IS_ENABLED(CONFIG_STM32MP15X_STM32IMAGE) && |
Patrick Delaunay | e65e80e | 2022-05-09 17:13:21 +0200 | [diff] [blame] | 251 | !tee_find_device(NULL, NULL, NULL, NULL)) |
| 252 | stm32_fdt_disable_optee(blob); |
| 253 | } |
Patrick Delaunay | d1633b3 | 2020-03-18 09:22:48 +0100 | [diff] [blame] | 254 | |
Patrick Delaunay | a6f0391 | 2019-07-05 17:20:14 +0200 | [diff] [blame] | 255 | return ret; |
| 256 | } |