]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
reset: zynqmp: Add reset controller for ZynqMP SoC
authorMichal Simek <michal.simek@xilinx.com>
Fri, 30 Jul 2021 06:00:10 +0000 (08:00 +0200)
committerMichal Simek <michal.simek@xilinx.com>
Fri, 6 Aug 2021 07:32:03 +0000 (09:32 +0200)
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 <michal.simek@xilinx.com>
MAINTAINERS
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-zynqmp.c [new file with mode: 0644]
include/zynqmp_firmware.h

index 483a4584080339a2a67095f2af3924d9ac1341da..868d4e145ca25f3fa9ea000dc65ace33a6eae154 100644 (file)
@@ -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
index a42b3f0077c9a53f0271673f5e3087f749e377d3..d73daf5e31897c895c9f202a9c2fb1d37d8d4c5d 100644 (file)
@@ -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
index 8a0f5280761adfe07999b357cdfa2a4d24ebcea5..d69486bdeb9e5dd69693bda2a55c548d7de63329 100644 (file)
@@ -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 (file)
index 0000000..5765234
--- /dev/null
@@ -0,0 +1,100 @@
+// 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),
+};
index 669af6765ce90029afe446256d39363000211fc4..e2ec8f6b5a52d7e1b517ab643542c8ba77ff4917 100644 (file)
@@ -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