From 31431dd466e7a3520ff780b893b5ca2279939c27 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 30 Jul 2021 07:59:29 +0200 Subject: firmware: xilinx: Use explicit values for all enum values Based on discussion at https://lore.kernel.org/r/20200318125003.GA2727094@kroah.com we got recommendation to use explicit values for all enum values. The patch is following this recommendation. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/daeb67ded45d8a8f6a96717d1fb9c84439dd2ae8.1612361627.git.michal.simek@xilinx.com --- include/zynqmp_firmware.h | 93 +++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 44 deletions(-) (limited to 'include') diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index f6f82bf8828..669af6765ce 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -10,54 +10,59 @@ 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, }; -- cgit v1.3.1 From 3f123b74242bc076ba6cae6d45a11bd5da1d977f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 30 Jul 2021 08:00:10 +0200 Subject: reset: zynqmp: Add reset controller for ZynqMP SoC Add firmware based reset controller for Xilinx ZynqMP SoC to let other drivers to call reset functions. Driver is only tested on Xilinx ZynqMP but support for Xilinx Versal can be simply added. That's why reset_id and nr_reset are assigned in probe folder. Driver is inpired by driver from Linux kernel. Signed-off-by: Michal Simek --- MAINTAINERS | 1 + drivers/reset/Kconfig | 9 +++ drivers/reset/Makefile | 1 + drivers/reset/reset-zynqmp.c | 100 +++++++++++++++++++++++++++++++++ include/zynqmp_firmware.h | 131 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 242 insertions(+) create mode 100644 drivers/reset/reset-zynqmp.c (limited to 'include') diff --git a/MAINTAINERS b/MAINTAINERS index 483a4584080..868d4e145ca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -600,6 +600,7 @@ 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/spi/zynq_qspi.c F: drivers/spi/zynq_spi.c diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index a42b3f0077c..d73daf5e318 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -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 diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 8a0f5280761..d69486bdeb9 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -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 diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c new file mode 100644 index 00000000000..57652346738 --- /dev/null +++ b/drivers/reset/reset-zynqmp.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Xilinx, Inc. - Michal Simek + */ + +#define LOG_CATEGORY UCLASS_RESET + +#include +#include +#include +#include +#include + +#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), +}; diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index 669af6765ce..e2ec8f6b5a5 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -84,6 +84,137 @@ 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 +}; + #define PM_SIP_SVC 0xc2000000 #define ZYNQMP_PM_VERSION_MAJOR 1 -- cgit v1.3.1 From 16b593bec7b965044b6157c54b89669894fc2d54 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Mon, 2 Aug 2021 23:20:41 -0600 Subject: mmc: sdhci: Change prototype of set_delay to return errors set_delay() has return type as void. If there are any errors while setting tapdelay's it won't be able to return them. Change the prototype of set_delay() in sdhci_ops structure and return the errors from wherever it is called. Signed-off-by: Ashok Reddy Soma Reviewed-by: Jaehoon Chung Signed-off-by: Michal Simek --- drivers/mmc/sdhci.c | 10 ++++++++-- include/sdhci.h | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index eea4701d8af..2f78da61beb 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -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) { /* diff --git a/include/sdhci.h b/include/sdhci.h index 0ae9471ad74..44a0d84e5ab 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -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); }; -- cgit v1.3.1 From 42e01bf20ab4f812a1048c8fb354e75f9e50c2f5 Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Mon, 2 Aug 2021 23:20:42 -0600 Subject: zynqmp_firmware: Add zynqmp firmware related enums Add enums for pm node id's, pm ioctl id's, tapdelay types, dll reset types Signed-off-by: T Karthik Reddy Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek --- include/zynqmp_firmware.h | 127 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) (limited to 'include') diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index e2ec8f6b5a5..0b068d7da29 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -67,6 +67,99 @@ enum pm_api_id { 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, @@ -215,6 +308,40 @@ enum zynqmp_pm_reset { 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 -- cgit v1.3.1 From d04498255559dfc002ad71816dfb37437d29f635 Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Mon, 2 Aug 2021 23:20:43 -0600 Subject: mmc: zynq_sdhci: Add xilinx_pm_request() method to set tapdelays Currently xilinx sdhci driver is using zynqmp_mmio_write() to set tapdelay values and DLL resets. Continue to use this for SPL and mini U-Boot where U-Boot will be executed at EL3 level. Use firmware call xilinx_pm_request() using appropriate arguments to set input/output tapdelays and also for DLL resets in regular flow(EL2). Host driver should explicitly request DLL reset before ITAP (assert DLL) and after OTAP (release DLL) to avoid issues in some cases. Also handle error return where possible. Signed-off-by: T Karthik Reddy Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Reviewed-by: Jaehoon Chung --- board/xilinx/zynqmp/tap_delays.c | 148 +++++++++++++++++++++------------------ drivers/mmc/zynq_sdhci.c | 73 +++++++++++++++---- include/zynqmp_tap_delay.h | 25 +++++-- 3 files changed, 159 insertions(+), 87 deletions(-) (limited to 'include') diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c index d16bbb8eff9..514f86a29ae 100644 --- a/board/xilinx/zynqmp/tap_delays.c +++ b/board/xilinx/zynqmp/tap_delays.c @@ -8,94 +8,108 @@ #include #include #include +#include #include #include +#include #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 +#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) -void zynqmp_dll_reset(u8 deviceid) +int zynqmp_dll_reset(u8 node_id, u32 type) { - /* 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); + 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); - 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); + 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); + } } -void arasan_zynqmp_set_in_tapdelay(u8 deviceid, u32 itap_delay) +int arasan_zynqmp_set_in_tapdelay(u8 node_id, u32 itap_delay) { - if (deviceid == 0) { - zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, SD0_DLL_RST); + int ret; - /* 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); + 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; - 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); + ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA, + SD0_ITAPDLYENA); + if (ret) + return ret; - /* 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); + ret = zynqmp_mmio_write(SD_ITAP_DLY, + SD0_ITAPDLYSEL_MASK, + itap_delay); + if (ret) + return ret; - zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0); - } -} + 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; -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); + ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA, + SD1_ITAPDLYENA); + if (ret) + return ret; - /* Program OTAP delay */ - zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, otap_delay); + ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK, + (itap_delay << 16)); + if (ret) + return ret; - zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0); + ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0); + if (ret) + return ret; } else { - zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, SD1_DLL_RST); + return xilinx_pm_request(PM_IOCTL, (u32)node_id, + IOCTL_SET_SD_TAPDELAY, + PM_TAPDELAY_INPUT, itap_delay, NULL); + } + + return 0; +} - /* Program OTAP delay */ - zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, - (otap_delay << 16)); +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); - zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0); + 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); } } diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 1ecc2ec6690..8397f242553 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -18,6 +18,7 @@ #include #include #include +#include #define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8 #define SDHCI_ARASAN_ITAPDLY_SEL_MASK GENMASK(7, 0) @@ -75,26 +76,40 @@ static const u8 mode2timing[] = { [MMC_HS_200] = MMC_TIMING_MMC_HS200, }; -static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid) +static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 node_id) { - u16 clk; + 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 +117,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 +129,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 +141,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 +187,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 +210,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 +252,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 +281,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 +297,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 +330,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; } diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h index 1c1e3e7deed..7ef172f0fa6 100644 --- a/include/zynqmp_tap_delay.h +++ b/include/zynqmp_tap_delay.h @@ -8,14 +8,27 @@ #ifndef __ZYNQMP_TAP_DELAY_H__ #define __ZYNQMP_TAP_DELAY_H__ +#include + #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); +int zynqmp_dll_reset(u8 node_id, u32 type); +int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay); +int 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) {} +inline int zynqmp_dll_reset(u8 deviceid, u32 type) +{ + return 0; +} + +inline int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay) +{ + return 0; +} + +inline int arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay) +{ + return 0; +} #endif #endif -- cgit v1.3.1 From 655d69faaf4bb1e7d3e9c31f07259b61c27e719e Mon Sep 17 00:00:00 2001 From: Ashok Reddy Soma Date: Mon, 2 Aug 2021 23:20:44 -0600 Subject: mmc: zynq_sdhci: Move setting tapdelay code to driver Move tapdelay function calls to zynq_sdhci.c and make them static inline. zynqmp_tap_delay.h has function prototypes for the functions defined in tap_delays.c, which will not be needed anymore. Remove tap_delays.c and zynqmp_tap_delay.h files. Signed-off-by: Ashok Reddy Soma Signed-off-by: Michal Simek Reviewed-by: Jaehoon Chung --- board/xilinx/zynqmp/Makefile | 2 - board/xilinx/zynqmp/tap_delays.c | 115 --------------------------------------- drivers/mmc/zynq_sdhci.c | 108 +++++++++++++++++++++++++++++++++++- include/zynqmp_tap_delay.h | 34 ------------ 4 files changed, 107 insertions(+), 152 deletions(-) delete mode 100644 board/xilinx/zynqmp/tap_delays.c delete mode 100644 include/zynqmp_tap_delay.h (limited to 'include') diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile index 7d8277ca400..a9140287533 100644 --- a/board/xilinx/zynqmp/Makefile +++ b/board/xilinx/zynqmp/Makefile @@ -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 diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c deleted file mode 100644 index 514f86a29ae..00000000000 --- a/board/xilinx/zynqmp/tap_delays.c +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Xilinx ZynqMP SoC Tap Delay Programming - * - * Copyright (C) 2018 Xilinx, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include - -#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) - -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); - } -} - -int arasan_zynqmp_set_in_tapdelay(u8 node_id, u32 itap_delay) -{ - 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; -} - -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); - } -} diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 8397f242553..9a1693940a7 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -15,9 +15,9 @@ #include #include #include +#include #include #include -#include #include #define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8 @@ -31,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]; @@ -49,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, @@ -76,6 +96,92 @@ static const u8 mode2timing[] = { [MMC_HS_200] = MMC_TIMING_MMC_HS200, }; +static inline int arasan_zynqmp_set_in_tapdelay(u8 node_id, u32 itap_delay) +{ + 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; diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h deleted file mode 100644 index 7ef172f0fa6..00000000000 --- a/include/zynqmp_tap_delay.h +++ /dev/null @@ -1,34 +0,0 @@ -/* 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__ - -#include - -#ifdef CONFIG_ARCH_ZYNQMP -int zynqmp_dll_reset(u8 node_id, u32 type); -int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay); -int arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay); -#else -inline int zynqmp_dll_reset(u8 deviceid, u32 type) -{ - return 0; -} - -inline int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay) -{ - return 0; -} - -inline int arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay) -{ - return 0; -} -#endif - -#endif -- cgit v1.3.1