aboutsummaryrefslogtreecommitdiff
path: root/board/xilinx
diff options
context:
space:
mode:
Diffstat (limited to 'board/xilinx')
-rw-r--r--board/xilinx/Kconfig31
-rw-r--r--board/xilinx/common/Makefile10
-rw-r--r--board/xilinx/common/board.c347
-rw-r--r--board/xilinx/common/board.h2
-rw-r--r--board/xilinx/common/fru.c91
-rw-r--r--board/xilinx/common/fru.h83
-rw-r--r--board/xilinx/common/fru_ops.c362
-rw-r--r--board/xilinx/microblaze-generic/microblaze-generic.c23
-rw-r--r--board/xilinx/versal/Makefile1
-rw-r--r--board/xilinx/versal/board.c3
-rw-r--r--board/xilinx/zynq/Makefile1
-rw-r--r--board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c273
-rw-r--r--board/xilinx/zynqmp/MAINTAINERS1
-rw-r--r--board/xilinx/zynqmp/Makefile1
-rw-r--r--board/xilinx/zynqmp/cmds.c228
-rw-r--r--board/xilinx/zynqmp/tap_delays.c200
-rw-r--r--board/xilinx/zynqmp/zynqmp.c32
17 files changed, 1496 insertions, 193 deletions
diff --git a/board/xilinx/Kconfig b/board/xilinx/Kconfig
index c80d0a8..64507b5 100644
--- a/board/xilinx/Kconfig
+++ b/board/xilinx/Kconfig
@@ -50,9 +50,34 @@ config XILINX_OF_BOARD_DTB_ADDR
config BOOT_SCRIPT_OFFSET
hex "Boot script offset"
- depends on ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL
- default 0xFC0000 if ARCH_ZYNQ
+ depends on ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || MICROBLAZE
+ default 0xFC0000 if ARCH_ZYNQ || MICROBLAZE
default 0x3E80000 if ARCH_ZYNQMP
default 0x7F80000 if ARCH_VERSAL
help
- Specifies distro boot script offset in NAND/NOR flash.
+ Specifies distro boot script offset in NAND/QSPI/NOR flash.
+
+config ZYNQ_MAC_IN_EEPROM
+ bool "Reading MAC address from EEPROM"
+ help
+ Enable this option if your MAC address is saved in eeprom and
+ xlnx,eeprom DT property in chosen node points to it.
+
+if ZYNQ_MAC_IN_EEPROM
+
+config ZYNQ_GEM_I2C_MAC_OFFSET
+ hex "Set the I2C MAC offset"
+ default 0x0
+ depends on DM_I2C
+ help
+ Set the MAC offset for i2C.
+
+endif
+
+config CMD_FRU
+ bool "FRU information for product"
+ help
+ This option enables FRU commands to capture and display FRU
+ information present in the device. The FRU Information is used
+ to primarily to provide "inventory" information about the boards
+ that the FRU Information Device is located on.
diff --git a/board/xilinx/common/Makefile b/board/xilinx/common/Makefile
new file mode 100644
index 0000000..2120284
--- /dev/null
+++ b/board/xilinx/common/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# (C) Copyright 2020 Xilinx, Inc.
+# Michal Simek <michal.simek@xilinx.com>
+#
+
+obj-y += board.o
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_CMD_FRU) += fru.o fru_ops.o
+endif
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index b0f60c4..cdc06a3 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * (C) Copyright 2014 - 2019 Xilinx, Inc.
+ * (C) Copyright 2014 - 2020 Xilinx, Inc.
* Michal Simek <michal.simek@xilinx.com>
*/
@@ -11,7 +11,14 @@
#include <dm/uclass.h>
#include <i2c.h>
#include <linux/sizes.h>
+#include <malloc.h>
#include "board.h"
+#include <dm.h>
+#include <i2c_eeprom.h>
+#include <net.h>
+#include <generated/dt.h>
+
+#include "fru.h"
#if defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET)
int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
@@ -41,6 +48,277 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
}
#endif
+#define EEPROM_HEADER_MAGIC 0xdaaddeed
+#define EEPROM_HDR_MANUFACTURER_LEN 16
+#define EEPROM_HDR_NAME_LEN 16
+#define EEPROM_HDR_REV_LEN 8
+#define EEPROM_HDR_SERIAL_LEN 20
+#define EEPROM_HDR_NO_OF_MAC_ADDR 4
+#define EEPROM_HDR_ETH_ALEN ETH_ALEN
+
+struct xilinx_board_description {
+ u32 header;
+ char manufacturer[EEPROM_HDR_MANUFACTURER_LEN + 1];
+ char name[EEPROM_HDR_NAME_LEN + 1];
+ char revision[EEPROM_HDR_REV_LEN + 1];
+ char serial[EEPROM_HDR_SERIAL_LEN + 1];
+ u8 mac_addr[EEPROM_HDR_NO_OF_MAC_ADDR][EEPROM_HDR_ETH_ALEN + 1];
+};
+
+static int highest_id = -1;
+static struct xilinx_board_description **board_info;
+
+#define XILINX_I2C_DETECTION_BITS sizeof(struct fru_common_hdr)
+
+/* Variable which stores pointer to array which stores eeprom content */
+struct xilinx_legacy_format {
+ char board_sn[18]; /* 0x0 */
+ char unused0[14]; /* 0x12 */
+ char eth_mac[6]; /* 0x20 */
+ char unused1[170]; /* 0x26 */
+ char board_name[11]; /* 0xd0 */
+ char unused2[5]; /* 0xdc */
+ char board_revision[3]; /* 0xe0 */
+ char unused3[29]; /* 0xe3 */
+};
+
+static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size)
+{
+ int i;
+ char byte;
+
+ for (i = 0; i < size; i++) {
+ byte = eeprom[i];
+
+ /* Remove all ffs and spaces */
+ if (byte == 0xff || byte == ' ')
+ eeprom[i] = 0;
+
+ /* Convert strings to lower case */
+ if (byte >= 'A' && byte <= 'Z')
+ eeprom[i] = byte + 'a' - 'A';
+ }
+}
+
+static int xilinx_read_eeprom_legacy(struct udevice *dev, char *name,
+ struct xilinx_board_description *desc)
+{
+ int ret, size;
+ struct xilinx_legacy_format *eeprom_content;
+ bool eth_valid = false;
+
+ size = sizeof(*eeprom_content);
+
+ eeprom_content = calloc(1, size);
+ if (!eeprom_content)
+ return -ENOMEM;
+
+ debug("%s: I2C EEPROM read pass data at %p\n", __func__,
+ eeprom_content);
+
+ ret = dm_i2c_read(dev, 0, (uchar *)eeprom_content, size);
+ if (ret) {
+ debug("%s: I2C EEPROM read failed\n", __func__);
+ free(eeprom_content);
+ return ret;
+ }
+
+ xilinx_eeprom_legacy_cleanup((char *)eeprom_content, size);
+
+ printf("Xilinx I2C Legacy format at %s:\n", name);
+ printf(" Board name:\t%s\n", eeprom_content->board_name);
+ printf(" Board rev:\t%s\n", eeprom_content->board_revision);
+ printf(" Board SN:\t%s\n", eeprom_content->board_sn);
+
+ eth_valid = is_valid_ethaddr((const u8 *)eeprom_content->eth_mac);
+ if (eth_valid)
+ printf(" Ethernet mac:\t%pM\n", eeprom_content->eth_mac);
+
+ /* Terminating \0 chars ensure end of string */
+ strcpy(desc->name, eeprom_content->board_name);
+ strcpy(desc->revision, eeprom_content->board_revision);
+ strcpy(desc->serial, eeprom_content->board_sn);
+ if (eth_valid)
+ memcpy(desc->mac_addr[0], eeprom_content->eth_mac, ETH_ALEN);
+
+ desc->header = EEPROM_HEADER_MAGIC;
+
+ free(eeprom_content);
+
+ return ret;
+}
+
+static bool xilinx_detect_legacy(u8 *buffer)
+{
+ int i;
+ char c;
+
+ for (i = 0; i < XILINX_I2C_DETECTION_BITS; i++) {
+ c = buffer[i];
+
+ if (c < '0' || c > '9')
+ return false;
+ }
+
+ return true;
+}
+
+static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
+ struct xilinx_board_description *desc)
+{
+ int ret, eeprom_size;
+ u8 *fru_content;
+
+ /* FIXME this is shortcut - if eeprom type is wrong it will fail */
+ eeprom_size = i2c_eeprom_size(dev);
+
+ fru_content = calloc(1, eeprom_size);
+ if (!fru_content)
+ return -ENOMEM;
+
+ debug("%s: I2C EEPROM read pass data at %p\n", __func__,
+ fru_content);
+
+ ret = dm_i2c_read(dev, 0, (uchar *)fru_content,
+ eeprom_size);
+ if (ret) {
+ debug("%s: I2C EEPROM read failed\n", __func__);
+ free(fru_content);
+ return ret;
+ }
+
+ printf("Xilinx I2C FRU format at %s:\n", name);
+ fru_capture((unsigned long)fru_content);
+ ret = fru_display(0);
+ if (ret) {
+ printf("FRU format decoding failed.\n");
+ return ret;
+ }
+
+ if (desc->header == EEPROM_HEADER_MAGIC) {
+ debug("Information already filled\n");
+ return -EINVAL;
+ }
+
+ /* It is clear that FRU was captured and structures were filled */
+ strncpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name,
+ sizeof(desc->manufacturer));
+ strncpy(desc->name, (char *)fru_data.brd.product_name,
+ sizeof(desc->name));
+ strncpy(desc->revision, (char *)fru_data.brd.rev,
+ sizeof(desc->revision));
+ strncpy(desc->serial, (char *)fru_data.brd.serial_number,
+ sizeof(desc->serial));
+ desc->header = EEPROM_HEADER_MAGIC;
+
+ return 0;
+}
+
+static bool xilinx_detect_fru(u8 *buffer)
+{
+ u8 checksum = 0;
+ int i;
+
+ checksum = fru_checksum((u8 *)buffer, sizeof(struct fru_common_hdr));
+ if (checksum) {
+ debug("%s Common header CRC FAIL\n", __func__);
+ return false;
+ }
+
+ bool all_zeros = true;
+ /* Checksum over all zeros is also zero that's why detect this case */
+ for (i = 0; i < sizeof(struct fru_common_hdr); i++) {
+ if (buffer[i] != 0)
+ all_zeros = false;
+ }
+
+ if (all_zeros)
+ return false;
+
+ debug("%s Common header CRC PASS\n", __func__);
+ return true;
+}
+
+static int xilinx_read_eeprom_single(char *name,
+ struct xilinx_board_description *desc)
+{
+ int ret;
+ struct udevice *dev;
+ ofnode eeprom;
+ u8 buffer[XILINX_I2C_DETECTION_BITS];
+
+ eeprom = ofnode_get_aliases_node(name);
+ if (!ofnode_valid(eeprom))
+ return -ENODEV;
+
+ ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, eeprom, &dev);
+ if (ret)
+ return ret;
+
+ ret = dm_i2c_read(dev, 0, buffer, sizeof(buffer));
+ if (ret) {
+ debug("%s: I2C EEPROM read failed\n", __func__);
+ return ret;
+ }
+
+ debug("%s: i2c memory detected: %s\n", __func__, name);
+
+ if (CONFIG_IS_ENABLED(CMD_FRU) && xilinx_detect_fru(buffer))
+ return xilinx_read_eeprom_fru(dev, name, desc);
+
+ if (xilinx_detect_legacy(buffer))
+ return xilinx_read_eeprom_legacy(dev, name, desc);
+
+ return -ENODEV;
+}
+
+__maybe_unused int xilinx_read_eeprom(void)
+{
+ int id, ret;
+ char name_buf[8]; /* 8 bytes should be enough for nvmem+number */
+ struct xilinx_board_description *desc;
+
+ highest_id = dev_read_alias_highest_id("nvmem");
+ /* No nvmem aliases present */
+ if (highest_id < 0)
+ return -EINVAL;
+
+ board_info = calloc(1, sizeof(desc) * highest_id);
+ if (!board_info)
+ return -ENOMEM;
+
+ debug("%s: Highest ID %d, board_info %p\n", __func__,
+ highest_id, board_info);
+
+ for (id = 0; id <= highest_id; id++) {
+ snprintf(name_buf, sizeof(name_buf), "nvmem%d", id);
+
+ /* Alloc structure */
+ desc = board_info[id];
+ if (!desc) {
+ desc = calloc(1, sizeof(*desc));
+ if (!desc)
+ return -ENOMEM;
+
+ board_info[id] = desc;
+ }
+
+ /* Ignoring return value for supporting multiple chips */
+ ret = xilinx_read_eeprom_single(name_buf, desc);
+ if (ret) {
+ free(desc);
+ board_info[id] = NULL;
+ }
+ }
+
+ /*
+ * Consider to clean board_info structure when board/cards are not
+ * detected.
+ */
+
+ return 0;
+}
+
#if defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE)
void *board_fdt_blob_setup(void)
{
@@ -75,12 +353,36 @@ void *board_fdt_blob_setup(void)
}
#endif
+#if defined(CONFIG_BOARD_LATE_INIT)
+static int env_set_by_index(const char *name, int index, char *data)
+{
+ char var[32];
+
+ if (!index)
+ sprintf(var, "board_%s", name);
+ else
+ sprintf(var, "card%d_%s", index, name);
+
+ return env_set(var, data);
+}
+
int board_late_init_xilinx(void)
{
u32 ret = 0;
+ int i, id, macid = 0;
+ struct xilinx_board_description *desc;
phys_size_t bootm_size = gd->ram_size;
+ struct bd_info *bd = gd->bd;
+
+ if (!CONFIG_IS_ENABLED(MICROBLAZE) && bd->bi_dram[0].start) {
+ ulong scriptaddr;
- if (CONFIG_IS_ENABLED(ARCH_ZYNQ))
+ scriptaddr = env_get_hex("scriptaddr", 0);
+ ret |= env_set_hex("scriptaddr",
+ bd->bi_dram[0].start + scriptaddr);
+ }
+
+ if (CONFIG_IS_ENABLED(ARCH_ZYNQ) || CONFIG_IS_ENABLED(MICROBLAZE))
bootm_size = min(bootm_size, (phys_size_t)(SZ_512M + SZ_256M));
ret |= env_set_hex("script_offset_f", CONFIG_BOOT_SCRIPT_OFFSET);
@@ -88,8 +390,49 @@ int board_late_init_xilinx(void)
ret |= env_set_addr("bootm_low", (void *)gd->ram_base);
ret |= env_set_addr("bootm_size", (void *)bootm_size);
+ for (id = 0; id <= highest_id; id++) {
+ desc = board_info[id];
+ if (desc && desc->header == EEPROM_HEADER_MAGIC) {
+ if (desc->manufacturer[0])
+ ret |= env_set_by_index("manufacturer", id,
+ desc->manufacturer);
+ if (desc->name[0])
+ ret |= env_set_by_index("name", id,
+ desc->name);
+ if (desc->revision[0])
+ ret |= env_set_by_index("rev", id,
+ desc->revision);
+ if (desc->serial[0])
+ ret |= env_set_by_index("serial", id,
+ desc->serial);
+
+ if (!CONFIG_IS_ENABLED(NET))
+ continue;
+
+ for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
+ if (!desc->mac_addr[i])
+ continue;
+
+ if (is_valid_ethaddr((const u8 *)desc->mac_addr[i]))
+ ret |= eth_env_set_enetaddr_by_index("eth",
+ macid++, desc->mac_addr[i]);
+ }
+ }
+ }
+
if (ret)
printf("%s: Saving run time variables FAILED\n", __func__);
return 0;
}
+#endif
+
+int __maybe_unused board_fit_config_name_match(const char *name)
+{
+ debug("%s: Check %s, default %s\n", __func__, name, DEVICE_TREE);
+
+ if (!strcmp(name, DEVICE_TREE))
+ return 0;
+
+ return -1;
+}
diff --git a/board/xilinx/common/board.h b/board/xilinx/common/board.h
index 180dfbc..69e6424 100644
--- a/board/xilinx/common/board.h
+++ b/board/xilinx/common/board.h
@@ -9,4 +9,6 @@
int board_late_init_xilinx(void);
+int xilinx_read_eeprom(void);
+
#endif /* BOARD_XILINX_COMMON_BOARD_H */
diff --git a/board/xilinx/common/fru.c b/board/xilinx/common/fru.c
new file mode 100644
index 0000000..ccf4872
--- /dev/null
+++ b/board/xilinx/common/fru.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2019 - 2020 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fdtdec.h>
+#include <malloc.h>
+
+#include "fru.h"
+
+static int do_fru_capture(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long addr;
+ char *endp;
+
+ if (argc < cmdtp->maxargs)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[2], &endp, 16);
+ if (*argv[1] == 0 || *endp != 0)
+ return -1;
+
+ return fru_capture(addr);
+}
+
+static int do_fru_display(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ fru_display(1);
+ return CMD_RET_SUCCESS;
+}
+
+static int do_fru_generate(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ unsigned long addr;
+
+ if (argc < cmdtp->maxargs)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[2], NULL, 16);
+
+ return fru_generate(addr, argv[3], argv[4], argv[5], argv[6], argv[7]);
+}
+
+static struct cmd_tbl cmd_fru_sub[] = {
+ U_BOOT_CMD_MKENT(capture, 3, 0, do_fru_capture, "", ""),
+ U_BOOT_CMD_MKENT(display, 2, 0, do_fru_display, "", ""),
+ U_BOOT_CMD_MKENT(board_gen, 8, 0, do_fru_generate, "", ""),
+};
+
+static int do_fru(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *c;
+ int ret;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ c = find_cmd_tbl(argv[1], &cmd_fru_sub[0],
+ ARRAY_SIZE(cmd_fru_sub));
+ if (!c)
+ return CMD_RET_USAGE;
+
+ ret = c->cmd(c, flag, argc, argv);
+
+ return cmd_process_error(c, ret);
+}
+
+/***************************************************/
+#ifdef CONFIG_SYS_LONGHELP
+static char fru_help_text[] =
+ "capture <addr> - Parse and capture FRU table present at address.\n"
+ "fru display - Displays content of FRU table that was captured using\n"
+ " fru capture command\n"
+ "fru board_gen <addr> <manufacturer> <board name> <serial number>\n"
+ " <part number> <revision> - Generate FRU format with\n"
+ " board info area filled based on parameters. <addr> is\n"
+ " pointing to place where FRU is generated.\n"
+ ;
+#endif
+
+U_BOOT_CMD(
+ fru, 8, 1, do_fru,
+ "FRU table info",
+ fru_help_text
+)
diff --git a/board/xilinx/common/fru.h b/board/xilinx/common/fru.h
new file mode 100644
index 0000000..a3e6520
--- /dev/null
+++ b/board/xilinx/common/fru.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Xilinx, Inc.
+ * Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
+ */
+
+#ifndef __FRU_H
+#define __FRU_H
+
+struct fru_common_hdr {
+ u8 version;
+ u8 off_internal;
+ u8 off_chassis;
+ u8 off_board;
+ u8 off_product;
+ u8 off_multirec;
+ u8 pad;
+ u8 crc;
+};
+
+#define FRU_BOARD_MAX_LEN 32
+
+struct __packed fru_board_info_header {
+ u8 ver;
+ u8 len;
+ u8 lang_code;
+ u8 time[3];
+};
+
+struct __packed fru_board_info_member {
+ u8 type_len;
+ u8 *name;
+};
+
+struct fru_board_data {
+ u8 ver;
+ u8 len;
+ u8 lang_code;
+ u8 time[3];
+ u8 manufacturer_type_len;
+ u8 manufacturer_name[FRU_BOARD_MAX_LEN];
+ u8 product_name_type_len;
+ u8 product_name[FRU_BOARD_MAX_LEN];
+ u8 serial_number_type_len;
+ u8 serial_number[FRU_BOARD_MAX_LEN];
+ u8 part_number_type_len;
+ u8 part_number[FRU_BOARD_MAX_LEN];
+ u8 file_id_type_len;
+ u8 file_id[FRU_BOARD_MAX_LEN];
+ /* Xilinx custom fields */
+ u8 rev_type_len;
+ u8 rev[FRU_BOARD_MAX_LEN];
+};
+
+struct fru_table {
+ bool captured;
+ struct fru_common_hdr hdr;
+ struct fru_board_data brd;
+};
+
+#define FRU_TYPELEN_CODE_MASK 0xC0
+#define FRU_TYPELEN_LEN_MASK 0x3F
+#define FRU_COMMON_HDR_VER_MASK 0xF
+#define FRU_COMMON_HDR_LEN_MULTIPLIER 8
+#define FRU_LANG_CODE_ENGLISH 0
+#define FRU_LANG_CODE_ENGLISH_1 25
+#define FRU_TYPELEN_EOF 0xC1
+
+/* This should be minimum of fields */
+#define FRU_BOARD_AREA_TOTAL_FIELDS 5
+#define FRU_TYPELEN_TYPE_SHIFT 6
+#define FRU_TYPELEN_TYPE_BINARY 0
+#define FRU_TYPELEN_TYPE_ASCII8 3
+
+int fru_display(int verbose);
+int fru_capture(unsigned long addr);
+int fru_generate(unsigned long addr, char *manufacturer, char *board_name,
+ char *serial_no, char *part_no, char *revision);
+u8 fru_checksum(u8 *addr, u8 len);
+
+extern struct fru_table fru_data;
+
+#endif /* FRU_H */
diff --git a/board/xilinx/common/fru_ops.c b/board/xilinx/common/fru_ops.c
new file mode 100644
index 0000000..fc3add7
--- /dev/null
+++ b/board/xilinx/common/fru_ops.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2019 - 2020 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <env.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+#include "fru.h"
+
+struct fru_table fru_data __section(.data);
+
+static u16 fru_cal_area_len(u8 len)
+{
+ return len * FRU_COMMON_HDR_LEN_MULTIPLIER;
+}
+
+static u8 fru_version(u8 ver)
+{
+ return ver & FRU_COMMON_HDR_VER_MASK;
+}
+
+static int fru_check_language(u8 code)
+{
+ if (code != FRU_LANG_CODE_ENGLISH && code != FRU_LANG_CODE_ENGLISH_1) {
+ printf("FRU_ERROR: Only English Language is supported\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+u8 fru_checksum(u8 *addr, u8 len)
+{
+ u8 checksum = 0;
+
+ while (len--) {
+ checksum += *addr;
+ addr++;
+ }
+
+ return checksum;
+}
+
+static int fru_check_type_len(u8 type_len, u8 language, u8 *type)
+{
+ int len;
+
+ if (type_len == FRU_TYPELEN_EOF)
+ return -EINVAL;
+
+ *type = (type_len & FRU_TYPELEN_CODE_MASK) >> FRU_TYPELEN_TYPE_SHIFT;
+
+ len = type_len & FRU_TYPELEN_LEN_MASK;
+
+ return len;
+}
+
+/* Return len */
+static u8 fru_gen_type_len(u8 *addr, char *name)
+{
+ int len = strlen(name);
+ struct fru_board_info_member *member;
+
+ member = (struct fru_board_info_member *)addr;
+ member->type_len = FRU_TYPELEN_TYPE_ASCII8 << FRU_TYPELEN_TYPE_SHIFT;
+ member->type_len |= len;
+
+ debug("%lx/%lx: Add %s to 0x%lx (len 0x%x)\n", (ulong)addr,
+ (ulong)&member->type_len, name, (ulong)&member->name, len);
+ memcpy(&member->name, name, len);
+
+ /* Add +1 for type_len parameter */
+ return 1 + len;
+}
+
+int fru_generate(unsigned long addr, char *manufacturer, char *board_name,
+ char *serial_no, char *part_no, char *revision)
+{
+ struct fru_common_hdr *header = (struct fru_common_hdr *)addr;
+ struct fru_board_info_header *board_info;
+ u8 *member;
+ u8 len, pad, modulo;
+
+ header->version = 1; /* Only version 1.0 is supported now */
+ header->off_internal = 0; /* not present */
+ header->off_chassis = 0; /* not present */
+ header->off_board = (sizeof(*header)) / 8; /* Starting offset 8 */
+ header->off_product = 0; /* not present */
+ header->off_multirec = 0; /* not present */
+ header->pad = 0;
+ /*
+ * This unsigned byte can be used to calculate a zero checksum
+ * for the data area following the header. I.e. the modulo 256 sum of
+ * the record data bytes plus the checksum byte equals zero.
+ */
+ header->crc = 0; /* Clear before calculation */
+ header->crc = 0 - fru_checksum((u8 *)header, sizeof(*header));
+
+ /* board info is just right after header */
+ board_info = (void *)((u8 *)header + sizeof(*header));
+
+ debug("header %lx, board_info %lx\n", (ulong)header, (ulong)board_info);
+
+ board_info->ver = 1; /* 1.0 spec */
+ board_info->lang_code = 0; /* English */
+ board_info->time[0] = 0; /* unspecified */
+ board_info->time[1] = 0; /* unspecified */
+ board_info->time[2] = 0; /* unspecified */
+
+ /* Member fields are just after board_info header */
+ member = (u8 *)board_info + sizeof(*board_info);
+
+ len = fru_gen_type_len(member, manufacturer); /* Board Manufacturer */
+ member += len;
+ len = fru_gen_type_len(member, board_name); /* Board Product name */
+ member += len;
+ len = fru_gen_type_len(member, serial_no); /* Board Serial number */
+ member += len;
+ len = fru_gen_type_len(member, part_no); /* Board part number */
+ member += len;
+ len = fru_gen_type_len(member, "U-Boot generator"); /* File ID */
+ member += len;
+ len = fru_gen_type_len(member, revision); /* Revision */
+ member += len;
+
+ *member++ = 0xc1; /* Indication of no more fields */
+
+ len = member - (u8 *)board_info; /* Find current length */
+ len += 1; /* Add checksum there too for calculation */
+
+ modulo = len % 8;
+
+ if (modulo) {
+ /* Do not fill last item which is checksum */
+ for (pad = 0; pad < 8 - modulo; pad++)
+ *member++ = 0;
+
+ /* Increase structure size */
+ len += 8 - modulo;
+ }
+
+ board_info->len = len / 8; /* Size in multiples of 8 bytes */
+
+ *member = 0; /* Clear before calculation */
+ *member = 0 - fru_checksum((u8 *)board_info, len);
+
+ debug("checksum %x(addr %x)\n", *member, len);
+
+ env_set_hex("fru_addr", addr);
+ env_set_hex("filesize", (unsigned long)member - addr + 1);
+
+ return 0;
+}
+
+static int fru_parse_board(unsigned long addr)
+{
+ u8 i, type;
+ int len;
+ u8 *data, *term;
+
+ memcpy(&fru_data.brd.ver, (void *)addr, 6);
+ addr += 6;
+ data = (u8 *)&fru_data.brd.manufacturer_type_len;
+
+ for (i = 0; ; i++, data += FRU_BOARD_MAX_LEN) {
+ len = fru_check_type_len(*(u8 *)addr, fru_data.brd.lang_code,
+ &type);
+ /*
+ * Stop cature if it end of fields
+ */
+ if (len == -EINVAL)
+ break;
+
+ /* This record type/len field */
+ *data++ = *(u8 *)addr;
+
+ /* Add offset to match data */
+ addr += 1;
+
+ /* If len is 0 it means empty field that's why skip writing */
+ if (!len)
+ continue;
+
+ /* Record data field */
+ memcpy(data, (u8 *)addr, len);
+ term = data + (u8)len;
+ *term = 0;
+ addr += len;
+ }
+
+ if (i < FRU_BOARD_AREA_TOTAL_FIELDS) {
+ printf("Board area require minimum %d fields\n",
+ FRU_BOARD_AREA_TOTAL_FIELDS);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int fru_capture(unsigned long addr)
+{
+ struct fru_common_hdr *hdr;
+ u8 checksum = 0;
+
+ checksum = fru_checksum((u8 *)addr, sizeof(struct fru_common_hdr));
+ if (checksum) {
+ printf("%s Common header CRC error\n", __func__);
+ return -EINVAL;
+ }
+
+ hdr = (struct fru_common_hdr *)addr;
+
+ memcpy((void *)&fru_data.hdr, (void *)hdr,
+ sizeof(struct fru_common_hdr));
+
+ fru_data.captured = true;
+
+ if (hdr->off_board) {
+ addr += fru_cal_area_len(hdr->off_board);
+ fru_parse_board(addr);
+ }
+
+ env_set_hex("fru_addr", addr);
+
+ return 0;
+}
+
+static int fru_display_board(struct fru_board_data *brd, int verbose)
+{
+ u32 time = 0;
+ u8 type;
+ int len;
+ u8 *data;
+ static const char * const typecode[] = {
+ "Binary/Unspecified",
+ "BCD plus",
+ "6-bit ASCII",
+ "8-bit ASCII",
+ "2-byte UNICODE"
+ };
+ static const char * const boardinfo[] = {
+ "Manufacturer Name",
+ "Product Name",
+ "Serial No",
+ "Part Number",
+ "File ID",
+ /* Xilinx spec */
+ "Revision Number",
+ };
+
+ if (verbose) {
+ printf("*****BOARD INFO*****\n");
+ printf("Version:%d\n", fru_version(brd->ver));
+ printf("Board Area Length:%d\n", fru_cal_area_len(brd->len));
+ }
+
+ if (fru_check_language(brd->lang_code))
+ return -EINVAL;
+
+ time = brd->time[2] << 16 | brd->time[1] << 8 |
+ brd->time[0];
+
+ if (verbose)
+ printf("Time in Minutes from 0:00hrs 1/1/96: %d\n", time);
+
+ data = (u8 *)&brd->manufacturer_type_len;
+
+ for (u8 i = 0; i < (sizeof(boardinfo) / sizeof(*boardinfo)); i++) {
+ len = fru_check_type_len(*data++, brd->lang_code,
+ &type);
+ if (len == -EINVAL) {
+ printf("**** EOF for Board Area ****\n");
+ break;
+ }
+
+ if (type <= FRU_TYPELEN_TYPE_ASCII8 &&
+ (brd->lang_code == FRU_LANG_CODE_ENGLISH ||
+ brd->lang_code == FRU_LANG_CODE_ENGLISH_1))
+ debug("Type code: %s\n", typecode[type]);
+ else
+ debug("Type code: %s\n", typecode[type + 1]);
+
+ if (!len) {
+ debug("%s not found\n", boardinfo[i]);
+ continue;
+ }
+
+ switch (type) {
+ case FRU_TYPELEN_TYPE_BINARY:
+ debug("Length: %d\n", len);
+ printf(" %s: 0x%x\n", boardinfo[i], *data);
+ break;
+ case FRU_TYPELEN_TYPE_ASCII8:
+ debug("Length: %d\n", len);
+ printf(" %s: %s\n", boardinfo[i], data);
+ break;
+ default:
+ debug("Unsupported type %x\n", type);
+ }
+
+ data += FRU_BOARD_MAX_LEN;
+ }
+
+ return 0;
+}
+
+static void fru_display_common_hdr(struct fru_common_hdr *hdr, int verbose)
+{
+ if (!verbose)
+ return;
+
+ printf("*****COMMON HEADER*****\n");
+ printf("Version:%d\n", fru_version(hdr->version));
+ if (hdr->off_internal)
+ printf("Internal Use Area Offset:%d\n",
+ fru_cal_area_len(hdr->off_internal));
+ else
+ printf("*** No Internal Area ***\n");
+
+ if (hdr->off_chassis)
+ printf("Chassis Info Area Offset:%d\n",
+ fru_cal_area_len(hdr->off_chassis));
+ else
+ printf("*** No Chassis Info Area ***\n");
+
+ if (hdr->off_board)
+ printf("Board Area Offset:%d\n",
+ fru_cal_area_len(hdr->off_board));
+ else
+ printf("*** No Board Area ***\n");
+
+ if (hdr->off_product)
+ printf("Product Info Area Offset:%d\n",
+ fru_cal_area_len(hdr->off_product));
+ else
+ printf("*** No Product Info Area ***\n");
+
+ if (hdr->off_multirec)
+ printf("MultiRecord Area Offset:%d\n",
+ fru_cal_area_len(hdr->off_multirec));
+ else
+ printf("*** No MultiRecord Area ***\n");
+}
+
+int fru_display(int verbose)
+{
+ if (!fru_data.captured) {
+ printf("FRU data not available please run fru parse\n");
+ return -EINVAL;
+ }
+
+ fru_display_common_hdr(&fru_data.hdr, verbose);
+
+ return fru_display_board(&fru_data.brd, verbose);
+}
diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c
index 4e569e9..e590999 100644
--- a/board/xilinx/microblaze-generic/microblaze-generic.c
+++ b/board/xilinx/microblaze-generic/microblaze-generic.c
@@ -18,6 +18,7 @@
#include <dm/lists.h>
#include <fdtdec.h>
#include <linux/sizes.h>
+#include "../common/board.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -36,7 +37,8 @@ int dram_init(void)
int board_late_init(void)
{
- ulong max_size, lowmem_size;
+ ulong max_size;
+ u32 status = 0;
#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SYSRESET_MICROBLAZE)
int ret;
@@ -55,12 +57,19 @@ int board_late_init(void)
max_size = gd->start_addr_sp - CONFIG_STACK_SIZE;
max_size = round_down(max_size, SZ_16M);
- /* Linux default LOWMEM_SIZE is 0x30000000 = 768MB */
- lowmem_size = gd->ram_base + 768 * 1024 * 1024;
+ status |= env_set_hex("scriptaddr", max_size + SZ_2M);
- env_set_addr("initrd_high", (void *)min_t(ulong, max_size,
- lowmem_size));
- env_set_addr("fdt_high", (void *)min_t(ulong, max_size, lowmem_size));
+ status |= env_set_hex("pxefile_addr_r", max_size + SZ_1M);
- return 0;
+ status |= env_set_hex("kernel_addr_r", gd->ram_base + SZ_32M);
+
+ status |= env_set_hex("fdt_addr_r", gd->ram_base + SZ_32M - SZ_1M);
+
+ status |= env_set_hex("ramdisk_addr_r",
+ gd->ram_base + SZ_32M + SZ_4M + SZ_2M);
+
+ if (status)
+ printf("%s: Saving run time variables FAILED\n", __func__);
+
+ return board_late_init_xilinx();
}
diff --git a/board/xilinx/versal/Makefile b/board/xilinx/versal/Makefile
index 90e0343..4a46ca0 100644
--- a/board/xilinx/versal/Makefile
+++ b/board/xilinx/versal/Makefile
@@ -6,4 +6,3 @@
obj-y := board.o
obj-$(CONFIG_CMD_VERSAL) += cmds.o
-obj-y += ../common/board.o
diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c
index a5ca4ca..912c114 100644
--- a/board/xilinx/versal/board.c
+++ b/board/xilinx/versal/board.c
@@ -36,6 +36,9 @@ int board_init(void)
fpga_add(fpga_xilinx, &versalpl);
#endif
+ if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM))
+ xilinx_read_eeprom();
+
return 0;
}
diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile
index 096a7ac..8566171 100644
--- a/board/xilinx/zynq/Makefile
+++ b/board/xilinx/zynq/Makefile
@@ -4,7 +4,6 @@
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
obj-y := board.o
-obj-y += ../common/board.o
ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"")
PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE))
diff --git a/board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c b/board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c
new file mode 100644
index 0000000..5d57386
--- /dev/null
+++ b/board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Xilinx, Inc.
+ */
+
+#include <asm/arch/ps7_init_gpl.h>
+
+static unsigned long ps7_pll_init_data[] = {
+ EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+ EMIT_MASKWRITE(0xF8000110, 0x003FFFF0U, 0x000FA220U),
+ EMIT_MASKWRITE(0xF8000100, 0x0007F000U, 0x00028000U),
+ EMIT_MASKWRITE(0xF8000100, 0x00000010U, 0x00000010U),
+ EMIT_MASKWRITE(0xF8000100, 0x00000001U, 0x00000001U),
+ EMIT_MASKWRITE(0xF8000100, 0x00000001U, 0x00000000U),
+ EMIT_MASKPOLL(0xF800010C, 0x00000001U),
+ EMIT_MASKWRITE(0xF8000100, 0x00000010U, 0x00000000U),
+ EMIT_MASKWRITE(0xF8000120, 0x1F003F30U, 0x1F000200U),
+ EMIT_MASKWRITE(0xF8000114, 0x003FFFF0U, 0x0012C220U),
+ EMIT_MASKWRITE(0xF8000104, 0x0007F000U, 0x00020000U),
+ EMIT_MASKWRITE(0xF8000104, 0x00000010U, 0x00000010U),
+ EMIT_MASKWRITE(0xF8000104, 0x00000001U, 0x00000001U),
+ EMIT_MASKWRITE(0xF8000104, 0x00000001U, 0x00000000U),
+ EMIT_MASKPOLL(0xF800010C, 0x00000002U),
+ EMIT_MASKWRITE(0xF8000104, 0x00000010U, 0x00000000U),
+ EMIT_MASKWRITE(0xF8000124, 0xFFF00003U, 0x0C200003U),
+ EMIT_MASKWRITE(0xF8000118, 0x003FFFF0U, 0x001452C0U),
+ EMIT_MASKWRITE(0xF8000108, 0x0007F000U, 0x0001E000U),
+ EMIT_MASKWRITE(0xF8000108, 0x00000010U, 0x00000010U),
+ EMIT_MASKWRITE(0xF8000108, 0x00000001U, 0x00000001U),
+ EMIT_MASKWRITE(0xF8000108, 0x00000001U, 0x00000000U),
+ EMIT_MASKPOLL(0xF800010C, 0x00000004U),
+ EMIT_MASKWRITE(0xF8000108, 0x00000010U, 0x00000000U),
+ EMIT_WRITE(0xF8000004, 0x0000767BU),
+ EMIT_EXIT(),
+};
+
+static unsigned long ps7_clock_init_data[] = {
+ EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+ EMIT_MASKWRITE(0xF8000128, 0x03F03F01U, 0x00700F01U),
+ EMIT_MASKWRITE(0xF8000138, 0x00000011U, 0x00000001U),
+ EMIT_MASKWRITE(0xF8000140, 0x03F03F71U, 0x00100801U),
+ EMIT_MASKWRITE(0xF800014C, 0x00003F31U, 0x00000501U),
+ EMIT_MASKWRITE(0xF8000150, 0x00003F33U, 0x00001401U),
+ EMIT_MASKWRITE(0xF8000154, 0x00003F33U, 0x00000A03U),
+ EMIT_MASKWRITE(0xF800015C, 0x03F03F33U, 0x00200501U),
+ EMIT_MASKWRITE(0xF8000160, 0x007F007FU, 0x00000000U),
+ EMIT_MASKWRITE(0xF8000168, 0x00003F31U, 0x00000501U),
+ EMIT_MASKWRITE(0xF8000170, 0x03F03F30U, 0x00200500U),
+ EMIT_MASKWRITE(0xF8000180, 0x03F03F30U, 0x00400500U),
+ EMIT_MASKWRITE(0xF80001C4, 0x00000001U, 0x00000001U),
+ EMIT_MASKWRITE(0xF800012C, 0x01FFCCCDU, 0x01FD044DU),
+ EMIT_WRITE(0xF8000004, 0x0000767BU),
+ EMIT_EXIT(),
+};
+
+static unsigned long ps7_ddr_init_data[] = {
+ EMIT_MASKWRITE(0xF8006000, 0x0001FFFFU, 0x00000080U),
+ EMIT_MASKWRITE(0xF8006004, 0x0007FFFFU, 0x00001082U),
+ EMIT_MASKWRITE(0xF8006008, 0x03FFFFFFU, 0x03C0780FU),
+ EMIT_MASKWRITE(0xF800600C, 0x03FFFFFFU, 0x02001001U),
+ EMIT_MASKWRITE(0xF8006010, 0x03FFFFFFU, 0x00014001U),
+ EMIT_MASKWRITE(0xF8006014, 0x001FFFFFU, 0x0004285BU),
+ EMIT_MASKWRITE(0xF8006018, 0xF7FFFFFFU, 0x44E458D3U),
+ EMIT_MASKWRITE(0xF800601C, 0xFFFFFFFFU, 0x7282BCE5U),
+ EMIT_MASKWRITE(0xF8006020, 0x7FDFFFFCU, 0x270872D0U),
+ EMIT_MASKWRITE(0xF8006024, 0x0FFFFFC3U, 0x00000000U),
+ EMIT_MASKWRITE(0xF8006028, 0x00003FFFU, 0x00002007U),
+ EMIT_MASKWRITE(0xF800602C, 0xFFFFFFFFU, 0x00000008U),
+ EMIT_MASKWRITE(0xF8006030, 0xFFFFFFFFU, 0x00040B30U),
+ EMIT_MASKWRITE(0xF8006034, 0x13FF3FFFU, 0x000116D4U),
+ EMIT_MASKWRITE(0xF8006038, 0x00000003U, 0x00000000U),
+ EMIT_MASKWRITE(0xF800603C, 0x000FFFFFU, 0x00000777U),
+ EMIT_MASKWRITE(0xF8006040, 0xFFFFFFFFU, 0xFFF00000U),
+ EMIT_MASKWRITE(0xF8006044, 0x0FFFFFFFU, 0x0F666666U),
+ EMIT_MASKWRITE(0xF8006048, 0x0003F03FU, 0x0003C008U),
+ EMIT_MASKWRITE(0xF8006050, 0xFF0F8FFFU, 0x77010800U),
+ EMIT_MASKWRITE(0xF8006058, 0x00010000U, 0x00000000U),
+ EMIT_MASKWRITE(0xF800605C, 0x0000FFFFU, 0x00005003U),
+ EMIT_MASKWRITE(0xF8006060, 0x000017FFU, 0x0000003EU),
+ EMIT_MASKWRITE(0xF8006064, 0x00021FE0U, 0x00020000U),
+ EMIT_MASKWRITE(0xF8006068, 0x03FFFFFFU, 0x00284141U),
+ EMIT_MASKWRITE(0xF800606C, 0x0000FFFFU, 0x00001610U),
+ EMIT_MASKWRITE(0xF8006078, 0x03FFFFFFU, 0x00466111U),
+ EMIT_MASKWRITE(0xF800607C, 0x000FFFFFU, 0x00032222U),
+ EMIT_MASKWRITE(0xF80060A4, 0xFFFFFFFFU, 0x10200802U),
+ EMIT_MASKWRITE(0xF80060A8, 0x0FFFFFFFU, 0x0690CB73U),
+ EMIT_MASKWRITE(0xF80060AC, 0x000001FFU, 0x000001FEU),
+ EMIT_MASKWRITE(0xF80060B0, 0x1FFFFFFFU, 0x1CFFFFFFU),
+ EMIT_MASKWRITE(0xF80060B4, 0x00000200U, 0x00000200U),
+ EMIT_MASKWRITE(0xF80060B8, 0x01FFFFFFU, 0x00200066U),
+ EMIT_MASKWRITE(0xF80060C4, 0x00000003U, 0x00000000U),
+ EMIT_MASKWRITE(0xF80060C8, 0x000000FFU, 0x00000000U),
+ EMIT_MASKWRITE(0xF80060DC, 0x00000001U, 0x00000000U),
+ EMIT_MASKWRITE(0xF80060F0, 0x0000FFFFU, 0x00000000U),
+ EMIT_MASKWRITE(0xF80060F4, 0x0000000FU, 0x00000008U),
+ EMIT_MASKWRITE(0xF8006114, 0x000000FFU, 0x00000000U),
+ EMIT_MASKWRITE(0xF8006118, 0x7FFFFFCFU, 0x40000001U),
+ EMIT_MASKWRITE(0xF800611C, 0x7FFFFFCFU, 0x40000001U),
+ EMIT_MASKWRITE(0xF8006120, 0x7FFFFFCFU, 0x40000001U),
+ EMIT_MASKWRITE(0xF8006124, 0x7FFFFFCFU, 0x40000001U),
+ EMIT_MASKWRITE(0xF800612C, 0x000FFFFFU, 0x0002A81FU),
+ EMIT_MASKWRITE(0xF8006130, 0x000FFFFFU, 0x00029822U),
+ EMIT_MASKWRITE(0xF8006134, 0x000FFFFFU, 0x00026C10U),
+ EMIT_MASKWRITE(0xF8006138, 0x000FFFFFU, 0x00026013U),
+ EMIT_MASKWRITE(0xF8006140, 0x000FFFFFU, 0x00000035U),
+ EMIT_MASKWRITE(0xF8006144, 0x000FFFFFU, 0x00000035U),
+ EMIT_MASKWRITE(0xF8006148, 0x000FFFFFU, 0x00000035U),
+ EMIT_MASKWRITE(0xF800614C, 0x000FFFFFU, 0x00000035U),
+ EMIT_MASKWRITE(0xF8006154, 0x000FFFFFU, 0x0000009FU),
+ EMIT_MASKWRITE(0xF8006158, 0x000FFFFFU, 0x000000A2U),
+ EMIT_MASKWRITE(0xF800615C, 0x000FFFFFU, 0x00000090U),
+ EMIT_MASKWRITE(0xF8006160, 0x000FFFFFU, 0x00000093U),
+ EMIT_MASKWRITE(0xF8006168, 0x001FFFFFU, 0x000000FFU),
+ EMIT_MASKWRITE(0xF800616C, 0x001FFFFFU, 0x000000FBU),
+ EMIT_MASKWRITE(0xF8006170, 0x001FFFFFU, 0x000000F0U),
+ EMIT_MASKWRITE(0xF8006174, 0x001FFFFFU, 0x000000EDU),
+ EMIT_MASKWRITE(0xF800617C, 0x000FFFFFU, 0x000000DFU),
+ EMIT_MASKWRITE(0xF8006180, 0x000FFFFFU, 0x000000E2U),
+ EMIT_MASKWRITE(0xF8006184, 0x000FFFFFU, 0x000000D0U),
+ EMIT_MASKWRITE(0xF8006188, 0x000FFFFFU, 0x000000D3U),
+ EMIT_MASKWRITE(0xF8006190, 0x6FFFFEFEU, 0x00040080U),
+ EMIT_MASKWRITE(0xF8006194, 0x000FFFFFU, 0x0001FC82U),
+ EMIT_MASKWRITE(0xF8006204, 0xFFFFFFFFU, 0x00000000U),
+ EMIT_MASKWRITE(0xF8006208, 0x000703FFU, 0x000003FFU),
+ EMIT_MASKWRITE(0xF800620C, 0x000703FFU, 0x000003FFU),
+ EMIT_MASKWRITE(0xF8006210, 0x000703FFU, 0x000003FFU),
+ EMIT_MASKWRITE(0xF8006214, 0x000703FFU, 0x000003FFU),
+ EMIT_MASKWRITE(0xF8006218, 0x000F03FFU, 0x000003FFU),
+ EMIT_MASKWRITE(0xF800621C, 0x000F03FFU, 0x000003FFU),
+ EMIT_MASKWRITE(0xF8006220, 0x000F03FFU, 0x000003FFU),
+ EMIT_MASKWRITE(0xF8006224, 0x000F03FFU, 0x000003FFU),
+ EMIT_MASKWRITE(0xF80062A8, 0x00000FF5U, 0x00000000U),
+ EMIT_MASKWRITE(0xF80062AC, 0xFFFFFFFFU, 0x00000000U),
+ EMIT_MASKWRITE(0xF80062B0, 0x003FFFFFU, 0x00005125U),
+ EMIT_MASKWRITE(0xF80062B4, 0x0003FFFFU, 0x000012A8U),
+ EMIT_MASKPOLL(0xF8000B74, 0x00002000U),
+ EMIT_MASKWRITE(0xF8006000, 0x0001FFFFU, 0x00000081U),
+ EMIT_MASKPOLL(0xF8006054, 0x00000007U),
+ EMIT_EXIT(),
+};
+
+static unsigned long ps7_mio_init_data[] = {
+ EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+ EMIT_MASKWRITE(0xF8000B40, 0x00000FFFU, 0x00000600U),
+ EMIT_MASKWRITE(0xF8000B44, 0x00000FFFU, 0x00000600U),
+ EMIT_MASKWRITE(0xF8000B48, 0x00000FFFU, 0x00000672U),
+ EMIT_MASKWRITE(0xF8000B4C, 0x00000FFFU, 0x00000672U),
+ EMIT_MASKWRITE(0xF8000B50, 0x00000FFFU, 0x00000674U),
+ EMIT_MASKWRITE(0xF8000B54, 0x00000FFFU, 0x00000674U),
+ EMIT_MASKWRITE(0xF8000B58, 0x00000FFFU, 0x00000600U),
+ EMIT_MASKWRITE(0xF8000B5C, 0xFFFFFFFFU, 0x0018C61CU),
+ EMIT_MASKWRITE(0xF8000B60, 0xFFFFFFFFU, 0x00F9861CU),
+ EMIT_MASKWRITE(0xF8000B64, 0xFFFFFFFFU, 0x00F9861CU),
+ EMIT_MASKWRITE(0xF8000B68, 0xFFFFFFFFU, 0x00F9861CU),
+ EMIT_MASKWRITE(0xF8000B6C, 0x00007FFFU, 0x00000260U),
+ EMIT_MASKWRITE(0xF8000B70, 0x00000001U, 0x00000001U),
+ EMIT_MASKWRITE(0xF8000B70, 0x00000021U, 0x00000020U),
+ EMIT_MASKWRITE(0xF8000B70, 0x07FEFFFFU, 0x00000823U),
+ EMIT_MASKWRITE(0xF8000700, 0x00003FFFU, 0x00001600U),
+ EMIT_MASKWRITE(0xF8000704, 0x00003FFFU, 0x00000602U),
+ EMIT_MASKWRITE(0xF8000708, 0x00003FFFU, 0x00000602U),
+ EMIT_MASKWRITE(0xF800070C, 0x00003FFFU, 0x00000602U),
+ EMIT_MASKWRITE(0xF8000710, 0x00003FFFU, 0x00000602U),
+ EMIT_MASKWRITE(0xF8000714, 0x00003FFFU, 0x00000602U),
+ EMIT_MASKWRITE(0xF8000718, 0x00003FFFU, 0x00000602U),
+ EMIT_MASKWRITE(0xF800071C, 0x00003FFFU, 0x00000600U),
+ EMIT_MASKWRITE(0xF8000720, 0x00003FFFU, 0x00000602U),
+ EMIT_MASKWRITE(0xF8000724, 0x00003FFFU, 0x00000600U),
+ EMIT_MASKWRITE(0xF8000728, 0x00003FFFU, 0x000016E1U),
+ EMIT_MASKWRITE(0xF800072C, 0x00003FFFU, 0x000016E0U),
+ EMIT_MASKWRITE(0xF8000730, 0x00003FFFU, 0x00001640U),
+ EMIT_MASKWRITE(0xF8000734, 0x00003FFFU, 0x00001640U),
+ EMIT_MASKWRITE(0xF8000738, 0x00003FFFU, 0x00001621U),
+ EMIT_MASKWRITE(0xF800073C, 0x00003FFFU, 0x00001620U),
+ EMIT_MASKWRITE(0xF8000740, 0x00003FFFU, 0x00001202U),
+ EMIT_MASKWRITE(0xF8000744, 0x00003FFFU, 0x00001202U),
+ EMIT_MASKWRITE(0xF8000748, 0x00003FFFU, 0x00001202U),
+ EMIT_MASKWRITE(0xF800074C, 0x00003FFFU, 0x00001202U),
+ EMIT_MASKWRITE(0xF8000750, 0x00003FFFU, 0x00001202U),
+ EMIT_MASKWRITE(0xF8000754, 0x00003FFFU, 0x00001202U),
+ EMIT_MASKWRITE(0xF8000758, 0x00003FFFU, 0x00001203U),
+ EMIT_MASKWRITE(0xF800075C, 0x00003FFFU, 0x00001203U),
+ EMIT_MASKWRITE(0xF8000760, 0x00003FFFU, 0x00001203U),
+ EMIT_MASKWRITE(0xF8000764, 0x00003FFFU, 0x00001203U),
+ EMIT_MASKWRITE(0xF8000768, 0x00003FFFU, 0x00001203U),
+ EMIT_MASKWRITE(0xF800076C, 0x00003FFFU, 0x00001203U),
+ EMIT_MASKWRITE(0xF8000770, 0x00003FFFU, 0x00001204U),
+ EMIT_MASKWRITE(0xF8000774, 0x00003FFFU, 0x00001205U),
+ EMIT_MASKWRITE(0xF8000778, 0x00003FFFU, 0x00001204U),
+ EMIT_MASKWRITE(0xF800077C, 0x00003FFFU, 0x00001205U),
+ EMIT_MASKWRITE(0xF8000780, 0x00003FFFU, 0x00001204U),
+ EMIT_MASKWRITE(0xF8000784, 0x00003FFFU, 0x00001204U),
+ EMIT_MASKWRITE(0xF8000788, 0x00003FFFU, 0x00001204U),
+ EMIT_MASKWRITE(0xF800078C, 0x00003FFFU, 0x00001204U),
+ EMIT_MASKWRITE(0xF8000790, 0x00003FFFU, 0x00001205U),
+ EMIT_MASKWRITE(0xF8000794, 0x00003FFFU, 0x00001204U),
+ EMIT_MASKWRITE(0xF8000798, 0x00003FFFU, 0x00001204U),
+ EMIT_MASKWRITE(0xF800079C, 0x00003FFFU, 0x00001204U),
+ EMIT_MASKWRITE(0xF80007A0, 0x00003FFFU, 0x00001280U),
+ EMIT_MASKWRITE(0xF80007A4, 0x00003FFFU, 0x00001280U),
+ EMIT_MASKWRITE(0xF80007A8, 0x00003FFFU, 0x00001280U),
+ EMIT_MASKWRITE(0xF80007AC, 0x00003FFFU, 0x00001280U),
+ EMIT_MASKWRITE(0xF80007B0, 0x00003FFFU, 0x00001280U),
+ EMIT_MASKWRITE(0xF80007B4, 0x00003FFFU, 0x00001280U),
+ EMIT_MASKWRITE(0xF80007B8, 0x00003F01U, 0x00000201U),
+ EMIT_MASKWRITE(0xF80007BC, 0x00003F01U, 0x00000201U),
+ EMIT_MASKWRITE(0xF80007C0, 0x00003FFFU, 0x000012E0U),
+ EMIT_MASKWRITE(0xF80007C4, 0x00003FFFU, 0x000012E1U),
+ EMIT_MASKWRITE(0xF80007C8, 0x00003FFFU, 0x00000200U),
+ EMIT_MASKWRITE(0xF80007CC, 0x00003FFFU, 0x00000200U),
+ EMIT_MASKWRITE(0xF80007D0, 0x00003FFFU, 0x00001280U),
+ EMIT_MASKWRITE(0xF80007D4, 0x00003FFFU, 0x00001280U),
+ EMIT_MASKWRITE(0xF8000830, 0x003F003FU, 0x002E002FU),
+ EMIT_WRITE(0xF8000004, 0x0000767BU),
+ EMIT_EXIT(),
+};
+
+static unsigned long ps7_peripherals_init_data[] = {
+ EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+ EMIT_MASKWRITE(0xF8000B48, 0x00000180U, 0x00000180U),
+ EMIT_MASKWRITE(0xF8000B4C, 0x00000180U, 0x00000180U),
+ EMIT_MASKWRITE(0xF8000B50, 0x00000180U, 0x00000180U),
+ EMIT_MASKWRITE(0xF8000B54, 0x00000180U, 0x00000180U),
+ EMIT_WRITE(0xF8000004, 0x0000767BU),
+ EMIT_MASKWRITE(0xE000D000, 0x00080000U, 0x00080000U),
+ EMIT_MASKWRITE(0xF8007000, 0x20000000U, 0x00000000U),
+ EMIT_MASKWRITE(0xE000A244, 0x003FFFFFU, 0x00080000U),
+ EMIT_MASKWRITE(0xE000A00C, 0x003F003FU, 0x00370008U),
+ EMIT_MASKWRITE(0xE000A248, 0x003FFFFFU, 0x00080000U),
+ EMIT_MASKWRITE(0xE000A00C, 0x003F003FU, 0x00370000U),
+ EMIT_MASKDELAY(0xF8F00200, 1),
+ EMIT_MASKWRITE(0xE000A00C, 0x003F003FU, 0x00370008U),
+ EMIT_EXIT(),
+};
+
+static unsigned long ps7_post_config_0[] = {
+ EMIT_WRITE(0xF8000008, 0x0000DF0DU),
+ EMIT_MASKWRITE(0xF8000900, 0x0000000FU, 0x0000000FU),
+ EMIT_MASKWRITE(0xF8000240, 0xFFFFFFFFU, 0x00000000U),
+ EMIT_WRITE(0xF8000004, 0x0000767BU),
+ EMIT_EXIT(),
+};
+
+int ps7_post_config(void)
+{
+ return ps7_config(ps7_post_config_0);
+}
+
+int ps7_init(void)
+{
+ int ret;
+
+ ret = ps7_config(ps7_mio_init_data);
+ if (ret != PS7_INIT_SUCCESS)
+ return ret;
+
+ ret = ps7_config(ps7_pll_init_data);
+ if (ret != PS7_INIT_SUCCESS)
+ return ret;
+
+ ret = ps7_config(ps7_clock_init_data);
+ if (ret != PS7_INIT_SUCCESS)
+ return ret;
+
+ ret = ps7_config(ps7_ddr_init_data);
+ if (ret != PS7_INIT_SUCCESS)
+ return ret;
+
+ ret = ps7_config(ps7_peripherals_init_data);
+ if (ret != PS7_INIT_SUCCESS)
+ return ret;
+ return PS7_INIT_SUCCESS;
+}
diff --git a/board/xilinx/zynqmp/MAINTAINERS b/board/xilinx/zynqmp/MAINTAINERS
index 04fc7f3..9cd4f3f 100644
--- a/board/xilinx/zynqmp/MAINTAINERS
+++ b/board/xilinx/zynqmp/MAINTAINERS
@@ -3,6 +3,7 @@ M: Michal Simek <michal.simek@xilinx.com>
S: Maintained
F: arch/arm/dts/zynqmp-*
F: arch/arm/dts/avnet-ultra96*
+F: board/xilinx/common/
F: board/xilinx/zynqmp/
F: include/configs/xilinx_zynqmp*
F: configs/xilinx_zynqmp*
diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile
index 398c6aa..7d8277c 100644
--- a/board/xilinx/zynqmp/Makefile
+++ b/board/xilinx/zynqmp/Makefile
@@ -4,7 +4,6 @@
# Michal Simek <michal.simek@xilinx.com>
obj-y := zynqmp.o
-obj-y += ../common/board.o
ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"")
PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE))
diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c
index c0d28a7..cf63ad9 100644
--- a/board/xilinx/zynqmp/cmds.c
+++ b/board/xilinx/zynqmp/cmds.c
@@ -9,11 +9,22 @@
#include <cpu_func.h>
#include <env.h>
#include <malloc.h>
+#include <memalign.h>
#include <zynqmp_firmware.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
+struct aes {
+ u64 srcaddr;
+ u64 ivaddr;
+ u64 keyaddr;
+ u64 dstaddr;
+ u64 len;
+ u64 op;
+ u64 keysrc;
+};
+
static int do_zynqmp_verify_secure(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
@@ -107,6 +118,66 @@ static int do_zynqmp_mmio_write(struct cmd_tbl *cmdtp, int flag, int argc,
return ret;
}
+static int do_zynqmp_aes(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ ALLOC_CACHE_ALIGN_BUFFER(struct aes, aes, 1);
+ int ret;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ if (zynqmp_firmware_version() <= PMUFW_V1_0) {
+ puts("ERR: PMUFW v1.0 or less is detected\n");
+ puts("ERR: Encrypt/Decrypt feature is not supported\n");
+ puts("ERR: Please upgrade PMUFW\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc < cmdtp->maxargs - 1)
+ return CMD_RET_USAGE;
+
+ aes->srcaddr = simple_strtoul(argv[2], NULL, 16);
+ aes->ivaddr = simple_strtoul(argv[3], NULL, 16);
+ aes->len = simple_strtoul(argv[4], NULL, 16);
+ aes->op = simple_strtoul(argv[5], NULL, 16);
+ aes->keysrc = simple_strtoul(argv[6], NULL, 16);
+ aes->dstaddr = simple_strtoul(argv[7], NULL, 16);
+
+ flush_dcache_range((ulong)aes, (ulong)(aes) +
+ roundup(sizeof(struct aes), ARCH_DMA_MINALIGN));
+
+ if (aes->srcaddr && aes->ivaddr && aes->dstaddr) {
+ flush_dcache_range(aes->srcaddr,
+ (aes->srcaddr +
+ roundup(aes->len, ARCH_DMA_MINALIGN)));
+ flush_dcache_range(aes->ivaddr,
+ (aes->ivaddr +
+ roundup(IV_SIZE, ARCH_DMA_MINALIGN)));
+ flush_dcache_range(aes->dstaddr,
+ (aes->dstaddr +
+ roundup(aes->len, ARCH_DMA_MINALIGN)));
+ }
+
+ if (aes->keysrc == 0) {
+ if (argc < cmdtp->maxargs)
+ return CMD_RET_USAGE;
+
+ aes->keyaddr = simple_strtoul(argv[8], NULL, 16);
+ if (aes->keyaddr)
+ flush_dcache_range(aes->keyaddr,
+ (aes->keyaddr +
+ roundup(KEY_PTR_LEN,
+ ARCH_DMA_MINALIGN)));
+ }
+
+ ret = xilinx_pm_request(PM_SECURE_AES, upper_32_bits((ulong)aes),
+ lower_32_bits((ulong)aes), 0, 0, ret_payload);
+ if (ret || ret_payload[1])
+ printf("Failed: AES op status:0x%x, errcode:0x%x\n",
+ ret, ret_payload[1]);
+
+ return ret;
+}
+
#ifdef CONFIG_DEFINE_TCM_OCM_MMAP
static int do_zynqmp_tcm_init(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
@@ -148,11 +219,145 @@ static int do_zynqmp_pmufw(struct cmd_tbl *cmdtp, int flag, int argc,
return 0;
}
+static int do_zynqmp_rsa(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ u64 srcaddr, mod, exp;
+ u32 srclen, rsaop, size, ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ if (argc != cmdtp->maxargs)
+ return CMD_RET_USAGE;
+
+ if (zynqmp_firmware_version() <= PMUFW_V1_0) {
+ puts("ERR: PMUFW v1.0 or less is detected\n");
+ puts("ERR: Encrypt/Decrypt feature is not supported\n");
+ puts("ERR: Please upgrade PMUFW\n");
+ return CMD_RET_FAILURE;
+ }
+
+ srcaddr = simple_strtoul(argv[2], NULL, 16);
+ srclen = simple_strtoul(argv[3], NULL, 16);
+ if (srclen != RSA_KEY_SIZE) {
+ puts("ERR: srclen should be equal to 0x200(512 bytes)\n");
+ return CMD_RET_USAGE;
+ }
+
+ mod = simple_strtoul(argv[4], NULL, 16);
+ exp = simple_strtoul(argv[5], NULL, 16);
+ rsaop = simple_strtoul(argv[6], NULL, 16);
+ if (!(rsaop == 0 || rsaop == 1)) {
+ puts("ERR: rsaop should be either 0 or 1\n");
+ return CMD_RET_USAGE;
+ }
+
+ memcpy((void *)srcaddr + srclen, (void *)mod, MODULUS_LEN);
+
+ /*
+ * For encryption we load public exponent (key size 4096-bits),
+ * for decryption we load private exponent (32-bits)
+ */
+ if (rsaop) {
+ memcpy((void *)srcaddr + srclen + MODULUS_LEN,
+ (void *)exp, PUB_EXPO_LEN);
+ size = srclen + MODULUS_LEN + PUB_EXPO_LEN;
+ } else {
+ memcpy((void *)srcaddr + srclen + MODULUS_LEN,
+ (void *)exp, PRIV_EXPO_LEN);
+ size = srclen + MODULUS_LEN + PRIV_EXPO_LEN;
+ }
+
+ flush_dcache_range((ulong)srcaddr,
+ (ulong)(srcaddr) + roundup(size, ARCH_DMA_MINALIGN));
+
+ ret = xilinx_pm_request(PM_SECURE_RSA, upper_32_bits((ulong)srcaddr),
+ lower_32_bits((ulong)srcaddr), srclen, rsaop,
+ ret_payload);
+ if (ret || ret_payload[1]) {
+ printf("Failed: RSA status:0x%x, errcode:0x%x\n",
+ ret, ret_payload[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_zynqmp_sha3(struct cmd_tbl *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ u64 srcaddr, hashaddr;
+ u32 srclen, ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ if (argc > cmdtp->maxargs || argc < (cmdtp->maxargs - 1))
+ return CMD_RET_USAGE;
+
+ if (zynqmp_firmware_version() <= PMUFW_V1_0) {
+ puts("ERR: PMUFW v1.0 or less is detected\n");
+ puts("ERR: Encrypt/Decrypt feature is not supported\n");
+ puts("ERR: Please upgrade PMUFW\n");
+ return CMD_RET_FAILURE;
+ }
+
+ srcaddr = simple_strtoul(argv[2], NULL, 16);
+ srclen = simple_strtoul(argv[3], NULL, 16);
+
+ if (argc == 5) {
+ hashaddr = simple_strtoul(argv[4], NULL, 16);
+ flush_dcache_range(hashaddr,
+ hashaddr + roundup(ZYNQMP_SHA3_SIZE,
+ ARCH_DMA_MINALIGN));
+ } else {
+ hashaddr = srcaddr;
+ }
+
+ /* Check srcaddr or srclen != 0 */
+ if (!srcaddr || !srclen) {
+ puts("ERR: srcaddr & srclen should not be 0\n");
+ return CMD_RET_USAGE;
+ }
+
+ flush_dcache_range(srcaddr,
+ srcaddr + roundup(srclen, ARCH_DMA_MINALIGN));
+
+ ret = xilinx_pm_request(PM_SECURE_SHA, 0, 0, 0,
+ ZYNQMP_SHA3_INIT, ret_payload);
+ if (ret || ret_payload[1]) {
+ printf("Failed: SHA INIT status:0x%x, errcode:0x%x\n",
+ ret, ret_payload[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ ret = xilinx_pm_request(PM_SECURE_SHA, upper_32_bits((ulong)srcaddr),
+ lower_32_bits((ulong)srcaddr),
+ srclen, ZYNQMP_SHA3_UPDATE, ret_payload);
+ if (ret || ret_payload[1]) {
+ printf("Failed: SHA UPDATE status:0x%x, errcode:0x%x\n",
+ ret, ret_payload[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ ret = xilinx_pm_request(PM_SECURE_SHA, upper_32_bits((ulong)hashaddr),
+ lower_32_bits((ulong)hashaddr),
+ ZYNQMP_SHA3_SIZE, ZYNQMP_SHA3_FINAL,
+ ret_payload);
+ if (ret || ret_payload[1]) {
+ printf("Failed: SHA FINAL status:0x%x, errcode:0x%x\n",
+ ret, ret_payload[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
static struct cmd_tbl cmd_zynqmp_sub[] = {
U_BOOT_CMD_MKENT(secure, 5, 0, do_zynqmp_verify_secure, "", ""),
U_BOOT_CMD_MKENT(pmufw, 4, 0, do_zynqmp_pmufw, "", ""),
U_BOOT_CMD_MKENT(mmio_read, 3, 0, do_zynqmp_mmio_read, "", ""),
U_BOOT_CMD_MKENT(mmio_write, 5, 0, do_zynqmp_mmio_write, "", ""),
+ U_BOOT_CMD_MKENT(aes, 9, 0, do_zynqmp_aes, "", ""),
+ U_BOOT_CMD_MKENT(rsa, 7, 0, do_zynqmp_rsa, "", ""),
+ U_BOOT_CMD_MKENT(sha3, 5, 0, do_zynqmp_sha3, "", ""),
#ifdef CONFIG_DEFINE_TCM_OCM_MMAP
U_BOOT_CMD_MKENT(tcminit, 3, 0, do_zynqmp_tcm_init, "", ""),
#endif
@@ -196,6 +401,14 @@ static char zynqmp_help_text[] =
"zynqmp mmio_read address - read from address\n"
"zynqmp mmio_write address mask value - write value after masking to\n"
" address\n"
+ "zynqmp aes srcaddr ivaddr len aesop keysrc dstaddr [keyaddr] -\n"
+ " Encrypts or decrypts blob of data at src address and puts it\n"
+ " back to dstaddr using key and iv at keyaddr and ivaddr\n"
+ " respectively. keysrc value specifies from which source key\n"
+ " has to be used, it can be User/Device/PUF key. A value of 0\n"
+ " for KUP(user key),1 for DeviceKey and 2 for PUF key. The\n"
+ " aesop value specifies the operation which can be 0 for\n"
+ " decrypt and 1 for encrypt operation\n"
#ifdef CONFIG_DEFINE_TCM_OCM_MMAP
"zynqmp tcminit mode - Initialize the TCM with zeros. TCM needs to be\n"
" initialized before accessing to avoid ECC\n"
@@ -204,11 +417,24 @@ static char zynqmp_help_text[] =
" lock(0)/split(1)\n"
#endif
"zynqmp pmufw address size - load PMU FW configuration object\n"
+ "zynqmp rsa srcaddr srclen mod exp rsaop -\n"
+ " Performs RSA encryption and RSA decryption on blob of data\n"
+ " at srcaddr and puts it back in srcaddr using modulus and\n"
+ " public or private exponent\n"
+ " srclen : must be key size(4096 bits)\n"
+ " exp : private key exponent for RSA decryption(4096 bits)\n"
+ " public key exponent for RSA encryption(32 bits)\n"
+ " rsaop : 0 for RSA Decryption, 1 for RSA Encryption\n"
+ "zynqmp sha3 srcaddr srclen [key_addr] -\n"
+ " Generates sha3 hash value for data blob at srcaddr and puts\n"
+ " 48 bytes hash value into srcaddr\n"
+ " Optional key_addr can be specified for saving sha3 hash value\n"
+ " Note: srcaddr/srclen should not be 0\n"
;
#endif
U_BOOT_CMD(
- zynqmp, 5, 1, do_zynqmp,
+ zynqmp, 9, 1, do_zynqmp,
"ZynqMP sub-system",
zynqmp_help_text
)
diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
index 5fde0ae..1cab25f 100644
--- a/board/xilinx/zynqmp/tap_delays.c
+++ b/board/xilinx/zynqmp/tap_delays.c
@@ -6,8 +6,10 @@
*/
#include <common.h>
+#include <zynqmp_tap_delay.h>
#include <asm/arch/sys_proto.h>
#include <linux/delay.h>
+#include <mmc.h>
#define SD_DLL_CTRL 0xFF180358
#define SD_ITAP_DLY 0xFF180314
@@ -25,43 +27,9 @@
#define SD1_ITAPDLYENA_MASK 0x01000000
#define SD1_ITAPDLYENA 0x01000000
#define SD0_ITAPDLYSEL_MASK 0x000000FF
-#define SD0_ITAPDLYSEL_HSD 0x00000015
-#define SD0_ITAPDLYSEL_SD_DDR50 0x0000003D
-#define SD0_ITAPDLYSEL_MMC_DDR50 0x00000012
-
#define SD1_ITAPDLYSEL_MASK 0x00FF0000
-#define SD1_ITAPDLYSEL_HSD 0x00150000
-#define SD1_ITAPDLYSEL_SD_DDR50 0x003D0000
-#define SD1_ITAPDLYSEL_MMC_DDR50 0x00120000
-
#define SD0_OTAPDLYSEL_MASK 0x0000003F
-#define SD0_OTAPDLYSEL_MMC_HSD 0x00000006
-#define SD0_OTAPDLYSEL_SD_HSD 0x00000005
-#define SD0_OTAPDLYSEL_SDR50 0x00000003
-#define SD0_OTAPDLYSEL_SDR104_B0 0x00000003
-#define SD0_OTAPDLYSEL_SDR104_B2 0x00000002
-#define SD0_OTAPDLYSEL_SD_DDR50 0x00000004
-#define SD0_OTAPDLYSEL_MMC_DDR50 0x00000006
-
#define SD1_OTAPDLYSEL_MASK 0x003F0000
-#define SD1_OTAPDLYSEL_MMC_HSD 0x00060000
-#define SD1_OTAPDLYSEL_SD_HSD 0x00050000
-#define SD1_OTAPDLYSEL_SDR50 0x00030000
-#define SD1_OTAPDLYSEL_SDR104_B0 0x00030000
-#define SD1_OTAPDLYSEL_SDR104_B2 0x00020000
-#define SD1_OTAPDLYSEL_SD_DDR50 0x00040000
-#define SD1_OTAPDLYSEL_MMC_DDR50 0x00060000
-
-#define MMC_BANK2 0x2
-
-#define MMC_TIMING_UHS_SDR25 1
-#define MMC_TIMING_UHS_SDR50 2
-#define MMC_TIMING_UHS_SDR104 3
-#define MMC_TIMING_UHS_DDR50 4
-#define MMC_TIMING_MMC_HS200 5
-#define MMC_TIMING_SD_HS 6
-#define MMC_TIMING_MMC_DDR52 7
-#define MMC_TIMING_MMC_HS 8
void zynqmp_dll_reset(u8 deviceid)
{
@@ -82,149 +50,49 @@ void zynqmp_dll_reset(u8 deviceid)
zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
}
-static void arasan_zynqmp_tap_sdr104(u8 deviceid, u8 timing, u8 bank)
-{
- if (deviceid == 0) {
- /* Program OTAP */
- if (bank == MMC_BANK2)
- zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
- SD0_OTAPDLYSEL_SDR104_B2);
- else
- zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
- SD0_OTAPDLYSEL_SDR104_B0);
- } else {
- /* Program OTAP */
- if (bank == MMC_BANK2)
- zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
- SD1_OTAPDLYSEL_SDR104_B2);
- else
- zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
- SD1_OTAPDLYSEL_SDR104_B0);
- }
-}
-
-static void arasan_zynqmp_tap_hs(u8 deviceid, u8 timing, u8 bank)
-{
- if (deviceid == 0) {
- /* Program ITAP */
- zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
- SD0_ITAPCHGWIN);
- zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
- SD0_ITAPDLYENA);
- zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
- SD0_ITAPDLYSEL_HSD);
- zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
- /* Program OTAP */
- if (timing == MMC_TIMING_MMC_HS)
- zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
- SD0_OTAPDLYSEL_MMC_HSD);
- else
- zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
- SD0_OTAPDLYSEL_SD_HSD);
- } else {
- /* Program ITAP */
- zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
- SD1_ITAPCHGWIN);
- zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
- SD1_ITAPDLYENA);
- zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
- SD1_ITAPDLYSEL_HSD);
- zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
- /* Program OTAP */
- if (timing == MMC_TIMING_MMC_HS)
- zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
- SD1_OTAPDLYSEL_MMC_HSD);
- else
- zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
- SD1_OTAPDLYSEL_SD_HSD);
- }
-}
-
-static void arasan_zynqmp_tap_ddr50(u8 deviceid, u8 timing, u8 bank)
+void arasan_zynqmp_set_tapdelay(u8 deviceid, u32 itap_delay, u32 otap_delay)
{
if (deviceid == 0) {
+ zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
+ SD0_DLL_RST);
/* Program ITAP */
- zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
- SD0_ITAPCHGWIN);
- zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
- SD0_ITAPDLYENA);
- if (timing == MMC_TIMING_UHS_DDR50)
- zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
- SD0_ITAPDLYSEL_SD_DDR50);
- else
+ if (itap_delay) {
+ zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+ SD0_ITAPCHGWIN);
+ zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
+ SD0_ITAPDLYENA);
zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
- SD0_ITAPDLYSEL_MMC_DDR50);
- zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+ itap_delay);
+ zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+ 0x0);
+ }
+
/* Program OTAP */
- if (timing == MMC_TIMING_UHS_DDR50)
- zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
- SD0_OTAPDLYSEL_SD_DDR50);
- else
+ if (otap_delay)
zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
- SD0_OTAPDLYSEL_MMC_DDR50);
- } else {
- /* Program ITAP */
- zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
- SD1_ITAPCHGWIN);
- zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
- SD1_ITAPDLYENA);
- if (timing == MMC_TIMING_UHS_DDR50)
- zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
- SD1_ITAPDLYSEL_SD_DDR50);
- else
- zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
- SD1_ITAPDLYSEL_MMC_DDR50);
- zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
- /* Program OTAP */
- if (timing == MMC_TIMING_UHS_DDR50)
- zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
- SD1_OTAPDLYSEL_SD_DDR50);
- else
- zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
- SD1_OTAPDLYSEL_MMC_DDR50);
- }
-}
+ otap_delay);
-static void arasan_zynqmp_tap_sdr50(u8 deviceid, u8 timing, u8 bank)
-{
- if (deviceid == 0) {
- /* Program OTAP */
- zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
- SD0_OTAPDLYSEL_SDR50);
+ zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
} else {
- /* Program OTAP */
- zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
- SD1_OTAPDLYSEL_SDR50);
- }
-}
-
-void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank)
-{
- if (deviceid == 0)
- zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
- SD0_DLL_RST);
- else
zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
SD1_DLL_RST);
+ /* Program ITAP */
+ if (itap_delay) {
+ zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+ SD1_ITAPCHGWIN);
+ zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
+ SD1_ITAPDLYENA);
+ zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+ (itap_delay << 16));
+ zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+ 0x0);
+ }
- switch (timing) {
- case MMC_TIMING_UHS_SDR25:
- arasan_zynqmp_tap_hs(deviceid, timing, bank);
- break;
- case MMC_TIMING_UHS_SDR50:
- arasan_zynqmp_tap_sdr50(deviceid, timing, bank);
- break;
- case MMC_TIMING_UHS_SDR104:
- case MMC_TIMING_MMC_HS200:
- arasan_zynqmp_tap_sdr104(deviceid, timing, bank);
- break;
- case MMC_TIMING_UHS_DDR50:
- arasan_zynqmp_tap_ddr50(deviceid, timing, bank);
- break;
- }
+ /* Program OTAP */
+ if (otap_delay)
+ zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+ (otap_delay << 16));
- if (deviceid == 0)
- zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
- else
zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+ }
}
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 28f067a..731285a 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -40,12 +40,12 @@
#include "pm_cfg_obj.h"
#define ZYNQMP_VERSION_SIZE 7
-#define EFUSE_VCU_DIS_MASK 0x100
-#define EFUSE_VCU_DIS_SHIFT 8
-#define EFUSE_GPU_DIS_MASK 0x20
-#define EFUSE_GPU_DIS_SHIFT 5
-#define IDCODE2_PL_INIT_MASK 0x200
-#define IDCODE2_PL_INIT_SHIFT 9
+#define EFUSE_VCU_DIS_MASK 0x100
+#define EFUSE_VCU_DIS_SHIFT 8
+#define EFUSE_GPU_DIS_MASK 0x20
+#define EFUSE_GPU_DIS_SHIFT 5
+#define IDCODE2_PL_INIT_MASK 0x200
+#define IDCODE2_PL_INIT_SHIFT 9
DECLARE_GLOBAL_DATA_PTR;
@@ -100,7 +100,7 @@ static const struct {
{
.id = 0x04738093,
.device = 9,
- .variants = ZYNQMP_VARIANT_EG,
+ .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG,
},
{
.id = 0x04740093,
@@ -190,8 +190,13 @@ static char *zynqmp_get_silicon_idcode_name(void)
u32 idcode, idcode2;
char name[ZYNQMP_VERSION_SIZE];
u32 ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
- xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
+ ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
+ if (ret) {
+ debug("%s: Getting chipid failed\n", __func__);
+ return "unknown";
+ }
/*
* Firmware returns:
@@ -204,7 +209,7 @@ static char *zynqmp_get_silicon_idcode_name(void)
idcode = ret_payload[1];
idcode2 = ret_payload[2] >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
- debug("%s, IDCODE: 0x%0X, IDCODE2: 0x%0X\r\n", __func__, idcode,
+ debug("%s, IDCODE: 0x%0x, IDCODE2: 0x%0x\r\n", __func__, idcode,
idcode2);
for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
@@ -216,8 +221,10 @@ static char *zynqmp_get_silicon_idcode_name(void)
return "unknown";
/* Add device prefix to the name */
- strncpy(name, "zu", ZYNQMP_VERSION_SIZE);
- strncat(&name[2], simple_itoa(zynqmp_devices[i].device), 2);
+ ret = snprintf(name, ZYNQMP_VERSION_SIZE, "zu%d",
+ zynqmp_devices[i].device);
+ if (ret < 0)
+ return "unknown";
if (zynqmp_devices[i].variants & ZYNQMP_VARIANT_EV) {
/* Devices with EV variant might be EG/CG/EV family */
@@ -321,6 +328,9 @@ int board_init(void)
if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1)
zynqmp_pmufw_load_config_object(zynqmp_pm_cfg_obj,
zynqmp_pm_cfg_obj_size);
+#else
+ if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM))
+ xilinx_read_eeprom();
#endif
printf("EL Level:\tEL%d\n", current_el());