]>
Commit | Line | Data |
---|---|---|
4549e789 | 1 | // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
f8598d98 PD |
2 | /* |
3 | * Copyright (C) 2018, STMicroelectronics - All Rights Reserved | |
f8598d98 | 4 | */ |
873bf448 PD |
5 | |
6 | #define LOG_CATEGORY LOGC_BOARD | |
7 | ||
395f1297 PC |
8 | #include <common.h> |
9 | #include <adc.h> | |
8e194777 | 10 | #include <bootm.h> |
4c834b96 | 11 | #include <clk.h> |
d1a597fc | 12 | #include <config.h> |
4c834b96 | 13 | #include <dm.h> |
d70c4a0a | 14 | #include <efi_loader.h> |
3a7d5571 | 15 | #include <env.h> |
f3998fdc | 16 | #include <env_internal.h> |
8ad37e6f | 17 | #include <fdt_simplefb.h> |
4d72caa5 | 18 | #include <fdt_support.h> |
c31000c5 | 19 | #include <g_dnl.h> |
4c834b96 | 20 | #include <generic-phy.h> |
db41d65a | 21 | #include <hang.h> |
6fe7dd33 | 22 | #include <i2c.h> |
5255932f | 23 | #include <init.h> |
d461f100 | 24 | #include <led.h> |
f7ae49fc | 25 | #include <log.h> |
336d4615 | 26 | #include <malloc.h> |
d461f100 | 27 | #include <misc.h> |
e81f8d16 | 28 | #include <mtd_node.h> |
90526e9f | 29 | #include <net.h> |
53e3d52c | 30 | #include <netdev.h> |
4c834b96 | 31 | #include <phy.h> |
a68ae8dc | 32 | #include <remoteproc.h> |
4c834b96 | 33 | #include <reset.h> |
45459747 | 34 | #include <syscon.h> |
6fe7dd33 | 35 | #include <usb.h> |
dd281085 | 36 | #include <watchdog.h> |
401d1c4f | 37 | #include <asm/global_data.h> |
4c834b96 | 38 | #include <asm/io.h> |
842ebb5f | 39 | #include <asm/gpio.h> |
45459747 | 40 | #include <asm/arch/stm32.h> |
7f90cd61 | 41 | #include <asm/arch/sys_proto.h> |
7de8bd03 | 42 | #include <dm/ofnode.h> |
e81f8d16 | 43 | #include <jffs2/load_kernel.h> |
cd93d625 | 44 | #include <linux/bitops.h> |
c05ed00a | 45 | #include <linux/delay.h> |
61b29b82 | 46 | #include <linux/err.h> |
5ef642c1 | 47 | #include <linux/iopoll.h> |
4c834b96 | 48 | #include <power/regulator.h> |
6fe7dd33 | 49 | #include <usb/dwc2_udc.h> |
f8598d98 | 50 | |
03fb0384 PD |
51 | #include "../../st/common/stusb160x.h" |
52 | ||
45459747 PD |
53 | /* SYSCFG registers */ |
54 | #define SYSCFG_BOOTR 0x00 | |
55 | #define SYSCFG_PMCSETR 0x04 | |
56 | #define SYSCFG_IOCTRLSETR 0x18 | |
57 | #define SYSCFG_ICNR 0x1C | |
58 | #define SYSCFG_CMPCR 0x20 | |
59 | #define SYSCFG_CMPENSETR 0x24 | |
60 | #define SYSCFG_PMCCLRR 0x44 | |
61 | ||
62 | #define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) | |
63 | #define SYSCFG_BOOTR_BOOTPD_SHIFT 4 | |
64 | ||
65 | #define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0) | |
66 | #define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1) | |
67 | #define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2) | |
68 | #define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3) | |
69 | #define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4) | |
70 | ||
71 | #define SYSCFG_CMPCR_SW_CTRL BIT(1) | |
72 | #define SYSCFG_CMPCR_READY BIT(8) | |
73 | ||
74 | #define SYSCFG_CMPENSETR_MPU_EN BIT(0) | |
75 | ||
76 | #define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16) | |
77 | #define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17) | |
78 | ||
79 | #define SYSCFG_PMCSETR_ETH_SELMII BIT(20) | |
80 | ||
81 | #define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) | |
edacf268 CR |
82 | #define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0 |
83 | #define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21) | |
84 | #define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23) | |
45459747 | 85 | |
28c064e6 | 86 | #define USB_LOW_THRESHOLD_UV 200000 |
395f1297 PC |
87 | #define USB_WARNING_LOW_THRESHOLD_UV 660000 |
88 | #define USB_START_LOW_THRESHOLD_UV 1230000 | |
28c064e6 | 89 | #define USB_START_HIGH_THRESHOLD_UV 2150000 |
395f1297 | 90 | |
71aa806d | 91 | #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) |
d70c4a0a SG |
92 | struct efi_fw_image fw_images[1]; |
93 | ||
94 | struct efi_capsule_update_info update_info = { | |
cccea188 | 95 | .num_images = ARRAY_SIZE(fw_images), |
d70c4a0a SG |
96 | .images = fw_images, |
97 | }; | |
98 | ||
d70c4a0a SG |
99 | #endif /* EFI_HAVE_CAPSULE_SUPPORT */ |
100 | ||
d1a4b09d PD |
101 | int board_early_init_f(void) |
102 | { | |
103 | /* nothing to do, only used in SPL */ | |
104 | return 0; | |
105 | } | |
106 | ||
d461f100 PD |
107 | int checkboard(void) |
108 | { | |
109 | int ret; | |
110 | char *mode; | |
111 | u32 otp; | |
112 | struct udevice *dev; | |
113 | const char *fdt_compat; | |
114 | int fdt_compat_len; | |
115 | ||
6de57b41 PD |
116 | if (IS_ENABLED(CONFIG_TFABOOT)) { |
117 | if (IS_ENABLED(CONFIG_STM32MP15x_STM32IMAGE)) | |
118 | mode = "trusted - stm32image"; | |
119 | else | |
120 | mode = "trusted"; | |
121 | } else { | |
d461f100 | 122 | mode = "basic"; |
6de57b41 | 123 | } |
d461f100 | 124 | |
6350633e PD |
125 | fdt_compat = ofnode_get_property(ofnode_root(), "compatible", |
126 | &fdt_compat_len); | |
873bf448 PD |
127 | |
128 | log_info("Board: stm32mp1 in %s mode (%s)\n", mode, | |
129 | fdt_compat && fdt_compat_len ? fdt_compat : ""); | |
d461f100 | 130 | |
888dc681 | 131 | /* display the STMicroelectronics board identification */ |
308d6771 | 132 | if (IS_ENABLED(CONFIG_CMD_STBOARD)) { |
61f6d461 | 133 | ret = uclass_get_device_by_driver(UCLASS_MISC, |
65e25bea | 134 | DM_DRIVER_GET(stm32mp_bsec), |
61f6d461 PD |
135 | &dev); |
136 | if (!ret) | |
137 | ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD), | |
138 | &otp, sizeof(otp)); | |
139 | if (ret > 0 && otp) | |
873bf448 PD |
140 | log_info("Board: MB%04x Var%d.%d Rev.%c-%02d\n", |
141 | otp >> 16, | |
142 | (otp >> 12) & 0xF, | |
143 | (otp >> 4) & 0xF, | |
144 | ((otp >> 8) & 0xF) - 1 + 'A', | |
145 | otp & 0xF); | |
d461f100 PD |
146 | } |
147 | ||
148 | return 0; | |
149 | } | |
150 | ||
9a2ba283 PD |
151 | static void board_key_check(void) |
152 | { | |
9a2ba283 PD |
153 | ofnode node; |
154 | struct gpio_desc gpio; | |
155 | enum forced_boot_mode boot_mode = BOOT_NORMAL; | |
156 | ||
00bac2ab PD |
157 | if (!IS_ENABLED(CONFIG_FASTBOOT) && !IS_ENABLED(CONFIG_CMD_STM32PROG)) |
158 | return; | |
159 | ||
9a2ba283 PD |
160 | node = ofnode_path("/config"); |
161 | if (!ofnode_valid(node)) { | |
873bf448 | 162 | log_debug("no /config node?\n"); |
9a2ba283 PD |
163 | return; |
164 | } | |
00bac2ab PD |
165 | if (IS_ENABLED(CONFIG_FASTBOOT)) { |
166 | if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0, | |
167 | &gpio, GPIOD_IS_IN)) { | |
873bf448 | 168 | log_debug("could not find a /config/st,fastboot-gpios\n"); |
00bac2ab | 169 | } else { |
2a7034c7 | 170 | udelay(20); |
00bac2ab | 171 | if (dm_gpio_get_value(&gpio)) { |
873bf448 | 172 | log_notice("Fastboot key pressed, "); |
00bac2ab PD |
173 | boot_mode = BOOT_FASTBOOT; |
174 | } | |
175 | ||
176 | dm_gpio_free(NULL, &gpio); | |
9a2ba283 | 177 | } |
9a2ba283 | 178 | } |
00bac2ab PD |
179 | if (IS_ENABLED(CONFIG_CMD_STM32PROG)) { |
180 | if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0, | |
181 | &gpio, GPIOD_IS_IN)) { | |
873bf448 | 182 | log_debug("could not find a /config/st,stm32prog-gpios\n"); |
00bac2ab | 183 | } else { |
2a7034c7 | 184 | udelay(20); |
00bac2ab | 185 | if (dm_gpio_get_value(&gpio)) { |
873bf448 | 186 | log_notice("STM32Programmer key pressed, "); |
00bac2ab PD |
187 | boot_mode = BOOT_STM32PROG; |
188 | } | |
189 | dm_gpio_free(NULL, &gpio); | |
9a2ba283 | 190 | } |
9a2ba283 | 191 | } |
9a2ba283 | 192 | if (boot_mode != BOOT_NORMAL) { |
873bf448 | 193 | log_notice("entering download mode...\n"); |
9a2ba283 PD |
194 | clrsetbits_le32(TAMP_BOOT_CONTEXT, |
195 | TAMP_BOOT_FORCED_MASK, | |
196 | boot_mode); | |
197 | } | |
9a2ba283 PD |
198 | } |
199 | ||
c31000c5 | 200 | int g_dnl_board_usb_cable_connected(void) |
4c834b96 | 201 | { |
c31000c5 | 202 | struct udevice *dwc2_udc_otg; |
4c834b96 PC |
203 | int ret; |
204 | ||
6a8713bb PD |
205 | if (!IS_ENABLED(CONFIG_USB_GADGET_DWC2_OTG)) |
206 | return -ENODEV; | |
207 | ||
67899c22 PC |
208 | /* |
209 | * In case of USB boot device is detected, consider USB cable is | |
210 | * connected | |
211 | */ | |
212 | if ((get_bootmode() & TAMP_BOOT_DEVICE_MASK) == BOOT_SERIAL_USB) | |
213 | return true; | |
214 | ||
03fb0384 PD |
215 | /* if typec stusb160x is present, means DK1 or DK2 board */ |
216 | ret = stusb160x_cable_connected(); | |
217 | if (ret >= 0) | |
218 | return ret; | |
6fe7dd33 | 219 | |
c31000c5 | 220 | ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC, |
65e25bea | 221 | DM_DRIVER_GET(dwc2_udc_otg), |
c31000c5 | 222 | &dwc2_udc_otg); |
873bf448 PD |
223 | if (ret) { |
224 | log_debug("dwc2_udc_otg init failed\n"); | |
225 | return ret; | |
226 | } | |
4c834b96 | 227 | |
c31000c5 | 228 | return dwc2_udc_B_session_valid(dwc2_udc_otg); |
4c834b96 | 229 | } |
fb90fcf8 | 230 | |
6a8713bb | 231 | #ifdef CONFIG_USB_GADGET_DOWNLOAD |
fb90fcf8 PD |
232 | #define STM32MP1_G_DNL_DFU_PRODUCT_NUM 0xdf11 |
233 | #define STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM 0x0afb | |
234 | ||
235 | int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) | |
236 | { | |
6a8713bb PD |
237 | if (IS_ENABLED(CONFIG_DFU_OVER_USB) && |
238 | !strcmp(name, "usb_dnl_dfu")) | |
fb90fcf8 | 239 | put_unaligned(STM32MP1_G_DNL_DFU_PRODUCT_NUM, &dev->idProduct); |
6a8713bb PD |
240 | else if (IS_ENABLED(CONFIG_FASTBOOT) && |
241 | !strcmp(name, "usb_dnl_fastboot")) | |
fb90fcf8 PD |
242 | put_unaligned(STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM, |
243 | &dev->idProduct); | |
244 | else | |
245 | put_unaligned(CONFIG_USB_GADGET_PRODUCT_NUM, &dev->idProduct); | |
246 | ||
247 | return 0; | |
248 | } | |
6a8713bb | 249 | #endif /* CONFIG_USB_GADGET_DOWNLOAD */ |
4c834b96 | 250 | |
395f1297 PC |
251 | static int get_led(struct udevice **dev, char *led_string) |
252 | { | |
7de8bd03 | 253 | const char *led_name; |
395f1297 PC |
254 | int ret; |
255 | ||
7de8bd03 | 256 | led_name = ofnode_conf_read_str(led_string); |
395f1297 | 257 | if (!led_name) { |
873bf448 | 258 | log_debug("could not find %s config string\n", led_string); |
395f1297 PC |
259 | return -ENOENT; |
260 | } | |
261 | ret = led_get_by_label(led_name, dev); | |
262 | if (ret) { | |
873bf448 | 263 | log_debug("get=%d\n", ret); |
395f1297 PC |
264 | return ret; |
265 | } | |
266 | ||
267 | return 0; | |
268 | } | |
269 | ||
270 | static int setup_led(enum led_state_t cmd) | |
271 | { | |
272 | struct udevice *dev; | |
273 | int ret; | |
274 | ||
0c95295e PD |
275 | if (!CONFIG_IS_ENABLED(LED)) |
276 | return 0; | |
277 | ||
395f1297 PC |
278 | ret = get_led(&dev, "u-boot,boot-led"); |
279 | if (ret) | |
280 | return ret; | |
281 | ||
282 | ret = led_set_state(dev, cmd); | |
283 | return ret; | |
284 | } | |
dd281085 PD |
285 | |
286 | static void __maybe_unused led_error_blink(u32 nb_blink) | |
287 | { | |
dd281085 PD |
288 | int ret; |
289 | struct udevice *led; | |
290 | u32 i; | |
dd281085 PD |
291 | |
292 | if (!nb_blink) | |
293 | return; | |
294 | ||
0c95295e PD |
295 | if (CONFIG_IS_ENABLED(LED)) { |
296 | ret = get_led(&led, "u-boot,error-led"); | |
297 | if (!ret) { | |
298 | /* make u-boot,error-led blinking */ | |
299 | /* if U32_MAX and 125ms interval, for 17.02 years */ | |
300 | for (i = 0; i < 2 * nb_blink; i++) { | |
301 | led_set_state(led, LEDST_TOGGLE); | |
302 | mdelay(125); | |
29caf930 | 303 | schedule(); |
0c95295e PD |
304 | } |
305 | led_set_state(led, LEDST_ON); | |
dd281085 PD |
306 | } |
307 | } | |
dd281085 PD |
308 | |
309 | /* infinite: the boot process must be stopped */ | |
310 | if (nb_blink == U32_MAX) | |
311 | hang(); | |
312 | } | |
395f1297 | 313 | |
42082bc6 | 314 | static int adc_measurement(ofnode node, int adc_count, int *min_uV, int *max_uV) |
395f1297 PC |
315 | { |
316 | struct ofnode_phandle_args adc_args; | |
317 | struct udevice *adc; | |
395f1297 | 318 | unsigned int raw; |
42082bc6 PC |
319 | int ret, uV; |
320 | int i; | |
395f1297 PC |
321 | |
322 | for (i = 0; i < adc_count; i++) { | |
323 | if (ofnode_parse_phandle_with_args(node, "st,adc_usb_pd", | |
324 | "#io-channel-cells", 0, i, | |
325 | &adc_args)) { | |
873bf448 | 326 | log_debug("can't find /config/st,adc_usb_pd\n"); |
395f1297 PC |
327 | return 0; |
328 | } | |
329 | ||
330 | ret = uclass_get_device_by_ofnode(UCLASS_ADC, adc_args.node, | |
331 | &adc); | |
332 | ||
333 | if (ret) { | |
873bf448 | 334 | log_err("Can't get adc device(%d)\n", ret); |
395f1297 PC |
335 | return ret; |
336 | } | |
337 | ||
338 | ret = adc_channel_single_shot(adc->name, adc_args.args[0], | |
339 | &raw); | |
340 | if (ret) { | |
873bf448 PD |
341 | log_err("single shot failed for %s[%d]!\n", |
342 | adc->name, adc_args.args[0]); | |
395f1297 PC |
343 | return ret; |
344 | } | |
345 | /* Convert to uV */ | |
346 | if (!adc_raw_to_uV(adc, raw, &uV)) { | |
42082bc6 PC |
347 | if (uV > *max_uV) |
348 | *max_uV = uV; | |
349 | if (uV < *min_uV) | |
350 | *min_uV = uV; | |
873bf448 PD |
351 | log_debug("%s[%02d] = %u, %d uV\n", |
352 | adc->name, adc_args.args[0], raw, uV); | |
395f1297 | 353 | } else { |
873bf448 PD |
354 | log_err("Can't get uV value for %s[%d]\n", |
355 | adc->name, adc_args.args[0]); | |
395f1297 PC |
356 | } |
357 | } | |
358 | ||
42082bc6 PC |
359 | return 0; |
360 | } | |
361 | ||
362 | static int board_check_usb_power(void) | |
363 | { | |
364 | ofnode node; | |
365 | int max_uV = 0; | |
366 | int min_uV = USB_START_HIGH_THRESHOLD_UV; | |
367 | int adc_count, ret; | |
368 | u32 nb_blink; | |
369 | u8 i; | |
370 | ||
2214d5e5 PD |
371 | if (!IS_ENABLED(CONFIG_ADC)) |
372 | return -ENODEV; | |
373 | ||
42082bc6 PC |
374 | node = ofnode_path("/config"); |
375 | if (!ofnode_valid(node)) { | |
376 | log_debug("no /config node?\n"); | |
377 | return -ENOENT; | |
378 | } | |
379 | ||
395f1297 | 380 | /* |
42082bc6 PC |
381 | * Retrieve the ADC channels devices and get measurement |
382 | * for each of them | |
395f1297 | 383 | */ |
42082bc6 PC |
384 | adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd", |
385 | "#io-channel-cells", 0); | |
386 | if (adc_count < 0) { | |
387 | if (adc_count == -ENOENT) | |
388 | return 0; | |
395f1297 | 389 | |
42082bc6 PC |
390 | log_err("Can't find adc channel (%d)\n", adc_count); |
391 | ||
392 | return adc_count; | |
393 | } | |
394 | ||
395 | /* perform maximum of 2 ADC measurements to detect power supply current */ | |
396 | for (i = 0; i < 2; i++) { | |
2214d5e5 | 397 | ret = adc_measurement(node, adc_count, &min_uV, &max_uV); |
42082bc6 PC |
398 | if (ret) |
399 | return ret; | |
400 | ||
401 | /* | |
402 | * If highest value is inside 1.23 Volts and 2.10 Volts, that means | |
403 | * board is plugged on an USB-C 3A power supply and boot process can | |
404 | * continue. | |
405 | */ | |
406 | if (max_uV > USB_START_LOW_THRESHOLD_UV && | |
407 | max_uV <= USB_START_HIGH_THRESHOLD_UV && | |
408 | min_uV <= USB_LOW_THRESHOLD_UV) | |
409 | return 0; | |
410 | ||
411 | if (i == 0) { | |
412 | log_err("Previous ADC measurements was not the one expected, retry in 20ms\n"); | |
413 | mdelay(20); /* equal to max tPDDebounce duration (min 10ms - max 20ms) */ | |
414 | } | |
415 | } | |
416 | ||
417 | log_notice("****************************************************\n"); | |
28c064e6 PC |
418 | /* |
419 | * If highest and lowest value are either both below | |
420 | * USB_LOW_THRESHOLD_UV or both above USB_LOW_THRESHOLD_UV, that | |
421 | * means USB TYPE-C is in unattached mode, this is an issue, make | |
422 | * u-boot,error-led blinking and stop boot process. | |
423 | */ | |
424 | if ((max_uV > USB_LOW_THRESHOLD_UV && | |
425 | min_uV > USB_LOW_THRESHOLD_UV) || | |
426 | (max_uV <= USB_LOW_THRESHOLD_UV && | |
427 | min_uV <= USB_LOW_THRESHOLD_UV)) { | |
873bf448 PD |
428 | log_notice("* ERROR USB TYPE-C connection in unattached mode *\n"); |
429 | log_notice("* Check that USB TYPE-C cable is correctly plugged *\n"); | |
28c064e6 PC |
430 | /* with 125ms interval, led will blink for 17.02 years ....*/ |
431 | nb_blink = U32_MAX; | |
432 | } | |
395f1297 | 433 | |
28c064e6 PC |
434 | if (max_uV > USB_LOW_THRESHOLD_UV && |
435 | max_uV <= USB_WARNING_LOW_THRESHOLD_UV && | |
436 | min_uV <= USB_LOW_THRESHOLD_UV) { | |
873bf448 | 437 | log_notice("* WARNING 500mA power supply detected *\n"); |
395f1297 | 438 | nb_blink = 2; |
28c064e6 PC |
439 | } |
440 | ||
441 | if (max_uV > USB_WARNING_LOW_THRESHOLD_UV && | |
442 | max_uV <= USB_START_LOW_THRESHOLD_UV && | |
443 | min_uV <= USB_LOW_THRESHOLD_UV) { | |
873bf448 | 444 | log_notice("* WARNING 1.5A power supply detected *\n"); |
395f1297 PC |
445 | nb_blink = 3; |
446 | } | |
447 | ||
28c064e6 PC |
448 | /* |
449 | * If highest value is above 2.15 Volts that means that the USB TypeC | |
450 | * supplies more than 3 Amp, this is not compliant with TypeC specification | |
451 | */ | |
452 | if (max_uV > USB_START_HIGH_THRESHOLD_UV) { | |
873bf448 PD |
453 | log_notice("* USB TYPE-C charger not compliant with *\n"); |
454 | log_notice("* specification *\n"); | |
455 | log_notice("****************************************************\n\n"); | |
28c064e6 PC |
456 | /* with 125ms interval, led will blink for 17.02 years ....*/ |
457 | nb_blink = U32_MAX; | |
458 | } else { | |
873bf448 PD |
459 | log_notice("* Current too low, use a 3A power supply! *\n"); |
460 | log_notice("****************************************************\n\n"); | |
28c064e6 | 461 | } |
395f1297 | 462 | |
dd281085 | 463 | led_error_blink(nb_blink); |
395f1297 PC |
464 | |
465 | return 0; | |
466 | } | |
467 | ||
45459747 PD |
468 | static void sysconf_init(void) |
469 | { | |
45459747 | 470 | u8 *syscfg; |
45459747 PD |
471 | struct udevice *pwr_dev; |
472 | struct udevice *pwr_reg; | |
473 | struct udevice *dev; | |
45459747 | 474 | u32 otp = 0; |
5ef642c1 PD |
475 | int ret; |
476 | u32 bootr, val; | |
45459747 PD |
477 | |
478 | syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); | |
479 | ||
480 | /* interconnect update : select master using the port 1 */ | |
481 | /* LTDC = AXI_M9 */ | |
482 | /* GPU = AXI_M8 */ | |
483 | /* today information is hardcoded in U-Boot */ | |
484 | writel(BIT(9), syscfg + SYSCFG_ICNR); | |
485 | ||
486 | /* disable Pull-Down for boot pin connected to VDD */ | |
487 | bootr = readl(syscfg + SYSCFG_BOOTR); | |
488 | bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT); | |
489 | bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT; | |
490 | writel(bootr, syscfg + SYSCFG_BOOTR); | |
491 | ||
45459747 PD |
492 | /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI |
493 | * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. | |
494 | * The customer will have to disable this for low frequencies | |
495 | * or if AFMUX is selected but the function not used, typically for | |
496 | * TRACE. Otherwise, impact on power consumption. | |
497 | * | |
498 | * WARNING: | |
499 | * enabling High Speed mode while VDD>2.7V | |
500 | * with the OTP product_below_2v5 (OTP 18, BIT 13) | |
501 | * erroneously set to 1 can damage the IC! | |
502 | * => U-Boot set the register only if VDD < 2.7V (in DT) | |
503 | * but this value need to be consistent with board design | |
504 | */ | |
5e959ab8 | 505 | ret = uclass_get_device_by_driver(UCLASS_PMIC, |
65e25bea | 506 | DM_DRIVER_GET(stm32mp_pwr_pmic), |
5e959ab8 | 507 | &pwr_dev); |
0a1a7556 | 508 | if (!ret) { |
45459747 | 509 | ret = uclass_get_device_by_driver(UCLASS_MISC, |
65e25bea | 510 | DM_DRIVER_GET(stm32mp_bsec), |
45459747 PD |
511 | &dev); |
512 | if (ret) { | |
873bf448 | 513 | log_err("Can't find stm32mp_bsec driver\n"); |
45459747 PD |
514 | return; |
515 | } | |
516 | ||
517 | ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4); | |
ff6618e9 | 518 | if (ret > 0) |
45459747 PD |
519 | otp = otp & BIT(13); |
520 | ||
5e959ab8 PD |
521 | /* get VDD = vdd-supply */ |
522 | ret = device_get_supply_regulator(pwr_dev, "vdd-supply", | |
45459747 PD |
523 | &pwr_reg); |
524 | ||
525 | /* check if VDD is Low Voltage */ | |
526 | if (!ret) { | |
527 | if (regulator_get_value(pwr_reg) < 2700000) { | |
528 | writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE | | |
529 | SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | | |
530 | SYSCFG_IOCTRLSETR_HSLVEN_ETH | | |
531 | SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | | |
532 | SYSCFG_IOCTRLSETR_HSLVEN_SPI, | |
533 | syscfg + SYSCFG_IOCTRLSETR); | |
534 | ||
535 | if (!otp) | |
873bf448 | 536 | log_err("product_below_2v5=0: HSLVEN protected by HW\n"); |
45459747 PD |
537 | } else { |
538 | if (otp) | |
873bf448 | 539 | log_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n"); |
45459747 PD |
540 | } |
541 | } else { | |
873bf448 | 542 | log_debug("VDD unknown"); |
45459747 PD |
543 | } |
544 | } | |
45459747 PD |
545 | |
546 | /* activate automatic I/O compensation | |
547 | * warning: need to ensure CSI enabled and ready in clock driver | |
548 | */ | |
549 | writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR); | |
550 | ||
5ef642c1 PD |
551 | /* poll until ready (1s timeout) */ |
552 | ret = readl_poll_timeout(syscfg + SYSCFG_CMPCR, val, | |
553 | val & SYSCFG_CMPCR_READY, | |
554 | 1000000); | |
555 | if (ret) { | |
873bf448 | 556 | log_err("SYSCFG: I/O compensation failed, timeout.\n"); |
5ef642c1 PD |
557 | led_error_blink(10); |
558 | } | |
559 | ||
45459747 | 560 | clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); |
45459747 PD |
561 | } |
562 | ||
ae3e2c2b | 563 | static int board_stm32mp15x_dk2_init(void) |
d573e461 PD |
564 | { |
565 | ofnode node; | |
566 | struct gpio_desc hdmi, audio; | |
567 | int ret = 0; | |
568 | ||
ae3e2c2b | 569 | /* Fix to make I2C1 usable on DK2 for touchscreen usage in kernel */ |
d573e461 PD |
570 | node = ofnode_path("/soc/i2c@40012000/hdmi-transmitter@39"); |
571 | if (!ofnode_valid(node)) { | |
873bf448 | 572 | log_debug("no hdmi-transmitter@39 ?\n"); |
d573e461 PD |
573 | return -ENOENT; |
574 | } | |
575 | ||
576 | if (gpio_request_by_name_nodev(node, "reset-gpios", 0, | |
577 | &hdmi, GPIOD_IS_OUT)) { | |
873bf448 | 578 | log_debug("could not find reset-gpios\n"); |
d573e461 PD |
579 | return -ENOENT; |
580 | } | |
581 | ||
582 | node = ofnode_path("/soc/i2c@40012000/cs42l51@4a"); | |
583 | if (!ofnode_valid(node)) { | |
873bf448 | 584 | log_debug("no cs42l51@4a ?\n"); |
d573e461 PD |
585 | return -ENOENT; |
586 | } | |
587 | ||
588 | if (gpio_request_by_name_nodev(node, "reset-gpios", 0, | |
589 | &audio, GPIOD_IS_OUT)) { | |
873bf448 | 590 | log_debug("could not find reset-gpios\n"); |
d573e461 PD |
591 | return -ENOENT; |
592 | } | |
593 | ||
594 | /* before power up, insure that HDMI and AUDIO IC is under reset */ | |
595 | ret = dm_gpio_set_value(&hdmi, 1); | |
596 | if (ret) { | |
873bf448 | 597 | log_err("can't set_value for hdmi_nrst gpio"); |
d573e461 PD |
598 | goto error; |
599 | } | |
600 | ret = dm_gpio_set_value(&audio, 1); | |
601 | if (ret) { | |
873bf448 | 602 | log_err("can't set_value for audio_nrst gpio"); |
d573e461 PD |
603 | goto error; |
604 | } | |
605 | ||
606 | /* power-up audio IC */ | |
607 | regulator_autoset_by_name("v1v8_audio", NULL); | |
608 | ||
609 | /* power-up HDMI IC */ | |
610 | regulator_autoset_by_name("v1v2_hdmi", NULL); | |
611 | regulator_autoset_by_name("v3v3_hdmi", NULL); | |
612 | ||
613 | error: | |
614 | return ret; | |
615 | } | |
616 | ||
ae3e2c2b | 617 | static bool board_is_stm32mp15x_dk2(void) |
d573e461 | 618 | { |
84625488 | 619 | if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) && |
d573e461 PD |
620 | of_machine_is_compatible("st,stm32mp157c-dk2")) |
621 | return true; | |
622 | ||
623 | return false; | |
624 | } | |
d573e461 | 625 | |
ae3e2c2b | 626 | static bool board_is_stm32mp15x_ev1(void) |
055065a8 PD |
627 | { |
628 | if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) && | |
629 | (of_machine_is_compatible("st,stm32mp157a-ev1") || | |
630 | of_machine_is_compatible("st,stm32mp157c-ev1") || | |
631 | of_machine_is_compatible("st,stm32mp157d-ev1") || | |
632 | of_machine_is_compatible("st,stm32mp157f-ev1"))) | |
633 | return true; | |
634 | ||
635 | return false; | |
636 | } | |
637 | ||
638 | /* touchscreen driver: only used for pincontrol configuration */ | |
639 | static const struct udevice_id goodix_ids[] = { | |
640 | { .compatible = "goodix,gt9147", }, | |
641 | { } | |
642 | }; | |
643 | ||
644 | U_BOOT_DRIVER(goodix) = { | |
645 | .name = "goodix", | |
646 | .id = UCLASS_NOP, | |
647 | .of_match = goodix_ids, | |
648 | }; | |
649 | ||
ae3e2c2b | 650 | static void board_stm32mp15x_ev1_init(void) |
055065a8 PD |
651 | { |
652 | struct udevice *dev; | |
653 | ||
654 | /* configure IRQ line on EV1 for touchscreen before LCD reset */ | |
65e25bea | 655 | uclass_get_device_by_driver(UCLASS_NOP, DM_DRIVER_GET(goodix), &dev); |
055065a8 PD |
656 | } |
657 | ||
f8598d98 PD |
658 | /* board dependent setup after realloc */ |
659 | int board_init(void) | |
660 | { | |
9a2ba283 PD |
661 | board_key_check(); |
662 | ||
ae3e2c2b PD |
663 | if (board_is_stm32mp15x_ev1()) |
664 | board_stm32mp15x_ev1_init(); | |
055065a8 | 665 | |
ae3e2c2b PD |
666 | if (board_is_stm32mp15x_dk2()) |
667 | board_stm32mp15x_dk2_init(); | |
d573e461 | 668 | |
0a1a7556 | 669 | regulators_enable_boot_on(_DEBUG); |
f59ad456 | 670 | |
f42045b2 PD |
671 | /* |
672 | * sysconf initialisation done only when U-Boot is running in secure | |
673 | * done in TF-A for TFABOOT. | |
674 | */ | |
675 | if (IS_ENABLED(CONFIG_ARMV7_NONSEC)) | |
3434bbe6 | 676 | sysconf_init(); |
45459747 | 677 | |
0c95295e PD |
678 | setup_led(LEDST_ON); |
679 | ||
71aa806d | 680 | #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) |
d70c4a0a SG |
681 | efi_guid_t image_type_guid = STM32MP_FIP_IMAGE_GUID; |
682 | ||
683 | guidcpy(&fw_images[0].image_type_id, &image_type_guid); | |
684 | fw_images[0].fw_name = u"STM32MP-FIP"; | |
685 | fw_images[0].image_index = 1; | |
686 | #endif | |
f8598d98 PD |
687 | return 0; |
688 | } | |
b4ae34b6 PD |
689 | |
690 | int board_late_init(void) | |
691 | { | |
b4ae34b6 PD |
692 | const void *fdt_compat; |
693 | int fdt_compat_len; | |
8b8b3d6b PD |
694 | int ret; |
695 | u32 otp; | |
696 | struct udevice *dev; | |
697 | char buf[10]; | |
72b09989 PD |
698 | char dtb_name[256]; |
699 | int buf_len; | |
700 | ||
701 | if (IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)) { | |
6350633e PD |
702 | fdt_compat = ofnode_get_property(ofnode_root(), "compatible", |
703 | &fdt_compat_len); | |
72b09989 PD |
704 | if (fdt_compat && fdt_compat_len) { |
705 | if (strncmp(fdt_compat, "st,", 3) != 0) { | |
706 | env_set("board_name", fdt_compat); | |
707 | } else { | |
708 | env_set("board_name", fdt_compat + 3); | |
b4ae34b6 | 709 | |
72b09989 PD |
710 | buf_len = sizeof(dtb_name); |
711 | strncpy(dtb_name, fdt_compat + 3, buf_len); | |
712 | buf_len -= strlen(fdt_compat + 3); | |
713 | strncat(dtb_name, ".dtb", buf_len); | |
714 | env_set("fdtfile", dtb_name); | |
715 | } | |
716 | } | |
717 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
65e25bea | 718 | DM_DRIVER_GET(stm32mp_bsec), |
72b09989 | 719 | &dev); |
99f6743d | 720 | |
72b09989 PD |
721 | if (!ret) |
722 | ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD), | |
723 | &otp, sizeof(otp)); | |
724 | if (ret > 0 && otp) { | |
725 | snprintf(buf, sizeof(buf), "0x%04x", otp >> 16); | |
726 | env_set("board_id", buf); | |
99f6743d | 727 | |
72b09989 PD |
728 | snprintf(buf, sizeof(buf), "0x%04x", |
729 | ((otp >> 8) & 0xF) - 1 + 0xA); | |
730 | env_set("board_rev", buf); | |
99f6743d | 731 | } |
b4ae34b6 | 732 | } |
b4ae34b6 | 733 | |
395f1297 PC |
734 | /* for DK1/DK2 boards */ |
735 | board_check_usb_power(); | |
736 | ||
b4ae34b6 PD |
737 | return 0; |
738 | } | |
395f1297 PC |
739 | |
740 | void board_quiesce_devices(void) | |
741 | { | |
742 | setup_led(LEDST_OFF); | |
edacf268 CR |
743 | } |
744 | ||
53e3d52c PD |
745 | /* eth init function : weak called in eqos driver */ |
746 | int board_interface_eth_init(struct udevice *dev, | |
747 | phy_interface_t interface_type) | |
edacf268 CR |
748 | { |
749 | u8 *syscfg; | |
750 | u32 value; | |
53e3d52c PD |
751 | bool eth_clk_sel_reg = false; |
752 | bool eth_ref_clk_sel_reg = false; | |
753 | ||
754 | /* Gigabit Ethernet 125MHz clock selection. */ | |
486808e3 | 755 | eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel"); |
53e3d52c PD |
756 | |
757 | /* Ethernet 50Mhz RMII clock selection */ | |
758 | eth_ref_clk_sel_reg = | |
486808e3 | 759 | dev_read_bool(dev, "st,eth-ref-clk-sel"); |
edacf268 CR |
760 | |
761 | syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); | |
762 | ||
763 | if (!syscfg) | |
764 | return -ENODEV; | |
765 | ||
766 | switch (interface_type) { | |
767 | case PHY_INTERFACE_MODE_MII: | |
768 | value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | | |
769 | SYSCFG_PMCSETR_ETH_REF_CLK_SEL; | |
873bf448 | 770 | log_debug("PHY_INTERFACE_MODE_MII\n"); |
edacf268 CR |
771 | break; |
772 | case PHY_INTERFACE_MODE_GMII: | |
773 | if (eth_clk_sel_reg) | |
774 | value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII | | |
775 | SYSCFG_PMCSETR_ETH_CLK_SEL; | |
776 | else | |
777 | value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII; | |
873bf448 | 778 | log_debug("PHY_INTERFACE_MODE_GMII\n"); |
edacf268 CR |
779 | break; |
780 | case PHY_INTERFACE_MODE_RMII: | |
781 | if (eth_ref_clk_sel_reg) | |
782 | value = SYSCFG_PMCSETR_ETH_SEL_RMII | | |
783 | SYSCFG_PMCSETR_ETH_REF_CLK_SEL; | |
784 | else | |
785 | value = SYSCFG_PMCSETR_ETH_SEL_RMII; | |
873bf448 | 786 | log_debug("PHY_INTERFACE_MODE_RMII\n"); |
edacf268 CR |
787 | break; |
788 | case PHY_INTERFACE_MODE_RGMII: | |
789 | case PHY_INTERFACE_MODE_RGMII_ID: | |
790 | case PHY_INTERFACE_MODE_RGMII_RXID: | |
791 | case PHY_INTERFACE_MODE_RGMII_TXID: | |
792 | if (eth_clk_sel_reg) | |
793 | value = SYSCFG_PMCSETR_ETH_SEL_RGMII | | |
794 | SYSCFG_PMCSETR_ETH_CLK_SEL; | |
795 | else | |
796 | value = SYSCFG_PMCSETR_ETH_SEL_RGMII; | |
873bf448 | 797 | log_debug("PHY_INTERFACE_MODE_RGMII\n"); |
edacf268 CR |
798 | break; |
799 | default: | |
873bf448 PD |
800 | log_debug("Do not manage %d interface\n", |
801 | interface_type); | |
edacf268 CR |
802 | /* Do not manage others interfaces */ |
803 | return -EINVAL; | |
804 | } | |
805 | ||
806 | /* clear and set ETH configuration bits */ | |
807 | writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII | | |
808 | SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL, | |
809 | syscfg + SYSCFG_PMCCLRR); | |
810 | writel(value, syscfg + SYSCFG_PMCSETR); | |
811 | ||
812 | return 0; | |
395f1297 | 813 | } |
87471649 | 814 | |
8f24b1a4 PC |
815 | enum env_location env_get_location(enum env_operation op, int prio) |
816 | { | |
817 | u32 bootmode = get_bootmode(); | |
818 | ||
819 | if (prio) | |
820 | return ENVL_UNKNOWN; | |
821 | ||
822 | switch (bootmode & TAMP_BOOT_DEVICE_MASK) { | |
a9addcaf PD |
823 | case BOOT_FLASH_SD: |
824 | case BOOT_FLASH_EMMC: | |
ebfd592f PD |
825 | if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC)) |
826 | return ENVL_MMC; | |
827 | else if (CONFIG_IS_ENABLED(ENV_IS_IN_EXT4)) | |
828 | return ENVL_EXT4; | |
829 | else | |
830 | return ENVL_NOWHERE; | |
831 | ||
8f24b1a4 | 832 | case BOOT_FLASH_NAND: |
b664a745 | 833 | case BOOT_FLASH_SPINAND: |
821d1df5 | 834 | if (IS_ENABLED(CONFIG_ENV_IS_IN_UBI)) |
ebfd592f PD |
835 | return ENVL_UBI; |
836 | else | |
837 | return ENVL_NOWHERE; | |
838 | ||
e5c38fdd | 839 | case BOOT_FLASH_NOR: |
ebfd592f PD |
840 | if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH)) |
841 | return ENVL_SPI_FLASH; | |
842 | else | |
843 | return ENVL_NOWHERE; | |
844 | ||
8f24b1a4 PC |
845 | default: |
846 | return ENVL_NOWHERE; | |
847 | } | |
848 | } | |
849 | ||
7f90cd61 PC |
850 | const char *env_ext4_get_intf(void) |
851 | { | |
852 | u32 bootmode = get_bootmode(); | |
853 | ||
854 | switch (bootmode & TAMP_BOOT_DEVICE_MASK) { | |
855 | case BOOT_FLASH_SD: | |
856 | case BOOT_FLASH_EMMC: | |
857 | return "mmc"; | |
858 | default: | |
859 | return ""; | |
860 | } | |
861 | } | |
862 | ||
3c1057c5 PD |
863 | int mmc_get_boot(void) |
864 | { | |
865 | struct udevice *dev; | |
866 | u32 boot_mode = get_bootmode(); | |
867 | unsigned int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1; | |
868 | char cmd[20]; | |
869 | const u32 sdmmc_addr[] = { | |
870 | STM32_SDMMC1_BASE, | |
871 | STM32_SDMMC2_BASE, | |
872 | STM32_SDMMC3_BASE | |
873 | }; | |
874 | ||
daf07215 | 875 | if (instance >= ARRAY_SIZE(sdmmc_addr)) |
3c1057c5 PD |
876 | return 0; |
877 | ||
878 | /* search associated sdmmc node in devicetree */ | |
879 | snprintf(cmd, sizeof(cmd), "mmc@%x", sdmmc_addr[instance]); | |
880 | if (uclass_get_device_by_name(UCLASS_MMC, cmd, &dev)) { | |
881 | log_err("mmc%d = %s not found in device tree!\n", instance, cmd); | |
882 | return 0; | |
883 | } | |
884 | ||
885 | return dev_seq(dev); | |
886 | }; | |
887 | ||
7f90cd61 PC |
888 | const char *env_ext4_get_dev_part(void) |
889 | { | |
81d4c4e4 MR |
890 | static char *const env_dev_part = |
891 | #ifdef CONFIG_ENV_EXT4_DEVICE_AND_PART | |
892 | CONFIG_ENV_EXT4_DEVICE_AND_PART; | |
893 | #else | |
894 | ""; | |
895 | #endif | |
7f90cd61 | 896 | static char *const dev_part[] = {"0:auto", "1:auto", "2:auto"}; |
81d4c4e4 MR |
897 | |
898 | if (strlen(env_dev_part) > 0) | |
899 | return env_dev_part; | |
900 | ||
3c1057c5 | 901 | return dev_part[mmc_get_boot()]; |
7f90cd61 | 902 | } |
81d4c4e4 | 903 | |
a9addcaf PD |
904 | int mmc_get_env_dev(void) |
905 | { | |
046bdb80 PD |
906 | const int mmc_env_dev = CONFIG_IS_ENABLED(ENV_IS_IN_MMC, (CONFIG_SYS_MMC_ENV_DEV), (-1)); |
907 | ||
908 | if (mmc_env_dev >= 0) | |
909 | return mmc_env_dev; | |
9f971936 | 910 | |
9f971936 | 911 | /* use boot instance to select the correct mmc device identifier */ |
3c1057c5 | 912 | return mmc_get_boot(); |
a9addcaf | 913 | } |
a9addcaf | 914 | |
e81f8d16 | 915 | #if defined(CONFIG_OF_BOARD_SETUP) |
b75d8dc5 | 916 | int ft_board_setup(void *blob, struct bd_info *bd) |
e81f8d16 | 917 | { |
d0a3c4f9 | 918 | static const struct node_info nodes[] = { |
89f37451 CK |
919 | { "jedec,spi-nor", MTD_DEV_TYPE_NOR, }, |
920 | { "spi-nand", MTD_DEV_TYPE_SPINAND}, | |
e81f8d16 | 921 | { "st,stm32mp15-fmc2", MTD_DEV_TYPE_NAND, }, |
300669ac | 922 | { "st,stm32mp1-fmc2-nfc", MTD_DEV_TYPE_NAND, }, |
e81f8d16 | 923 | }; |
29e5c027 PD |
924 | char *boot_device; |
925 | ||
926 | /* Check the boot-source and don't update MTD for serial or usb boot */ | |
927 | boot_device = env_get("boot_device"); | |
928 | if (!boot_device || | |
929 | (strcmp(boot_device, "serial") && strcmp(boot_device, "usb"))) | |
930 | if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS)) | |
931 | fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); | |
e81f8d16 | 932 | |
96e3b52b | 933 | if (IS_ENABLED(CONFIG_FDT_SIMPLEFB)) |
8ad37e6f PD |
934 | fdt_simplefb_enable_and_mem_rsv(blob); |
935 | ||
e81f8d16 PD |
936 | return 0; |
937 | } | |
938 | #endif | |
a68ae8dc PD |
939 | |
940 | static void board_copro_image_process(ulong fw_image, size_t fw_size) | |
941 | { | |
942 | int ret, id = 0; /* Copro id fixed to 0 as only one coproc on mp1 */ | |
943 | ||
944 | if (!rproc_is_initialized()) | |
945 | if (rproc_init()) { | |
873bf448 PD |
946 | log_err("Remote Processor %d initialization failed\n", |
947 | id); | |
a68ae8dc PD |
948 | return; |
949 | } | |
950 | ||
951 | ret = rproc_load(id, fw_image, fw_size); | |
873bf448 PD |
952 | log_err("Load Remote Processor %d with data@addr=0x%08lx %u bytes:%s\n", |
953 | id, fw_image, fw_size, ret ? " Failed!" : " Success!"); | |
a68ae8dc | 954 | |
790d5b36 | 955 | if (!ret) |
a68ae8dc | 956 | rproc_start(id); |
a68ae8dc PD |
957 | } |
958 | ||
959 | U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); | |
95b5a7de SG |
960 | |
961 | #if defined(CONFIG_FWU_MULTI_BANK_UPDATE) | |
962 | ||
963 | #include <fwu.h> | |
964 | ||
965 | /** | |
966 | * fwu_plat_get_bootidx() - Get the value of the boot index | |
967 | * @boot_idx: Boot index value | |
968 | * | |
969 | * Get the value of the bank(partition) from which the platform | |
970 | * has booted. This value is passed to U-Boot from the earlier | |
971 | * stage bootloader which loads and boots all the relevant | |
972 | * firmware images | |
973 | * | |
974 | */ | |
975 | void fwu_plat_get_bootidx(uint *boot_idx) | |
976 | { | |
977 | *boot_idx = (readl(TAMP_FWU_BOOT_INFO_REG) >> | |
978 | TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; | |
979 | } | |
980 | #endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ |