blob: 7a4c08cb7fda00e0b183fd9b8b672573313ec4c9 [file] [log] [blame]
Marek Vasut5ff05292020-01-24 18:39:16 +01001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4 */
5
6#include <common.h>
7#include <adc.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Simon Glass274e0b02020-05-10 11:39:56 -06009#include <net.h>
Marek Vasut5ff05292020-01-24 18:39:16 +010010#include <asm/arch/stm32.h>
11#include <asm/arch/sys_proto.h>
12#include <asm/gpio.h>
13#include <asm/io.h>
14#include <bootm.h>
15#include <clk.h>
16#include <config.h>
17#include <dm.h>
18#include <dm/device.h>
19#include <dm/uclass.h>
20#include <env.h>
21#include <env_internal.h>
22#include <g_dnl.h>
23#include <generic-phy.h>
24#include <hang.h>
25#include <i2c.h>
26#include <i2c_eeprom.h>
27#include <init.h>
28#include <led.h>
29#include <memalign.h>
30#include <misc.h>
31#include <mtd.h>
32#include <mtd_node.h>
33#include <netdev.h>
34#include <phy.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060035#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060036#include <linux/delay.h>
Marek Vasut5ff05292020-01-24 18:39:16 +010037#include <power/regulator.h>
38#include <remoteproc.h>
39#include <reset.h>
40#include <syscon.h>
41#include <usb.h>
42#include <usb/dwc2_udc.h>
43#include <watchdog.h>
Simon Glass0034d962021-08-07 07:24:01 -060044#include <dm/ofnode.h>
Patrick Delaunayf2f25c32020-05-25 12:19:46 +020045#include "../../st/common/stpmic1.h"
Marek Vasut5ff05292020-01-24 18:39:16 +010046
47/* SYSCFG registers */
48#define SYSCFG_BOOTR 0x00
49#define SYSCFG_PMCSETR 0x04
50#define SYSCFG_IOCTRLSETR 0x18
51#define SYSCFG_ICNR 0x1C
52#define SYSCFG_CMPCR 0x20
53#define SYSCFG_CMPENSETR 0x24
54#define SYSCFG_PMCCLRR 0x44
55
56#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
57#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
58
59#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
60#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
61#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
62#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
63#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
64
65#define SYSCFG_CMPCR_SW_CTRL BIT(1)
66#define SYSCFG_CMPCR_READY BIT(8)
67
68#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
69
70#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16)
71#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17)
72
73#define SYSCFG_PMCSETR_ETH_SELMII BIT(20)
74
75#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21)
76#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0
77#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21)
78#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23)
79
Marek Vasut145a8762020-10-08 15:14:58 +020080#define KS_CCR 0x08
81#define KS_CCR_EEPROM BIT(9)
82#define KS_BE0 BIT(12)
83#define KS_BE1 BIT(13)
Marek Vasutb2b31c12021-05-03 13:31:39 +020084#define KS_CIDER 0xC0
85#define CIDER_ID 0x8870
Marek Vasut145a8762020-10-08 15:14:58 +020086
Marek Vasut5ff05292020-01-24 18:39:16 +010087int setup_mac_address(void)
88{
Marek Vasut5ff05292020-01-24 18:39:16 +010089 unsigned char enetaddr[6];
Marek Vasutb0a2a492020-07-31 01:34:50 +020090 bool skip_eth0 = false;
91 bool skip_eth1 = false;
Marek Vasut2ab7a2a2020-03-31 19:51:29 +020092 struct udevice *dev;
Patrick Delaunay280949c2022-06-06 16:04:15 +020093 int ret;
94 ofnode node;
Marek Vasut5ff05292020-01-24 18:39:16 +010095
96 ret = eth_env_get_enetaddr("ethaddr", enetaddr);
97 if (ret) /* ethaddr is already set */
Marek Vasutb0a2a492020-07-31 01:34:50 +020098 skip_eth0 = true;
99
Patrick Delaunay280949c2022-06-06 16:04:15 +0200100 node = ofnode_path("ethernet1");
101 if (!ofnode_valid(node)) {
Marek Vasutb0a2a492020-07-31 01:34:50 +0200102 /* ethernet1 is not present in the system */
103 skip_eth1 = true;
Marek Vasut145a8762020-10-08 15:14:58 +0200104 goto out_set_ethaddr;
105 }
106
107 ret = eth_env_get_enetaddr("eth1addr", enetaddr);
108 if (ret) {
109 /* eth1addr is already set */
110 skip_eth1 = true;
111 goto out_set_ethaddr;
112 }
113
Patrick Delaunay280949c2022-06-06 16:04:15 +0200114 ret = ofnode_device_is_compatible(node, "micrel,ks8851-mll");
Marek Vasut145a8762020-10-08 15:14:58 +0200115 if (ret)
116 goto out_set_ethaddr;
117
118 /*
119 * KS8851 with EEPROM may use custom MAC from EEPROM, read
120 * out the KS8851 CCR register to determine whether EEPROM
121 * is present. If EEPROM is present, it must contain valid
122 * MAC address.
123 */
Marek Vasutb2b31c12021-05-03 13:31:39 +0200124 u32 reg, cider, ccr;
Patrick Delaunay280949c2022-06-06 16:04:15 +0200125 reg = ofnode_get_addr(node);
Marek Vasut145a8762020-10-08 15:14:58 +0200126 if (!reg)
127 goto out_set_ethaddr;
128
Marek Vasutb2b31c12021-05-03 13:31:39 +0200129 writew(KS_BE0 | KS_BE1 | KS_CIDER, reg + 2);
130 cider = readw(reg);
131 if ((cider & 0xfff0) != CIDER_ID) {
132 skip_eth1 = true;
133 goto out_set_ethaddr;
134 }
135
Marek Vasut145a8762020-10-08 15:14:58 +0200136 writew(KS_BE0 | KS_BE1 | KS_CCR, reg + 2);
137 ccr = readw(reg);
138 if (ccr & KS_CCR_EEPROM) {
139 skip_eth1 = true;
140 goto out_set_ethaddr;
Marek Vasutb0a2a492020-07-31 01:34:50 +0200141 }
142
Marek Vasut145a8762020-10-08 15:14:58 +0200143out_set_ethaddr:
Marek Vasutb0a2a492020-07-31 01:34:50 +0200144 if (skip_eth0 && skip_eth1)
Marek Vasut5ff05292020-01-24 18:39:16 +0100145 return 0;
146
Patrick Delaunay280949c2022-06-06 16:04:15 +0200147 node = ofnode_path("eeprom0");
148 if (!ofnode_valid(node)) {
Marek Vasut2ab7a2a2020-03-31 19:51:29 +0200149 printf("%s: No eeprom0 path offset\n", __func__);
Patrick Delaunay280949c2022-06-06 16:04:15 +0200150 return -ENOENT;
Marek Vasut5ff05292020-01-24 18:39:16 +0100151 }
152
Patrick Delaunay280949c2022-06-06 16:04:15 +0200153 ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, node, &dev);
Marek Vasut5ff05292020-01-24 18:39:16 +0100154 if (ret) {
155 printf("Cannot find EEPROM!\n");
156 return ret;
157 }
158
159 ret = i2c_eeprom_read(dev, 0xfa, enetaddr, 0x6);
160 if (ret) {
161 printf("Error reading configuration EEPROM!\n");
162 return ret;
163 }
164
Marek Vasutb0a2a492020-07-31 01:34:50 +0200165 if (is_valid_ethaddr(enetaddr)) {
166 if (!skip_eth0)
167 eth_env_set_enetaddr("ethaddr", enetaddr);
168
169 enetaddr[5]++;
170 if (!skip_eth1)
171 eth_env_set_enetaddr("eth1addr", enetaddr);
172 }
Marek Vasut5ff05292020-01-24 18:39:16 +0100173
174 return 0;
175}
176
177int checkboard(void)
178{
179 char *mode;
180 const char *fdt_compat;
181 int fdt_compat_len;
182
Patrick Delaunay472407a2020-03-18 09:22:49 +0100183 if (IS_ENABLED(CONFIG_TFABOOT))
Marek Vasut5ff05292020-01-24 18:39:16 +0100184 mode = "trusted";
185 else
186 mode = "basic";
187
188 printf("Board: stm32mp1 in %s mode", mode);
Patrick Delaunay280949c2022-06-06 16:04:15 +0200189 fdt_compat = ofnode_get_property(ofnode_root(), "compatible",
190 &fdt_compat_len);
Marek Vasut5ff05292020-01-24 18:39:16 +0100191 if (fdt_compat && fdt_compat_len)
192 printf(" (%s)", fdt_compat);
193 puts("\n");
194
195 return 0;
196}
197
Marek Vasut47b98ba2020-04-22 13:18:11 +0200198#ifdef CONFIG_BOARD_EARLY_INIT_F
199static u8 brdcode __section("data");
Marek Vasut39221b52020-04-22 13:18:14 +0200200static u8 ddr3code __section("data");
Marek Vasut47b98ba2020-04-22 13:18:11 +0200201static u8 somcode __section("data");
Patrick Delaunay08c891a2020-05-25 12:19:47 +0200202static u32 opp_voltage_mv __section(".data");
Marek Vasut47b98ba2020-04-22 13:18:11 +0200203
204static void board_get_coding_straps(void)
205{
206 struct gpio_desc gpio[4];
207 ofnode node;
208 int i, ret;
209
Marek Vasut4bd7a5a2021-11-13 03:26:39 +0100210 brdcode = 0;
211 ddr3code = 0;
212 somcode = 0;
213
Marek Vasut47b98ba2020-04-22 13:18:11 +0200214 node = ofnode_path("/config");
215 if (!ofnode_valid(node)) {
216 printf("%s: no /config node?\n", __func__);
217 return;
218 }
219
Marek Vasut47b98ba2020-04-22 13:18:11 +0200220 ret = gpio_request_list_by_name_nodev(node, "dh,som-coding-gpios",
221 gpio, ARRAY_SIZE(gpio),
222 GPIOD_IS_IN);
223 for (i = 0; i < ret; i++)
224 somcode |= !!dm_gpio_get_value(&(gpio[i])) << i;
225
Marek Vasut4bd7a5a2021-11-13 03:26:39 +0100226 gpio_free_list_nodev(gpio, ret);
227
Marek Vasut39221b52020-04-22 13:18:14 +0200228 ret = gpio_request_list_by_name_nodev(node, "dh,ddr3-coding-gpios",
229 gpio, ARRAY_SIZE(gpio),
230 GPIOD_IS_IN);
231 for (i = 0; i < ret; i++)
232 ddr3code |= !!dm_gpio_get_value(&(gpio[i])) << i;
233
Marek Vasut4bd7a5a2021-11-13 03:26:39 +0100234 gpio_free_list_nodev(gpio, ret);
235
Marek Vasut47b98ba2020-04-22 13:18:11 +0200236 ret = gpio_request_list_by_name_nodev(node, "dh,board-coding-gpios",
237 gpio, ARRAY_SIZE(gpio),
238 GPIOD_IS_IN);
239 for (i = 0; i < ret; i++)
240 brdcode |= !!dm_gpio_get_value(&(gpio[i])) << i;
241
Marek Vasut4bd7a5a2021-11-13 03:26:39 +0100242 gpio_free_list_nodev(gpio, ret);
243
Marek Vasut39221b52020-04-22 13:18:14 +0200244 printf("Code: SoM:rev=%d,ddr3=%d Board:rev=%d\n",
245 somcode, ddr3code, brdcode);
246}
247
248int board_stm32mp1_ddr_config_name_match(struct udevice *dev,
249 const char *name)
250{
Marek Vasut272198e2020-04-29 15:08:38 +0200251 if (ddr3code == 1 &&
252 !strcmp(name, "st,ddr3l-dhsom-1066-888-bin-g-2x1gb-533mhz"))
253 return 0;
254
Marek Vasut39221b52020-04-22 13:18:14 +0200255 if (ddr3code == 2 &&
Marek Vasut272198e2020-04-29 15:08:38 +0200256 !strcmp(name, "st,ddr3l-dhsom-1066-888-bin-g-2x2gb-533mhz"))
Marek Vasut39221b52020-04-22 13:18:14 +0200257 return 0;
258
259 if (ddr3code == 3 &&
Marek Vasut272198e2020-04-29 15:08:38 +0200260 !strcmp(name, "st,ddr3l-dhsom-1066-888-bin-g-2x4gb-533mhz"))
Marek Vasut39221b52020-04-22 13:18:14 +0200261 return 0;
262
263 return -EINVAL;
Marek Vasut47b98ba2020-04-22 13:18:11 +0200264}
265
Patrick Delaunay08c891a2020-05-25 12:19:47 +0200266void board_vddcore_init(u32 voltage_mv)
267{
268 if (IS_ENABLED(CONFIG_SPL_BUILD))
269 opp_voltage_mv = voltage_mv;
270}
271
Marek Vasut47b98ba2020-04-22 13:18:11 +0200272int board_early_init_f(void)
273{
Patrick Delaunayf2f25c32020-05-25 12:19:46 +0200274 if (IS_ENABLED(CONFIG_SPL_BUILD))
Patrick Delaunay08c891a2020-05-25 12:19:47 +0200275 stpmic1_init(opp_voltage_mv);
Marek Vasut47b98ba2020-04-22 13:18:11 +0200276 board_get_coding_straps();
277
278 return 0;
279}
280
281#ifdef CONFIG_SPL_LOAD_FIT
282int board_fit_config_name_match(const char *name)
283{
Marek Vasut060cb122020-07-31 01:35:33 +0200284 const char *compat;
285 char test[128];
286
Patrick Delaunay280949c2022-06-06 16:04:15 +0200287 compat = ofnode_get_property(ofnode_root(), "compatible", NULL);
Marek Vasut47b98ba2020-04-22 13:18:11 +0200288
Marek Vasut060cb122020-07-31 01:35:33 +0200289 snprintf(test, sizeof(test), "%s_somrev%d_boardrev%d",
290 compat, somcode, brdcode);
Marek Vasut47b98ba2020-04-22 13:18:11 +0200291
292 if (!strcmp(name, test))
293 return 0;
294
295 return -EINVAL;
296}
297#endif
298#endif
299
Marek Vasut5ff05292020-01-24 18:39:16 +0100300static void board_key_check(void)
301{
302#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
303 ofnode node;
304 struct gpio_desc gpio;
305 enum forced_boot_mode boot_mode = BOOT_NORMAL;
306
307 node = ofnode_path("/config");
308 if (!ofnode_valid(node)) {
309 debug("%s: no /config node?\n", __func__);
310 return;
311 }
312#ifdef CONFIG_FASTBOOT
313 if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
314 &gpio, GPIOD_IS_IN)) {
315 debug("%s: could not find a /config/st,fastboot-gpios\n",
316 __func__);
317 } else {
318 if (dm_gpio_get_value(&gpio)) {
319 puts("Fastboot key pressed, ");
320 boot_mode = BOOT_FASTBOOT;
321 }
322
323 dm_gpio_free(NULL, &gpio);
324 }
325#endif
326#ifdef CONFIG_CMD_STM32PROG
327 if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
328 &gpio, GPIOD_IS_IN)) {
329 debug("%s: could not find a /config/st,stm32prog-gpios\n",
330 __func__);
331 } else {
332 if (dm_gpio_get_value(&gpio)) {
333 puts("STM32Programmer key pressed, ");
334 boot_mode = BOOT_STM32PROG;
335 }
336 dm_gpio_free(NULL, &gpio);
337 }
338#endif
339
340 if (boot_mode != BOOT_NORMAL) {
341 puts("entering download mode...\n");
342 clrsetbits_le32(TAMP_BOOT_CONTEXT,
343 TAMP_BOOT_FORCED_MASK,
344 boot_mode);
345 }
346#endif
347}
348
349#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
350
351#include <usb/dwc2_udc.h>
352int g_dnl_board_usb_cable_connected(void)
353{
354 struct udevice *dwc2_udc_otg;
355 int ret;
356
357 ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC,
Simon Glass65130cd2020-12-28 20:34:56 -0700358 DM_DRIVER_GET(dwc2_udc_otg),
Marek Vasut5ff05292020-01-24 18:39:16 +0100359 &dwc2_udc_otg);
360 if (!ret)
361 debug("dwc2_udc_otg init failed\n");
362
363 return dwc2_udc_B_session_valid(dwc2_udc_otg);
364}
365
366#define STM32MP1_G_DNL_DFU_PRODUCT_NUM 0xdf11
367#define STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM 0x0afb
368
369int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
370{
371 if (!strcmp(name, "usb_dnl_dfu"))
372 put_unaligned(STM32MP1_G_DNL_DFU_PRODUCT_NUM, &dev->idProduct);
373 else if (!strcmp(name, "usb_dnl_fastboot"))
374 put_unaligned(STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM,
375 &dev->idProduct);
376 else
377 put_unaligned(CONFIG_USB_GADGET_PRODUCT_NUM, &dev->idProduct);
378
379 return 0;
380}
381
382#endif /* CONFIG_USB_GADGET */
383
384#ifdef CONFIG_LED
385static int get_led(struct udevice **dev, char *led_string)
386{
Simon Glass0034d962021-08-07 07:24:01 -0600387 const char *led_name;
Marek Vasut5ff05292020-01-24 18:39:16 +0100388 int ret;
389
Simon Glass0034d962021-08-07 07:24:01 -0600390 led_name = ofnode_conf_read_str(led_string);
Marek Vasut5ff05292020-01-24 18:39:16 +0100391 if (!led_name) {
392 pr_debug("%s: could not find %s config string\n",
393 __func__, led_string);
394 return -ENOENT;
395 }
396 ret = led_get_by_label(led_name, dev);
397 if (ret) {
398 debug("%s: get=%d\n", __func__, ret);
399 return ret;
400 }
401
402 return 0;
403}
404
405static int setup_led(enum led_state_t cmd)
406{
407 struct udevice *dev;
408 int ret;
409
410 ret = get_led(&dev, "u-boot,boot-led");
411 if (ret)
412 return ret;
413
414 ret = led_set_state(dev, cmd);
415 return ret;
416}
417#endif
418
419static void __maybe_unused led_error_blink(u32 nb_blink)
420{
421#ifdef CONFIG_LED
422 int ret;
423 struct udevice *led;
424 u32 i;
425#endif
426
427 if (!nb_blink)
428 return;
429
430#ifdef CONFIG_LED
431 ret = get_led(&led, "u-boot,error-led");
432 if (!ret) {
433 /* make u-boot,error-led blinking */
434 /* if U32_MAX and 125ms interval, for 17.02 years */
435 for (i = 0; i < 2 * nb_blink; i++) {
436 led_set_state(led, LEDST_TOGGLE);
437 mdelay(125);
438 WATCHDOG_RESET();
439 }
440 }
441#endif
442
443 /* infinite: the boot process must be stopped */
444 if (nb_blink == U32_MAX)
445 hang();
446}
447
448static void sysconf_init(void)
449{
Patrick Delaunayf8fe21d2020-04-01 09:07:33 +0200450#ifndef CONFIG_TFABOOT
Marek Vasut5ff05292020-01-24 18:39:16 +0100451 u8 *syscfg;
452#ifdef CONFIG_DM_REGULATOR
453 struct udevice *pwr_dev;
454 struct udevice *pwr_reg;
455 struct udevice *dev;
456 int ret;
457 u32 otp = 0;
458#endif
459 u32 bootr;
460
461 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
462
463 /* interconnect update : select master using the port 1 */
464 /* LTDC = AXI_M9 */
465 /* GPU = AXI_M8 */
466 /* today information is hardcoded in U-Boot */
467 writel(BIT(9), syscfg + SYSCFG_ICNR);
468
469 /* disable Pull-Down for boot pin connected to VDD */
470 bootr = readl(syscfg + SYSCFG_BOOTR);
471 bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
472 bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
473 writel(bootr, syscfg + SYSCFG_BOOTR);
474
475#ifdef CONFIG_DM_REGULATOR
476 /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
477 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
478 * The customer will have to disable this for low frequencies
479 * or if AFMUX is selected but the function not used, typically for
480 * TRACE. Otherwise, impact on power consumption.
481 *
482 * WARNING:
483 * enabling High Speed mode while VDD>2.7V
484 * with the OTP product_below_2v5 (OTP 18, BIT 13)
485 * erroneously set to 1 can damage the IC!
486 * => U-Boot set the register only if VDD < 2.7V (in DT)
487 * but this value need to be consistent with board design
488 */
489 ret = uclass_get_device_by_driver(UCLASS_PMIC,
Simon Glass65130cd2020-12-28 20:34:56 -0700490 DM_DRIVER_GET(stm32mp_pwr_pmic),
Marek Vasut5ff05292020-01-24 18:39:16 +0100491 &pwr_dev);
492 if (!ret) {
493 ret = uclass_get_device_by_driver(UCLASS_MISC,
Simon Glass65130cd2020-12-28 20:34:56 -0700494 DM_DRIVER_GET(stm32mp_bsec),
Marek Vasut5ff05292020-01-24 18:39:16 +0100495 &dev);
496 if (ret) {
497 pr_err("Can't find stm32mp_bsec driver\n");
498 return;
499 }
500
501 ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4);
502 if (ret > 0)
503 otp = otp & BIT(13);
504
505 /* get VDD = vdd-supply */
506 ret = device_get_supply_regulator(pwr_dev, "vdd-supply",
507 &pwr_reg);
508
509 /* check if VDD is Low Voltage */
510 if (!ret) {
511 if (regulator_get_value(pwr_reg) < 2700000) {
512 writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
513 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
514 SYSCFG_IOCTRLSETR_HSLVEN_ETH |
515 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
516 SYSCFG_IOCTRLSETR_HSLVEN_SPI,
517 syscfg + SYSCFG_IOCTRLSETR);
518
519 if (!otp)
520 pr_err("product_below_2v5=0: HSLVEN protected by HW\n");
521 } else {
522 if (otp)
523 pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
524 }
525 } else {
526 debug("VDD unknown");
527 }
528 }
529#endif
530
531 /* activate automatic I/O compensation
532 * warning: need to ensure CSI enabled and ready in clock driver
533 */
534 writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
535
536 while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
537 ;
538 clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
539#endif
540}
541
Marek Vasut0839ea92020-03-28 02:01:58 +0100542static void board_init_fmc2(void)
543{
544#define STM32_FMC2_BCR1 0x0
545#define STM32_FMC2_BTR1 0x4
546#define STM32_FMC2_BWTR1 0x104
547#define STM32_FMC2_BCR(x) ((x) * 0x8 + STM32_FMC2_BCR1)
548#define STM32_FMC2_BCRx_FMCEN BIT(31)
549#define STM32_FMC2_BCRx_WREN BIT(12)
550#define STM32_FMC2_BCRx_RSVD BIT(7)
551#define STM32_FMC2_BCRx_FACCEN BIT(6)
552#define STM32_FMC2_BCRx_MWID(n) ((n) << 4)
553#define STM32_FMC2_BCRx_MTYP(n) ((n) << 2)
554#define STM32_FMC2_BCRx_MUXEN BIT(1)
555#define STM32_FMC2_BCRx_MBKEN BIT(0)
556#define STM32_FMC2_BTR(x) ((x) * 0x8 + STM32_FMC2_BTR1)
557#define STM32_FMC2_BTRx_DATAHLD(n) ((n) << 30)
558#define STM32_FMC2_BTRx_BUSTURN(n) ((n) << 16)
559#define STM32_FMC2_BTRx_DATAST(n) ((n) << 8)
560#define STM32_FMC2_BTRx_ADDHLD(n) ((n) << 4)
561#define STM32_FMC2_BTRx_ADDSET(n) ((n) << 0)
562
563#define RCC_MP_AHB6RSTCLRR 0x218
564#define RCC_MP_AHB6RSTCLRR_FMCRST BIT(12)
565#define RCC_MP_AHB6ENSETR 0x19c
566#define RCC_MP_AHB6ENSETR_FMCEN BIT(12)
567
568 const u32 bcr = STM32_FMC2_BCRx_WREN |STM32_FMC2_BCRx_RSVD |
569 STM32_FMC2_BCRx_FACCEN | STM32_FMC2_BCRx_MWID(1) |
570 STM32_FMC2_BCRx_MTYP(2) | STM32_FMC2_BCRx_MUXEN |
571 STM32_FMC2_BCRx_MBKEN;
572 const u32 btr = STM32_FMC2_BTRx_DATAHLD(3) |
573 STM32_FMC2_BTRx_BUSTURN(2) |
574 STM32_FMC2_BTRx_DATAST(0x22) |
575 STM32_FMC2_BTRx_ADDHLD(2) |
576 STM32_FMC2_BTRx_ADDSET(2);
577
578 /* Set up FMC2 bus for KS8851-16MLL and X11 SRAM */
579 writel(RCC_MP_AHB6RSTCLRR_FMCRST, STM32_RCC_BASE + RCC_MP_AHB6RSTCLRR);
580 writel(RCC_MP_AHB6ENSETR_FMCEN, STM32_RCC_BASE + RCC_MP_AHB6ENSETR);
581
582 /* KS8851-16MLL -- Muxed mode */
583 writel(bcr, STM32_FMC2_BASE + STM32_FMC2_BCR(1));
584 writel(btr, STM32_FMC2_BASE + STM32_FMC2_BTR(1));
585 /* AS7C34098 SRAM on X11 -- Muxed mode */
586 writel(bcr, STM32_FMC2_BASE + STM32_FMC2_BCR(3));
587 writel(btr, STM32_FMC2_BASE + STM32_FMC2_BTR(3));
588
589 setbits_le32(STM32_FMC2_BASE + STM32_FMC2_BCR1, STM32_FMC2_BCRx_FMCEN);
590}
591
Marek Vasut7f809fe2022-05-11 23:09:33 +0200592#ifdef CONFIG_DM_REGULATOR
593#define STPMIC_NVM_BUCKS_VOUT_SHR 0xfc
594#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_1V2 0
595#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_1V8 1
596#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V0 2
597#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V3 3
598#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_MASK GENMASK(1, 0)
599#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_OFFSET(n) ((((n) - 1) & 3) * 2)
600static int board_get_regulator_buck3_nvm_uv_av96(int *uv)
601{
Marek Vasut7f809fe2022-05-11 23:09:33 +0200602 struct udevice *dev;
603 u8 bucks_vout = 0;
604 const char *prop;
605 int len, ret;
606
607 /* Check whether this is Avenger96 board. */
Patrick Delaunay280949c2022-06-06 16:04:15 +0200608 prop = ofnode_get_property(ofnode_root(), "compatible", &len);
Marek Vasut7f809fe2022-05-11 23:09:33 +0200609 if (!prop || !len)
610 return -ENODEV;
611
612 if (!strstr(prop, "avenger96"))
613 return -EINVAL;
614
615 /* Read out STPMIC1 NVM and determine default Buck3 voltage. */
616 ret = uclass_get_device_by_driver(UCLASS_MISC,
617 DM_DRIVER_GET(stpmic1_nvm),
618 &dev);
619 if (ret)
620 return ret;
621
622 ret = misc_read(dev, STPMIC_NVM_BUCKS_VOUT_SHR, &bucks_vout, 1);
623 if (ret != 1)
624 return -EINVAL;
625
626 bucks_vout >>= STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_OFFSET(3);
627 bucks_vout &= STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_MASK;
628
629 /*
630 * Avenger96 board comes in multiple regulator configurations:
631 * - rev.100 or rev.200 have Buck3 preconfigured to 3V3 operation on
632 * boot and contains extra Enpirion EP53A8LQI DCDC converter which
633 * supplies the IO. Reduce Buck3 voltage to 2V9 to not waste power.
634 * - rev.200L have Buck3 preconfigured to 1V8 operation and have no
635 * Enpirion EP53A8LQI DCDC anymore, the IO is supplied from Buck3.
636 */
637 if (bucks_vout == STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V3)
638 *uv = 2900000;
639 else
640 *uv = 1800000;
641
642 return 0;
643}
644
645static void board_init_regulator_av96(void)
646{
647 struct udevice *rdev;
648 int ret, uv;
649
650 ret = board_get_regulator_buck3_nvm_uv_av96(&uv);
651 if (ret) /* Not Avenger96 board. */
652 return;
653
654 ret = regulator_get_by_devname("buck3", &rdev);
655 if (ret)
656 return;
657
658 /* Adjust Buck3 per preconfigured PMIC voltage from NVM. */
659 regulator_set_value(rdev, uv);
660}
661
662static void board_init_regulator(void)
663{
664 board_init_regulator_av96();
665
666 regulators_enable_boot_on(_DEBUG);
667}
668#else
669static inline int board_get_regulator_buck3_nvm_uv_av96(int *uv)
670{
671 return -EINVAL;
672}
673
674static inline void board_init_regulator(void) {}
675#endif
676
Marek Vasut5ff05292020-01-24 18:39:16 +0100677/* board dependent setup after realloc */
678int board_init(void)
679{
Marek Vasut5ff05292020-01-24 18:39:16 +0100680 board_key_check();
681
Marek Vasut7f809fe2022-05-11 23:09:33 +0200682 board_init_regulator();
Marek Vasut5ff05292020-01-24 18:39:16 +0100683
684 sysconf_init();
685
Marek Vasut0839ea92020-03-28 02:01:58 +0100686 board_init_fmc2();
687
Marek Vasut5ff05292020-01-24 18:39:16 +0100688 return 0;
689}
690
691int board_late_init(void)
692{
693 char *boot_device;
694#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
695 const void *fdt_compat;
696 int fdt_compat_len;
697
Patrick Delaunay280949c2022-06-06 16:04:15 +0200698 fdt_compat = ofnode_get_property(ofnode_root(), "compatible",
699 &fdt_compat_len);
Marek Vasut5ff05292020-01-24 18:39:16 +0100700 if (fdt_compat && fdt_compat_len) {
701 if (strncmp(fdt_compat, "st,", 3) != 0)
702 env_set("board_name", fdt_compat);
703 else
704 env_set("board_name", fdt_compat + 3);
705 }
706#endif
707
708 /* Check the boot-source to disable bootdelay */
709 boot_device = env_get("boot_device");
710 if (!strcmp(boot_device, "serial") || !strcmp(boot_device, "usb"))
711 env_set("bootdelay", "0");
712
Marek Vasut47b98ba2020-04-22 13:18:11 +0200713#ifdef CONFIG_BOARD_EARLY_INIT_F
714 env_set_ulong("dh_som_rev", somcode);
715 env_set_ulong("dh_board_rev", brdcode);
Marek Vasut39221b52020-04-22 13:18:14 +0200716 env_set_ulong("dh_ddr3_code", ddr3code);
Marek Vasut47b98ba2020-04-22 13:18:11 +0200717#endif
718
Marek Vasut5ff05292020-01-24 18:39:16 +0100719 return 0;
720}
721
722void board_quiesce_devices(void)
723{
724#ifdef CONFIG_LED
725 setup_led(LEDST_OFF);
726#endif
727}
728
729/* eth init function : weak called in eqos driver */
730int board_interface_eth_init(struct udevice *dev,
731 phy_interface_t interface_type)
732{
733 u8 *syscfg;
734 u32 value;
735 bool eth_clk_sel_reg = false;
736 bool eth_ref_clk_sel_reg = false;
737
738 /* Gigabit Ethernet 125MHz clock selection. */
Patrick Delaunay00cf4a82021-06-04 18:25:55 +0200739 eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel");
Marek Vasut5ff05292020-01-24 18:39:16 +0100740
741 /* Ethernet 50Mhz RMII clock selection */
742 eth_ref_clk_sel_reg =
Patrick Delaunay00cf4a82021-06-04 18:25:55 +0200743 dev_read_bool(dev, "st,eth-ref-clk-sel");
Marek Vasut5ff05292020-01-24 18:39:16 +0100744
745 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
746
747 if (!syscfg)
748 return -ENODEV;
749
750 switch (interface_type) {
751 case PHY_INTERFACE_MODE_MII:
752 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
753 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
754 debug("%s: PHY_INTERFACE_MODE_MII\n", __func__);
755 break;
756 case PHY_INTERFACE_MODE_GMII:
757 if (eth_clk_sel_reg)
758 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
759 SYSCFG_PMCSETR_ETH_CLK_SEL;
760 else
761 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII;
762 debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__);
763 break;
764 case PHY_INTERFACE_MODE_RMII:
765 if (eth_ref_clk_sel_reg)
766 value = SYSCFG_PMCSETR_ETH_SEL_RMII |
767 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
768 else
769 value = SYSCFG_PMCSETR_ETH_SEL_RMII;
770 debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__);
771 break;
772 case PHY_INTERFACE_MODE_RGMII:
773 case PHY_INTERFACE_MODE_RGMII_ID:
774 case PHY_INTERFACE_MODE_RGMII_RXID:
775 case PHY_INTERFACE_MODE_RGMII_TXID:
776 if (eth_clk_sel_reg)
777 value = SYSCFG_PMCSETR_ETH_SEL_RGMII |
778 SYSCFG_PMCSETR_ETH_CLK_SEL;
779 else
780 value = SYSCFG_PMCSETR_ETH_SEL_RGMII;
781 debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__);
782 break;
783 default:
784 debug("%s: Do not manage %d interface\n",
785 __func__, interface_type);
786 /* Do not manage others interfaces */
787 return -EINVAL;
788 }
789
790 /* clear and set ETH configuration bits */
791 writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII |
792 SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL,
793 syscfg + SYSCFG_PMCCLRR);
794 writel(value, syscfg + SYSCFG_PMCSETR);
795
796 return 0;
797}
798
Marek Vasut5ff05292020-01-24 18:39:16 +0100799#if defined(CONFIG_OF_BOARD_SETUP)
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900800int ft_board_setup(void *blob, struct bd_info *bd)
Marek Vasut5ff05292020-01-24 18:39:16 +0100801{
Marek Vasut7f809fe2022-05-11 23:09:33 +0200802 const char *buck3path = "/soc/i2c@5c002000/stpmic@33/regulators/buck3";
803 int buck3off, ret, uv;
804
805 ret = board_get_regulator_buck3_nvm_uv_av96(&uv);
806 if (ret) /* Not Avenger96 board, do not patch Buck3 in DT. */
807 return 0;
808
809 buck3off = fdt_path_offset(blob, buck3path);
810 if (buck3off < 0) /* No Buck3 regulator found. */
811 return 0;
812
813 ret = fdt_setprop_u32(blob, buck3off, "regulator-min-microvolt", uv);
814 if (ret < 0)
815 return ret;
816
817 ret = fdt_setprop_u32(blob, buck3off, "regulator-max-microvolt", uv);
818 if (ret < 0)
819 return ret;
820
Marek Vasut5ff05292020-01-24 18:39:16 +0100821 return 0;
822}
823#endif
824
Marek Vasut5ff05292020-01-24 18:39:16 +0100825static void board_copro_image_process(ulong fw_image, size_t fw_size)
826{
827 int ret, id = 0; /* Copro id fixed to 0 as only one coproc on mp1 */
828
829 if (!rproc_is_initialized())
830 if (rproc_init()) {
831 printf("Remote Processor %d initialization failed\n",
832 id);
833 return;
834 }
835
836 ret = rproc_load(id, fw_image, fw_size);
837 printf("Load Remote Processor %d with data@addr=0x%08lx %u bytes:%s\n",
838 id, fw_image, fw_size, ret ? " Failed!" : " Success!");
839
840 if (!ret) {
841 rproc_start(id);
842 env_set("copro_state", "booted");
843 }
844}
845
846U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process);