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