diff options
Diffstat (limited to 'board/BuR/zynq/common/board.c')
-rw-r--r-- | board/BuR/zynq/common/board.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/board/BuR/zynq/common/board.c b/board/BuR/zynq/common/board.c new file mode 100644 index 00000000000..35e8ed81181 --- /dev/null +++ b/board/BuR/zynq/common/board.c @@ -0,0 +1,231 @@ +// 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; +} |