Files
u-boot/board/BuR/zynq/common/board.c
Bernhard Messerklinger 8e25e76fff board/BuR/zynq: initial commit
This commit adds support for the brcp1, brsmarc2, brcp150 and brcp170
boards. This boards are based on the Xilinx Zynq SoC.

Signed-off-by: Bernhard Messerklinger <bernhard.messerklinger@br-automation.com>
Acked-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20250404072819.69642-5-bernhard.messerklinger@br-automation.com
Signed-off-by: Michal Simek <michal.simek@amd.com>
2025-04-16 15:39:48 +02:00

232 lines
4.9 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Board functions for B&R brcp150, brcp170, brcp1, brsmarc2 Board
*
* B&R Industrial Automation GmbH - http://www.br-automation.com
*
*/
#include <fdtdec.h>
#include <miiphy.h>
#include <netdev.h>
#include <asm/arch/sys_proto.h>
#include <asm/gpio.h>
#include <init.h>
#include <i2c.h>
#include <dm/uclass.h>
#include <command.h>
#include <binman.h>
#include "../../common/br_resetc.h"
#include "../../common/bur_common.h"
#include <fdt_support.h>
#include <spi_flash.h>
#include <fpga.h>
#include <zynqpl.h>
#define RSTCTRL_CTRLSPEC_nPCIRST 0x1
__weak int br_board_late_init(void)
{
return 0;
}
#if defined(CONFIG_SPL_BUILD) && CONFIG_IS_ENABLED(FPGA)
const char *fpga_paths[2] = { "/binman/blob-ext@4",
"/binman/blob-ext@1"};
static int start_fpga(unsigned int bank)
{
struct spi_flash *flash_dev;
ofnode fpga_node;
void *buf;
u32 flash_offset, flash_size;
int rc;
fpga_node = ofnode_path(fpga_paths[bank]);
if (!ofnode_valid(fpga_node)) {
printf("WARN: binman node not found %s\n", fpga_paths[bank]);
return -ENOENT;
}
flash_offset = ofnode_read_u32_default(fpga_node, "offset", ~0UL);
flash_size = ofnode_read_u32_default(fpga_node, "size", ~0UL);
if (flash_offset == ~0UL || flash_size == ~0UL) {
printf("WARN: invalid fpga 'offset, size' in fdt (0x%x, 0x%x)",
flash_offset, flash_size);
return -EINVAL;
}
printf("loading bitstream from bank #%d (0x%08x / 0x%08x)\n", bank,
flash_offset, flash_size);
flash_dev = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
if (rc) {
printf("WARN: cannot probe SPI-flash for bitstream!\n");
return -ENODEV;
}
buf = kmalloc(flash_size, 0);
if (!buf) {
spi_flash_free(flash_dev);
return -ENOMEM;
}
debug("using buf @ %p, flashbase: 0x%08x, len: 0x%08x\n",
buf, flash_offset, flash_size);
rc = spi_flash_read(flash_dev, flash_offset, flash_size, buf);
spi_flash_free(flash_dev);
if (rc) {
printf("WARN: cannot read bitstream from spi-flash!\n");
kfree(buf);
return -EIO;
}
rc = fpga_loadbitstream(0, buf, flash_size, BIT_FULL);
if (rc) {
printf("WARN: FPGA configuration from bank #%d failed!\n", bank);
kfree(buf);
return -EIO;
}
kfree(buf);
return 0;
}
#endif
#if defined(CONFIG_SPL_BUILD)
const char *boot_gpios[] = { "br,rs232-en",
"br,board-reset",
NULL};
/* spl stage */
int board_init(void)
{
struct gpio_desc gpio;
int node;
int rc;
/* peripheral RESET on PSOC reset-controller */
rc = br_resetc_regset(RSTCTRL_SPECGPIO_O, RSTCTRL_CTRLSPEC_nPCIRST);
if (rc != 0)
printf("ERROR: cannot write to resetc (nPCIRST)!\n");
for (int i = 0; boot_gpios[i]; i++) {
node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, boot_gpios[i]);
if (node < 0) {
printf("INFO: %s not found!\n", boot_gpios[i]);
} else {
rc = gpio_request_by_name_nodev(offset_to_ofnode(node), "pin",
0, &gpio, GPIOD_IS_OUT);
if (!rc)
dm_gpio_set_value(&gpio, 1);
else
printf("ERROR: failed to setup %s!\n", boot_gpios[i]);
}
}
#if CONFIG_IS_ENABLED(FPGA)
unsigned int bmode;
unsigned int bank;
rc = br_resetc_bmode_get(&bmode);
if (rc) {
printf("WARN: can't get Boot Mode!\n");
return -ENODEV;
}
/* use golden FPGA image in case of special boot flow (PME, BootAR, USB, Net ...) */
bank = ((bmode == 0) || (bmode == 12)) ? 1 : 0;
/* bring up FPGA */
if (start_fpga(bank) != 0) {
printf("WARN: cannot start fpga from bank %d, trying bank %d!\n", bank, bank ^ 1);
bank ^= 1;
start_fpga(bank);
}
#endif
return 0;
}
#else
int board_init(void)
{
return 0;
}
/*
* PMIC buckboost regulator workaround:
* The DA9062 PMIC can switch its buckboost regulator output
* between PFM and PWM mode for eco-purpose.
* In very rare situations this transition leads into a non-
* functional buckboost regulator with zero output.
* With this workaround we prevent this with turning this
* feature off by forcing PWM-mode if auto-mode is selected.
*/
static void pmic_fixup(int addr)
{
u8 regs[] = { 0x9E, 0x9D, 0xA0, 0x9F };
struct udevice *i2cdev = NULL;
unsigned int i;
u8 val;
int rc;
i2c_get_chip_for_busnum(0, addr, 1, &i2cdev);
if (!i2cdev)
return;
printf("PMIC: fixup buckboost at i2c device 0x%x\n", addr);
for (i = 0; i < sizeof(regs); i++) {
rc = dm_i2c_read(i2cdev, regs[i], &val, 1);
if (rc == 0 && val == 0xC0) {
val = 0x80;
dm_i2c_write(i2cdev, regs[i], &val, 1);
}
}
}
int board_late_init(void)
{
ofnode node;
u32 addr;
br_resetc_bmode();
br_board_late_init();
node = ofnode_by_compatible(ofnode_null(), "dlg,da9062");
if (!ofnode_valid(node))
return 0;
if (!ofnode_read_u32(node, "reg", &addr))
pmic_fixup(addr);
else
printf("WARN: cannot read PMIC address!");
return 0;
}
#endif
int dram_init(void)
{
if (fdtdec_setup_mem_size_base() != 0)
return -EINVAL;
zynq_ddrc_init();
return 0;
}