提交 b9cb74a5 编写于 作者: T Tom Rini

Merge tag 'xilinx-for-v2021.10-rc3' of https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze

Xilinx changes for v2021.10-rc3

xilinx:
- Disable CONFIG_ARCH_FIXUP_FDT_MEMORY
- Print information about cpu via soc drivers and enable DISPLAY_CPUINFO
- Wire infrastructure for DTB_RESELECT and MULTI_DTB_FIT

zynq:
- Wire single QSPI
- Use power-source instead of io-standard properties
- Enable nor on zc770-xm012

zynqmp:
- Change handling around multi_boot()
- Setup offset for u-boot.itb in spi
- Generate run time dfu_alt_info for capsule update
- Use explicit values for enums (zynqmp_firmware.h)
- Enable RTC/SHA1/BUTTON/BUTTON_GPIO command
- Disable WDT driver by default
- Bind usb/scsi via preboot because of EFI
- DT updates/fixes
- Add soc driver
- Fix SPL SPI boot mode

versal:
- Add soc driver

sdhci:
- Update tap delay programming for zynq_sdhci driver

cmd:
- Fix RTC uclass handling in date command
- Update pwm help message
- Update reset help message

watchdog:
- Fix wwdt compilation

rtc:
- Deal with seq alias in rtc uclass
- Add zynqmp RTC driver

fdt:
- Add kernel-doc for fdt_fixup_memory_banks()
......@@ -546,6 +546,7 @@ S: Maintained
T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git
F: arch/arm/mach-versal/
F: drivers/net/xilinx_axi_mrmac.*
F: drivers/soc/soc_xilinx_versal.c
F: drivers/watchdog/xilinx_wwdt.c
N: (?<!uni)versal
......@@ -600,6 +601,9 @@ F: drivers/mtd/nand/raw/zynq_nand.c
F: drivers/net/phy/xilinx_phy.c
F: drivers/net/zynq_gem.c
F: drivers/serial/serial_zynq.c
F: drivers/reset/reset-zynqmp.c
F: drivers/rtc/zynqmp_rtc.c
F: drivers/soc/soc_xilinx_zynqmp.c
F: drivers/spi/zynq_qspi.c
F: drivers/spi/zynq_spi.c
F: drivers/timer/cadence-ttc.c
......
......@@ -1169,6 +1169,8 @@ MKIMAGEFLAGS_fit-dtb.blob = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
-a 0 -e 0 -E \
$(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) -d /dev/null
MKIMAGEFLAGS_fit-dtb.blob += -B 0x8
ifneq ($(EXT_DTB),)
u-boot-fit-dtb.bin: u-boot-nodtb.bin $(EXT_DTB)
$(call if_changed,cat)
......@@ -1431,6 +1433,7 @@ MKIMAGEFLAGS_u-boot.itb =
else
MKIMAGEFLAGS_u-boot.itb = -E
endif
MKIMAGEFLAGS_u-boot.itb += -B 0x8
ifdef U_BOOT_ITS
u-boot.itb: u-boot-nodtb.bin \
......
......@@ -1064,6 +1064,7 @@ config ARCH_VERSAL
select DM_SERIAL
select GPIO_EXTRA_HEADER
select OF_CONTROL
select SOC_DEVICE
imply BOARD_LATE_INIT
imply ENV_VARS_UBOOT_RUNTIME_CONFIG
......@@ -1142,6 +1143,7 @@ config ARCH_ZYNQMP
select SPL_SEPARATE_BSS if SPL
select SUPPORT_SPL
select ZYNQMP_IPI
select SOC_DEVICE
imply BOARD_LATE_INIT
imply CMD_DM
imply ENV_VARS_UBOOT_RUNTIME_CONFIG
......
......@@ -1133,7 +1133,7 @@ dtb-$(CONFIG_TARGET_EA_LPC3250DEVKITV2) += lpc3250-ea3250.dtb
targets += $(dtb-y)
# Add any required device tree compiler flags here
DTC_FLAGS +=
DTC_FLAGS += -a 0x8
PHONY += dtbs
dtbs: $(addprefix $(obj)/, $(dtb-y))
......
......@@ -58,7 +58,7 @@
is-dual = <0>;
num-cs = <1>;
flash@0 { /* 16 MB */
compatible = "n25q128a11";
compatible = "n25q128a11", "jedec,spi-nor";
reg = <0x0>;
spi-max-frequency = <50000000>;
spi-tx-bus-width = <1>;
......
......@@ -60,7 +60,7 @@
#size-cells = <0>;
num-cs = <1>;
flash0: flash@0 {
compatible = "n25q128a11";
compatible = "n25q128a11", "jedec,spi-nor";
reg = <0x0>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
......
......@@ -36,7 +36,7 @@
is-dual = <0>;
num-cs = <1>;
flash@0 {
compatible = "st,m25p80", "n25q256a";
compatible = "st,m25p80", "n25q256a", "jedec,spi-nor";
m25p,fast-read;
reg = <0x0>;
spi-tx-bus-width = <1>;
......
......@@ -213,7 +213,7 @@
conf {
groups = "can0_9_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
conf-rx {
......@@ -236,7 +236,7 @@
conf {
groups = "ethernet0_0_grp";
slew-rate = <0>;
io-standard = <4>;
power-source = <4>;
};
conf-rx {
......@@ -259,7 +259,7 @@
conf-mdio {
groups = "mdio0_0_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
bias-disable;
};
};
......@@ -277,7 +277,7 @@
"gpio0_10_grp", "gpio0_11_grp", "gpio0_12_grp",
"gpio0_13_grp", "gpio0_14_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
conf-pull-up {
......@@ -301,7 +301,7 @@
groups = "i2c0_10_grp";
bias-pull-up;
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
};
......@@ -314,7 +314,7 @@
conf {
groups = "gpio0_50_grp", "gpio0_51_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
};
......@@ -327,7 +327,7 @@
conf {
groups = "sdio0_2_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
bias-disable;
};
......@@ -341,7 +341,7 @@
bias-high-impedance;
bias-pull-up;
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
mux-wp {
......@@ -354,7 +354,7 @@
bias-high-impedance;
bias-pull-up;
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
};
......@@ -367,7 +367,7 @@
conf {
groups = "uart1_10_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
conf-rx {
......@@ -390,7 +390,7 @@
conf {
groups = "usb0_0_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
conf-rx {
......@@ -409,6 +409,14 @@
&qspi {
u-boot,dm-pre-reloc;
status = "okay";
num-cs = <1>;
flash@0 {
compatible = "n25q128a11", "jedec,spi-nor";
reg = <0x0>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
spi-max-frequency = <50000000>;
};
};
&sdhci0 {
......
......@@ -151,7 +151,7 @@
conf {
groups = "ethernet0_0_grp";
slew-rate = <0>;
io-standard = <4>;
power-source = <4>;
};
conf-rx {
......@@ -174,7 +174,7 @@
conf-mdio {
groups = "mdio0_0_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
bias-disable;
};
};
......@@ -188,7 +188,7 @@
conf {
groups = "gpio0_7_grp", "gpio0_46_grp", "gpio0_47_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
conf-pull-up {
......@@ -212,7 +212,7 @@
groups = "i2c0_10_grp";
bias-pull-up;
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
};
......@@ -225,7 +225,7 @@
conf {
groups = "sdio0_2_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
bias-disable;
};
......@@ -239,7 +239,7 @@
bias-high-impedance;
bias-pull-up;
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
mux-wp {
......@@ -252,7 +252,7 @@
bias-high-impedance;
bias-pull-up;
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
};
......@@ -265,7 +265,7 @@
conf {
groups = "uart1_10_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
conf-rx {
......@@ -288,7 +288,7 @@
conf {
groups = "usb0_0_grp";
slew-rate = <0>;
io-standard = <1>;
power-source = <1>;
};
conf-rx {
......@@ -307,6 +307,14 @@
&qspi {
u-boot,dm-pre-reloc;
status = "okay";
num-cs = <1>;
flash@0 {
compatible = "n25q128a11", "jedec,spi-nor";
reg = <0x0>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
spi-max-frequency = <50000000>;
};
};
&sdhci0 {
......
......@@ -62,6 +62,14 @@
&qspi {
status = "okay";
num-cs = <1>;
flash@0 {
compatible = "n25q128a11", "jedec,spi-nor";
reg = <0x0>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
spi-max-frequency = <50000000>;
};
};
&sdhci0 {
......
......@@ -53,6 +53,15 @@
};
};
&nor0 {
status = "okay";
bank-width = <1>;
};
&smcc {
status = "okay";
};
&spi1 {
status = "okay";
num-cs = <4>;
......
......@@ -61,6 +61,14 @@
&qspi {
status = "okay";
num-cs = <1>;
flash@0 {
compatible = "n25q128a11", "jedec,spi-nor";
reg = <0x0>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
spi-max-frequency = <50000000>;
};
};
&spi0 {
......
......@@ -12,10 +12,10 @@
* Michal Simek <michal.simek@xilinx.com>
*/
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/net/ti-dp83867.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/net/ti-dp83867.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
/dts-v1/;
/plugin/;
......
......@@ -7,10 +7,10 @@
* Michal Simek <michal.simek@xilinx.com>
*/
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/net/ti-dp83867.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/net/ti-dp83867.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
/dts-v1/;
/plugin/;
......
......@@ -60,13 +60,13 @@
leds {
compatible = "gpio-leds";
ds35 {
ds35-led {
label = "heartbeat";
gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
ds36 {
ds36-led {
label = "vbus_det";
gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
default-state = "on";
......@@ -183,7 +183,7 @@
};
};
&sdhci0 { /* MIO13-23 - 16GB emmc MTFC16GAPALBH-IT - U133A*/
&sdhci0 { /* MIO13-23 - 16GB emmc MTFC16GAPALBH-IT - U133A */
status = "okay";
non-removable;
disable-wp;
......@@ -204,17 +204,20 @@
&i2c1 {
status = "okay";
u-boot,dm-pre-reloc;
clock-frequency = <400000>;
scl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
sda-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
eeprom: eeprom@50 { /* u46 - also at address 0x58 */
u-boot,dm-pre-reloc;
compatible = "st,24c64", "atmel,24c64"; /* st m24c64 */
reg = <0x50>;
/* WP pin EE_WP_EN connected to slg7x644092@68 */
};
eeprom_cc: eeprom@51 { /* required by spec - also at address 0x59 */
u-boot,dm-pre-reloc;
compatible = "st,24c64", "atmel,24c64"; /* st m24c64 */
reg = <0x51>;
};
......
......@@ -58,7 +58,7 @@
status = "okay";
is-dual = <1>;
flash@0 {
compatible = "st,m25p80", "n25q256a";
compatible = "st,m25p80", "n25q256a", "jedec,spi-nor";
m25p,fast-read;
reg = <0x0>;
spi-tx-bus-width = <1>;
......
......@@ -13,6 +13,7 @@
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/cache.h>
#include <dm/platdata.h>
DECLARE_GLOBAL_DATA_PTR;
......@@ -120,3 +121,7 @@ int arm_reserve_mmu(void)
return 0;
}
#endif
U_BOOT_DRVINFO(soc_xilinx_versal) = {
.name = "soc_xilinx_versal",
};
......@@ -65,6 +65,10 @@ struct crp_regs {
#define crp_base ((struct crp_regs *)VERSAL_CRP_BASEADDR)
#define VERSAL_PS_PMC_VERSION 0xF11A0004
#define VERSAL_PS_VER_MASK GENMASK(7, 0)
#define VERSAL_PS_VER_SHIFT 12
/* Bootmode setting values */
#define BOOT_MODES_MASK 0x0000000F
#define QSPI_MODE_24BIT 0x00000001
......
......@@ -15,6 +15,7 @@
#include <asm/io.h>
#include <zynqmp_firmware.h>
#include <asm/cache.h>
#include <dm/platdata.h>
#define ZYNQ_SILICON_VER_MASK 0xF000
#define ZYNQ_SILICON_VER_SHIFT 12
......@@ -218,3 +219,7 @@ int zynqmp_mmio_read(const u32 address, u32 *value)
return ret;
}
U_BOOT_DRVINFO(soc_xilinx_zynqmp) = {
.name = "soc_xilinx_zynqmp",
};
......@@ -69,6 +69,9 @@ struct iou_scntr_secure {
#define iou_scntr_secure ((struct iou_scntr_secure *)ZYNQMP_IOU_SCNTR_SECURE)
#define ZYNQMP_PS_VERSION 0xFFCA0044
#define ZYNQMP_PS_VER_MASK GENMASK(1, 0)
/* Bootmode setting values */
#define BOOT_MODES_MASK 0x0000000F
#define QSPI_MODE_24BIT 0x00000001
......
......@@ -57,7 +57,7 @@ cat << __HEADER_EOF
/dts-v1/;
/ {
description = "Configuration to load ATF before U-Boot";
description = "Configuration for Xilinx ZynqMP SoC";
images {
uboot {
......@@ -78,7 +78,7 @@ __HEADER_EOF
if [ -f $BL31 ]; then
cat << __ATF
atf {
description = "ARM Trusted Firmware";
description = "Trusted Firmware-A";
data = /incbin/("$BL31");
type = "firmware";
os = "arm-trusted-firmware";
......@@ -111,6 +111,51 @@ cat << __TEE
__TEE
fi
MULTI_DTB=`awk '/CONFIG_MULTI_DTB_FIT / { print $3 }' include/generated/autoconf.h`
if [ 1"$MULTI_DTB" -eq 11 ]; then
cat << __FDT_IMAGE_EOF
fdt_1 {
description = "Multi DTB fit image";
data = /incbin/("fit-dtb.blob");
type = "flat_dt";
arch = "arm64";
compression = "none";
$DTB_LOAD
hash {
algo = "md5";
};
};
};
configurations {
default = "config_1";
__FDT_IMAGE_EOF
if [ ! -f $BL31 ]; then
cat << __CONF_SECTION1_EOF
config_1 {
description = "Multi DTB without TF-A";
firmware = "uboot";
loadables = "fdt_1";
};
__CONF_SECTION1_EOF
else
cat << __CONF_SECTION1_EOF
config_1 {
description = "Multi DTB with TF-A";
firmware = "atf";
loadables = "uboot", "fdt_1";
};
__CONF_SECTION1_EOF
fi
cat << __ITS_EOF
};
};
__ITS_EOF
else
DEFAULT=1
cnt=1
for dtname in $DT
......@@ -181,3 +226,5 @@ cat << __ITS_EOF
};
};
__ITS_EOF
fi
......@@ -18,6 +18,8 @@
#include <i2c_eeprom.h>
#include <net.h>
#include <generated/dt.h>
#include <soc.h>
#include <linux/ctype.h>
#include "fru.h"
......@@ -67,7 +69,7 @@ struct xilinx_board_description {
};
static int highest_id = -1;
static struct xilinx_board_description **board_info;
static struct xilinx_board_description *board_info;
#define XILINX_I2C_DETECTION_BITS sizeof(struct fru_common_hdr)
......@@ -167,7 +169,7 @@ static bool xilinx_detect_legacy(u8 *buffer)
static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
struct xilinx_board_description *desc)
{
int ret, eeprom_size;
int i, ret, eeprom_size;
u8 *fru_content;
/* FIXME this is shortcut - if eeprom type is wrong it will fail */
......@@ -184,21 +186,23 @@ static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
eeprom_size);
if (ret) {
debug("%s: I2C EEPROM read failed\n", __func__);
free(fru_content);
return ret;
goto end;
}
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 (gd->flags & GD_FLG_RELOC || (_DEBUG && CONFIG_IS_ENABLED(DTB_RESELECT))) {
printf("Xilinx I2C FRU format at %s:\n", name);
ret = fru_display(0);
if (ret) {
printf("FRU format decoding failed.\n");
goto end;
}
}
if (desc->header == EEPROM_HEADER_MAGIC) {
debug("Information already filled\n");
return -EINVAL;
ret = -EINVAL;
goto end;
}
/* It is clear that FRU was captured and structures were filled */
......@@ -206,13 +210,19 @@ static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
sizeof(desc->manufacturer));
strncpy(desc->name, (char *)fru_data.brd.product_name,
sizeof(desc->name));
for (i = 0; i < sizeof(desc->name); i++) {
if (desc->name[i] == ' ')
desc->name[i] = '\0';
}
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;
end:
free(fru_content);
return ret;
}
static bool xilinx_detect_fru(u8 *buffer)
......@@ -275,7 +285,7 @@ static int xilinx_read_eeprom_single(char *name,
__maybe_unused int xilinx_read_eeprom(void)
{
int id, ret;
int id;
char name_buf[8]; /* 8 bytes should be enough for nvmem+number */
struct xilinx_board_description *desc;
......@@ -284,7 +294,7 @@ __maybe_unused int xilinx_read_eeprom(void)
if (highest_id < 0)
return -EINVAL;
board_info = calloc(1, sizeof(desc) * highest_id);
board_info = calloc(1, sizeof(*desc) * (highest_id + 1));
if (!board_info)
return -ENOMEM;
......@@ -295,21 +305,10 @@ __maybe_unused int xilinx_read_eeprom(void)
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;
}
desc = &board_info[id];
/* Ignoring return value for supporting multiple chips */
ret = xilinx_read_eeprom_single(name_buf, desc);
if (ret) {
free(desc);
board_info[id] = NULL;
}
xilinx_read_eeprom_single(name_buf, desc);
}
/*
......@@ -395,7 +394,7 @@ int board_late_init_xilinx(void)
ret |= env_set_addr("bootm_size", (void *)bootm_size);
for (id = 0; id <= highest_id; id++) {
desc = board_info[id];
desc = &board_info[id];
if (desc && desc->header == EEPROM_HEADER_MAGIC) {
if (desc->manufacturer[0])
ret |= env_set_by_index("manufacturer", id,
......@@ -431,12 +430,139 @@ int board_late_init_xilinx(void)
}
#endif
static char *board_name = DEVICE_TREE;
int __maybe_unused board_fit_config_name_match(const char *name)
{
debug("%s: Check %s, default %s\n", __func__, name, DEVICE_TREE);
debug("%s: Check %s, default %s\n", __func__, name, board_name);
if (!strcmp(name, DEVICE_TREE))
if (!strcmp(name, board_name))
return 0;
return -1;
}
#if defined(CONFIG_DISPLAY_CPUINFO) && !defined(CONFIG_ARCH_ZYNQ)
int print_cpuinfo(void)
{
struct udevice *soc;
char name[SOC_MAX_STR_SIZE];
int ret;
ret = soc_get(&soc);
if (ret) {
printf("CPU: UNKNOWN\n");
return 0;
}
ret = soc_get_family(soc, name, SOC_MAX_STR_SIZE);
if (ret)
printf("CPU: %s\n", name);
ret = soc_get_revision(soc, name, SOC_MAX_STR_SIZE);
if (ret)
printf("Silicon: %s\n", name);
return 0;
}
#endif
#if CONFIG_IS_ENABLED(DTB_RESELECT)
#define MAX_NAME_LENGTH 50
char * __maybe_unused __weak board_name_decode(void)
{
char *board_local_name;
struct xilinx_board_description *desc;
int i, id;
board_local_name = calloc(1, MAX_NAME_LENGTH);
if (!board_info)
return NULL;
for (id = 0; id <= highest_id; id++) {
desc = &board_info[id];
/* No board description */
if (!desc)
goto error;
/* Board is not detected */
if (desc->header != EEPROM_HEADER_MAGIC)
continue;
/* The first string should be soc name */
if (!id)
strcat(board_local_name, CONFIG_SYS_BOARD);
/*
* For two purpose here:
* soc_name- eg: zynqmp-
* and between base board and CC eg: ..revA-sck...
*/
strcat(board_local_name, "-");
if (desc->name[0]) {
/* For DT composition name needs to be lowercase */
for (i = 0; i < sizeof(desc->name); i++)
desc->name[i] = tolower(desc->name[i]);
strcat(board_local_name, desc->name);
}
if (desc->revision[0]) {
strcat(board_local_name, "-rev");
/* And revision needs to be uppercase */
for (i = 0; i < sizeof(desc->revision); i++)
desc->revision[i] = toupper(desc->revision[i]);
strcat(board_local_name, desc->revision);
}
}
/*
* Longer strings will end up with buffer overflow and potential
* attacks that's why check it
*/
if (strlen(board_local_name) >= MAX_NAME_LENGTH)
panic("Board name can't be determined\n");
if (strlen(board_local_name))
return board_local_name;
error:
free(board_local_name);
return NULL;
}
bool __maybe_unused __weak board_detection(void)
{
if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM)) {
int ret;
ret = xilinx_read_eeprom();
return !ret ? true : false;
}
return false;
}
int embedded_dtb_select(void)
{
if (board_detection()) {
char *board_local_name;
board_local_name = board_name_decode();
if (board_local_name) {
board_name = board_local_name;
printf("Detected name: %s\n", board_name);
/* Time to change DTB on fly */
/* Both ways should work here */
/* fdtdec_resetup(&rescan); */
fdtdec_setup();
}
}
return 0;
}
#endif
......@@ -44,8 +44,6 @@ $(obj)/pm_cfg_obj.o: $(shell cd $(srctree); readlink -f $(CONFIG_ZYNQMP_SPL_PM_C
endif
endif
obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_CMD_ZYNQMP) += cmds.o
endif
......
// SPDX-License-Identifier: GPL-2.0
/*
* Xilinx ZynqMP SoC Tap Delay Programming
*
* Copyright (C) 2018 Xilinx, Inc.
*/
#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
#define SD_OTAP_DLY 0xFF180318
#define SD0_DLL_RST_MASK 0x00000004
#define SD0_DLL_RST 0x00000004
#define SD1_DLL_RST_MASK 0x00040000
#define SD1_DLL_RST 0x00040000
#define SD0_ITAPCHGWIN_MASK 0x00000200
#define SD0_ITAPCHGWIN 0x00000200
#define SD1_ITAPCHGWIN_MASK 0x02000000
#define SD1_ITAPCHGWIN 0x02000000
#define SD0_ITAPDLYENA_MASK 0x00000100
#define SD0_ITAPDLYENA 0x00000100
#define SD1_ITAPDLYENA_MASK 0x01000000
#define SD1_ITAPDLYENA 0x01000000
#define SD0_ITAPDLYSEL_MASK 0x000000FF
#define SD1_ITAPDLYSEL_MASK 0x00FF0000
#define SD0_OTAPDLYSEL_MASK 0x0000003F
#define SD1_OTAPDLYSEL_MASK 0x003F0000
void zynqmp_dll_reset(u8 deviceid)
{
/* Issue DLL Reset */
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);
mdelay(1);
/* Release DLL Reset */
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);
}
void arasan_zynqmp_set_in_tapdelay(u8 deviceid, u32 itap_delay)
{
if (deviceid == 0) {
zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, SD0_DLL_RST);
/* Program 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);
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 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);
zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
}
}
void arasan_zynqmp_set_out_tapdelay(u8 deviceid, u32 otap_delay)
{
if (deviceid == 0) {
zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, SD0_DLL_RST);
/* Program 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 OTAP delay */
zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
(otap_delay << 16));
zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
}
}
......@@ -8,6 +8,7 @@
#include <command.h>
#include <cpu_func.h>
#include <debug_uart.h>
#include <dfu.h>
#include <env.h>
#include <env_internal.h>
#include <init.h>
......@@ -19,6 +20,7 @@
#include <ahci.h>
#include <scsi.h>
#include <malloc.h>
#include <memalign.h>
#include <wdt.h>
#include <asm/arch/clk.h>
#include <asm/arch/hardware.h>
......@@ -346,13 +348,14 @@ int board_early_init_f(void)
static int multi_boot(void)
{
u32 multiboot;
multiboot = readl(&csu_base->multi_boot);
u32 multiboot = 0;
int ret;
printf("Multiboot:\t%d\n", multiboot);
ret = zynqmp_mmio_read((ulong)&csu_base->multi_boot, &multiboot);
if (ret)
return -EINVAL;
return 0;
return multiboot;
}
#define PS_SYSMON_ANALOG_BUS_VAL 0x3210
......@@ -392,7 +395,7 @@ int board_init(void)
#endif
if (current_el() == 3)
multi_boot();
printf("Multiboot:\t%d\n", multi_boot());
return 0;
}
......@@ -467,6 +470,9 @@ ulong board_get_usable_ram_top(ulong total_size)
phys_addr_t reg;
struct lmb lmb;
if (!IS_ALIGNED((ulong)gd->fdt_blob, 0x8))
panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob);
/* found enough not-reserved memory to relocated U-Boot */
lmb_init(&lmb);
lmb_add(&lmb, gd->ram_base, gd->ram_size);
......@@ -515,6 +521,9 @@ static u8 __maybe_unused zynqmp_get_bootmode(void)
if (ret)
return -EINVAL;
debug("HW boot mode: %x\n", reg & BOOT_MODES_MASK);
debug("ALT boot mode: %x\n", reg >> BOOT_MODE_ALT_SHIFT);
if (reg >> BOOT_MODE_ALT_SHIFT)
reg >>= BOOT_MODE_ALT_SHIFT;
......@@ -735,6 +744,7 @@ int board_late_init(void)
env_targets ? env_targets : "");
env_set("boot_targets", new_targets);
free(new_targets);
reset_reason();
......@@ -816,3 +826,55 @@ enum env_location env_get_location(enum env_operation op, int prio)
return ENVL_NOWHERE;
}
}
#if defined(CONFIG_SET_DFU_ALT_INFO)
#define DFU_ALT_BUF_LEN SZ_1K
void set_dfu_alt_info(char *interface, char *devstr)
{
u8 multiboot;
int bootseq = 0;
ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
if (env_get("dfu_alt_info"))
return;
memset(buf, 0, sizeof(buf));
multiboot = multi_boot();
debug("Multiboot: %d\n", multiboot);
switch (zynqmp_get_bootmode()) {
case EMMC_MODE:
case SD_MODE:
case SD1_LSHFT_MODE:
case SD_MODE1:
bootseq = mmc_get_env_dev();
if (!multiboot)
snprintf(buf, DFU_ALT_BUF_LEN,
"mmc %d:1=boot.bin fat %d 1;"
"u-boot.itb fat %d 1",
bootseq, bootseq, bootseq);
else
snprintf(buf, DFU_ALT_BUF_LEN,
"mmc %d:1=boot%04d.bin fat %d 1;"
"u-boot.itb fat %d 1",
bootseq, multiboot, bootseq, bootseq);
break;
case QSPI_MODE_24BIT:
case QSPI_MODE_32BIT:
snprintf(buf, DFU_ALT_BUF_LEN,
"sf 0:0=boot.bin raw %x 0x1500000;"
"u-boot.itb raw 0x%x 0x500000",
multiboot * SZ_32K, CONFIG_SYS_SPI_U_BOOT_OFFS);
break;
default:
return;
}
env_set("dfu_alt_info", buf);
puts("DFU alt info setting: done\n");
}
#endif
......@@ -58,7 +58,8 @@ U_BOOT_CMD(
U_BOOT_CMD(
reset, 2, 0, do_reset,
"Perform RESET of the CPU",
""
"- cold boot without level specifier\n"
"reset -w - warm reset if implemented"
);
#ifdef CONFIG_CMD_POWEROFF
......
......@@ -41,10 +41,13 @@ static int do_date(struct cmd_tbl *cmdtp, int flag, int argc,
#ifdef CONFIG_DM_RTC
struct udevice *dev;
rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
rcode = uclass_get_device_by_seq(UCLASS_RTC, 0, &dev);
if (rcode) {
printf("Cannot find RTC: err=%d\n", rcode);
return CMD_RET_FAILURE;
rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
if (rcode) {
printf("Cannot find RTC: err=%d\n", rcode);
return CMD_RET_FAILURE;
}
}
#elif defined(CONFIG_SYS_I2C_LEGACY)
old_bus = i2c_get_bus_num();
......
......@@ -108,7 +108,8 @@ static int do_pwm(struct cmd_tbl *cmdtp, int flag, int argc,
U_BOOT_CMD(pwm, 6, 0, do_pwm,
"control pwm channels",
"pwm <invert> <pwm_dev_num> <channel> <polarity>\n"
"pwm <config> <pwm_dev_num> <channel> <period_ns> <duty_ns>\n"
"pwm <enable/disable> <pwm_dev_num> <channel>\n"
"invert <pwm_dev_num> <channel> <polarity> - invert polarity\n"
"pwm config <pwm_dev_num> <channel> <period_ns> <duty_ns> - config PWM\n"
"pwm enable <pwm_dev_num> <channel> - enable PWM output\n"
"pwm disable <pwm_dev_num> <channel> - eisable PWM output\n"
"Note: All input values are in decimal");
......@@ -420,6 +420,24 @@ static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size,
#else
#define MEMORY_BANKS_MAX 4
#endif
/**
* fdt_fixup_memory_banks - Update DT memory node
* @blob: Pointer to DT blob
* @start: Pointer to memory start addresses array
* @size: Pointer to memory sizes array
* @banks: Number of memory banks
*
* Return: 0 on success, negative value on failure
*
* Based on the passed number of banks and arrays, the function is able to
* update existing DT memory nodes to match run time detected/changed memory
* configuration. Implementation is handling one specific case with only one
* memory node where multiple tuples could be added/updated.
* The case where multiple memory nodes with a single tuple (base, size) are
* used, this function is only updating the first memory node without removing
* others.
*/
int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
{
int err, nodeoffset;
......
......@@ -13,9 +13,9 @@ CONFIG_COUNTER_FREQUENCY=100000000
CONFIG_DISTRO_DEFAULTS=y
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
CONFIG_BOOTDELAY=5
CONFIG_USE_PREBOOT=y
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_BOARD_EARLY_INIT_R=y
CONFIG_SYS_PROMPT="Versal> "
CONFIG_CMD_BOOTMENU=y
......@@ -95,6 +95,7 @@ CONFIG_ZYNQ_GEM=y
CONFIG_ARM_DCC=y
CONFIG_PL01X_SERIAL=y
CONFIG_XILINX_UARTLITE=y
CONFIG_SOC_XILINX_VERSAL=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_ZYNQ_SPI=y
......
......@@ -22,6 +22,7 @@ CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000
# CONFIG_USE_SPL_FIT_GENERATOR is not set
CONFIG_LEGACY_IMAGE_FORMAT=y
# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
CONFIG_USE_PREBOOT=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_FPGA=y
......
......@@ -5,8 +5,12 @@ CONFIG_SYS_TEXT_BASE=0x8000000
CONFIG_SYS_MALLOC_F_LEN=0x8000
CONFIG_SYS_MEMTEST_START=0x00000000
CONFIG_SYS_MEMTEST_END=0x00001000
CONFIG_SYS_SPI_U_BOOT_OFFS=0x100000
CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu100-revC"
CONFIG_SPL_STACK_R_ADDR=0x18000000
CONFIG_SPL_SIZE_LIMIT=0x2a000
CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x0
CONFIG_SPL=y
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI_SUPPORT=y
......@@ -20,10 +24,12 @@ CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000
# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
CONFIG_USE_PREBOOT=y
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_PREBOOT="run scsi_init;usb start"
CONFIG_BOARD_EARLY_INIT_F=y
CONFIG_BOARD_EARLY_INIT_R=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_FPGA=y
CONFIG_SPL_OS_BOOT=y
CONFIG_SPL_RAM_SUPPORT=y
......@@ -36,6 +42,7 @@ CONFIG_CMD_THOR_DOWNLOAD=y
CONFIG_CMD_NVEDIT_EFI=y
CONFIG_CMD_MEMTEST=y
CONFIG_SYS_ALT_MEMTEST=y
CONFIG_CMD_SHA1SUM=y
CONFIG_CMD_BIND=y
CONFIG_CMD_CLK=y
CONFIG_CMD_DFU=y
......@@ -59,6 +66,7 @@ CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_BMP=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_EFIDEBUG=y
CONFIG_CMD_RTC=y
CONFIG_CMD_TIME=y
CONFIG_CMD_GETTIME=y
CONFIG_CMD_TIMER=y
......@@ -85,6 +93,8 @@ CONFIG_NETCONSOLE=y
CONFIG_SPL_DM_SEQ_ALIAS=y
CONFIG_SCSI_AHCI=y
CONFIG_SATA_CEVA=y
CONFIG_BUTTON=y
CONFIG_BUTTON_GPIO=y
CONFIG_CLK_ZYNQMP=y
CONFIG_DFU_TFTP=y
CONFIG_DFU_TIMEOUT=y
......@@ -93,6 +103,7 @@ CONFIG_DFU_NAND=y
CONFIG_DFU_RAM=y
CONFIG_DFU_SF=y
CONFIG_DFU_MTD=y
CONFIG_SET_DFU_ALT_INFO=y
CONFIG_SYS_DFU_DATA_BUF_SIZE=0x1800000
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_FASTBOOT_FLASH=y
......@@ -149,11 +160,13 @@ CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_RTC=y
CONFIG_RTC_EMULATION=y
CONFIG_RTC_ZYNQMP=y
CONFIG_SCSI=y
CONFIG_DM_SCSI=y
CONFIG_ARM_DCC=y
CONFIG_XILINX_UARTLITE=y
CONFIG_ZYNQ_SERIAL=y
CONFIG_SOC_XILINX_ZYNQMP=y
CONFIG_SPI=y
CONFIG_ZYNQ_SPI=y
CONFIG_ZYNQMP_GQSPI=y
......@@ -187,7 +200,6 @@ CONFIG_BMP_16BPP=y
CONFIG_BMP_24BPP=y
CONFIG_BMP_32BPP=y
CONFIG_WDT=y
CONFIG_WDT_CDNS=y
CONFIG_PANIC_HANG=y
CONFIG_TPM=y
CONFIG_SPL_GZIP=y
......
......@@ -366,6 +366,7 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
{
struct sdhci_host *host = mmc->priv;
unsigned int div, clk = 0, timeout;
int ret;
/* Wait max 20 ms */
timeout = 200;
......@@ -386,8 +387,13 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
if (clock == 0)
return 0;
if (host->ops && host->ops->set_delay)
host->ops->set_delay(host);
if (host->ops && host->ops->set_delay) {
ret = host->ops->set_delay(host);
if (ret) {
printf("%s: Error while setting tap delay\n", __func__);
return ret;
}
}
if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
/*
......
......@@ -15,9 +15,10 @@
#include <dm/device_compat.h>
#include <linux/err.h>
#include <linux/libfdt.h>
#include <asm/cache.h>
#include <malloc.h>
#include <sdhci.h>
#include <zynqmp_tap_delay.h>
#include <zynqmp_firmware.h>
#define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8
#define SDHCI_ARASAN_ITAPDLY_SEL_MASK GENMASK(7, 0)
......@@ -30,6 +31,20 @@
#define SDHCI_TUNING_LOOP_COUNT 40
#define MMC_BANK2 0x2
#define SD_DLL_CTRL 0xFF180358
#define SD_ITAP_DLY 0xFF180314
#define SD_OTAP_DLY 0xFF180318
#define SD0_DLL_RST BIT(2)
#define SD1_DLL_RST BIT(18)
#define SD0_ITAPCHGWIN BIT(9)
#define SD1_ITAPCHGWIN BIT(25)
#define SD0_ITAPDLYENA BIT(8)
#define SD1_ITAPDLYENA BIT(24)
#define SD0_ITAPDLYSEL_MASK GENMASK(7, 0)
#define SD1_ITAPDLYSEL_MASK GENMASK(23, 16)
#define SD0_OTAPDLYSEL_MASK GENMASK(5, 0)
#define SD1_OTAPDLYSEL_MASK GENMASK(21, 16)
struct arasan_sdhci_clk_data {
int clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
int clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
......@@ -48,6 +63,12 @@ struct arasan_sdhci_priv {
u8 no_1p8;
};
/* For Versal platforms zynqmp_mmio_write() won't be available */
__weak int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value)
{
return 0;
}
#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
/* Default settings for ZynqMP Clock Phases */
static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0,
......@@ -75,26 +96,126 @@ static const u8 mode2timing[] = {
[MMC_HS_200] = MMC_TIMING_MMC_HS200,
};
static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
static inline int arasan_zynqmp_set_in_tapdelay(u8 node_id, u32 itap_delay)
{
u16 clk;
int ret;
if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
if (node_id == NODE_SD_0) {
ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN,
SD0_ITAPCHGWIN);
if (ret)
return ret;
ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA,
SD0_ITAPDLYENA);
if (ret)
return ret;
ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
itap_delay);
if (ret)
return ret;
ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, 0);
if (ret)
return ret;
}
ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN,
SD1_ITAPCHGWIN);
if (ret)
return ret;
ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA,
SD1_ITAPDLYENA);
if (ret)
return ret;
ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
(itap_delay << 16));
if (ret)
return ret;
ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0);
if (ret)
return ret;
} else {
return xilinx_pm_request(PM_IOCTL, (u32)node_id,
IOCTL_SET_SD_TAPDELAY,
PM_TAPDELAY_INPUT, itap_delay, NULL);
}
return 0;
}
static inline int arasan_zynqmp_set_out_tapdelay(u8 node_id, u32 otap_delay)
{
if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
if (node_id == NODE_SD_0)
return zynqmp_mmio_write(SD_OTAP_DLY,
SD0_OTAPDLYSEL_MASK,
otap_delay);
return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
(otap_delay << 16));
} else {
return xilinx_pm_request(PM_IOCTL, (u32)node_id,
IOCTL_SET_SD_TAPDELAY,
PM_TAPDELAY_OUTPUT, otap_delay, NULL);
}
}
static inline int zynqmp_dll_reset(u8 node_id, u32 type)
{
if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
if (node_id == NODE_SD_0)
return zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST,
type == PM_DLL_RESET_ASSERT ?
SD0_DLL_RST : 0);
return zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST,
type == PM_DLL_RESET_ASSERT ?
SD1_DLL_RST : 0);
} else {
return xilinx_pm_request(PM_IOCTL, (u32)node_id,
IOCTL_SD_DLL_RESET, type, 0, NULL);
}
}
static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 node_id)
{
struct mmc *mmc = (struct mmc *)host->mmc;
struct udevice *dev = mmc->dev;
unsigned long timeout;
int ret;
u16 clk;
clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
clk &= ~(SDHCI_CLOCK_CARD_EN);
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
/* Issue DLL Reset */
zynqmp_dll_reset(deviceid);
ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
if (ret) {
dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
return ret;
}
/* Allow atleast 1ms delay for proper DLL reset */
mdelay(1);
ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
if (ret) {
dev_err(dev, "dll_reset release failed with err: %d\n", ret);
return ret;
}
/* Wait max 20 ms */
timeout = 100;
while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
& SDHCI_CLOCK_INT_STABLE)) {
if (timeout == 0) {
dev_err(mmc_dev(host->mmc),
": Internal clock never stabilised.\n");
return;
dev_err(dev, ": Internal clock never stabilised.\n");
return -EBUSY;
}
timeout--;
udelay(1000);
......@@ -102,6 +223,8 @@ static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
clk |= SDHCI_CLOCK_CARD_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
return 0;
}
static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
......@@ -112,12 +235,11 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
struct sdhci_host *host;
struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
u8 deviceid;
u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
debug("%s\n", __func__);
host = priv->host;
deviceid = priv->deviceid;
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
ctrl |= SDHCI_CTRL_EXEC_TUNING;
......@@ -125,7 +247,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
mdelay(1);
arasan_zynqmp_dll_reset(host, deviceid);
arasan_zynqmp_dll_reset(host, node_id);
sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
......@@ -171,7 +293,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
}
udelay(1);
arasan_zynqmp_dll_reset(host, deviceid);
arasan_zynqmp_dll_reset(host, node_id);
/* Enable only interrupts served by the SD controller */
sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
......@@ -194,10 +316,13 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
int degrees)
{
struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
struct mmc *mmc = (struct mmc *)host->mmc;
struct udevice *dev = mmc->dev;
struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
u8 tap_delay, tap_max = 0;
int timing = mode2timing[mmc->selected_mode];
int ret;
/*
* This is applicable for SDHCI_SPEC_300 and above
......@@ -233,7 +358,19 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
/* Limit output tap_delay value to 6 bits */
tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
arasan_zynqmp_set_out_tapdelay(priv->deviceid, tap_delay);
/* Set the Clock Phase */
ret = arasan_zynqmp_set_out_tapdelay(node_id, tap_delay);
if (ret) {
dev_err(dev, "Error setting output Tap Delay\n");
return ret;
}
/* Release DLL Reset */
ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
if (ret) {
dev_err(dev, "dll_reset release failed with err: %d\n", ret);
return ret;
}
return 0;
}
......@@ -250,10 +387,13 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
int degrees)
{
struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
struct mmc *mmc = (struct mmc *)host->mmc;
struct udevice *dev = mmc->dev;
struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
u8 tap_delay, tap_max = 0;
int timing = mode2timing[mmc->selected_mode];
int ret;
/*
* This is applicable for SDHCI_SPEC_300 and above
......@@ -263,6 +403,13 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
return 0;
/* Assert DLL Reset */
ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
if (ret) {
dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
return ret;
}
switch (timing) {
case MMC_TIMING_MMC_HS:
case MMC_TIMING_SD_HS:
......@@ -289,7 +436,11 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
/* Limit input tap_delay value to 8 bits */
tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
arasan_zynqmp_set_in_tapdelay(priv->deviceid, tap_delay);
ret = arasan_zynqmp_set_in_tapdelay(node_id, tap_delay);
if (ret) {
dev_err(dev, "Error setting Input Tap Delay\n");
return ret;
}
return 0;
}
......@@ -422,7 +573,7 @@ static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
return 0;
}
static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
static int arasan_sdhci_set_tapdelay(struct sdhci_host *host)
{
struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
......@@ -431,18 +582,31 @@ static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
u8 timing = mode2timing[mmc->selected_mode];
u32 iclk_phase = clk_data->clk_phase_in[timing];
u32 oclk_phase = clk_data->clk_phase_out[timing];
int ret;
dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
ret = sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
if (ret)
return ret;
ret = sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
if (ret)
return ret;
} else if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
device_is_compatible(dev, "xlnx,versal-8.9a")) {
sdhci_versal_sampleclk_set_phase(host, iclk_phase);
sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
ret = sdhci_versal_sampleclk_set_phase(host, iclk_phase);
if (ret)
return ret;
ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
if (ret)
return ret;
}
return 0;
}
static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
......@@ -526,29 +690,10 @@ static void arasan_dt_parse_clk_phases(struct udevice *dev)
"clk-phase-mmc-hs400");
}
static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
{
struct mmc *mmc = (struct mmc *)host->mmc;
u32 reg;
if (!IS_SD(mmc))
return;
if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
reg |= SDHCI_CTRL_VDD_180;
sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
}
if (mmc->selected_mode > SD_HS &&
mmc->selected_mode <= MMC_HS_200)
sdhci_set_uhs_timing(host);
}
static const struct sdhci_ops arasan_ops = {
.platform_execute_tuning = &arasan_sdhci_execute_tuning,
.set_delay = &arasan_sdhci_set_tapdelay,
.set_control_reg = &arasan_sdhci_set_control_reg,
.set_control_reg = &sdhci_set_control_reg,
};
#endif
......@@ -612,6 +757,25 @@ static int arasan_sdhci_probe(struct udevice *dev)
return ret;
upriv->mmc = host->mmc;
/*
* WORKAROUND: Versal platforms have an issue with card detect state.
* Due to this, host controller is switching off voltage to sd card
* causing sd card timeout error. Workaround this by adding a wait for
* 1000msec till the card detect state gets stable.
*/
if (IS_ENABLED(CONFIG_ARCH_VERSAL)) {
u32 timeout = 1000;
while (((sdhci_readl(host, SDHCI_PRESENT_STATE) &
SDHCI_CARD_STATE_STABLE) == 0) && timeout--) {
mdelay(1);
}
if (!timeout) {
dev_err(dev, "Sdhci card detect state not stable\n");
return -ETIMEDOUT;
}
}
return sdhci_probe(dev);
}
......
......@@ -197,4 +197,13 @@ config RESET_SCMI
Enable this option if you want to support reset controller
devices exposed by a SCMI agent based on SCMI reset domain
protocol communication with a SCMI server.
config RESET_ZYNQMP
bool "Reset Driver for Xilinx ZynqMP SoC's"
depends on DM_RESET && ZYNQMP_FIRMWARE
help
Support for reset controller on Xilinx ZynqMP SoC. Driver is only
passing request via Xilinx firmware interface to TF-A and PMU
firmware.
endmenu
......@@ -29,3 +29,4 @@ obj-$(CONFIG_RESET_SIFIVE) += reset-sifive.o
obj-$(CONFIG_RESET_SYSCON) += reset-syscon.o
obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Xilinx, Inc. - Michal Simek
*/
#define LOG_CATEGORY UCLASS_RESET
#include <common.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <reset-uclass.h>
#include <zynqmp_firmware.h>
#define ZYNQMP_NR_RESETS (ZYNQMP_PM_RESET_END - ZYNQMP_PM_RESET_START)
#define ZYNQMP_RESET_ID ZYNQMP_PM_RESET_START
struct zynqmp_reset_priv {
u32 reset_id;
u32 nr_reset;
};
static int zynqmp_pm_reset_assert(const u32 reset,
const enum zynqmp_pm_reset_action assert_flag)
{
return xilinx_pm_request(PM_RESET_ASSERT, reset, assert_flag, 0, 0,
NULL);
}
static int zynqmp_reset_assert(struct reset_ctl *rst)
{
struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
dev_dbg(rst->dev, "%s(rst=%p) (id=%lu)\n", __func__, rst, rst->id);
return zynqmp_pm_reset_assert(priv->reset_id + rst->id,
PM_RESET_ACTION_ASSERT);
}
static int zynqmp_reset_deassert(struct reset_ctl *rst)
{
struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
dev_dbg(rst->dev, "%s(rst=%p) (id=%lu)\n", __func__, rst, rst->id);
return zynqmp_pm_reset_assert(priv->reset_id + rst->id,
PM_RESET_ACTION_RELEASE);
}
static int zynqmp_reset_request(struct reset_ctl *rst)
{
struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
dev_dbg(rst->dev, "%s(rst=%p) (id=%lu) (nr_reset=%d)\n", __func__,
rst, rst->id, priv->nr_reset);
if (rst->id > priv->nr_reset)
return -EINVAL;
return 0;
}
static int zynqmp_reset_free(struct reset_ctl *rst)
{
struct zynqmp_reset_priv *priv = dev_get_priv(rst->dev);
dev_dbg(rst->dev, "%s(rst=%p) (id=%lu) (nr_reset=%d)\n", __func__,
rst, rst->id, priv->nr_reset);
return 0;
}
static int zynqmp_reset_probe(struct udevice *dev)
{
struct zynqmp_reset_priv *priv = dev_get_priv(dev);
priv->reset_id = ZYNQMP_RESET_ID;
priv->nr_reset = ZYNQMP_NR_RESETS;
return 0;
}
const struct reset_ops zynqmp_reset_ops = {
.request = zynqmp_reset_request,
.rfree = zynqmp_reset_free,
.rst_assert = zynqmp_reset_assert,
.rst_deassert = zynqmp_reset_deassert,
};
static const struct udevice_id zynqmp_reset_ids[] = {
{ .compatible = "xlnx,zynqmp-reset" },
{ }
};
U_BOOT_DRIVER(zynqmp_reset) = {
.name = "zynqmp_reset",
.id = UCLASS_RESET,
.of_match = zynqmp_reset_ids,
.ops = &zynqmp_reset_ops,
.probe = zynqmp_reset_probe,
.priv_auto = sizeof(struct zynqmp_reset_priv),
};
......@@ -195,4 +195,11 @@ config RTC_DAVINCI
Say "yes" here to support the on chip real time clock
present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
config RTC_ZYNQMP
bool "Enable ZynqMP RTC driver"
depends on ARCH_ZYNQMP
help
Say "yes" here to support the on chip real time clock
present on Xilinx ZynqMP SoC.
endmenu
......@@ -57,3 +57,4 @@ obj-$(CONFIG_RTC_STM32) += stm32_rtc.o
obj-$(CONFIG_SANDBOX) += sandbox_rtc.o
obj-$(CONFIG_RTC_X1205) += x1205.o
obj-$(CONFIG_RTC_ABX80X) += abx80x.o
obj-$(CONFIG_RTC_ZYNQMP) += zynqmp_rtc.o
......@@ -176,6 +176,7 @@ int rtc_write32(struct udevice *dev, unsigned int reg, u32 value)
UCLASS_DRIVER(rtc) = {
.name = "rtc",
.id = UCLASS_RTC,
.flags = DM_UC_FLAG_SEQ_ALIAS,
#if !CONFIG_IS_ENABLED(OF_PLATDATA)
.post_bind = dm_scan_fdt_dev,
#endif
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021, Xilinx, Inc.
*/
#define LOG_CATEGORY UCLASS_RTC
#include <common.h>
#include <dm.h>
#include <rtc.h>
#include <asm/io.h>
/* RTC Registers */
#define RTC_SET_TM_WR 0x00
#define RTC_SET_TM_RD 0x04
#define RTC_CALIB_WR 0x08
#define RTC_CUR_TM 0x10
#define RTC_INT_STS 0x20
#define RTC_CTRL 0x40
#define RTC_INT_SEC BIT(0)
#define RTC_BATT_EN BIT(31)
#define RTC_CALIB_DEF 0x198233
#define RTC_CALIB_MASK 0x1FFFFF
struct zynqmp_rtc_priv {
fdt_addr_t base;
unsigned int calibval;
};
static int zynqmp_rtc_get(struct udevice *dev, struct rtc_time *tm)
{
struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
u32 status;
unsigned long read_time;
status = readl(priv->base + RTC_INT_STS);
if (status & RTC_INT_SEC) {
/*
* RTC has updated the CURRENT_TIME with the time written into
* SET_TIME_WRITE register.
*/
read_time = readl(priv->base + RTC_CUR_TM);
} else {
/*
* Time written in SET_TIME_WRITE has not yet updated into
* the seconds read register, so read the time from the
* SET_TIME_WRITE instead of CURRENT_TIME register.
* Since we add +1 sec while writing, we need to -1 sec while
* reading.
*/
read_time = readl(priv->base + RTC_SET_TM_RD) - 1;
}
rtc_to_tm(read_time, tm);
return 0;
}
static int zynqmp_rtc_set(struct udevice *dev, const struct rtc_time *tm)
{
struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
unsigned long new_time = 0;
if (tm)
/*
* The value written will be updated after 1 sec into the
* seconds read register, so we need to program time +1 sec
* to get the correct time on read.
*/
new_time = rtc_mktime(tm) + 1;
/*
* Writing into calibration register will clear the Tick Counter and
* force the next second to be signaled exactly in 1 second period
*/
priv->calibval &= RTC_CALIB_MASK;
writel(priv->calibval, (priv->base + RTC_CALIB_WR));
writel(new_time, priv->base + RTC_SET_TM_WR);
/*
* Clear the rtc interrupt status register after setting the
* time. During a read_time function, the code should read the
* RTC_INT_STATUS register and if bit 0 is still 0, it means
* that one second has not elapsed yet since RTC was set and
* the current time should be read from SET_TIME_READ register;
* otherwise, CURRENT_TIME register is read to report the time
*/
writel(RTC_INT_SEC, priv->base + RTC_INT_STS);
return 0;
}
static int zynqmp_rtc_reset(struct udevice *dev)
{
return zynqmp_rtc_set(dev, NULL);
}
static int zynqmp_rtc_init(struct udevice *dev)
{
struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
u32 rtc_ctrl;
/* Enable RTC switch to battery when VCC_PSAUX is not available */
rtc_ctrl = readl(priv->base + RTC_CTRL);
rtc_ctrl |= RTC_BATT_EN;
writel(rtc_ctrl, priv->base + RTC_CTRL);
/*
* Based on crystal freq of 33.330 KHz
* set the seconds counter and enable, set fractions counter
* to default value suggested as per design spec
* to correct RTC delay in frequency over period of time.
*/
priv->calibval &= RTC_CALIB_MASK;
writel(priv->calibval, (priv->base + RTC_CALIB_WR));
return 0;
}
static int zynqmp_rtc_probe(struct udevice *dev)
{
struct zynqmp_rtc_priv *priv = dev_get_priv(dev);
int ret;
priv->base = dev_read_addr(dev);
if (priv->base == FDT_ADDR_T_NONE)
return -EINVAL;
priv->calibval = dev_read_u32_default(dev, "calibration",
RTC_CALIB_DEF);
ret = zynqmp_rtc_init(dev);
return ret;
}
static const struct rtc_ops zynqmp_rtc_ops = {
.get = zynqmp_rtc_get,
.set = zynqmp_rtc_set,
.reset = zynqmp_rtc_reset,
};
static const struct udevice_id zynqmp_rtc_ids[] = {
{ .compatible = "xlnx,zynqmp-rtc" },
{ }
};
U_BOOT_DRIVER(rtc_zynqmp) = {
.name = "rtc-zynqmp",
.id = UCLASS_RTC,
.probe = zynqmp_rtc_probe,
.of_match = zynqmp_rtc_ids,
.ops = &zynqmp_rtc_ops,
.priv_auto = sizeof(struct zynqmp_rtc_priv),
};
......@@ -16,6 +16,22 @@ config SOC_DEVICE_TI_K3
This allows Texas Instruments Keystone 3 SoCs to identify
specifics about the SoC in use.
config SOC_XILINX_ZYNQMP
bool "Enable SoC Device ID driver for Xilinx ZynqMP"
depends on SOC_DEVICE && ARCH_ZYNQMP
help
Enable this option to select SoC device id driver for Xilinx ZynqMP.
This allows other drivers to verify the SoC familiy & revision
using matching SoC attributes.
config SOC_XILINX_VERSAL
bool "Enable SoC Device ID driver for Xilinx Versal"
depends on SOC_DEVICE && ARCH_VERSAL
help
Enable this option to select SoC device id driver for Xilinx Versal.
This allows other drivers to verify the SoC familiy & revision using
matching SoC attributes.
source "drivers/soc/ti/Kconfig"
endmenu
......@@ -6,3 +6,5 @@ obj-$(CONFIG_SOC_TI) += ti/
obj-$(CONFIG_SOC_DEVICE) += soc-uclass.o
obj-$(CONFIG_SOC_DEVICE_TI_K3) += soc_ti_k3.o
obj-$(CONFIG_SANDBOX) += soc_sandbox.o
obj-$(CONFIG_SOC_XILINX_ZYNQMP) += soc_xilinx_zynqmp.o
obj-$(CONFIG_SOC_XILINX_VERSAL) += soc_xilinx_versal.o
// SPDX-License-Identifier: GPL-2.0
/*
* Xilinx Versal SOC driver
*
* Copyright (C) 2021 Xilinx, Inc.
*/
#include <common.h>
#include <dm.h>
#include <soc.h>
#include <zynqmp_firmware.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
/*
* v1 -> 0x10 - ES1
* v2 -> 0x20 - Production
*/
static const char versal_family[] = "Versal";
struct soc_xilinx_versal_priv {
const char *family;
char revision;
};
static int soc_xilinx_versal_get_family(struct udevice *dev, char *buf, int size)
{
struct soc_xilinx_versal_priv *priv = dev_get_priv(dev);
return snprintf(buf, size, "%s", priv->family);
}
static int soc_xilinx_versal_get_revision(struct udevice *dev, char *buf, int size)
{
struct soc_xilinx_versal_priv *priv = dev_get_priv(dev);
return snprintf(buf, size, "v%d", priv->revision);
}
static const struct soc_ops soc_xilinx_versal_ops = {
.get_family = soc_xilinx_versal_get_family,
.get_revision = soc_xilinx_versal_get_revision,
};
static int soc_xilinx_versal_probe(struct udevice *dev)
{
struct soc_xilinx_versal_priv *priv = dev_get_priv(dev);
u32 ret_payload[4];
int ret;
priv->family = versal_family;
if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0,
ret_payload);
if (ret)
return ret;
} else {
ret_payload[2] = readl(VERSAL_PS_PMC_VERSION);
if (!ret_payload[2])
return -EINVAL;
}
priv->revision = ret_payload[2] >> VERSAL_PS_VER_SHIFT;
return 0;
}
U_BOOT_DRIVER(soc_xilinx_versal) = {
.name = "soc_xilinx_versal",
.id = UCLASS_SOC,
.ops = &soc_xilinx_versal_ops,
.probe = soc_xilinx_versal_probe,
.priv_auto = sizeof(struct soc_xilinx_versal_priv),
.flags = DM_FLAG_PRE_RELOC,
};
// SPDX-License-Identifier: GPL-2.0
/*
* Xilinx ZynqMP SOC driver
*
* Copyright (C) 2021 Xilinx, Inc.
*/
#include <common.h>
#include <dm.h>
#include <asm/cache.h>
#include <soc.h>
#include <zynqmp_firmware.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/hardware.h>
/*
* Zynqmp has 4 silicon revisions
* v0 -> 0(XCZU9EG-ES1)
* v1 -> 1(XCZU3EG-ES1, XCZU15EG-ES1)
* v2 -> 2(XCZU7EV-ES1, XCZU9EG-ES2, XCZU19EG-ES1)
* v3 -> 3(Production Level)
*/
static const char zynqmp_family[] = "ZynqMP";
struct soc_xilinx_zynqmp_priv {
const char *family;
char revision;
};
static int soc_xilinx_zynqmp_get_family(struct udevice *dev, char *buf, int size)
{
struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
return snprintf(buf, size, "%s", priv->family);
}
static int soc_xilinx_zynqmp_get_revision(struct udevice *dev, char *buf, int size)
{
struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
return snprintf(buf, size, "v%d", priv->revision);
}
static const struct soc_ops soc_xilinx_zynqmp_ops = {
.get_family = soc_xilinx_zynqmp_get_family,
.get_revision = soc_xilinx_zynqmp_get_revision,
};
static int soc_xilinx_zynqmp_probe(struct udevice *dev)
{
struct soc_xilinx_zynqmp_priv *priv = dev_get_priv(dev);
u32 ret_payload[4];
int ret;
priv->family = zynqmp_family;
if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3 ||
!IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE))
ret = zynqmp_mmio_read(ZYNQMP_PS_VERSION, &ret_payload[2]);
else
ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0,
ret_payload);
if (ret < 0)
return ret;
priv->revision = ret_payload[2] & ZYNQMP_PS_VER_MASK;
return 0;
}
U_BOOT_DRIVER(soc_xilinx_zynqmp) = {
.name = "soc_xilinx_zynqmp",
.id = UCLASS_SOC,
.ops = &soc_xilinx_zynqmp_ops,
.probe = soc_xilinx_zynqmp_probe,
.priv_auto = sizeof(struct soc_xilinx_zynqmp_priv),
.flags = DM_FLAG_PRE_RELOC,
};
......@@ -14,6 +14,7 @@
#include <regmap.h>
#include <wdt.h>
#include <linux/compat.h>
#include <dm/device_compat.h>
#include <linux/io.h>
/* Refresh Register Masks */
......
......@@ -268,7 +268,7 @@ struct sdhci_ops {
int (*set_ios_post)(struct sdhci_host *host);
void (*set_clock)(struct sdhci_host *host, u32 div);
int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
void (*set_delay)(struct sdhci_host *host);
int (*set_delay)(struct sdhci_host *host);
int (*deferred_probe)(struct sdhci_host *host);
};
......
......@@ -10,58 +10,156 @@
enum pm_api_id {
PM_GET_API_VERSION = 1,
PM_SET_CONFIGURATION,
PM_GET_NODE_STATUS,
PM_GET_OPERATING_CHARACTERISTIC,
PM_REGISTER_NOTIFIER,
PM_REQUEST_SUSPEND,
PM_SELF_SUSPEND,
PM_FORCE_POWERDOWN,
PM_ABORT_SUSPEND,
PM_REQUEST_WAKEUP,
PM_SET_WAKEUP_SOURCE,
PM_SYSTEM_SHUTDOWN,
PM_REQUEST_NODE,
PM_RELEASE_NODE,
PM_SET_REQUIREMENT,
PM_SET_MAX_LATENCY,
PM_RESET_ASSERT,
PM_RESET_GET_STATUS,
PM_MMIO_WRITE,
PM_MMIO_READ,
PM_PM_INIT_FINALIZE,
PM_FPGA_LOAD,
PM_FPGA_GET_STATUS,
PM_GET_CHIPID,
PM_SET_CONFIGURATION = 2,
PM_GET_NODE_STATUS = 3,
PM_GET_OPERATING_CHARACTERISTIC = 4,
PM_REGISTER_NOTIFIER = 5,
/* API for suspending */
PM_REQUEST_SUSPEND = 6,
PM_SELF_SUSPEND = 7,
PM_FORCE_POWERDOWN = 8,
PM_ABORT_SUSPEND = 9,
PM_REQUEST_WAKEUP = 10,
PM_SET_WAKEUP_SOURCE = 11,
PM_SYSTEM_SHUTDOWN = 12,
PM_REQUEST_NODE = 13,
PM_RELEASE_NODE = 14,
PM_SET_REQUIREMENT = 15,
PM_SET_MAX_LATENCY = 16,
/* Direct control API functions: */
PM_RESET_ASSERT = 17,
PM_RESET_GET_STATUS = 18,
PM_MMIO_WRITE = 19,
PM_MMIO_READ = 20,
PM_PM_INIT_FINALIZE = 21,
PM_FPGA_LOAD = 22,
PM_FPGA_GET_STATUS = 23,
PM_GET_CHIPID = 24,
/* ID 25 is been used by U-boot to process secure boot images */
/* Secure library generic API functions */
PM_SECURE_SHA = 26,
PM_SECURE_RSA,
PM_PINCTRL_REQUEST,
PM_PINCTRL_RELEASE,
PM_PINCTRL_GET_FUNCTION,
PM_PINCTRL_SET_FUNCTION,
PM_PINCTRL_CONFIG_PARAM_GET,
PM_PINCTRL_CONFIG_PARAM_SET,
PM_IOCTL,
PM_QUERY_DATA,
PM_CLOCK_ENABLE,
PM_CLOCK_DISABLE,
PM_CLOCK_GETSTATE,
PM_CLOCK_SETDIVIDER,
PM_CLOCK_GETDIVIDER,
PM_CLOCK_SETRATE,
PM_CLOCK_GETRATE,
PM_CLOCK_SETPARENT,
PM_CLOCK_GETPARENT,
PM_SECURE_IMAGE,
PM_SECURE_RSA = 27,
PM_PINCTRL_REQUEST = 28,
PM_PINCTRL_RELEASE = 29,
PM_PINCTRL_GET_FUNCTION = 30,
PM_PINCTRL_SET_FUNCTION = 31,
PM_PINCTRL_CONFIG_PARAM_GET = 32,
PM_PINCTRL_CONFIG_PARAM_SET = 33,
PM_IOCTL = 34,
PM_QUERY_DATA = 35,
PM_CLOCK_ENABLE = 36,
PM_CLOCK_DISABLE = 37,
PM_CLOCK_GETSTATE = 38,
PM_CLOCK_SETDIVIDER = 39,
PM_CLOCK_GETDIVIDER = 40,
PM_CLOCK_SETRATE = 41,
PM_CLOCK_GETRATE = 42,
PM_CLOCK_SETPARENT = 43,
PM_CLOCK_GETPARENT = 44,
PM_SECURE_IMAGE = 45,
PM_FPGA_READ = 46,
PM_SECURE_AES,
PM_SECURE_AES = 47,
PM_CLOCK_PLL_GETPARAM = 49,
/* PM_REGISTER_ACCESS API */
PM_REGISTER_ACCESS = 52,
PM_EFUSE_ACCESS,
PM_EFUSE_ACCESS = 53,
PM_FEATURE_CHECK = 63,
PM_API_MAX,
};
enum pm_node_id {
NODE_UNKNOWN = 0,
NODE_APU = 1,
NODE_APU_0 = 2,
NODE_APU_1 = 3,
NODE_APU_2 = 4,
NODE_APU_3 = 5,
NODE_RPU = 6,
NODE_RPU_0 = 7,
NODE_RPU_1 = 8,
NODE_PLD = 9,
NODE_FPD = 10,
NODE_OCM_BANK_0 = 11,
NODE_OCM_BANK_1 = 12,
NODE_OCM_BANK_2 = 13,
NODE_OCM_BANK_3 = 14,
NODE_TCM_0_A = 15,
NODE_TCM_0_B = 16,
NODE_TCM_1_A = 17,
NODE_TCM_1_B = 18,
NODE_L2 = 19,
NODE_GPU_PP_0 = 20,
NODE_GPU_PP_1 = 21,
NODE_USB_0 = 22,
NODE_USB_1 = 23,
NODE_TTC_0 = 24,
NODE_TTC_1 = 25,
NODE_TTC_2 = 26,
NODE_TTC_3 = 27,
NODE_SATA = 28,
NODE_ETH_0 = 29,
NODE_ETH_1 = 30,
NODE_ETH_2 = 31,
NODE_ETH_3 = 32,
NODE_UART_0 = 33,
NODE_UART_1 = 34,
NODE_SPI_0 = 35,
NODE_SPI_1 = 36,
NODE_I2C_0 = 37,
NODE_I2C_1 = 38,
NODE_SD_0 = 39,
NODE_SD_1 = 40,
NODE_DP = 41,
NODE_GDMA = 42,
NODE_ADMA = 43,
NODE_NAND = 44,
NODE_QSPI = 45,
NODE_GPIO = 46,
NODE_CAN_0 = 47,
NODE_CAN_1 = 48,
NODE_EXTERN = 49,
NODE_APLL = 50,
NODE_VPLL = 51,
NODE_DPLL = 52,
NODE_RPLL = 53,
NODE_IOPLL = 54,
NODE_DDR = 55,
NODE_IPI_APU = 56,
NODE_IPI_RPU_0 = 57,
NODE_GPU = 58,
NODE_PCIE = 59,
NODE_PCAP = 60,
NODE_RTC = 61,
NODE_LPD = 62,
NODE_VCU = 63,
NODE_IPI_RPU_1 = 64,
NODE_IPI_PL_0 = 65,
NODE_IPI_PL_1 = 66,
NODE_IPI_PL_2 = 67,
NODE_IPI_PL_3 = 68,
NODE_PL = 69,
NODE_GEM_TSU = 70,
NODE_SWDT_0 = 71,
NODE_SWDT_1 = 72,
NODE_CSU = 73,
NODE_PJTAG = 74,
NODE_TRACE = 75,
NODE_TESTSCAN = 76,
NODE_PMU = 77,
NODE_MAX = 78,
};
enum tap_delay_type {
PM_TAPDELAY_INPUT = 0,
PM_TAPDELAY_OUTPUT = 1,
};
enum dll_reset_type {
PM_DLL_RESET_ASSERT = 0,
PM_DLL_RESET_RELEASE = 1,
PM_DLL_RESET_PULSE = 2,
};
enum pm_query_id {
PM_QID_INVALID = 0,
PM_QID_CLOCK_GET_NAME = 1,
......@@ -79,6 +177,171 @@ enum pm_query_id {
PM_QID_CLOCK_GET_MAX_DIVISOR = 13,
};
enum zynqmp_pm_reset_action {
PM_RESET_ACTION_RELEASE = 0,
PM_RESET_ACTION_ASSERT = 1,
PM_RESET_ACTION_PULSE = 2,
};
enum zynqmp_pm_reset {
ZYNQMP_PM_RESET_START = 1000,
ZYNQMP_PM_RESET_PCIE_CFG = ZYNQMP_PM_RESET_START,
ZYNQMP_PM_RESET_PCIE_BRIDGE = 1001,
ZYNQMP_PM_RESET_PCIE_CTRL = 1002,
ZYNQMP_PM_RESET_DP = 1003,
ZYNQMP_PM_RESET_SWDT_CRF = 1004,
ZYNQMP_PM_RESET_AFI_FM5 = 1005,
ZYNQMP_PM_RESET_AFI_FM4 = 1006,
ZYNQMP_PM_RESET_AFI_FM3 = 1007,
ZYNQMP_PM_RESET_AFI_FM2 = 1008,
ZYNQMP_PM_RESET_AFI_FM1 = 1009,
ZYNQMP_PM_RESET_AFI_FM0 = 1010,
ZYNQMP_PM_RESET_GDMA = 1011,
ZYNQMP_PM_RESET_GPU_PP1 = 1012,
ZYNQMP_PM_RESET_GPU_PP0 = 1013,
ZYNQMP_PM_RESET_GPU = 1014,
ZYNQMP_PM_RESET_GT = 1015,
ZYNQMP_PM_RESET_SATA = 1016,
ZYNQMP_PM_RESET_ACPU3_PWRON = 1017,
ZYNQMP_PM_RESET_ACPU2_PWRON = 1018,
ZYNQMP_PM_RESET_ACPU1_PWRON = 1019,
ZYNQMP_PM_RESET_ACPU0_PWRON = 1020,
ZYNQMP_PM_RESET_APU_L2 = 1021,
ZYNQMP_PM_RESET_ACPU3 = 1022,
ZYNQMP_PM_RESET_ACPU2 = 1023,
ZYNQMP_PM_RESET_ACPU1 = 1024,
ZYNQMP_PM_RESET_ACPU0 = 1025,
ZYNQMP_PM_RESET_DDR = 1026,
ZYNQMP_PM_RESET_APM_FPD = 1027,
ZYNQMP_PM_RESET_SOFT = 1028,
ZYNQMP_PM_RESET_GEM0 = 1029,
ZYNQMP_PM_RESET_GEM1 = 1030,
ZYNQMP_PM_RESET_GEM2 = 1031,
ZYNQMP_PM_RESET_GEM3 = 1032,
ZYNQMP_PM_RESET_QSPI = 1033,
ZYNQMP_PM_RESET_UART0 = 1034,
ZYNQMP_PM_RESET_UART1 = 1035,
ZYNQMP_PM_RESET_SPI0 = 1036,
ZYNQMP_PM_RESET_SPI1 = 1037,
ZYNQMP_PM_RESET_SDIO0 = 1038,
ZYNQMP_PM_RESET_SDIO1 = 1039,
ZYNQMP_PM_RESET_CAN0 = 1040,
ZYNQMP_PM_RESET_CAN1 = 1041,
ZYNQMP_PM_RESET_I2C0 = 1042,
ZYNQMP_PM_RESET_I2C1 = 1043,
ZYNQMP_PM_RESET_TTC0 = 1044,
ZYNQMP_PM_RESET_TTC1 = 1045,
ZYNQMP_PM_RESET_TTC2 = 1046,
ZYNQMP_PM_RESET_TTC3 = 1047,
ZYNQMP_PM_RESET_SWDT_CRL = 1048,
ZYNQMP_PM_RESET_NAND = 1049,
ZYNQMP_PM_RESET_ADMA = 1050,
ZYNQMP_PM_RESET_GPIO = 1051,
ZYNQMP_PM_RESET_IOU_CC = 1052,
ZYNQMP_PM_RESET_TIMESTAMP = 1053,
ZYNQMP_PM_RESET_RPU_R50 = 1054,
ZYNQMP_PM_RESET_RPU_R51 = 1055,
ZYNQMP_PM_RESET_RPU_AMBA = 1056,
ZYNQMP_PM_RESET_OCM = 1057,
ZYNQMP_PM_RESET_RPU_PGE = 1058,
ZYNQMP_PM_RESET_USB0_CORERESET = 1059,
ZYNQMP_PM_RESET_USB1_CORERESET = 1060,
ZYNQMP_PM_RESET_USB0_HIBERRESET = 1061,
ZYNQMP_PM_RESET_USB1_HIBERRESET = 1062,
ZYNQMP_PM_RESET_USB0_APB = 1063,
ZYNQMP_PM_RESET_USB1_APB = 1064,
ZYNQMP_PM_RESET_IPI = 1065,
ZYNQMP_PM_RESET_APM_LPD = 1066,
ZYNQMP_PM_RESET_RTC = 1067,
ZYNQMP_PM_RESET_SYSMON = 1068,
ZYNQMP_PM_RESET_AFI_FM6 = 1069,
ZYNQMP_PM_RESET_LPD_SWDT = 1070,
ZYNQMP_PM_RESET_FPD = 1071,
ZYNQMP_PM_RESET_RPU_DBG1 = 1072,
ZYNQMP_PM_RESET_RPU_DBG0 = 1073,
ZYNQMP_PM_RESET_DBG_LPD = 1074,
ZYNQMP_PM_RESET_DBG_FPD = 1075,
ZYNQMP_PM_RESET_APLL = 1076,
ZYNQMP_PM_RESET_DPLL = 1077,
ZYNQMP_PM_RESET_VPLL = 1078,
ZYNQMP_PM_RESET_IOPLL = 1079,
ZYNQMP_PM_RESET_RPLL = 1080,
ZYNQMP_PM_RESET_GPO3_PL_0 = 1081,
ZYNQMP_PM_RESET_GPO3_PL_1 = 1082,
ZYNQMP_PM_RESET_GPO3_PL_2 = 1083,
ZYNQMP_PM_RESET_GPO3_PL_3 = 1084,
ZYNQMP_PM_RESET_GPO3_PL_4 = 1085,
ZYNQMP_PM_RESET_GPO3_PL_5 = 1086,
ZYNQMP_PM_RESET_GPO3_PL_6 = 1087,
ZYNQMP_PM_RESET_GPO3_PL_7 = 1088,
ZYNQMP_PM_RESET_GPO3_PL_8 = 1089,
ZYNQMP_PM_RESET_GPO3_PL_9 = 1090,
ZYNQMP_PM_RESET_GPO3_PL_10 = 1091,
ZYNQMP_PM_RESET_GPO3_PL_11 = 1092,
ZYNQMP_PM_RESET_GPO3_PL_12 = 1093,
ZYNQMP_PM_RESET_GPO3_PL_13 = 1094,
ZYNQMP_PM_RESET_GPO3_PL_14 = 1095,
ZYNQMP_PM_RESET_GPO3_PL_15 = 1096,
ZYNQMP_PM_RESET_GPO3_PL_16 = 1097,
ZYNQMP_PM_RESET_GPO3_PL_17 = 1098,
ZYNQMP_PM_RESET_GPO3_PL_18 = 1099,
ZYNQMP_PM_RESET_GPO3_PL_19 = 1100,
ZYNQMP_PM_RESET_GPO3_PL_20 = 1101,
ZYNQMP_PM_RESET_GPO3_PL_21 = 1102,
ZYNQMP_PM_RESET_GPO3_PL_22 = 1103,
ZYNQMP_PM_RESET_GPO3_PL_23 = 1104,
ZYNQMP_PM_RESET_GPO3_PL_24 = 1105,
ZYNQMP_PM_RESET_GPO3_PL_25 = 1106,
ZYNQMP_PM_RESET_GPO3_PL_26 = 1107,
ZYNQMP_PM_RESET_GPO3_PL_27 = 1108,
ZYNQMP_PM_RESET_GPO3_PL_28 = 1109,
ZYNQMP_PM_RESET_GPO3_PL_29 = 1110,
ZYNQMP_PM_RESET_GPO3_PL_30 = 1111,
ZYNQMP_PM_RESET_GPO3_PL_31 = 1112,
ZYNQMP_PM_RESET_RPU_LS = 1113,
ZYNQMP_PM_RESET_PS_ONLY = 1114,
ZYNQMP_PM_RESET_PL = 1115,
ZYNQMP_PM_RESET_PS_PL0 = 1116,
ZYNQMP_PM_RESET_PS_PL1 = 1117,
ZYNQMP_PM_RESET_PS_PL2 = 1118,
ZYNQMP_PM_RESET_PS_PL3 = 1119,
ZYNQMP_PM_RESET_END = ZYNQMP_PM_RESET_PS_PL3
};
enum pm_ioctl_id {
IOCTL_GET_RPU_OPER_MODE = 0,
IOCTL_SET_RPU_OPER_MODE = 1,
IOCTL_RPU_BOOT_ADDR_CONFIG = 2,
IOCTL_TCM_COMB_CONFIG = 3,
IOCTL_SET_TAPDELAY_BYPASS = 4,
IOCTL_SET_SGMII_MODE = 5,
IOCTL_SD_DLL_RESET = 6,
IOCTL_SET_SD_TAPDELAY = 7,
IOCTL_SET_PLL_FRAC_MODE = 8,
IOCTL_GET_PLL_FRAC_MODE = 9,
IOCTL_SET_PLL_FRAC_DATA = 10,
IOCTL_GET_PLL_FRAC_DATA = 11,
IOCTL_WRITE_GGS = 12,
IOCTL_READ_GGS = 13,
IOCTL_WRITE_PGGS = 14,
IOCTL_READ_PGGS = 15,
/* IOCTL for ULPI reset */
IOCTL_ULPI_RESET = 16,
/* Set healthy bit value*/
IOCTL_SET_BOOT_HEALTH_STATUS = 17,
IOCTL_AFI = 18,
/* Probe counter read/write */
IOCTL_PROBE_COUNTER_READ = 19,
IOCTL_PROBE_COUNTER_WRITE = 20,
IOCTL_OSPI_MUX_SELECT = 21,
/* IOCTL for USB power request */
IOCTL_USB_SET_STATE = 22,
/* IOCTL to get last reset reason */
IOCTL_GET_LAST_RESET_REASON = 23,
/* AIE ISR Clear */
IOCTL_AIE_ISR_CLEAR = 24,
};
#define PM_SIP_SVC 0xc2000000
#define ZYNQMP_PM_VERSION_MAJOR 1
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Xilinx ZynqMP SoC Tap Delay Programming
*
* Copyright (C) 2018 Xilinx, Inc.
*/
#ifndef __ZYNQMP_TAP_DELAY_H__
#define __ZYNQMP_TAP_DELAY_H__
#ifdef CONFIG_ARCH_ZYNQMP
void zynqmp_dll_reset(u8 deviceid);
void arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay);
void arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay);
#else
inline void zynqmp_dll_reset(u8 deviceid) {}
inline void arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay) {}
inline void arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay) {}
#endif
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册