Merge tag 'xilinx-for-v2021.01-v2' of https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze
Xilinx changes for v2021.01-v2 common: - Add support for 64bit loadables from SPL xilinx: - Update documentation and record ownership - Enable eeprom board detection based legacy and fru formats - Add support for FRU format microblaze: - Optimize low level ASM code - Enable SPI/I2C - Enable distro boot zynq: - Add support for Zturn V5 zynqmp: - Improve silicon detection code - Enable several kconfig options - Align DT with the latest state - Enabling security commands - Enable and support FPGA loading from SPL - Optimize xilinx_pm_request() calling versal: - Some DTs/Kconfig/defconfig alignments - Add binding header for clock and power zynq-sdhci: - Add support for tap delay programming zynq-spi/zynq-qspi: - Use clock framework for getting clocks xilinx-spi: - Fix some code issues (unused variables) serial: - Check return value from clock functions in pl01x
This commit is contained in:
@@ -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.
|
||||
|
||||
10
board/xilinx/common/Makefile
Normal file
10
board/xilinx/common/Makefile
Normal file
@@ -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
|
||||
@@ -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(ARCH_ZYNQ))
|
||||
if (!CONFIG_IS_ENABLED(MICROBLAZE) && bd->bi_dram[0].start) {
|
||||
ulong scriptaddr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -9,4 +9,6 @@
|
||||
|
||||
int board_late_init_xilinx(void);
|
||||
|
||||
int xilinx_read_eeprom(void);
|
||||
|
||||
#endif /* BOARD_XILINX_COMMON_BOARD_H */
|
||||
|
||||
91
board/xilinx/common/fru.c
Normal file
91
board/xilinx/common/fru.c
Normal file
@@ -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
|
||||
)
|
||||
83
board/xilinx/common/fru.h
Normal file
83
board/xilinx/common/fru.h
Normal file
@@ -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 */
|
||||
362
board/xilinx/common/fru_ops.c
Normal file
362
board/xilinx/common/fru_ops.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -6,4 +6,3 @@
|
||||
|
||||
obj-y := board.o
|
||||
obj-$(CONFIG_CMD_VERSAL) += cmds.o
|
||||
obj-y += ../common/board.o
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
273
board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c
Normal file
273
board/xilinx/zynq/zynq-zturn-v5/ps7_init_gpl.c
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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*
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
void arasan_zynqmp_set_tapdelay(u8 deviceid, u32 itap_delay, u32 otap_delay)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (timing == MMC_TIMING_UHS_DDR50)
|
||||
zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
|
||||
SD0_ITAPDLYSEL_SD_DDR50);
|
||||
else
|
||||
zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
|
||||
SD0_ITAPDLYSEL_MMC_DDR50);
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
} 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
|
||||
/* Program ITAP */
|
||||
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,
|
||||
itap_delay);
|
||||
zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
|
||||
0x0);
|
||||
}
|
||||
|
||||
/* Program OTAP */
|
||||
if (otap_delay)
|
||||
zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
|
||||
otap_delay);
|
||||
|
||||
zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user