blob: 18f9b848765576fcad82661b461e938df53af35a [file] [log] [blame]
Tom Rini8b0c8a12018-05-06 18:27:01 -04001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
Patrick Delaunay8eb3b1e2018-03-12 10:46:18 +01002/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
Patrick Delaunay8eb3b1e2018-03-12 10:46:18 +01004 */
Patrice Chotard879cde52019-02-12 16:50:40 +01005#include <common.h>
6#include <adc.h>
Patrick Delaunay500401f2019-06-21 15:26:40 +02007#include <bootm.h>
Patrice Chotard204079b2018-08-10 17:12:14 +02008#include <clk.h>
Patrick Delaunay266bf102019-07-30 19:16:44 +02009#include <config.h>
Patrice Chotard204079b2018-08-10 17:12:14 +020010#include <dm.h>
Simon Glassdb229612019-08-01 09:46:42 -060011#include <env.h>
Simon Glass9d1f6192019-08-02 09:44:25 -060012#include <env_internal.h>
Patrick Delaunay58bc0cd2019-03-29 15:42:23 +010013#include <g_dnl.h>
Patrice Chotard204079b2018-08-10 17:12:14 +020014#include <generic-phy.h>
Patrick Delaunay7f3384d2019-03-29 15:42:24 +010015#include <i2c.h>
Patrick Delaunay92dc1022019-02-12 11:44:41 +010016#include <led.h>
17#include <misc.h>
Patrick Delaunayde98cbf2019-07-02 13:26:07 +020018#include <mtd.h>
19#include <mtd_node.h>
Patrick Delaunaybff66f92019-08-01 11:29:03 +020020#include <netdev.h>
Patrice Chotard204079b2018-08-10 17:12:14 +020021#include <phy.h>
Patrick Delaunayc17d7252019-08-02 15:07:20 +020022#include <remoteproc.h>
Patrice Chotard204079b2018-08-10 17:12:14 +020023#include <reset.h>
Patrick Delaunay4ace1d12019-02-27 17:01:24 +010024#include <syscon.h>
Patrick Delaunay7f3384d2019-03-29 15:42:24 +010025#include <usb.h>
Patrick Delaunayae0931d02019-07-30 19:16:39 +020026#include <watchdog.h>
Patrice Chotard204079b2018-08-10 17:12:14 +020027#include <asm/io.h>
Patrick Delaunayf2a7b872019-02-27 17:01:18 +010028#include <asm/gpio.h>
Patrick Delaunay4ace1d12019-02-27 17:01:24 +010029#include <asm/arch/stm32.h>
Patrice Chotarddad97bf2019-05-02 18:36:01 +020030#include <asm/arch/sys_proto.h>
Patrick Delaunayde98cbf2019-07-02 13:26:07 +020031#include <jffs2/load_kernel.h>
Patrice Chotard204079b2018-08-10 17:12:14 +020032#include <power/regulator.h>
Patrick Delaunay7f3384d2019-03-29 15:42:24 +010033#include <usb/dwc2_udc.h>
Patrick Delaunay8eb3b1e2018-03-12 10:46:18 +010034
Patrick Delaunay4ace1d12019-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 Roullier69ac3f52019-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 Delaunay4ace1d12019-02-27 17:01:24 +010067
Patrick Delaunay8eb3b1e2018-03-12 10:46:18 +010068/*
69 * Get a global data pointer
70 */
71DECLARE_GLOBAL_DATA_PTR;
72
Patrice Chotardcded32f2019-04-30 18:09:38 +020073#define USB_LOW_THRESHOLD_UV 200000
Patrice Chotard879cde52019-02-12 16:50:40 +010074#define USB_WARNING_LOW_THRESHOLD_UV 660000
75#define USB_START_LOW_THRESHOLD_UV 1230000
Patrice Chotardcded32f2019-04-30 18:09:38 +020076#define USB_START_HIGH_THRESHOLD_UV 2150000
Patrice Chotard879cde52019-02-12 16:50:40 +010077
Patrick Delaunay92dc1022019-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 Delaunayff215a42019-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 Delaunay92dc1022019-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 Delaunaydcb89fd2019-08-02 13:08:05 +0200108 if (ret > 0 && otp) {
Patrick Delaunay92dc1022019-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 Delaunay008d3c32019-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 Delaunay58bc0cd2019-03-29 15:42:23 +0100168#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
Patrice Chotard204079b2018-08-10 17:12:14 +0200169
Patrick Delaunay7f3384d2019-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 Delaunay58bc0cd2019-03-29 15:42:23 +0100219int g_dnl_board_usb_cable_connected(void)
Patrice Chotard204079b2018-08-10 17:12:14 +0200220{
Patrick Delaunay7f3384d2019-03-29 15:42:24 +0100221 struct udevice *stusb1600;
Patrick Delaunay58bc0cd2019-03-29 15:42:23 +0100222 struct udevice *dwc2_udc_otg;
Patrice Chotard204079b2018-08-10 17:12:14 +0200223 int ret;
224
Patrick Delaunay7f3384d2019-03-29 15:42:24 +0100225 if (!stusb1600_init(&stusb1600))
226 return stusb1600_cable_connected(stusb1600);
227
Patrick Delaunay58bc0cd2019-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 Chotard204079b2018-08-10 17:12:14 +0200233
Patrick Delaunay58bc0cd2019-03-29 15:42:23 +0100234 return dwc2_udc_B_session_valid(dwc2_udc_otg);
Patrice Chotard879cde52019-02-12 16:50:40 +0100235}
Patrick Delaunay58bc0cd2019-03-29 15:42:23 +0100236#endif /* CONFIG_USB_GADGET */
Patrice Chotard879cde52019-02-12 16:50:40 +0100237
Patrick Delaunayae0931d02019-07-30 19:16:39 +0200238#ifdef CONFIG_LED
Patrice Chotard879cde52019-02-12 16:50:40 +0100239static int get_led(struct udevice **dev, char *led_string)
240{
241 char *led_name;
242 int ret;
243
244 led_name = fdtdec_get_config_string(gd->fdt_blob, led_string);
245 if (!led_name) {
246 pr_debug("%s: could not find %s config string\n",
247 __func__, led_string);
248 return -ENOENT;
249 }
250 ret = led_get_by_label(led_name, dev);
251 if (ret) {
252 debug("%s: get=%d\n", __func__, ret);
253 return ret;
254 }
255
256 return 0;
257}
258
259static int setup_led(enum led_state_t cmd)
260{
261 struct udevice *dev;
262 int ret;
263
264 ret = get_led(&dev, "u-boot,boot-led");
265 if (ret)
266 return ret;
267
268 ret = led_set_state(dev, cmd);
Patrice Chotard204079b2018-08-10 17:12:14 +0200269 return ret;
270}
Patrick Delaunayae0931d02019-07-30 19:16:39 +0200271#endif
272
273static void __maybe_unused led_error_blink(u32 nb_blink)
274{
275#ifdef CONFIG_LED
276 int ret;
277 struct udevice *led;
278 u32 i;
279#endif
280
281 if (!nb_blink)
282 return;
283
284#ifdef CONFIG_LED
285 ret = get_led(&led, "u-boot,error-led");
286 if (!ret) {
287 /* make u-boot,error-led blinking */
288 /* if U32_MAX and 125ms interval, for 17.02 years */
289 for (i = 0; i < 2 * nb_blink; i++) {
290 led_set_state(led, LEDST_TOGGLE);
291 mdelay(125);
292 WATCHDOG_RESET();
293 }
294 }
295#endif
296
297 /* infinite: the boot process must be stopped */
298 if (nb_blink == U32_MAX)
299 hang();
300}
Patrice Chotard204079b2018-08-10 17:12:14 +0200301
Patrick Delaunayf6626e72019-07-30 19:16:43 +0200302#ifdef CONFIG_ADC
Patrice Chotard879cde52019-02-12 16:50:40 +0100303static int board_check_usb_power(void)
304{
305 struct ofnode_phandle_args adc_args;
306 struct udevice *adc;
Patrice Chotard879cde52019-02-12 16:50:40 +0100307 ofnode node;
308 unsigned int raw;
309 int max_uV = 0;
Patrice Chotardcded32f2019-04-30 18:09:38 +0200310 int min_uV = USB_START_HIGH_THRESHOLD_UV;
Patrice Chotard879cde52019-02-12 16:50:40 +0100311 int ret, uV, adc_count;
Patrice Chotardcded32f2019-04-30 18:09:38 +0200312 u32 nb_blink;
313 u8 i;
Patrice Chotard879cde52019-02-12 16:50:40 +0100314 node = ofnode_path("/config");
315 if (!ofnode_valid(node)) {
316 debug("%s: no /config node?\n", __func__);
317 return -ENOENT;
318 }
319
320 /*
321 * Retrieve the ADC channels devices and get measurement
322 * for each of them
323 */
324 adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
325 "#io-channel-cells");
326 if (adc_count < 0) {
327 if (adc_count == -ENOENT)
328 return 0;
329
330 pr_err("%s: can't find adc channel (%d)\n", __func__,
331 adc_count);
332
333 return adc_count;
334 }
335
336 for (i = 0; i < adc_count; i++) {
337 if (ofnode_parse_phandle_with_args(node, "st,adc_usb_pd",
338 "#io-channel-cells", 0, i,
339 &adc_args)) {
340 pr_debug("%s: can't find /config/st,adc_usb_pd\n",
341 __func__);
342 return 0;
343 }
344
345 ret = uclass_get_device_by_ofnode(UCLASS_ADC, adc_args.node,
346 &adc);
347
348 if (ret) {
349 pr_err("%s: Can't get adc device(%d)\n", __func__,
350 ret);
351 return ret;
352 }
353
354 ret = adc_channel_single_shot(adc->name, adc_args.args[0],
355 &raw);
356 if (ret) {
357 pr_err("%s: single shot failed for %s[%d]!\n",
358 __func__, adc->name, adc_args.args[0]);
359 return ret;
360 }
361 /* Convert to uV */
362 if (!adc_raw_to_uV(adc, raw, &uV)) {
363 if (uV > max_uV)
364 max_uV = uV;
Patrice Chotardcded32f2019-04-30 18:09:38 +0200365 if (uV < min_uV)
366 min_uV = uV;
Patrice Chotard879cde52019-02-12 16:50:40 +0100367 pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__,
368 adc->name, adc_args.args[0], raw, uV);
369 } else {
370 pr_err("%s: Can't get uV value for %s[%d]\n",
371 __func__, adc->name, adc_args.args[0]);
372 }
373 }
374
375 /*
376 * If highest value is inside 1.23 Volts and 2.10 Volts, that means
377 * board is plugged on an USB-C 3A power supply and boot process can
378 * continue.
379 */
380 if (max_uV > USB_START_LOW_THRESHOLD_UV &&
Patrice Chotardcded32f2019-04-30 18:09:38 +0200381 max_uV <= USB_START_HIGH_THRESHOLD_UV &&
382 min_uV <= USB_LOW_THRESHOLD_UV)
Patrice Chotard879cde52019-02-12 16:50:40 +0100383 return 0;
384
Patrice Chotardcded32f2019-04-30 18:09:38 +0200385 pr_err("****************************************************\n");
386
387 /*
388 * If highest and lowest value are either both below
389 * USB_LOW_THRESHOLD_UV or both above USB_LOW_THRESHOLD_UV, that
390 * means USB TYPE-C is in unattached mode, this is an issue, make
391 * u-boot,error-led blinking and stop boot process.
392 */
393 if ((max_uV > USB_LOW_THRESHOLD_UV &&
394 min_uV > USB_LOW_THRESHOLD_UV) ||
395 (max_uV <= USB_LOW_THRESHOLD_UV &&
396 min_uV <= USB_LOW_THRESHOLD_UV)) {
397 pr_err("* ERROR USB TYPE-C connection in unattached mode *\n");
398 pr_err("* Check that USB TYPE-C cable is correctly plugged *\n");
399 /* with 125ms interval, led will blink for 17.02 years ....*/
400 nb_blink = U32_MAX;
401 }
Patrice Chotard879cde52019-02-12 16:50:40 +0100402
Patrice Chotardcded32f2019-04-30 18:09:38 +0200403 if (max_uV > USB_LOW_THRESHOLD_UV &&
404 max_uV <= USB_WARNING_LOW_THRESHOLD_UV &&
405 min_uV <= USB_LOW_THRESHOLD_UV) {
406 pr_err("* WARNING 500mA power supply detected *\n");
Patrice Chotard879cde52019-02-12 16:50:40 +0100407 nb_blink = 2;
Patrice Chotardcded32f2019-04-30 18:09:38 +0200408 }
409
410 if (max_uV > USB_WARNING_LOW_THRESHOLD_UV &&
411 max_uV <= USB_START_LOW_THRESHOLD_UV &&
412 min_uV <= USB_LOW_THRESHOLD_UV) {
413 pr_err("* WARNING 1.5mA power supply detected *\n");
Patrice Chotard879cde52019-02-12 16:50:40 +0100414 nb_blink = 3;
415 }
416
Patrice Chotardcded32f2019-04-30 18:09:38 +0200417 /*
418 * If highest value is above 2.15 Volts that means that the USB TypeC
419 * supplies more than 3 Amp, this is not compliant with TypeC specification
420 */
421 if (max_uV > USB_START_HIGH_THRESHOLD_UV) {
422 pr_err("* USB TYPE-C charger not compliant with *\n");
423 pr_err("* specification *\n");
424 pr_err("****************************************************\n\n");
425 /* with 125ms interval, led will blink for 17.02 years ....*/
426 nb_blink = U32_MAX;
427 } else {
428 pr_err("* Current too low, use a 3A power supply! *\n");
429 pr_err("****************************************************\n\n");
430 }
Patrice Chotard879cde52019-02-12 16:50:40 +0100431
Patrick Delaunayae0931d02019-07-30 19:16:39 +0200432 led_error_blink(nb_blink);
Patrice Chotard879cde52019-02-12 16:50:40 +0100433
434 return 0;
435}
Patrick Delaunayf6626e72019-07-30 19:16:43 +0200436#endif /* CONFIG_ADC */
Patrice Chotard879cde52019-02-12 16:50:40 +0100437
Patrick Delaunay4ace1d12019-02-27 17:01:24 +0100438static void sysconf_init(void)
439{
440#ifndef CONFIG_STM32MP1_TRUSTED
441 u8 *syscfg;
442#ifdef CONFIG_DM_REGULATOR
443 struct udevice *pwr_dev;
444 struct udevice *pwr_reg;
445 struct udevice *dev;
446 int ret;
447 u32 otp = 0;
448#endif
449 u32 bootr;
450
451 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
452
453 /* interconnect update : select master using the port 1 */
454 /* LTDC = AXI_M9 */
455 /* GPU = AXI_M8 */
456 /* today information is hardcoded in U-Boot */
457 writel(BIT(9), syscfg + SYSCFG_ICNR);
458
459 /* disable Pull-Down for boot pin connected to VDD */
460 bootr = readl(syscfg + SYSCFG_BOOTR);
461 bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
462 bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
463 writel(bootr, syscfg + SYSCFG_BOOTR);
464
465#ifdef CONFIG_DM_REGULATOR
466 /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
467 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
468 * The customer will have to disable this for low frequencies
469 * or if AFMUX is selected but the function not used, typically for
470 * TRACE. Otherwise, impact on power consumption.
471 *
472 * WARNING:
473 * enabling High Speed mode while VDD>2.7V
474 * with the OTP product_below_2v5 (OTP 18, BIT 13)
475 * erroneously set to 1 can damage the IC!
476 * => U-Boot set the register only if VDD < 2.7V (in DT)
477 * but this value need to be consistent with board design
478 */
Patrick Delaunay6b2baa02019-07-30 19:16:42 +0200479 ret = uclass_get_device_by_driver(UCLASS_PMIC,
480 DM_GET_DRIVER(stm32mp_pwr_pmic),
481 &pwr_dev);
Patrick Delaunay4ace1d12019-02-27 17:01:24 +0100482 if (!ret) {
483 ret = uclass_get_device_by_driver(UCLASS_MISC,
484 DM_GET_DRIVER(stm32mp_bsec),
485 &dev);
486 if (ret) {
487 pr_err("Can't find stm32mp_bsec driver\n");
488 return;
489 }
490
491 ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4);
Patrick Delaunayceb82e32019-08-02 13:08:06 +0200492 if (ret > 0)
Patrick Delaunay4ace1d12019-02-27 17:01:24 +0100493 otp = otp & BIT(13);
494
Patrick Delaunay6b2baa02019-07-30 19:16:42 +0200495 /* get VDD = vdd-supply */
496 ret = device_get_supply_regulator(pwr_dev, "vdd-supply",
Patrick Delaunay4ace1d12019-02-27 17:01:24 +0100497 &pwr_reg);
498
499 /* check if VDD is Low Voltage */
500 if (!ret) {
501 if (regulator_get_value(pwr_reg) < 2700000) {
502 writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
503 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
504 SYSCFG_IOCTRLSETR_HSLVEN_ETH |
505 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
506 SYSCFG_IOCTRLSETR_HSLVEN_SPI,
507 syscfg + SYSCFG_IOCTRLSETR);
508
509 if (!otp)
510 pr_err("product_below_2v5=0: HSLVEN protected by HW\n");
511 } else {
512 if (otp)
513 pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
514 }
515 } else {
516 debug("VDD unknown");
517 }
518 }
519#endif
520
521 /* activate automatic I/O compensation
522 * warning: need to ensure CSI enabled and ready in clock driver
523 */
524 writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
525
526 while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
527 ;
528 clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
529#endif
530}
531
Patrick Delaunay9f76fdf2019-07-30 19:16:38 +0200532#ifdef CONFIG_DM_REGULATOR
533/* Fix to make I2C1 usable on DK2 for touchscreen usage in kernel */
534static int dk2_i2c1_fix(void)
535{
536 ofnode node;
537 struct gpio_desc hdmi, audio;
538 int ret = 0;
539
540 node = ofnode_path("/soc/i2c@40012000/hdmi-transmitter@39");
541 if (!ofnode_valid(node)) {
542 pr_debug("%s: no hdmi-transmitter@39 ?\n", __func__);
543 return -ENOENT;
544 }
545
546 if (gpio_request_by_name_nodev(node, "reset-gpios", 0,
547 &hdmi, GPIOD_IS_OUT)) {
548 pr_debug("%s: could not find reset-gpios\n",
549 __func__);
550 return -ENOENT;
551 }
552
553 node = ofnode_path("/soc/i2c@40012000/cs42l51@4a");
554 if (!ofnode_valid(node)) {
555 pr_debug("%s: no cs42l51@4a ?\n", __func__);
556 return -ENOENT;
557 }
558
559 if (gpio_request_by_name_nodev(node, "reset-gpios", 0,
560 &audio, GPIOD_IS_OUT)) {
561 pr_debug("%s: could not find reset-gpios\n",
562 __func__);
563 return -ENOENT;
564 }
565
566 /* before power up, insure that HDMI and AUDIO IC is under reset */
567 ret = dm_gpio_set_value(&hdmi, 1);
568 if (ret) {
569 pr_err("%s: can't set_value for hdmi_nrst gpio", __func__);
570 goto error;
571 }
572 ret = dm_gpio_set_value(&audio, 1);
573 if (ret) {
574 pr_err("%s: can't set_value for audio_nrst gpio", __func__);
575 goto error;
576 }
577
578 /* power-up audio IC */
579 regulator_autoset_by_name("v1v8_audio", NULL);
580
581 /* power-up HDMI IC */
582 regulator_autoset_by_name("v1v2_hdmi", NULL);
583 regulator_autoset_by_name("v3v3_hdmi", NULL);
584
585error:
586 return ret;
587}
588
589static bool board_is_dk2(void)
590{
591 if (CONFIG_IS_ENABLED(TARGET_STM32MP157C_DK2) &&
592 of_machine_is_compatible("st,stm32mp157c-dk2"))
593 return true;
594
595 return false;
596}
597#endif
598
Patrick Delaunay8eb3b1e2018-03-12 10:46:18 +0100599/* board dependent setup after realloc */
600int board_init(void)
601{
Patrice Chotard972723a2019-03-11 11:13:17 +0100602 struct udevice *dev;
603
Patrick Delaunay8eb3b1e2018-03-12 10:46:18 +0100604 /* address of boot parameters */
605 gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
606
Patrice Chotard972723a2019-03-11 11:13:17 +0100607 /* probe all PINCTRL for hog */
608 for (uclass_first_device(UCLASS_PINCTRL, &dev);
609 dev;
610 uclass_next_device(&dev)) {
611 pr_debug("probe pincontrol = %s\n", dev->name);
612 }
613
Patrick Delaunay008d3c32019-02-27 17:01:20 +0100614 board_key_check();
615
Patrick Delaunay6519e442019-07-05 17:20:09 +0200616#ifdef CONFIG_DM_REGULATOR
Patrick Delaunay9f76fdf2019-07-30 19:16:38 +0200617 if (board_is_dk2())
618 dk2_i2c1_fix();
619
Patrick Delaunay6519e442019-07-05 17:20:09 +0200620 regulators_enable_boot_on(_DEBUG);
621#endif
622
Patrick Delaunay4ace1d12019-02-27 17:01:24 +0100623 sysconf_init();
624
Patrick Delaunay7a3e4422019-07-30 19:16:40 +0200625 if (CONFIG_IS_ENABLED(CONFIG_LED))
Patrick Delaunay36e3d112018-07-27 16:37:08 +0200626 led_default_state();
627
Patrick Delaunay8eb3b1e2018-03-12 10:46:18 +0100628 return 0;
629}
Patrick Delaunayd70e3f82019-02-27 17:01:11 +0100630
631int board_late_init(void)
632{
Patrick Delaunayf2451262019-07-30 19:16:41 +0200633 char *boot_device;
Patrick Delaunayd70e3f82019-02-27 17:01:11 +0100634#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
635 const void *fdt_compat;
636 int fdt_compat_len;
Patrick Delaunaye8566ec2019-07-30 19:16:37 +0200637 int ret;
638 u32 otp;
639 struct udevice *dev;
640 char buf[10];
Patrick Delaunayd70e3f82019-02-27 17:01:11 +0100641
642 fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
643 &fdt_compat_len);
644 if (fdt_compat && fdt_compat_len) {
645 if (strncmp(fdt_compat, "st,", 3) != 0)
646 env_set("board_name", fdt_compat);
647 else
648 env_set("board_name", fdt_compat + 3);
649 }
Patrick Delaunaye8566ec2019-07-30 19:16:37 +0200650 ret = uclass_get_device_by_driver(UCLASS_MISC,
651 DM_GET_DRIVER(stm32mp_bsec),
652 &dev);
653
654 if (!ret)
655 ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
656 &otp, sizeof(otp));
657 if (!ret && otp) {
658 snprintf(buf, sizeof(buf), "0x%04x", otp >> 16);
659 env_set("board_id", buf);
660
661 snprintf(buf, sizeof(buf), "0x%04x",
662 ((otp >> 8) & 0xF) - 1 + 0xA);
663 env_set("board_rev", buf);
664 }
Patrick Delaunayd70e3f82019-02-27 17:01:11 +0100665#endif
666
Patrick Delaunayf6626e72019-07-30 19:16:43 +0200667#ifdef CONFIG_ADC
Patrice Chotard879cde52019-02-12 16:50:40 +0100668 /* for DK1/DK2 boards */
669 board_check_usb_power();
Patrick Delaunayf6626e72019-07-30 19:16:43 +0200670#endif /* CONFIG_ADC */
Patrice Chotard879cde52019-02-12 16:50:40 +0100671
Patrick Delaunayf2451262019-07-30 19:16:41 +0200672 /* Check the boot-source to disable bootdelay */
673 boot_device = env_get("boot_device");
674 if (!strcmp(boot_device, "serial") || !strcmp(boot_device, "usb"))
675 env_set("bootdelay", "0");
676
Patrick Delaunayd70e3f82019-02-27 17:01:11 +0100677 return 0;
678}
Patrice Chotard879cde52019-02-12 16:50:40 +0100679
680void board_quiesce_devices(void)
681{
Patrick Delaunay7a3e4422019-07-30 19:16:40 +0200682#ifdef CONFIG_LED
Patrice Chotard879cde52019-02-12 16:50:40 +0100683 setup_led(LEDST_OFF);
Patrick Delaunay7a3e4422019-07-30 19:16:40 +0200684#endif
Patrice Chotard879cde52019-02-12 16:50:40 +0100685}
Patrice Chotard41443cf2019-05-02 18:07:14 +0200686
Patrick Delaunaybff66f92019-08-01 11:29:03 +0200687/* eth init function : weak called in eqos driver */
688int board_interface_eth_init(struct udevice *dev,
689 phy_interface_t interface_type)
Christophe Roullier69ac3f52019-05-17 15:08:43 +0200690{
691 u8 *syscfg;
692 u32 value;
Patrick Delaunaybff66f92019-08-01 11:29:03 +0200693 bool eth_clk_sel_reg = false;
694 bool eth_ref_clk_sel_reg = false;
695
696 /* Gigabit Ethernet 125MHz clock selection. */
697 eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
698
699 /* Ethernet 50Mhz RMII clock selection */
700 eth_ref_clk_sel_reg =
701 dev_read_bool(dev, "st,eth_ref_clk_sel");
Christophe Roullier69ac3f52019-05-17 15:08:43 +0200702
703 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
704
705 if (!syscfg)
706 return -ENODEV;
707
708 switch (interface_type) {
709 case PHY_INTERFACE_MODE_MII:
710 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
711 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
712 debug("%s: PHY_INTERFACE_MODE_MII\n", __func__);
713 break;
714 case PHY_INTERFACE_MODE_GMII:
715 if (eth_clk_sel_reg)
716 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
717 SYSCFG_PMCSETR_ETH_CLK_SEL;
718 else
719 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII;
720 debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__);
721 break;
722 case PHY_INTERFACE_MODE_RMII:
723 if (eth_ref_clk_sel_reg)
724 value = SYSCFG_PMCSETR_ETH_SEL_RMII |
725 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
726 else
727 value = SYSCFG_PMCSETR_ETH_SEL_RMII;
728 debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__);
729 break;
730 case PHY_INTERFACE_MODE_RGMII:
731 case PHY_INTERFACE_MODE_RGMII_ID:
732 case PHY_INTERFACE_MODE_RGMII_RXID:
733 case PHY_INTERFACE_MODE_RGMII_TXID:
734 if (eth_clk_sel_reg)
735 value = SYSCFG_PMCSETR_ETH_SEL_RGMII |
736 SYSCFG_PMCSETR_ETH_CLK_SEL;
737 else
738 value = SYSCFG_PMCSETR_ETH_SEL_RGMII;
739 debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__);
740 break;
741 default:
742 debug("%s: Do not manage %d interface\n",
743 __func__, interface_type);
744 /* Do not manage others interfaces */
745 return -EINVAL;
746 }
747
748 /* clear and set ETH configuration bits */
749 writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII |
750 SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL,
751 syscfg + SYSCFG_PMCCLRR);
752 writel(value, syscfg + SYSCFG_PMCSETR);
753
754 return 0;
755}
756
Patrice Chotard34320372019-05-02 18:28:05 +0200757enum env_location env_get_location(enum env_operation op, int prio)
758{
759 u32 bootmode = get_bootmode();
760
761 if (prio)
762 return ENVL_UNKNOWN;
763
764 switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
765#ifdef CONFIG_ENV_IS_IN_EXT4
766 case BOOT_FLASH_SD:
767 case BOOT_FLASH_EMMC:
768 return ENVL_EXT4;
769#endif
770#ifdef CONFIG_ENV_IS_IN_UBI
771 case BOOT_FLASH_NAND:
772 return ENVL_UBI;
773#endif
Patrice Chotard2c461ec2019-05-09 14:25:36 +0200774#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
775 case BOOT_FLASH_NOR:
776 return ENVL_SPI_FLASH;
777#endif
Patrice Chotard34320372019-05-02 18:28:05 +0200778 default:
779 return ENVL_NOWHERE;
780 }
781}
782
Patrice Chotarddad97bf2019-05-02 18:36:01 +0200783#if defined(CONFIG_ENV_IS_IN_EXT4)
784const char *env_ext4_get_intf(void)
785{
786 u32 bootmode = get_bootmode();
787
788 switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
789 case BOOT_FLASH_SD:
790 case BOOT_FLASH_EMMC:
791 return "mmc";
792 default:
793 return "";
794 }
795}
796
797const char *env_ext4_get_dev_part(void)
798{
799 static char *const dev_part[] = {"0:auto", "1:auto", "2:auto"};
800 u32 bootmode = get_bootmode();
801
802 return dev_part[(bootmode & TAMP_BOOT_INSTANCE_MASK) - 1];
803}
804#endif
805
Patrice Chotard41443cf2019-05-02 18:07:14 +0200806#ifdef CONFIG_SYS_MTDPARTS_RUNTIME
807
808#define MTDPARTS_LEN 256
809#define MTDIDS_LEN 128
810
811/**
812 * The mtdparts_nand0 and mtdparts_nor0 variable tends to be long.
813 * If we need to access it before the env is relocated, then we need
814 * to use our own stack buffer. gd->env_buf will be too small.
815 *
816 * @param buf temporary buffer pointer MTDPARTS_LEN long
817 * @return mtdparts variable string, NULL if not found
818 */
819static const char *env_get_mtdparts(const char *str, char *buf)
820{
821 if (gd->flags & GD_FLG_ENV_READY)
822 return env_get(str);
823 if (env_get_f(str, buf, MTDPARTS_LEN) != -1)
824 return buf;
825
826 return NULL;
827}
828
829/**
830 * update the variables "mtdids" and "mtdparts" with content of mtdparts_<dev>
831 */
832static void board_get_mtdparts(const char *dev,
833 char *mtdids,
834 char *mtdparts)
835{
836 char env_name[32] = "mtdparts_";
837 char tmp_mtdparts[MTDPARTS_LEN];
838 const char *tmp;
839
840 /* name of env variable to read = mtdparts_<dev> */
841 strcat(env_name, dev);
842 tmp = env_get_mtdparts(env_name, tmp_mtdparts);
843 if (tmp) {
844 /* mtdids: "<dev>=<dev>, ...." */
845 if (mtdids[0] != '\0')
846 strcat(mtdids, ",");
847 strcat(mtdids, dev);
848 strcat(mtdids, "=");
849 strcat(mtdids, dev);
850
851 /* mtdparts: "mtdparts=<dev>:<mtdparts_<dev>>;..." */
852 if (mtdparts[0] != '\0')
853 strncat(mtdparts, ";", MTDPARTS_LEN);
854 else
855 strcat(mtdparts, "mtdparts=");
856 strncat(mtdparts, dev, MTDPARTS_LEN);
857 strncat(mtdparts, ":", MTDPARTS_LEN);
858 strncat(mtdparts, tmp, MTDPARTS_LEN);
859 }
860}
861
862void board_mtdparts_default(const char **mtdids, const char **mtdparts)
863{
864 struct udevice *dev;
865 static char parts[2 * MTDPARTS_LEN + 1];
866 static char ids[MTDIDS_LEN + 1];
867 static bool mtd_initialized;
868
869 if (mtd_initialized) {
870 *mtdids = ids;
871 *mtdparts = parts;
872 return;
873 }
874
875 memset(parts, 0, sizeof(parts));
876 memset(ids, 0, sizeof(ids));
877
878 if (!uclass_get_device(UCLASS_MTD, 0, &dev))
879 board_get_mtdparts("nand0", ids, parts);
880
881 if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
882 board_get_mtdparts("nor0", ids, parts);
883
884 mtd_initialized = true;
885 *mtdids = ids;
886 *mtdparts = parts;
887 debug("%s:mtdids=%s & mtdparts=%s\n", __func__, ids, parts);
888}
889#endif
Patrick Delaunayde98cbf2019-07-02 13:26:07 +0200890
891#if defined(CONFIG_OF_BOARD_SETUP)
892int ft_board_setup(void *blob, bd_t *bd)
893{
894#ifdef CONFIG_FDT_FIXUP_PARTITIONS
895 struct node_info nodes[] = {
896 { "st,stm32f469-qspi", MTD_DEV_TYPE_NOR, },
897 { "st,stm32mp15-fmc2", MTD_DEV_TYPE_NAND, },
898 };
899 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
900#endif
901
902 return 0;
903}
904#endif
Patrick Delaunayc17d7252019-08-02 15:07:20 +0200905
906static void board_copro_image_process(ulong fw_image, size_t fw_size)
907{
908 int ret, id = 0; /* Copro id fixed to 0 as only one coproc on mp1 */
909
910 if (!rproc_is_initialized())
911 if (rproc_init()) {
912 printf("Remote Processor %d initialization failed\n",
913 id);
914 return;
915 }
916
917 ret = rproc_load(id, fw_image, fw_size);
918 printf("Load Remote Processor %d with data@addr=0x%08lx %u bytes:%s\n",
919 id, fw_image, fw_size, ret ? " Failed!" : " Success!");
920
921 if (!ret) {
922 rproc_start(id);
923 env_set("copro_state", "booted");
924 }
925}
926
927U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process);