blob: 126af301732701803290aa539870d11c6749e896 [file] [log] [blame]
Tom Rini4549e782018-05-06 18:27:01 -04001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
Patrick Delaunayf8598d92018-03-12 10:46:18 +01002/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
Patrick Delaunayf8598d92018-03-12 10:46:18 +01004 */
Patrice Chotard395f1292019-02-12 16:50:40 +01005#include <common.h>
6#include <adc.h>
Patrick Delaunay8e194772019-06-21 15:26:40 +02007#include <bootm.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +02008#include <clk.h>
Patrick Delaunayd1a597f2019-07-30 19:16:44 +02009#include <config.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020010#include <dm.h>
Simon Glass3a7d5572019-08-01 09:46:42 -060011#include <env.h>
Simon Glassf3998fd2019-08-02 09:44:25 -060012#include <env_internal.h>
Patrick Delaunayc31000c2019-03-29 15:42:23 +010013#include <g_dnl.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020014#include <generic-phy.h>
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +010015#include <i2c.h>
Patrick Delaunayd461f102019-02-12 11:44:41 +010016#include <led.h>
17#include <misc.h>
Patrick Delaunaye81f8d12019-07-02 13:26:07 +020018#include <mtd.h>
19#include <mtd_node.h>
Patrick Delaunay53e3d522019-08-01 11:29:03 +020020#include <netdev.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020021#include <phy.h>
Patrick Delaunaya68ae8d2019-08-02 15:07:20 +020022#include <remoteproc.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020023#include <reset.h>
Patrick Delaunay45459742019-02-27 17:01:24 +010024#include <syscon.h>
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +010025#include <usb.h>
Patrick Delaunaydd281082019-07-30 19:16:39 +020026#include <watchdog.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020027#include <asm/io.h>
Patrick Delaunay842ebb52019-02-27 17:01:18 +010028#include <asm/gpio.h>
Patrick Delaunay45459742019-02-27 17:01:24 +010029#include <asm/arch/stm32.h>
Patrice Chotard7f90cd62019-05-02 18:36:01 +020030#include <asm/arch/sys_proto.h>
Patrick Delaunaye81f8d12019-07-02 13:26:07 +020031#include <jffs2/load_kernel.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020032#include <power/regulator.h>
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +010033#include <usb/dwc2_udc.h>
Patrick Delaunayf8598d92018-03-12 10:46:18 +010034
Patrick Delaunay45459742019-02-27 17:01:24 +010035/* SYSCFG registers */
36#define SYSCFG_BOOTR 0x00
37#define SYSCFG_PMCSETR 0x04
38#define SYSCFG_IOCTRLSETR 0x18
39#define SYSCFG_ICNR 0x1C
40#define SYSCFG_CMPCR 0x20
41#define SYSCFG_CMPENSETR 0x24
42#define SYSCFG_PMCCLRR 0x44
43
44#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
45#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
46
47#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
48#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
49#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
50#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
51#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
52
53#define SYSCFG_CMPCR_SW_CTRL BIT(1)
54#define SYSCFG_CMPCR_READY BIT(8)
55
56#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
57
58#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16)
59#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17)
60
61#define SYSCFG_PMCSETR_ETH_SELMII BIT(20)
62
63#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21)
Christophe Roullieredacf262019-05-17 15:08:43 +020064#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0
65#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21)
66#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23)
Patrick Delaunay45459742019-02-27 17:01:24 +010067
Patrick Delaunayf8598d92018-03-12 10:46:18 +010068/*
69 * Get a global data pointer
70 */
71DECLARE_GLOBAL_DATA_PTR;
72
Patrice Chotard28c064e2019-04-30 18:09:38 +020073#define USB_LOW_THRESHOLD_UV 200000
Patrice Chotard395f1292019-02-12 16:50:40 +010074#define USB_WARNING_LOW_THRESHOLD_UV 660000
75#define USB_START_LOW_THRESHOLD_UV 1230000
Patrice Chotard28c064e2019-04-30 18:09:38 +020076#define USB_START_HIGH_THRESHOLD_UV 2150000
Patrice Chotard395f1292019-02-12 16:50:40 +010077
Patrick Delaunayd461f102019-02-12 11:44:41 +010078int checkboard(void)
79{
80 int ret;
81 char *mode;
82 u32 otp;
83 struct udevice *dev;
84 const char *fdt_compat;
85 int fdt_compat_len;
86
Patrick Delaunay152c84b2019-07-02 13:26:06 +020087 if (IS_ENABLED(CONFIG_STM32MP1_OPTEE))
88 mode = "trusted with OP-TEE";
89 else if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED))
Patrick Delaunayd461f102019-02-12 11:44:41 +010090 mode = "trusted";
91 else
92 mode = "basic";
93
94 printf("Board: stm32mp1 in %s mode", mode);
95 fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
96 &fdt_compat_len);
97 if (fdt_compat && fdt_compat_len)
98 printf(" (%s)", fdt_compat);
99 puts("\n");
100
101 ret = uclass_get_device_by_driver(UCLASS_MISC,
102 DM_GET_DRIVER(stm32mp_bsec),
103 &dev);
104
105 if (!ret)
106 ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
107 &otp, sizeof(otp));
Patrick Delaunay19efa392019-08-02 13:08:05 +0200108 if (ret > 0 && otp) {
Patrick Delaunayd461f102019-02-12 11:44:41 +0100109 printf("Board: MB%04x Var%d Rev.%c-%02d\n",
110 otp >> 16,
111 (otp >> 12) & 0xF,
112 ((otp >> 8) & 0xF) - 1 + 'A',
113 otp & 0xF);
114 }
115
116 return 0;
117}
118
Patrick Delaunay9a2ba282019-02-27 17:01:20 +0100119static void board_key_check(void)
120{
121#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
122 ofnode node;
123 struct gpio_desc gpio;
124 enum forced_boot_mode boot_mode = BOOT_NORMAL;
125
126 node = ofnode_path("/config");
127 if (!ofnode_valid(node)) {
128 debug("%s: no /config node?\n", __func__);
129 return;
130 }
131#ifdef CONFIG_FASTBOOT
132 if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
133 &gpio, GPIOD_IS_IN)) {
134 debug("%s: could not find a /config/st,fastboot-gpios\n",
135 __func__);
136 } else {
137 if (dm_gpio_get_value(&gpio)) {
138 puts("Fastboot key pressed, ");
139 boot_mode = BOOT_FASTBOOT;
140 }
141
142 dm_gpio_free(NULL, &gpio);
143 }
144#endif
145#ifdef CONFIG_CMD_STM32PROG
146 if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
147 &gpio, GPIOD_IS_IN)) {
148 debug("%s: could not find a /config/st,stm32prog-gpios\n",
149 __func__);
150 } else {
151 if (dm_gpio_get_value(&gpio)) {
152 puts("STM32Programmer key pressed, ");
153 boot_mode = BOOT_STM32PROG;
154 }
155 dm_gpio_free(NULL, &gpio);
156 }
157#endif
158
159 if (boot_mode != BOOT_NORMAL) {
160 puts("entering download mode...\n");
161 clrsetbits_le32(TAMP_BOOT_CONTEXT,
162 TAMP_BOOT_FORCED_MASK,
163 boot_mode);
164 }
165#endif
166}
167
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100168#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
Patrice Chotard4c834b92018-08-10 17:12:14 +0200169
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +0100170/* STMicroelectronics STUSB1600 Type-C controller */
171#define STUSB1600_CC_CONNECTION_STATUS 0x0E
172
173/* STUSB1600_CC_CONNECTION_STATUS bitfields */
174#define STUSB1600_CC_ATTACH BIT(0)
175
176static int stusb1600_init(struct udevice **dev_stusb1600)
177{
178 ofnode node;
179 struct udevice *dev, *bus;
180 int ret;
181 u32 chip_addr;
182
183 *dev_stusb1600 = NULL;
184
185 /* if node stusb1600 is present, means DK1 or DK2 board */
186 node = ofnode_by_compatible(ofnode_null(), "st,stusb1600");
187 if (!ofnode_valid(node))
188 return -ENODEV;
189
190 ret = ofnode_read_u32(node, "reg", &chip_addr);
191 if (ret)
192 return -EINVAL;
193
194 ret = uclass_get_device_by_ofnode(UCLASS_I2C, ofnode_get_parent(node),
195 &bus);
196 if (ret) {
197 printf("bus for stusb1600 not found\n");
198 return -ENODEV;
199 }
200
201 ret = dm_i2c_probe(bus, chip_addr, 0, &dev);
202 if (!ret)
203 *dev_stusb1600 = dev;
204
205 return ret;
206}
207
208static int stusb1600_cable_connected(struct udevice *dev)
209{
210 u8 status;
211
212 if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS, &status, 1))
213 return 0;
214
215 return status & STUSB1600_CC_ATTACH;
216}
217
218#include <usb/dwc2_udc.h>
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100219int g_dnl_board_usb_cable_connected(void)
Patrice Chotard4c834b92018-08-10 17:12:14 +0200220{
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +0100221 struct udevice *stusb1600;
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100222 struct udevice *dwc2_udc_otg;
Patrice Chotard4c834b92018-08-10 17:12:14 +0200223 int ret;
224
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +0100225 if (!stusb1600_init(&stusb1600))
226 return stusb1600_cable_connected(stusb1600);
227
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100228 ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC,
229 DM_GET_DRIVER(dwc2_udc_otg),
230 &dwc2_udc_otg);
231 if (!ret)
232 debug("dwc2_udc_otg init failed\n");
Patrice Chotard4c834b92018-08-10 17:12:14 +0200233
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100234 return dwc2_udc_B_session_valid(dwc2_udc_otg);
Patrice Chotard4c834b92018-08-10 17:12:14 +0200235}
Patrick Delaunayfb90fcf2019-09-13 15:24:17 +0200236
237#define STM32MP1_G_DNL_DFU_PRODUCT_NUM 0xdf11
238#define STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM 0x0afb
239
240int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
241{
242 if (!strcmp(name, "usb_dnl_dfu"))
243 put_unaligned(STM32MP1_G_DNL_DFU_PRODUCT_NUM, &dev->idProduct);
244 else if (!strcmp(name, "usb_dnl_fastboot"))
245 put_unaligned(STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM,
246 &dev->idProduct);
247 else
248 put_unaligned(CONFIG_USB_GADGET_PRODUCT_NUM, &dev->idProduct);
249
250 return 0;
251}
252
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100253#endif /* CONFIG_USB_GADGET */
Patrice Chotard4c834b92018-08-10 17:12:14 +0200254
Patrick Delaunaydd281082019-07-30 19:16:39 +0200255#ifdef CONFIG_LED
Patrice Chotard395f1292019-02-12 16:50:40 +0100256static int get_led(struct udevice **dev, char *led_string)
257{
258 char *led_name;
259 int ret;
260
261 led_name = fdtdec_get_config_string(gd->fdt_blob, led_string);
262 if (!led_name) {
263 pr_debug("%s: could not find %s config string\n",
264 __func__, led_string);
265 return -ENOENT;
266 }
267 ret = led_get_by_label(led_name, dev);
268 if (ret) {
269 debug("%s: get=%d\n", __func__, ret);
270 return ret;
271 }
272
273 return 0;
274}
275
276static int setup_led(enum led_state_t cmd)
277{
278 struct udevice *dev;
279 int ret;
280
281 ret = get_led(&dev, "u-boot,boot-led");
282 if (ret)
283 return ret;
284
285 ret = led_set_state(dev, cmd);
286 return ret;
287}
Patrick Delaunaydd281082019-07-30 19:16:39 +0200288#endif
289
290static void __maybe_unused led_error_blink(u32 nb_blink)
291{
292#ifdef CONFIG_LED
293 int ret;
294 struct udevice *led;
295 u32 i;
296#endif
297
298 if (!nb_blink)
299 return;
300
301#ifdef CONFIG_LED
302 ret = get_led(&led, "u-boot,error-led");
303 if (!ret) {
304 /* make u-boot,error-led blinking */
305 /* if U32_MAX and 125ms interval, for 17.02 years */
306 for (i = 0; i < 2 * nb_blink; i++) {
307 led_set_state(led, LEDST_TOGGLE);
308 mdelay(125);
309 WATCHDOG_RESET();
310 }
311 }
312#endif
313
314 /* infinite: the boot process must be stopped */
315 if (nb_blink == U32_MAX)
316 hang();
317}
Patrice Chotard395f1292019-02-12 16:50:40 +0100318
Patrick Delaunay41542472019-07-30 19:16:43 +0200319#ifdef CONFIG_ADC
Patrice Chotard395f1292019-02-12 16:50:40 +0100320static int board_check_usb_power(void)
321{
322 struct ofnode_phandle_args adc_args;
323 struct udevice *adc;
Patrice Chotard395f1292019-02-12 16:50:40 +0100324 ofnode node;
325 unsigned int raw;
326 int max_uV = 0;
Patrice Chotard28c064e2019-04-30 18:09:38 +0200327 int min_uV = USB_START_HIGH_THRESHOLD_UV;
Patrice Chotard395f1292019-02-12 16:50:40 +0100328 int ret, uV, adc_count;
Patrice Chotard28c064e2019-04-30 18:09:38 +0200329 u32 nb_blink;
330 u8 i;
Patrice Chotard395f1292019-02-12 16:50:40 +0100331 node = ofnode_path("/config");
332 if (!ofnode_valid(node)) {
333 debug("%s: no /config node?\n", __func__);
334 return -ENOENT;
335 }
336
337 /*
338 * Retrieve the ADC channels devices and get measurement
339 * for each of them
340 */
341 adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
342 "#io-channel-cells");
343 if (adc_count < 0) {
344 if (adc_count == -ENOENT)
345 return 0;
346
347 pr_err("%s: can't find adc channel (%d)\n", __func__,
348 adc_count);
349
350 return adc_count;
351 }
352
353 for (i = 0; i < adc_count; i++) {
354 if (ofnode_parse_phandle_with_args(node, "st,adc_usb_pd",
355 "#io-channel-cells", 0, i,
356 &adc_args)) {
357 pr_debug("%s: can't find /config/st,adc_usb_pd\n",
358 __func__);
359 return 0;
360 }
361
362 ret = uclass_get_device_by_ofnode(UCLASS_ADC, adc_args.node,
363 &adc);
364
365 if (ret) {
366 pr_err("%s: Can't get adc device(%d)\n", __func__,
367 ret);
368 return ret;
369 }
370
371 ret = adc_channel_single_shot(adc->name, adc_args.args[0],
372 &raw);
373 if (ret) {
374 pr_err("%s: single shot failed for %s[%d]!\n",
375 __func__, adc->name, adc_args.args[0]);
376 return ret;
377 }
378 /* Convert to uV */
379 if (!adc_raw_to_uV(adc, raw, &uV)) {
380 if (uV > max_uV)
381 max_uV = uV;
Patrice Chotard28c064e2019-04-30 18:09:38 +0200382 if (uV < min_uV)
383 min_uV = uV;
Patrice Chotard395f1292019-02-12 16:50:40 +0100384 pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__,
385 adc->name, adc_args.args[0], raw, uV);
386 } else {
387 pr_err("%s: Can't get uV value for %s[%d]\n",
388 __func__, adc->name, adc_args.args[0]);
389 }
390 }
391
392 /*
393 * If highest value is inside 1.23 Volts and 2.10 Volts, that means
394 * board is plugged on an USB-C 3A power supply and boot process can
395 * continue.
396 */
397 if (max_uV > USB_START_LOW_THRESHOLD_UV &&
Patrice Chotard28c064e2019-04-30 18:09:38 +0200398 max_uV <= USB_START_HIGH_THRESHOLD_UV &&
399 min_uV <= USB_LOW_THRESHOLD_UV)
Patrice Chotard395f1292019-02-12 16:50:40 +0100400 return 0;
401
Patrice Chotard28c064e2019-04-30 18:09:38 +0200402 pr_err("****************************************************\n");
Patrice Chotard395f1292019-02-12 16:50:40 +0100403
Patrice Chotard28c064e2019-04-30 18:09:38 +0200404 /*
405 * If highest and lowest value are either both below
406 * USB_LOW_THRESHOLD_UV or both above USB_LOW_THRESHOLD_UV, that
407 * means USB TYPE-C is in unattached mode, this is an issue, make
408 * u-boot,error-led blinking and stop boot process.
409 */
410 if ((max_uV > USB_LOW_THRESHOLD_UV &&
411 min_uV > USB_LOW_THRESHOLD_UV) ||
412 (max_uV <= USB_LOW_THRESHOLD_UV &&
413 min_uV <= USB_LOW_THRESHOLD_UV)) {
414 pr_err("* ERROR USB TYPE-C connection in unattached mode *\n");
415 pr_err("* Check that USB TYPE-C cable is correctly plugged *\n");
416 /* with 125ms interval, led will blink for 17.02 years ....*/
417 nb_blink = U32_MAX;
418 }
419
420 if (max_uV > USB_LOW_THRESHOLD_UV &&
421 max_uV <= USB_WARNING_LOW_THRESHOLD_UV &&
422 min_uV <= USB_LOW_THRESHOLD_UV) {
423 pr_err("* WARNING 500mA power supply detected *\n");
Patrice Chotard395f1292019-02-12 16:50:40 +0100424 nb_blink = 2;
Patrice Chotard28c064e2019-04-30 18:09:38 +0200425 }
426
427 if (max_uV > USB_WARNING_LOW_THRESHOLD_UV &&
428 max_uV <= USB_START_LOW_THRESHOLD_UV &&
429 min_uV <= USB_LOW_THRESHOLD_UV) {
430 pr_err("* WARNING 1.5mA power supply detected *\n");
Patrice Chotard395f1292019-02-12 16:50:40 +0100431 nb_blink = 3;
432 }
433
Patrice Chotard28c064e2019-04-30 18:09:38 +0200434 /*
435 * If highest value is above 2.15 Volts that means that the USB TypeC
436 * supplies more than 3 Amp, this is not compliant with TypeC specification
437 */
438 if (max_uV > USB_START_HIGH_THRESHOLD_UV) {
439 pr_err("* USB TYPE-C charger not compliant with *\n");
440 pr_err("* specification *\n");
441 pr_err("****************************************************\n\n");
442 /* with 125ms interval, led will blink for 17.02 years ....*/
443 nb_blink = U32_MAX;
444 } else {
445 pr_err("* Current too low, use a 3A power supply! *\n");
446 pr_err("****************************************************\n\n");
447 }
Patrice Chotard395f1292019-02-12 16:50:40 +0100448
Patrick Delaunaydd281082019-07-30 19:16:39 +0200449 led_error_blink(nb_blink);
Patrice Chotard395f1292019-02-12 16:50:40 +0100450
451 return 0;
452}
Patrick Delaunay41542472019-07-30 19:16:43 +0200453#endif /* CONFIG_ADC */
Patrice Chotard395f1292019-02-12 16:50:40 +0100454
Patrick Delaunay45459742019-02-27 17:01:24 +0100455static void sysconf_init(void)
456{
457#ifndef CONFIG_STM32MP1_TRUSTED
458 u8 *syscfg;
459#ifdef CONFIG_DM_REGULATOR
460 struct udevice *pwr_dev;
461 struct udevice *pwr_reg;
462 struct udevice *dev;
463 int ret;
464 u32 otp = 0;
465#endif
466 u32 bootr;
467
468 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
469
470 /* interconnect update : select master using the port 1 */
471 /* LTDC = AXI_M9 */
472 /* GPU = AXI_M8 */
473 /* today information is hardcoded in U-Boot */
474 writel(BIT(9), syscfg + SYSCFG_ICNR);
475
476 /* disable Pull-Down for boot pin connected to VDD */
477 bootr = readl(syscfg + SYSCFG_BOOTR);
478 bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
479 bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
480 writel(bootr, syscfg + SYSCFG_BOOTR);
481
482#ifdef CONFIG_DM_REGULATOR
483 /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
484 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
485 * The customer will have to disable this for low frequencies
486 * or if AFMUX is selected but the function not used, typically for
487 * TRACE. Otherwise, impact on power consumption.
488 *
489 * WARNING:
490 * enabling High Speed mode while VDD>2.7V
491 * with the OTP product_below_2v5 (OTP 18, BIT 13)
492 * erroneously set to 1 can damage the IC!
493 * => U-Boot set the register only if VDD < 2.7V (in DT)
494 * but this value need to be consistent with board design
495 */
Patrick Delaunay5e959ab2019-07-30 19:16:42 +0200496 ret = uclass_get_device_by_driver(UCLASS_PMIC,
497 DM_GET_DRIVER(stm32mp_pwr_pmic),
498 &pwr_dev);
Patrick Delaunay45459742019-02-27 17:01:24 +0100499 if (!ret) {
500 ret = uclass_get_device_by_driver(UCLASS_MISC,
501 DM_GET_DRIVER(stm32mp_bsec),
502 &dev);
503 if (ret) {
504 pr_err("Can't find stm32mp_bsec driver\n");
505 return;
506 }
507
508 ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4);
Patrick Delaunayff6618e2019-08-02 13:08:06 +0200509 if (ret > 0)
Patrick Delaunay45459742019-02-27 17:01:24 +0100510 otp = otp & BIT(13);
511
Patrick Delaunay5e959ab2019-07-30 19:16:42 +0200512 /* get VDD = vdd-supply */
513 ret = device_get_supply_regulator(pwr_dev, "vdd-supply",
Patrick Delaunay45459742019-02-27 17:01:24 +0100514 &pwr_reg);
515
516 /* check if VDD is Low Voltage */
517 if (!ret) {
518 if (regulator_get_value(pwr_reg) < 2700000) {
519 writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
520 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
521 SYSCFG_IOCTRLSETR_HSLVEN_ETH |
522 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
523 SYSCFG_IOCTRLSETR_HSLVEN_SPI,
524 syscfg + SYSCFG_IOCTRLSETR);
525
526 if (!otp)
527 pr_err("product_below_2v5=0: HSLVEN protected by HW\n");
528 } else {
529 if (otp)
530 pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
531 }
532 } else {
533 debug("VDD unknown");
534 }
535 }
536#endif
537
538 /* activate automatic I/O compensation
539 * warning: need to ensure CSI enabled and ready in clock driver
540 */
541 writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
542
543 while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
544 ;
545 clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
546#endif
547}
548
Patrick Delaunayd573e462019-07-30 19:16:38 +0200549#ifdef CONFIG_DM_REGULATOR
550/* Fix to make I2C1 usable on DK2 for touchscreen usage in kernel */
551static int dk2_i2c1_fix(void)
552{
553 ofnode node;
554 struct gpio_desc hdmi, audio;
555 int ret = 0;
556
557 node = ofnode_path("/soc/i2c@40012000/hdmi-transmitter@39");
558 if (!ofnode_valid(node)) {
559 pr_debug("%s: no hdmi-transmitter@39 ?\n", __func__);
560 return -ENOENT;
561 }
562
563 if (gpio_request_by_name_nodev(node, "reset-gpios", 0,
564 &hdmi, GPIOD_IS_OUT)) {
565 pr_debug("%s: could not find reset-gpios\n",
566 __func__);
567 return -ENOENT;
568 }
569
570 node = ofnode_path("/soc/i2c@40012000/cs42l51@4a");
571 if (!ofnode_valid(node)) {
572 pr_debug("%s: no cs42l51@4a ?\n", __func__);
573 return -ENOENT;
574 }
575
576 if (gpio_request_by_name_nodev(node, "reset-gpios", 0,
577 &audio, GPIOD_IS_OUT)) {
578 pr_debug("%s: could not find reset-gpios\n",
579 __func__);
580 return -ENOENT;
581 }
582
583 /* before power up, insure that HDMI and AUDIO IC is under reset */
584 ret = dm_gpio_set_value(&hdmi, 1);
585 if (ret) {
586 pr_err("%s: can't set_value for hdmi_nrst gpio", __func__);
587 goto error;
588 }
589 ret = dm_gpio_set_value(&audio, 1);
590 if (ret) {
591 pr_err("%s: can't set_value for audio_nrst gpio", __func__);
592 goto error;
593 }
594
595 /* power-up audio IC */
596 regulator_autoset_by_name("v1v8_audio", NULL);
597
598 /* power-up HDMI IC */
599 regulator_autoset_by_name("v1v2_hdmi", NULL);
600 regulator_autoset_by_name("v3v3_hdmi", NULL);
601
602error:
603 return ret;
604}
605
606static bool board_is_dk2(void)
607{
608 if (CONFIG_IS_ENABLED(TARGET_STM32MP157C_DK2) &&
609 of_machine_is_compatible("st,stm32mp157c-dk2"))
610 return true;
611
612 return false;
613}
614#endif
615
Patrick Delaunayf8598d92018-03-12 10:46:18 +0100616/* board dependent setup after realloc */
617int board_init(void)
618{
Patrice Chotard8b4afe82019-03-11 11:13:17 +0100619 struct udevice *dev;
620
Patrick Delaunayf8598d92018-03-12 10:46:18 +0100621 /* address of boot parameters */
622 gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
623
Patrice Chotard8b4afe82019-03-11 11:13:17 +0100624 /* probe all PINCTRL for hog */
625 for (uclass_first_device(UCLASS_PINCTRL, &dev);
626 dev;
627 uclass_next_device(&dev)) {
628 pr_debug("probe pincontrol = %s\n", dev->name);
629 }
630
Patrick Delaunay9a2ba282019-02-27 17:01:20 +0100631 board_key_check();
632
Patrick Delaunayf59ad452019-07-05 17:20:09 +0200633#ifdef CONFIG_DM_REGULATOR
Patrick Delaunayd573e462019-07-30 19:16:38 +0200634 if (board_is_dk2())
635 dk2_i2c1_fix();
636
Patrick Delaunayf59ad452019-07-05 17:20:09 +0200637 regulators_enable_boot_on(_DEBUG);
638#endif
639
Patrick Delaunay45459742019-02-27 17:01:24 +0100640 sysconf_init();
641
Patrick Delaunay4616ff42019-07-30 19:16:40 +0200642 if (CONFIG_IS_ENABLED(CONFIG_LED))
Patrick Delaunay1f5118b2018-07-27 16:37:08 +0200643 led_default_state();
644
Patrick Delaunayf8598d92018-03-12 10:46:18 +0100645 return 0;
646}
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100647
648int board_late_init(void)
649{
Patrick Delaunay55f9cd22019-07-30 19:16:41 +0200650 char *boot_device;
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100651#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
652 const void *fdt_compat;
653 int fdt_compat_len;
Patrick Delaunay8b8b3d62019-07-30 19:16:37 +0200654 int ret;
655 u32 otp;
656 struct udevice *dev;
657 char buf[10];
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100658
659 fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
660 &fdt_compat_len);
661 if (fdt_compat && fdt_compat_len) {
662 if (strncmp(fdt_compat, "st,", 3) != 0)
663 env_set("board_name", fdt_compat);
664 else
665 env_set("board_name", fdt_compat + 3);
666 }
Patrick Delaunay8b8b3d62019-07-30 19:16:37 +0200667 ret = uclass_get_device_by_driver(UCLASS_MISC,
668 DM_GET_DRIVER(stm32mp_bsec),
669 &dev);
670
671 if (!ret)
672 ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
673 &otp, sizeof(otp));
674 if (!ret && otp) {
675 snprintf(buf, sizeof(buf), "0x%04x", otp >> 16);
676 env_set("board_id", buf);
677
678 snprintf(buf, sizeof(buf), "0x%04x",
679 ((otp >> 8) & 0xF) - 1 + 0xA);
680 env_set("board_rev", buf);
681 }
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100682#endif
683
Patrick Delaunay41542472019-07-30 19:16:43 +0200684#ifdef CONFIG_ADC
Patrice Chotard395f1292019-02-12 16:50:40 +0100685 /* for DK1/DK2 boards */
686 board_check_usb_power();
Patrick Delaunay41542472019-07-30 19:16:43 +0200687#endif /* CONFIG_ADC */
Patrice Chotard395f1292019-02-12 16:50:40 +0100688
Patrick Delaunay55f9cd22019-07-30 19:16:41 +0200689 /* Check the boot-source to disable bootdelay */
690 boot_device = env_get("boot_device");
691 if (!strcmp(boot_device, "serial") || !strcmp(boot_device, "usb"))
692 env_set("bootdelay", "0");
693
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100694 return 0;
695}
Patrice Chotard395f1292019-02-12 16:50:40 +0100696
697void board_quiesce_devices(void)
698{
Patrick Delaunay4616ff42019-07-30 19:16:40 +0200699#ifdef CONFIG_LED
Patrice Chotard395f1292019-02-12 16:50:40 +0100700 setup_led(LEDST_OFF);
Patrick Delaunay4616ff42019-07-30 19:16:40 +0200701#endif
Patrice Chotard395f1292019-02-12 16:50:40 +0100702}
Patrice Chotard87471642019-05-02 18:07:14 +0200703
Patrick Delaunay53e3d522019-08-01 11:29:03 +0200704/* eth init function : weak called in eqos driver */
705int board_interface_eth_init(struct udevice *dev,
706 phy_interface_t interface_type)
Christophe Roullieredacf262019-05-17 15:08:43 +0200707{
708 u8 *syscfg;
709 u32 value;
Patrick Delaunay53e3d522019-08-01 11:29:03 +0200710 bool eth_clk_sel_reg = false;
711 bool eth_ref_clk_sel_reg = false;
712
713 /* Gigabit Ethernet 125MHz clock selection. */
714 eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
715
716 /* Ethernet 50Mhz RMII clock selection */
717 eth_ref_clk_sel_reg =
718 dev_read_bool(dev, "st,eth_ref_clk_sel");
Christophe Roullieredacf262019-05-17 15:08:43 +0200719
720 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
721
722 if (!syscfg)
723 return -ENODEV;
724
725 switch (interface_type) {
726 case PHY_INTERFACE_MODE_MII:
727 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
728 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
729 debug("%s: PHY_INTERFACE_MODE_MII\n", __func__);
730 break;
731 case PHY_INTERFACE_MODE_GMII:
732 if (eth_clk_sel_reg)
733 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
734 SYSCFG_PMCSETR_ETH_CLK_SEL;
735 else
736 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII;
737 debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__);
738 break;
739 case PHY_INTERFACE_MODE_RMII:
740 if (eth_ref_clk_sel_reg)
741 value = SYSCFG_PMCSETR_ETH_SEL_RMII |
742 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
743 else
744 value = SYSCFG_PMCSETR_ETH_SEL_RMII;
745 debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__);
746 break;
747 case PHY_INTERFACE_MODE_RGMII:
748 case PHY_INTERFACE_MODE_RGMII_ID:
749 case PHY_INTERFACE_MODE_RGMII_RXID:
750 case PHY_INTERFACE_MODE_RGMII_TXID:
751 if (eth_clk_sel_reg)
752 value = SYSCFG_PMCSETR_ETH_SEL_RGMII |
753 SYSCFG_PMCSETR_ETH_CLK_SEL;
754 else
755 value = SYSCFG_PMCSETR_ETH_SEL_RGMII;
756 debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__);
757 break;
758 default:
759 debug("%s: Do not manage %d interface\n",
760 __func__, interface_type);
761 /* Do not manage others interfaces */
762 return -EINVAL;
763 }
764
765 /* clear and set ETH configuration bits */
766 writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII |
767 SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL,
768 syscfg + SYSCFG_PMCCLRR);
769 writel(value, syscfg + SYSCFG_PMCSETR);
770
771 return 0;
772}
773
Patrice Chotard8f24b1a2019-05-02 18:28:05 +0200774enum env_location env_get_location(enum env_operation op, int prio)
775{
776 u32 bootmode = get_bootmode();
777
778 if (prio)
779 return ENVL_UNKNOWN;
780
781 switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
782#ifdef CONFIG_ENV_IS_IN_EXT4
783 case BOOT_FLASH_SD:
784 case BOOT_FLASH_EMMC:
785 return ENVL_EXT4;
786#endif
787#ifdef CONFIG_ENV_IS_IN_UBI
788 case BOOT_FLASH_NAND:
789 return ENVL_UBI;
790#endif
Patrice Chotarde5c38fd2019-05-09 14:25:36 +0200791#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
792 case BOOT_FLASH_NOR:
793 return ENVL_SPI_FLASH;
794#endif
Patrice Chotard8f24b1a2019-05-02 18:28:05 +0200795 default:
796 return ENVL_NOWHERE;
797 }
798}
799
Patrice Chotard7f90cd62019-05-02 18:36:01 +0200800#if defined(CONFIG_ENV_IS_IN_EXT4)
801const char *env_ext4_get_intf(void)
802{
803 u32 bootmode = get_bootmode();
804
805 switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
806 case BOOT_FLASH_SD:
807 case BOOT_FLASH_EMMC:
808 return "mmc";
809 default:
810 return "";
811 }
812}
813
814const char *env_ext4_get_dev_part(void)
815{
816 static char *const dev_part[] = {"0:auto", "1:auto", "2:auto"};
817 u32 bootmode = get_bootmode();
818
819 return dev_part[(bootmode & TAMP_BOOT_INSTANCE_MASK) - 1];
820}
821#endif
822
Patrice Chotard87471642019-05-02 18:07:14 +0200823#ifdef CONFIG_SYS_MTDPARTS_RUNTIME
824
825#define MTDPARTS_LEN 256
826#define MTDIDS_LEN 128
827
828/**
829 * The mtdparts_nand0 and mtdparts_nor0 variable tends to be long.
830 * If we need to access it before the env is relocated, then we need
831 * to use our own stack buffer. gd->env_buf will be too small.
832 *
833 * @param buf temporary buffer pointer MTDPARTS_LEN long
834 * @return mtdparts variable string, NULL if not found
835 */
836static const char *env_get_mtdparts(const char *str, char *buf)
837{
838 if (gd->flags & GD_FLG_ENV_READY)
839 return env_get(str);
840 if (env_get_f(str, buf, MTDPARTS_LEN) != -1)
841 return buf;
842
843 return NULL;
844}
845
846/**
847 * update the variables "mtdids" and "mtdparts" with content of mtdparts_<dev>
848 */
849static void board_get_mtdparts(const char *dev,
850 char *mtdids,
851 char *mtdparts)
852{
853 char env_name[32] = "mtdparts_";
854 char tmp_mtdparts[MTDPARTS_LEN];
855 const char *tmp;
856
857 /* name of env variable to read = mtdparts_<dev> */
858 strcat(env_name, dev);
859 tmp = env_get_mtdparts(env_name, tmp_mtdparts);
860 if (tmp) {
861 /* mtdids: "<dev>=<dev>, ...." */
862 if (mtdids[0] != '\0')
863 strcat(mtdids, ",");
864 strcat(mtdids, dev);
865 strcat(mtdids, "=");
866 strcat(mtdids, dev);
867
868 /* mtdparts: "mtdparts=<dev>:<mtdparts_<dev>>;..." */
869 if (mtdparts[0] != '\0')
870 strncat(mtdparts, ";", MTDPARTS_LEN);
871 else
872 strcat(mtdparts, "mtdparts=");
873 strncat(mtdparts, dev, MTDPARTS_LEN);
874 strncat(mtdparts, ":", MTDPARTS_LEN);
875 strncat(mtdparts, tmp, MTDPARTS_LEN);
876 }
877}
878
879void board_mtdparts_default(const char **mtdids, const char **mtdparts)
880{
881 struct udevice *dev;
882 static char parts[2 * MTDPARTS_LEN + 1];
883 static char ids[MTDIDS_LEN + 1];
884 static bool mtd_initialized;
885
886 if (mtd_initialized) {
887 *mtdids = ids;
888 *mtdparts = parts;
889 return;
890 }
891
892 memset(parts, 0, sizeof(parts));
893 memset(ids, 0, sizeof(ids));
894
895 if (!uclass_get_device(UCLASS_MTD, 0, &dev))
896 board_get_mtdparts("nand0", ids, parts);
897
898 if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
899 board_get_mtdparts("nor0", ids, parts);
900
901 mtd_initialized = true;
902 *mtdids = ids;
903 *mtdparts = parts;
904 debug("%s:mtdids=%s & mtdparts=%s\n", __func__, ids, parts);
905}
906#endif
Patrick Delaunaye81f8d12019-07-02 13:26:07 +0200907
908#if defined(CONFIG_OF_BOARD_SETUP)
909int ft_board_setup(void *blob, bd_t *bd)
910{
911#ifdef CONFIG_FDT_FIXUP_PARTITIONS
912 struct node_info nodes[] = {
913 { "st,stm32f469-qspi", MTD_DEV_TYPE_NOR, },
914 { "st,stm32mp15-fmc2", MTD_DEV_TYPE_NAND, },
915 };
916 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
917#endif
918
919 return 0;
920}
921#endif
Patrick Delaunaya68ae8d2019-08-02 15:07:20 +0200922
923static void board_copro_image_process(ulong fw_image, size_t fw_size)
924{
925 int ret, id = 0; /* Copro id fixed to 0 as only one coproc on mp1 */
926
927 if (!rproc_is_initialized())
928 if (rproc_init()) {
929 printf("Remote Processor %d initialization failed\n",
930 id);
931 return;
932 }
933
934 ret = rproc_load(id, fw_image, fw_size);
935 printf("Load Remote Processor %d with data@addr=0x%08lx %u bytes:%s\n",
936 id, fw_image, fw_size, ret ? " Failed!" : " Success!");
937
938 if (!ret) {
939 rproc_start(id);
940 env_set("copro_state", "booted");
941 }
942}
943
944U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process);