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