blob: 24d299ac33bddf7803ce129e23d12aee85793dc0 [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 Delaunayf8598d92018-03-12 10:46:18 +01007#include <config.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +02008#include <clk.h>
9#include <dm.h>
10#include <generic-phy.h>
Patrick Delaunayd461f102019-02-12 11:44:41 +010011#include <led.h>
12#include <misc.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020013#include <phy.h>
14#include <reset.h>
Patrick Delaunay45459742019-02-27 17:01:24 +010015#include <syscon.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020016#include <usb.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020017#include <asm/io.h>
Patrick Delaunay842ebb52019-02-27 17:01:18 +010018#include <asm/gpio.h>
Patrick Delaunay45459742019-02-27 17:01:24 +010019#include <asm/arch/stm32.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020020#include <power/regulator.h>
21#include <usb/dwc2_udc.h>
Patrick Delaunayf8598d92018-03-12 10:46:18 +010022
Patrick Delaunay45459742019-02-27 17:01:24 +010023/* SYSCFG registers */
24#define SYSCFG_BOOTR 0x00
25#define SYSCFG_PMCSETR 0x04
26#define SYSCFG_IOCTRLSETR 0x18
27#define SYSCFG_ICNR 0x1C
28#define SYSCFG_CMPCR 0x20
29#define SYSCFG_CMPENSETR 0x24
30#define SYSCFG_PMCCLRR 0x44
31
32#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
33#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
34
35#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
36#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
37#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
38#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
39#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
40
41#define SYSCFG_CMPCR_SW_CTRL BIT(1)
42#define SYSCFG_CMPCR_READY BIT(8)
43
44#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
45
46#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16)
47#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17)
48
49#define SYSCFG_PMCSETR_ETH_SELMII BIT(20)
50
51#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21)
52#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII (0 << 21)
53#define SYSCFG_PMCSETR_ETH_SEL_RGMII (1 << 21)
54#define SYSCFG_PMCSETR_ETH_SEL_RMII (4 << 21)
55
Patrick Delaunayf8598d92018-03-12 10:46:18 +010056/*
57 * Get a global data pointer
58 */
59DECLARE_GLOBAL_DATA_PTR;
60
Patrice Chotard4c834b92018-08-10 17:12:14 +020061#define STM32MP_GUSBCFG 0x40002407
62
63#define STM32MP_GGPIO 0x38
64#define STM32MP_GGPIO_VBUS_SENSING BIT(21)
65
Patrice Chotard395f1292019-02-12 16:50:40 +010066#define USB_WARNING_LOW_THRESHOLD_UV 660000
67#define USB_START_LOW_THRESHOLD_UV 1230000
68#define USB_START_HIGH_THRESHOLD_UV 2100000
69
Patrick Delaunayd461f102019-02-12 11:44:41 +010070int checkboard(void)
71{
72 int ret;
73 char *mode;
74 u32 otp;
75 struct udevice *dev;
76 const char *fdt_compat;
77 int fdt_compat_len;
78
79 if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED))
80 mode = "trusted";
81 else
82 mode = "basic";
83
84 printf("Board: stm32mp1 in %s mode", mode);
85 fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
86 &fdt_compat_len);
87 if (fdt_compat && fdt_compat_len)
88 printf(" (%s)", fdt_compat);
89 puts("\n");
90
91 ret = uclass_get_device_by_driver(UCLASS_MISC,
92 DM_GET_DRIVER(stm32mp_bsec),
93 &dev);
94
95 if (!ret)
96 ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
97 &otp, sizeof(otp));
98 if (!ret && otp) {
99 printf("Board: MB%04x Var%d Rev.%c-%02d\n",
100 otp >> 16,
101 (otp >> 12) & 0xF,
102 ((otp >> 8) & 0xF) - 1 + 'A',
103 otp & 0xF);
104 }
105
106 return 0;
107}
108
Patrick Delaunay9a2ba282019-02-27 17:01:20 +0100109static void board_key_check(void)
110{
111#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
112 ofnode node;
113 struct gpio_desc gpio;
114 enum forced_boot_mode boot_mode = BOOT_NORMAL;
115
116 node = ofnode_path("/config");
117 if (!ofnode_valid(node)) {
118 debug("%s: no /config node?\n", __func__);
119 return;
120 }
121#ifdef CONFIG_FASTBOOT
122 if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
123 &gpio, GPIOD_IS_IN)) {
124 debug("%s: could not find a /config/st,fastboot-gpios\n",
125 __func__);
126 } else {
127 if (dm_gpio_get_value(&gpio)) {
128 puts("Fastboot key pressed, ");
129 boot_mode = BOOT_FASTBOOT;
130 }
131
132 dm_gpio_free(NULL, &gpio);
133 }
134#endif
135#ifdef CONFIG_CMD_STM32PROG
136 if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
137 &gpio, GPIOD_IS_IN)) {
138 debug("%s: could not find a /config/st,stm32prog-gpios\n",
139 __func__);
140 } else {
141 if (dm_gpio_get_value(&gpio)) {
142 puts("STM32Programmer key pressed, ");
143 boot_mode = BOOT_STM32PROG;
144 }
145 dm_gpio_free(NULL, &gpio);
146 }
147#endif
148
149 if (boot_mode != BOOT_NORMAL) {
150 puts("entering download mode...\n");
151 clrsetbits_le32(TAMP_BOOT_CONTEXT,
152 TAMP_BOOT_FORCED_MASK,
153 boot_mode);
154 }
155#endif
156}
157
Patrice Chotard4c834b92018-08-10 17:12:14 +0200158static struct dwc2_plat_otg_data stm32mp_otg_data = {
159 .usb_gusbcfg = STM32MP_GUSBCFG,
160};
161
162static struct reset_ctl usbotg_reset;
163
164int board_usb_init(int index, enum usb_init_type init)
165{
166 struct fdtdec_phandle_args args;
167 struct udevice *dev;
168 const void *blob = gd->fdt_blob;
169 struct clk clk;
170 struct phy phy;
171 int node;
172 int phy_provider;
173 int ret;
174
175 /* find the usb otg node */
176 node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2");
177 if (node < 0) {
178 debug("Not found usb_otg device\n");
179 return -ENODEV;
180 }
181
182 if (!fdtdec_get_is_enabled(blob, node)) {
183 debug("stm32 usbotg is disabled in the device tree\n");
184 return -ENODEV;
185 }
186
187 /* Enable clock */
188 ret = fdtdec_parse_phandle_with_args(blob, node, "clocks",
189 "#clock-cells", 0, 0, &args);
190 if (ret) {
191 debug("usbotg has no clocks defined in the device tree\n");
192 return ret;
193 }
194
195 ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev);
196 if (ret)
197 return ret;
198
199 if (args.args_count != 1) {
200 debug("Can't find clock ID in the device tree\n");
201 return -ENODATA;
202 }
203
204 clk.dev = dev;
205 clk.id = args.args[0];
206
207 ret = clk_enable(&clk);
208 if (ret) {
209 debug("Failed to enable usbotg clock\n");
210 return ret;
211 }
212
213 /* Reset */
214 ret = fdtdec_parse_phandle_with_args(blob, node, "resets",
215 "#reset-cells", 0, 0, &args);
216 if (ret) {
217 debug("usbotg has no resets defined in the device tree\n");
218 goto clk_err;
219 }
220
221 ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, &dev);
222 if (ret || args.args_count != 1)
223 goto clk_err;
224
225 usbotg_reset.dev = dev;
226 usbotg_reset.id = args.args[0];
227
228 reset_assert(&usbotg_reset);
229 udelay(2);
230 reset_deassert(&usbotg_reset);
231
232 /* Get USB PHY */
233 ret = fdtdec_parse_phandle_with_args(blob, node, "phys",
234 "#phy-cells", 0, 0, &args);
235 if (!ret) {
236 phy_provider = fdt_parent_offset(blob, args.node);
237 ret = uclass_get_device_by_of_offset(UCLASS_PHY,
238 phy_provider, &dev);
239 if (ret)
240 goto clk_err;
241
242 phy.dev = dev;
243 phy.id = fdtdec_get_uint(blob, args.node, "reg", -1);
244
245 ret = generic_phy_power_on(&phy);
246 if (ret) {
247 debug("unable to power on the phy\n");
248 goto clk_err;
249 }
250
251 ret = generic_phy_init(&phy);
252 if (ret) {
253 debug("failed to init usb phy\n");
254 goto phy_power_err;
255 }
256 }
257
258 /* Parse and store data needed for gadget */
259 stm32mp_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
260 if (stm32mp_otg_data.regs_otg == FDT_ADDR_T_NONE) {
261 debug("usbotg: can't get base address\n");
262 ret = -ENODATA;
263 goto phy_init_err;
264 }
265
266 stm32mp_otg_data.rx_fifo_sz = fdtdec_get_int(blob, node,
267 "g-rx-fifo-size", 0);
268 stm32mp_otg_data.np_tx_fifo_sz = fdtdec_get_int(blob, node,
269 "g-np-tx-fifo-size", 0);
270 stm32mp_otg_data.tx_fifo_sz = fdtdec_get_int(blob, node,
271 "g-tx-fifo-size", 0);
272 /* Enable voltage level detector */
273 if (!(fdtdec_parse_phandle_with_args(blob, node, "usb33d-supply",
274 NULL, 0, 0, &args))) {
275 if (!uclass_get_device_by_of_offset(UCLASS_REGULATOR,
276 args.node, &dev)) {
277 ret = regulator_set_enable(dev, true);
278 if (ret) {
279 debug("Failed to enable usb33d\n");
280 goto phy_init_err;
281 }
282 }
283 }
284 /* Enable vbus sensing */
285 setbits_le32(stm32mp_otg_data.regs_otg + STM32MP_GGPIO,
286 STM32MP_GGPIO_VBUS_SENSING);
287
288 return dwc2_udc_probe(&stm32mp_otg_data);
289
290phy_init_err:
291 generic_phy_exit(&phy);
292
293phy_power_err:
294 generic_phy_power_off(&phy);
295
296clk_err:
297 clk_disable(&clk);
298
299 return ret;
300}
301
Patrice Chotard395f1292019-02-12 16:50:40 +0100302static int get_led(struct udevice **dev, char *led_string)
303{
304 char *led_name;
305 int ret;
306
307 led_name = fdtdec_get_config_string(gd->fdt_blob, led_string);
308 if (!led_name) {
309 pr_debug("%s: could not find %s config string\n",
310 __func__, led_string);
311 return -ENOENT;
312 }
313 ret = led_get_by_label(led_name, dev);
314 if (ret) {
315 debug("%s: get=%d\n", __func__, ret);
316 return ret;
317 }
318
319 return 0;
320}
321
322static int setup_led(enum led_state_t cmd)
323{
324 struct udevice *dev;
325 int ret;
326
327 ret = get_led(&dev, "u-boot,boot-led");
328 if (ret)
329 return ret;
330
331 ret = led_set_state(dev, cmd);
332 return ret;
333}
334
335static int board_check_usb_power(void)
336{
337 struct ofnode_phandle_args adc_args;
338 struct udevice *adc;
339 struct udevice *led;
340 ofnode node;
341 unsigned int raw;
342 int max_uV = 0;
343 int ret, uV, adc_count;
344 u8 i, nb_blink;
345
346 node = ofnode_path("/config");
347 if (!ofnode_valid(node)) {
348 debug("%s: no /config node?\n", __func__);
349 return -ENOENT;
350 }
351
352 /*
353 * Retrieve the ADC channels devices and get measurement
354 * for each of them
355 */
356 adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
357 "#io-channel-cells");
358 if (adc_count < 0) {
359 if (adc_count == -ENOENT)
360 return 0;
361
362 pr_err("%s: can't find adc channel (%d)\n", __func__,
363 adc_count);
364
365 return adc_count;
366 }
367
368 for (i = 0; i < adc_count; i++) {
369 if (ofnode_parse_phandle_with_args(node, "st,adc_usb_pd",
370 "#io-channel-cells", 0, i,
371 &adc_args)) {
372 pr_debug("%s: can't find /config/st,adc_usb_pd\n",
373 __func__);
374 return 0;
375 }
376
377 ret = uclass_get_device_by_ofnode(UCLASS_ADC, adc_args.node,
378 &adc);
379
380 if (ret) {
381 pr_err("%s: Can't get adc device(%d)\n", __func__,
382 ret);
383 return ret;
384 }
385
386 ret = adc_channel_single_shot(adc->name, adc_args.args[0],
387 &raw);
388 if (ret) {
389 pr_err("%s: single shot failed for %s[%d]!\n",
390 __func__, adc->name, adc_args.args[0]);
391 return ret;
392 }
393 /* Convert to uV */
394 if (!adc_raw_to_uV(adc, raw, &uV)) {
395 if (uV > max_uV)
396 max_uV = uV;
397 pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__,
398 adc->name, adc_args.args[0], raw, uV);
399 } else {
400 pr_err("%s: Can't get uV value for %s[%d]\n",
401 __func__, adc->name, adc_args.args[0]);
402 }
403 }
404
405 /*
406 * If highest value is inside 1.23 Volts and 2.10 Volts, that means
407 * board is plugged on an USB-C 3A power supply and boot process can
408 * continue.
409 */
410 if (max_uV > USB_START_LOW_THRESHOLD_UV &&
411 max_uV < USB_START_HIGH_THRESHOLD_UV)
412 return 0;
413
414 /* Display warning message and make u-boot,error-led blinking */
415 pr_err("\n*******************************************\n");
416
417 if (max_uV < USB_WARNING_LOW_THRESHOLD_UV) {
418 pr_err("* WARNING 500mA power supply detected *\n");
419 nb_blink = 2;
420 } else {
421 pr_err("* WARNING 1.5A power supply detected *\n");
422 nb_blink = 3;
423 }
424
425 pr_err("* Current too low, use a 3A power supply! *\n");
426 pr_err("*******************************************\n\n");
427
428 ret = get_led(&led, "u-boot,error-led");
429 if (ret)
430 return ret;
431
432 for (i = 0; i < nb_blink * 2; i++) {
433 led_set_state(led, LEDST_TOGGLE);
434 mdelay(125);
435 }
436 led_set_state(led, LEDST_ON);
437
438 return 0;
439}
440
Patrice Chotard4c834b92018-08-10 17:12:14 +0200441int board_usb_cleanup(int index, enum usb_init_type init)
442{
443 /* Reset usbotg */
444 reset_assert(&usbotg_reset);
445 udelay(2);
446 reset_deassert(&usbotg_reset);
447
448 return 0;
449}
450
Patrick Delaunay45459742019-02-27 17:01:24 +0100451static void sysconf_init(void)
452{
453#ifndef CONFIG_STM32MP1_TRUSTED
454 u8 *syscfg;
455#ifdef CONFIG_DM_REGULATOR
456 struct udevice *pwr_dev;
457 struct udevice *pwr_reg;
458 struct udevice *dev;
459 int ret;
460 u32 otp = 0;
461#endif
462 u32 bootr;
463
464 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
465
466 /* interconnect update : select master using the port 1 */
467 /* LTDC = AXI_M9 */
468 /* GPU = AXI_M8 */
469 /* today information is hardcoded in U-Boot */
470 writel(BIT(9), syscfg + SYSCFG_ICNR);
471
472 /* disable Pull-Down for boot pin connected to VDD */
473 bootr = readl(syscfg + SYSCFG_BOOTR);
474 bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
475 bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
476 writel(bootr, syscfg + SYSCFG_BOOTR);
477
478#ifdef CONFIG_DM_REGULATOR
479 /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
480 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
481 * The customer will have to disable this for low frequencies
482 * or if AFMUX is selected but the function not used, typically for
483 * TRACE. Otherwise, impact on power consumption.
484 *
485 * WARNING:
486 * enabling High Speed mode while VDD>2.7V
487 * with the OTP product_below_2v5 (OTP 18, BIT 13)
488 * erroneously set to 1 can damage the IC!
489 * => U-Boot set the register only if VDD < 2.7V (in DT)
490 * but this value need to be consistent with board design
491 */
492 ret = syscon_get_by_driver_data(STM32MP_SYSCON_PWR, &pwr_dev);
493 if (!ret) {
494 ret = uclass_get_device_by_driver(UCLASS_MISC,
495 DM_GET_DRIVER(stm32mp_bsec),
496 &dev);
497 if (ret) {
498 pr_err("Can't find stm32mp_bsec driver\n");
499 return;
500 }
501
502 ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4);
503 if (!ret)
504 otp = otp & BIT(13);
505
506 /* get VDD = pwr-supply */
507 ret = device_get_supply_regulator(pwr_dev, "pwr-supply",
508 &pwr_reg);
509
510 /* check if VDD is Low Voltage */
511 if (!ret) {
512 if (regulator_get_value(pwr_reg) < 2700000) {
513 writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
514 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
515 SYSCFG_IOCTRLSETR_HSLVEN_ETH |
516 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
517 SYSCFG_IOCTRLSETR_HSLVEN_SPI,
518 syscfg + SYSCFG_IOCTRLSETR);
519
520 if (!otp)
521 pr_err("product_below_2v5=0: HSLVEN protected by HW\n");
522 } else {
523 if (otp)
524 pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
525 }
526 } else {
527 debug("VDD unknown");
528 }
529 }
530#endif
531
532 /* activate automatic I/O compensation
533 * warning: need to ensure CSI enabled and ready in clock driver
534 */
535 writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
536
537 while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
538 ;
539 clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
540#endif
541}
542
Patrick Delaunayf8598d92018-03-12 10:46:18 +0100543/* board dependent setup after realloc */
544int board_init(void)
545{
Patrice Chotard8b4afe82019-03-11 11:13:17 +0100546 struct udevice *dev;
547
Patrick Delaunayf8598d92018-03-12 10:46:18 +0100548 /* address of boot parameters */
549 gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
550
Patrice Chotard8b4afe82019-03-11 11:13:17 +0100551 /* probe all PINCTRL for hog */
552 for (uclass_first_device(UCLASS_PINCTRL, &dev);
553 dev;
554 uclass_next_device(&dev)) {
555 pr_debug("probe pincontrol = %s\n", dev->name);
556 }
557
Patrick Delaunay9a2ba282019-02-27 17:01:20 +0100558 board_key_check();
559
Patrick Delaunay45459742019-02-27 17:01:24 +0100560 sysconf_init();
561
Patrick Delaunay1f5118b2018-07-27 16:37:08 +0200562 if (IS_ENABLED(CONFIG_LED))
563 led_default_state();
564
Patrick Delaunayf8598d92018-03-12 10:46:18 +0100565 return 0;
566}
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100567
568int board_late_init(void)
569{
570#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
571 const void *fdt_compat;
572 int fdt_compat_len;
573
574 fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
575 &fdt_compat_len);
576 if (fdt_compat && fdt_compat_len) {
577 if (strncmp(fdt_compat, "st,", 3) != 0)
578 env_set("board_name", fdt_compat);
579 else
580 env_set("board_name", fdt_compat + 3);
581 }
582#endif
583
Patrice Chotard395f1292019-02-12 16:50:40 +0100584 /* for DK1/DK2 boards */
585 board_check_usb_power();
586
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100587 return 0;
588}
Patrice Chotard395f1292019-02-12 16:50:40 +0100589
590void board_quiesce_devices(void)
591{
592 setup_led(LEDST_OFF);
593}