1// 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> 8#include <log.h> 9#include <net.h> 10#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> 35#include <linux/bitops.h> 36#include <linux/delay.h> 37#include <linux/printk.h> 38#include <power/regulator.h> 39#include <remoteproc.h> 40#include <reset.h> 41#include <syscon.h> 42#include <usb.h> 43#include <usb/dwc2_udc.h> 44#include <watchdog.h> 45#include <dm/ofnode.h> 46#include "../common/dh_common.h" 47#include "../../st/common/stpmic1.h" 48 49/* SYSCFG registers */ 50#define SYSCFG_BOOTR 0x00 51#define SYSCFG_IOCTRLSETR 0x18 52#define SYSCFG_ICNR 0x1C 53#define SYSCFG_CMPCR 0x20 54#define SYSCFG_CMPENSETR 0x24 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 KS_CCR 0x08 71#define KS_CCR_EEPROM BIT(9) 72#define KS_BE0 BIT(12) 73#define KS_BE1 BIT(13) 74#define KS_CIDER 0xC0 75#define CIDER_ID 0x8870 76 77static bool dh_stm32_mac_is_in_ks8851(void) 78{ 79 ofnode node; 80 u32 reg, cider, ccr; 81 82 node = ofnode_path("ethernet1"); 83 if (!ofnode_valid(node)) 84 return false; 85 86 if (ofnode_device_is_compatible(node, "micrel,ks8851-mll")) 87 return false; 88 89 /* 90 * KS8851 with EEPROM may use custom MAC from EEPROM, read 91 * out the KS8851 CCR register to determine whether EEPROM 92 * is present. If EEPROM is present, it must contain valid 93 * MAC address. 94 */ 95 reg = ofnode_get_addr(node); 96 if (!reg) 97 return false; 98 99 writew(KS_BE0 | KS_BE1 | KS_CIDER, reg + 2); 100 cider = readw(reg); 101 if ((cider & 0xfff0) != CIDER_ID) 102 return true; 103 104 writew(KS_BE0 | KS_BE1 | KS_CCR, reg + 2); 105 ccr = readw(reg); 106 if (ccr & KS_CCR_EEPROM) 107 return true; 108 109 return false; 110} 111 112static int dh_stm32_setup_ethaddr(void) 113{ 114 unsigned char enetaddr[6]; 115 116 if (dh_mac_is_in_env("ethaddr")) 117 return 0; 118 119 if (dh_get_mac_is_enabled("ethernet0")) 120 return 0; 121 122 if (!dh_get_mac_from_eeprom(enetaddr, "eeprom0")) 123 return eth_env_set_enetaddr("ethaddr", enetaddr); 124 125 return -ENXIO; 126} 127 128static int dh_stm32_setup_eth1addr(void) 129{ 130 unsigned char enetaddr[6]; 131 132 if (dh_mac_is_in_env("eth1addr")) 133 return 0; 134 135 if (dh_get_mac_is_enabled("ethernet1")) 136 return 0; 137 138 if (dh_stm32_mac_is_in_ks8851()) 139 return 0; 140 141 if (!dh_get_mac_from_eeprom(enetaddr, "eeprom0")) { 142 enetaddr[5]++; 143 return eth_env_set_enetaddr("eth1addr", enetaddr); 144 } 145 146 return -ENXIO; 147} 148 149int setup_mac_address(void) 150{ 151 if (dh_stm32_setup_ethaddr()) 152 log_err("%s: Unable to setup ethaddr!\n", __func__); 153 154 if (dh_stm32_setup_eth1addr()) 155 log_err("%s: Unable to setup eth1addr!\n", __func__); 156 157 return 0; 158} 159 160int checkboard(void) 161{ 162 char *mode; 163 const char *fdt_compat; 164 int fdt_compat_len; 165 166 if (IS_ENABLED(CONFIG_TFABOOT)) 167 mode = "trusted"; 168 else 169 mode = "basic"; 170 171 printf("Board: stm32mp1 in %s mode", mode); 172 fdt_compat = ofnode_get_property(ofnode_root(), "compatible", 173 &fdt_compat_len); 174 if (fdt_compat && fdt_compat_len) 175 printf(" (%s)", fdt_compat); 176 puts("\n"); 177 178 return 0; 179} 180 181#ifdef CONFIG_BOARD_EARLY_INIT_F 182static u8 brdcode __section(".data"); 183static u8 ddr3code __section(".data"); 184static u8 somcode __section(".data"); 185static u32 opp_voltage_mv __section(".data"); 186 187static void board_get_coding_straps(void) 188{ 189 struct gpio_desc gpio[4]; 190 ofnode node; 191 int i, ret; 192 193 brdcode = 0; 194 ddr3code = 0; 195 somcode = 0; 196 197 node = ofnode_path("/config"); 198 if (!ofnode_valid(node)) { 199 printf("%s: no /config node?\n", __func__); 200 return; 201 } 202 203 ret = gpio_request_list_by_name_nodev(node, "dh,som-coding-gpios", 204 gpio, ARRAY_SIZE(gpio), 205 GPIOD_IS_IN); 206 for (i = 0; i < ret; i++) 207 somcode |= !!dm_gpio_get_value(&(gpio[i])) << i; 208 209 gpio_free_list_nodev(gpio, ret); 210 211 ret = gpio_request_list_by_name_nodev(node, "dh,ddr3-coding-gpios", 212 gpio, ARRAY_SIZE(gpio), 213 GPIOD_IS_IN); 214 for (i = 0; i < ret; i++) 215 ddr3code |= !!dm_gpio_get_value(&(gpio[i])) << i; 216 217 gpio_free_list_nodev(gpio, ret); 218 219 ret = gpio_request_list_by_name_nodev(node, "dh,board-coding-gpios", 220 gpio, ARRAY_SIZE(gpio), 221 GPIOD_IS_IN); 222 for (i = 0; i < ret; i++) 223 brdcode |= !!dm_gpio_get_value(&(gpio[i])) << i; 224 225 gpio_free_list_nodev(gpio, ret); 226 227 if (CONFIG_IS_ENABLED(DISPLAY_PRINT)) 228 printf("Code: SoM:rev=%d,ddr3=%d Board:rev=%d\n", 229 somcode, ddr3code, brdcode); 230} 231 232int board_stm32mp1_ddr_config_name_match(struct udevice *dev, 233 const char *name) 234{ 235 if (ddr3code == 1 && 236 !strcmp(name, "st,ddr3l-dhsom-1066-888-bin-g-2x1gb-533mhz")) 237 return 0; 238 239 if (ddr3code == 2 && 240 !strcmp(name, "st,ddr3l-dhsom-1066-888-bin-g-2x2gb-533mhz")) 241 return 0; 242 243 if (ddr3code == 3 && 244 !strcmp(name, "st,ddr3l-dhsom-1066-888-bin-g-2x4gb-533mhz")) 245 return 0; 246 247 return -EINVAL; 248} 249 250void board_vddcore_init(u32 voltage_mv) 251{ 252 if (IS_ENABLED(CONFIG_SPL_BUILD)) 253 opp_voltage_mv = voltage_mv; 254} 255 256int board_early_init_f(void) 257{ 258 if (IS_ENABLED(CONFIG_SPL_BUILD)) 259 stpmic1_init(opp_voltage_mv); 260 board_get_coding_straps(); 261 262 return 0; 263} 264 265#ifdef CONFIG_SPL_LOAD_FIT 266int board_fit_config_name_match(const char *name) 267{ 268 const char *compat; 269 char test[128]; 270 271 compat = ofnode_get_property(ofnode_root(), "compatible", NULL); 272 273 snprintf(test, sizeof(test), "%s_somrev%d_boardrev%d", 274 compat, somcode, brdcode); 275 276 if (!strcmp(name, test)) 277 return 0; 278 279 return -EINVAL; 280} 281#endif 282#endif 283 284static void board_key_check(void) 285{ 286#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG) 287 ofnode node; 288 struct gpio_desc gpio; 289 enum forced_boot_mode boot_mode = BOOT_NORMAL; 290 291 node = ofnode_path("/config"); 292 if (!ofnode_valid(node)) { 293 debug("%s: no /config node?\n", __func__); 294 return; 295 } 296#ifdef CONFIG_FASTBOOT 297 if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0, 298 &gpio, GPIOD_IS_IN)) { 299 debug("%s: could not find a /config/st,fastboot-gpios\n", 300 __func__); 301 } else { 302 if (dm_gpio_get_value(&gpio)) { 303 puts("Fastboot key pressed, "); 304 boot_mode = BOOT_FASTBOOT; 305 } 306 307 dm_gpio_free(NULL, &gpio); 308 } 309#endif 310#ifdef CONFIG_CMD_STM32PROG 311 if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0, 312 &gpio, GPIOD_IS_IN)) { 313 debug("%s: could not find a /config/st,stm32prog-gpios\n", 314 __func__); 315 } else { 316 if (dm_gpio_get_value(&gpio)) { 317 puts("STM32Programmer key pressed, "); 318 boot_mode = BOOT_STM32PROG; 319 } 320 dm_gpio_free(NULL, &gpio); 321 } 322#endif 323 324 if (boot_mode != BOOT_NORMAL) { 325 puts("entering download mode...\n"); 326 clrsetbits_le32(TAMP_BOOT_CONTEXT, 327 TAMP_BOOT_FORCED_MASK, 328 boot_mode); 329 } 330#endif 331} 332 333#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) 334 335#include <usb/dwc2_udc.h> 336int g_dnl_board_usb_cable_connected(void) 337{ 338 struct udevice *dwc2_udc_otg; 339 int ret; 340 341 ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC, 342 DM_DRIVER_GET(dwc2_udc_otg), 343 &dwc2_udc_otg); 344 if (!ret) 345 debug("dwc2_udc_otg init failed\n"); 346 347 return dwc2_udc_B_session_valid(dwc2_udc_otg); 348} 349 350#define STM32MP1_G_DNL_DFU_PRODUCT_NUM 0xdf11 351#define STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM 0x0afb 352 353int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) 354{ 355 if (!strcmp(name, "usb_dnl_dfu")) 356 put_unaligned(STM32MP1_G_DNL_DFU_PRODUCT_NUM, &dev->idProduct); 357 else if (!strcmp(name, "usb_dnl_fastboot")) 358 put_unaligned(STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM, 359 &dev->idProduct); 360 else 361 put_unaligned(CONFIG_USB_GADGET_PRODUCT_NUM, &dev->idProduct); 362 363 return 0; 364} 365 366#endif /* CONFIG_USB_GADGET */ 367 368#ifdef CONFIG_LED 369static int get_led(struct udevice **dev, char *led_string) 370{ 371 const char *led_name; 372 int ret; 373 374 led_name = ofnode_conf_read_str(led_string); 375 if (!led_name) { 376 pr_debug("%s: could not find %s config string\n", 377 __func__, led_string); 378 return -ENOENT; 379 } 380 ret = led_get_by_label(led_name, dev); 381 if (ret) { 382 debug("%s: get=%d\n", __func__, ret); 383 return ret; 384 } 385 386 return 0; 387} 388 389static int setup_led(enum led_state_t cmd) 390{ 391 struct udevice *dev; 392 int ret; 393 394 ret = get_led(&dev, "u-boot,boot-led"); 395 if (ret) 396 return ret; 397 398 ret = led_set_state(dev, cmd); 399 return ret; 400} 401#endif 402 403static void __maybe_unused led_error_blink(u32 nb_blink) 404{ 405#ifdef CONFIG_LED 406 int ret; 407 struct udevice *led; 408 u32 i; 409#endif 410 411 if (!nb_blink) 412 return; 413 414#ifdef CONFIG_LED 415 ret = get_led(&led, "u-boot,error-led"); 416 if (!ret) { 417 /* make u-boot,error-led blinking */ 418 /* if U32_MAX and 125ms interval, for 17.02 years */ 419 for (i = 0; i < 2 * nb_blink; i++) { 420 led_set_state(led, LEDST_TOGGLE); 421 mdelay(125); 422 schedule(); 423 } 424 } 425#endif 426 427 /* infinite: the boot process must be stopped */ 428 if (nb_blink == U32_MAX) 429 hang(); 430} 431 432static void sysconf_init(void) 433{ 434#ifndef CONFIG_TFABOOT 435 u8 *syscfg; 436#ifdef CONFIG_DM_REGULATOR 437 struct udevice *pwr_dev; 438 struct udevice *pwr_reg; 439 struct udevice *dev; 440 int ret; 441 u32 otp = 0; 442#endif 443 u32 bootr; 444 445 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); 446 447 /* interconnect update : select master using the port 1 */ 448 /* LTDC = AXI_M9 */ 449 /* GPU = AXI_M8 */ 450 /* today information is hardcoded in U-Boot */ 451 writel(BIT(9), syscfg + SYSCFG_ICNR); 452 453 /* disable Pull-Down for boot pin connected to VDD */ 454 bootr = readl(syscfg + SYSCFG_BOOTR); 455 bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT); 456 bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT; 457 writel(bootr, syscfg + SYSCFG_BOOTR); 458 459#ifdef CONFIG_DM_REGULATOR 460 /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI 461 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. 462 * The customer will have to disable this for low frequencies 463 * or if AFMUX is selected but the function not used, typically for 464 * TRACE. Otherwise, impact on power consumption. 465 * 466 * WARNING: 467 * enabling High Speed mode while VDD>2.7V 468 * with the OTP product_below_2v5 (OTP 18, BIT 13) 469 * erroneously set to 1 can damage the IC! 470 * => U-Boot set the register only if VDD < 2.7V (in DT) 471 * but this value need to be consistent with board design 472 */ 473 ret = uclass_get_device_by_driver(UCLASS_PMIC, 474 DM_DRIVER_GET(stm32mp_pwr_pmic), 475 &pwr_dev); 476 if (!ret) { 477 ret = uclass_get_device_by_driver(UCLASS_MISC, 478 DM_DRIVER_GET(stm32mp_bsec), 479 &dev); 480 if (ret) { 481 pr_err("Can't find stm32mp_bsec driver\n"); 482 return; 483 } 484 485 ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4); 486 if (ret > 0) 487 otp = otp & BIT(13); 488 489 /* get VDD = vdd-supply */ 490 ret = device_get_supply_regulator(pwr_dev, "vdd-supply", 491 &pwr_reg); 492 493 /* check if VDD is Low Voltage */ 494 if (!ret) { 495 if (regulator_get_value(pwr_reg) < 2700000) { 496 writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE | 497 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | 498 SYSCFG_IOCTRLSETR_HSLVEN_ETH | 499 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | 500 SYSCFG_IOCTRLSETR_HSLVEN_SPI, 501 syscfg + SYSCFG_IOCTRLSETR); 502 503 if (!otp) 504 pr_err("product_below_2v5=0: HSLVEN protected by HW\n"); 505 } else { 506 if (otp) 507 pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n"); 508 } 509 } else { 510 debug("VDD unknown"); 511 } 512 } 513#endif 514 515 /* activate automatic I/O compensation 516 * warning: need to ensure CSI enabled and ready in clock driver 517 */ 518 writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR); 519 520 while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY)) 521 ; 522 clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); 523#endif 524} 525 526#ifdef CONFIG_DM_REGULATOR 527#define STPMIC_NVM_BUCKS_VOUT_SHR 0xfc 528#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_1V2 0 529#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_1V8 1 530#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V0 2 531#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V3 3 532#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_MASK GENMASK(1, 0) 533#define STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_OFFSET(n) ((((n) - 1) & 3) * 2) 534static int board_get_regulator_buck3_nvm_uv_av96(int *uv) 535{ 536 struct udevice *dev; 537 u8 bucks_vout = 0; 538 const char *prop; 539 int len, ret; 540 541 /* Check whether this is Avenger96 board. */ 542 prop = ofnode_get_property(ofnode_root(), "compatible", &len); 543 if (!prop || !len) 544 return -ENODEV; 545 546 if (!strstr(prop, "avenger96") && !strstr(prop, "dhcor-testbench")) 547 return -EINVAL; 548 549 /* Read out STPMIC1 NVM and determine default Buck3 voltage. */ 550 ret = uclass_get_device_by_driver(UCLASS_MISC, 551 DM_DRIVER_GET(stpmic1_nvm), 552 &dev); 553 if (ret) 554 return ret; 555 556 ret = misc_read(dev, STPMIC_NVM_BUCKS_VOUT_SHR, &bucks_vout, 1); 557 if (ret != 1) 558 return -EINVAL; 559 560 bucks_vout >>= STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_OFFSET(3); 561 bucks_vout &= STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_MASK; 562 563 if (strstr(prop, "avenger96")) { 564 /* 565 * Avenger96 board comes in multiple regulator configurations: 566 * - rev.100 or rev.200 have Buck3 preconfigured to 567 * 3V3 operation on boot and contains extra Enpirion 568 * EP53A8LQI DCDC converter which supplies the IO. 569 * Reduce Buck3 voltage to 2V9 to not waste power. 570 * - rev.200L have Buck3 preconfigured to 1V8 operation 571 * and have no Enpirion EP53A8LQI DCDC anymore, the 572 * IO is supplied from Buck3. 573 */ 574 if (bucks_vout == STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V3) 575 *uv = 2900000; 576 else 577 *uv = 1800000; 578 } else { 579 /* Testbench always respects Buck3 NVM settings */ 580 if (bucks_vout == STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V3) 581 *uv = 3300000; 582 else if (bucks_vout == STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_3V0) 583 *uv = 3000000; 584 else if (bucks_vout == STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_1V8) 585 *uv = 1800000; 586 else /* STPMIC_NVM_BUCKS_VOUT_SHR_BUCK_1V2 */ 587 *uv = 1200000; 588 } 589 590 return 0; 591} 592 593static void board_init_regulator_av96(void) 594{ 595 struct udevice *rdev; 596 int ret, uv; 597 598 ret = board_get_regulator_buck3_nvm_uv_av96(&uv); 599 if (ret) /* Not Avenger96 board. */ 600 return; 601 602 ret = regulator_get_by_devname("buck3", &rdev); 603 if (ret) 604 return; 605 606 /* Adjust Buck3 per preconfigured PMIC voltage from NVM. */ 607 regulator_set_value(rdev, uv); 608 regulator_set_enable(rdev, true); 609} 610 611static void board_init_regulator(void) 612{ 613 board_init_regulator_av96(); 614 615 regulators_enable_boot_on(_DEBUG); 616} 617#else 618static inline int board_get_regulator_buck3_nvm_uv_av96(int *uv) 619{ 620 return -EINVAL; 621} 622 623static inline void board_init_regulator(void) {} 624#endif 625 626/* board dependent setup after realloc */ 627int board_init(void) 628{ 629 board_key_check(); 630 631 board_init_regulator(); 632 633 sysconf_init(); 634 635 return 0; 636} 637 638int board_late_init(void) 639{ 640 char *boot_device; 641#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 642 const void *fdt_compat; 643 int fdt_compat_len; 644 645 fdt_compat = ofnode_get_property(ofnode_root(), "compatible", 646 &fdt_compat_len); 647 if (fdt_compat && fdt_compat_len) { 648 if (strncmp(fdt_compat, "st,", 3) != 0) 649 env_set("board_name", fdt_compat); 650 else 651 env_set("board_name", fdt_compat + 3); 652 } 653#endif 654 655 /* Check the boot-source to disable bootdelay */ 656 boot_device = env_get("boot_device"); 657 if (!strcmp(boot_device, "serial") || !strcmp(boot_device, "usb")) 658 env_set("bootdelay", "0"); 659 660#ifdef CONFIG_BOARD_EARLY_INIT_F 661 env_set_ulong("dh_som_rev", somcode); 662 env_set_ulong("dh_board_rev", brdcode); 663 env_set_ulong("dh_ddr3_code", ddr3code); 664#endif 665 666 return 0; 667} 668 669void board_quiesce_devices(void) 670{ 671#ifdef CONFIG_LED 672 setup_led(LEDST_OFF); 673#endif 674} 675 676#if defined(CONFIG_OF_BOARD_SETUP) 677int ft_board_setup(void *blob, struct bd_info *bd) 678{ 679 const char *buck3path = "/soc/i2c@5c002000/stpmic@33/regulators/buck3"; 680 int buck3off, ret, uv; 681 682 ret = board_get_regulator_buck3_nvm_uv_av96(&uv); 683 if (ret) /* Not Avenger96 board, do not patch Buck3 in DT. */ 684 return 0; 685 686 buck3off = fdt_path_offset(blob, buck3path); 687 if (buck3off < 0) /* No Buck3 regulator found. */ 688 return 0; 689 690 ret = fdt_setprop_u32(blob, buck3off, "regulator-min-microvolt", uv); 691 if (ret < 0) 692 return ret; 693 694 ret = fdt_setprop_u32(blob, buck3off, "regulator-max-microvolt", uv); 695 if (ret < 0) 696 return ret; 697 698 return 0; 699} 700#endif 701 702static void board_copro_image_process(ulong fw_image, size_t fw_size) 703{ 704 int ret, id = 0; /* Copro id fixed to 0 as only one coproc on mp1 */ 705 706 if (!rproc_is_initialized()) 707 if (rproc_init()) { 708 printf("Remote Processor %d initialization failed\n", 709 id); 710 return; 711 } 712 713 ret = rproc_load(id, fw_image, fw_size); 714 printf("Load Remote Processor %d with data@addr=0x%08lx %u bytes:%s\n", 715 id, fw_image, fw_size, ret ? " Failed!" : " Success!"); 716 717 if (!ret) { 718 rproc_start(id); 719 env_set("copro_state", "booted"); 720 } 721} 722 723U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); 724