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 <michal.simek@xilinx.com>
This commit is contained in:
parent
8396700c33
commit
3f123b7424
@ -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
|
||||
|
@ -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
|
||||
|
100
drivers/reset/reset-zynqmp.c
Normal file
100
drivers/reset/reset-zynqmp.c
Normal file
@ -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),
|
||||
};
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user