Merge tag 'zynqmp-soc-for-6.18' of https://github.com/Xilinx/linux-xlnx into soc/drivers
arm64: Xilinx SOC changes for 6.18 firmware: - Add debugfs interface - Wire versal-net compatible string - Change SOC family detection * tag 'zynqmp-soc-for-6.18' of https://github.com/Xilinx/linux-xlnx: drivers: firmware: xilinx: Switch to new family code in zynqmp_pm_get_family_info() drivers: firmware: xilinx: Add unique family code for all platforms firmware: xilinx: Add Versal NET platform compatible string firmware: xilinx: Add debugfs support for PM_GET_NODE_STATUS
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
* Xilinx Zynq MPSoC Firmware layer for debugfs APIs
|
||||
*
|
||||
* Copyright (C) 2014-2018 Xilinx, Inc.
|
||||
* Copyright (C) 2022 - 2025 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Michal Simek <michal.simek@amd.com>
|
||||
* Davorin Mista <davorin.mista@aggios.com>
|
||||
@@ -38,6 +39,7 @@ static struct pm_api_info pm_api_list[] = {
|
||||
PM_API(PM_RELEASE_NODE),
|
||||
PM_API(PM_SET_REQUIREMENT),
|
||||
PM_API(PM_GET_API_VERSION),
|
||||
PM_API(PM_GET_NODE_STATUS),
|
||||
PM_API(PM_REGISTER_NOTIFIER),
|
||||
PM_API(PM_RESET_ASSERT),
|
||||
PM_API(PM_RESET_GET_STATUS),
|
||||
@@ -167,6 +169,17 @@ static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret)
|
||||
pm_api_arg[3] ? pm_api_arg[3] :
|
||||
ZYNQMP_PM_REQUEST_ACK_BLOCKING);
|
||||
break;
|
||||
case PM_GET_NODE_STATUS:
|
||||
ret = zynqmp_pm_get_node_status(pm_api_arg[0],
|
||||
&pm_api_ret[0],
|
||||
&pm_api_ret[1],
|
||||
&pm_api_ret[2]);
|
||||
if (!ret)
|
||||
sprintf(debugfs_buf,
|
||||
"GET_NODE_STATUS:\n\tNodeId: %llu\n\tStatus: %u\n\tRequirements: %u\n\tUsage: %u\n",
|
||||
pm_api_arg[0], pm_api_ret[0],
|
||||
pm_api_ret[1], pm_api_ret[2]);
|
||||
break;
|
||||
case PM_REGISTER_NOTIFIER:
|
||||
ret = zynqmp_pm_register_notifier(pm_api_arg[0],
|
||||
pm_api_arg[1] ?
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Xilinx Zynq MPSoC Firmware layer
|
||||
*
|
||||
* Copyright (C) 2014-2022 Xilinx, Inc.
|
||||
* Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2022 - 2025 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Michal Simek <michal.simek@amd.com>
|
||||
* Davorin Mista <davorin.mista@aggios.com>
|
||||
@@ -72,6 +72,15 @@ struct pm_api_feature_data {
|
||||
struct hlist_node hentry;
|
||||
};
|
||||
|
||||
struct platform_fw_data {
|
||||
/*
|
||||
* Family code for platform.
|
||||
*/
|
||||
const u32 family_code;
|
||||
};
|
||||
|
||||
static struct platform_fw_data *active_platform_fw_data;
|
||||
|
||||
static const struct mfd_cell firmware_devs[] = {
|
||||
{
|
||||
.name = "zynqmp_power_controller",
|
||||
@@ -464,8 +473,6 @@ int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...)
|
||||
|
||||
static u32 pm_api_version;
|
||||
static u32 pm_tz_version;
|
||||
static u32 pm_family_code;
|
||||
static u32 pm_sub_family_code;
|
||||
|
||||
int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset)
|
||||
{
|
||||
@@ -532,32 +539,18 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
|
||||
/**
|
||||
* zynqmp_pm_get_family_info() - Get family info of platform
|
||||
* @family: Returned family code value
|
||||
* @subfamily: Returned sub-family code value
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily)
|
||||
int zynqmp_pm_get_family_info(u32 *family)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
u32 idcode;
|
||||
int ret;
|
||||
if (!active_platform_fw_data)
|
||||
return -ENODEV;
|
||||
|
||||
/* Check is family or sub-family code already received */
|
||||
if (pm_family_code && pm_sub_family_code) {
|
||||
*family = pm_family_code;
|
||||
*subfamily = pm_sub_family_code;
|
||||
return 0;
|
||||
}
|
||||
if (!family)
|
||||
return -EINVAL;
|
||||
|
||||
ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, ret_payload, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
idcode = ret_payload[1];
|
||||
pm_family_code = FIELD_GET(FAMILY_CODE_MASK, idcode);
|
||||
pm_sub_family_code = FIELD_GET(SUB_FAMILY_CODE_MASK, idcode);
|
||||
*family = pm_family_code;
|
||||
*subfamily = pm_sub_family_code;
|
||||
*family = active_platform_fw_data->family_code;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1238,8 +1231,13 @@ int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
|
||||
u32 value)
|
||||
{
|
||||
int ret;
|
||||
u32 pm_family_code;
|
||||
|
||||
if (pm_family_code == ZYNQMP_FAMILY_CODE &&
|
||||
ret = zynqmp_pm_get_family_info(&pm_family_code);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pm_family_code == PM_ZYNQMP_FAMILY_CODE &&
|
||||
param == PM_PINCTRL_CONFIG_TRI_STATE) {
|
||||
ret = zynqmp_pm_feature(PM_PINCTRL_CONFIG_PARAM_SET);
|
||||
if (ret < PM_PINCTRL_PARAM_SET_VERSION) {
|
||||
@@ -1413,6 +1411,45 @@ int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_set_tcm_config);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_get_node_status - PM call to request a node's current power state
|
||||
* @node: ID of the component or sub-system in question
|
||||
* @status: Current operating state of the requested node
|
||||
* @requirements: Current requirements asserted on the node,
|
||||
* used for slave nodes only.
|
||||
* @usage: Usage information, used for slave nodes only:
|
||||
* PM_USAGE_NO_MASTER - No master is currently using
|
||||
* the node
|
||||
* PM_USAGE_CURRENT_MASTER - Only requesting master is
|
||||
* currently using the node
|
||||
* PM_USAGE_OTHER_MASTER - Only other masters are
|
||||
* currently using the node
|
||||
* PM_USAGE_BOTH_MASTERS - Both the current and at least
|
||||
* one other master is currently
|
||||
* using the node
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
|
||||
u32 *const requirements, u32 *const usage)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
|
||||
if (!status || !requirements || !usage)
|
||||
return -EINVAL;
|
||||
|
||||
ret = zynqmp_pm_invoke_fn(PM_GET_NODE_STATUS, ret_payload, 1, node);
|
||||
if (ret_payload[0] == XST_PM_SUCCESS) {
|
||||
*status = ret_payload[1];
|
||||
*requirements = ret_payload[2];
|
||||
*usage = ret_payload[3];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_get_node_status);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_force_pwrdwn - PM call to request for another PU or subsystem to
|
||||
* be powered down forcefully
|
||||
@@ -2007,12 +2044,18 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct zynqmp_devinfo *devinfo;
|
||||
u32 pm_family_code;
|
||||
int ret;
|
||||
|
||||
ret = get_set_conduit_method(dev->of_node);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Get platform-specific firmware data from device tree match */
|
||||
active_platform_fw_data = (struct platform_fw_data *)device_get_match_data(dev);
|
||||
if (!active_platform_fw_data)
|
||||
return -EINVAL;
|
||||
|
||||
/* Get SiP SVC version number */
|
||||
ret = zynqmp_pm_get_sip_svc_version(&sip_svc_version);
|
||||
if (ret)
|
||||
@@ -2045,8 +2088,8 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
|
||||
pr_info("%s Platform Management API v%d.%d\n", __func__,
|
||||
pm_api_version >> 16, pm_api_version & 0xFFFF);
|
||||
|
||||
/* Get the Family code and sub family code of platform */
|
||||
ret = zynqmp_pm_get_family_info(&pm_family_code, &pm_sub_family_code);
|
||||
/* Get the Family code of platform */
|
||||
ret = zynqmp_pm_get_family_info(&pm_family_code);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -2073,7 +2116,7 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
|
||||
|
||||
zynqmp_pm_api_debugfs_init();
|
||||
|
||||
if (pm_family_code == VERSAL_FAMILY_CODE) {
|
||||
if (pm_family_code != PM_ZYNQMP_FAMILY_CODE) {
|
||||
em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager",
|
||||
-1, NULL, 0);
|
||||
if (IS_ERR(em_dev))
|
||||
@@ -2113,9 +2156,22 @@ static void zynqmp_firmware_sync_state(struct device *dev)
|
||||
dev_warn(dev, "failed to release power management to firmware\n");
|
||||
}
|
||||
|
||||
static const struct platform_fw_data platform_fw_data_versal = {
|
||||
.family_code = PM_VERSAL_FAMILY_CODE,
|
||||
};
|
||||
|
||||
static const struct platform_fw_data platform_fw_data_versal_net = {
|
||||
.family_code = PM_VERSAL_NET_FAMILY_CODE,
|
||||
};
|
||||
|
||||
static const struct platform_fw_data platform_fw_data_zynqmp = {
|
||||
.family_code = PM_ZYNQMP_FAMILY_CODE,
|
||||
};
|
||||
|
||||
static const struct of_device_id zynqmp_firmware_of_match[] = {
|
||||
{.compatible = "xlnx,zynqmp-firmware"},
|
||||
{.compatible = "xlnx,versal-firmware"},
|
||||
{.compatible = "xlnx,zynqmp-firmware", .data = &platform_fw_data_zynqmp},
|
||||
{.compatible = "xlnx,versal-firmware", .data = &platform_fw_data_versal},
|
||||
{.compatible = "xlnx,versal-net-firmware", .data = &platform_fw_data_versal_net},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
|
||||
|
||||
@@ -100,7 +100,6 @@ struct zynqmp_pctrl_group {
|
||||
|
||||
static struct pinctrl_desc zynqmp_desc;
|
||||
static u32 family_code;
|
||||
static u32 sub_family_code;
|
||||
|
||||
static int zynqmp_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
@@ -605,7 +604,7 @@ static int zynqmp_pinctrl_prepare_func_groups(struct device *dev, u32 fid,
|
||||
return -ENOMEM;
|
||||
|
||||
for (pin = 0; pin < groups[resp[i]].npins; pin++) {
|
||||
if (family_code == ZYNQMP_FAMILY_CODE)
|
||||
if (family_code == PM_ZYNQMP_FAMILY_CODE)
|
||||
__set_bit(groups[resp[i]].pins[pin], used_pins);
|
||||
else
|
||||
__set_bit((u8)groups[resp[i]].pins[pin] - 1, used_pins);
|
||||
@@ -958,11 +957,11 @@ static int zynqmp_pinctrl_probe(struct platform_device *pdev)
|
||||
if (!pctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = zynqmp_pm_get_family_info(&family_code, &sub_family_code);
|
||||
ret = zynqmp_pm_get_family_info(&family_code);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (family_code == ZYNQMP_FAMILY_CODE) {
|
||||
if (family_code == PM_ZYNQMP_FAMILY_CODE) {
|
||||
ret = zynqmp_pinctrl_prepare_pin_desc(&pdev->dev, &zynqmp_desc.pins,
|
||||
&zynqmp_desc.npins);
|
||||
} else {
|
||||
|
||||
@@ -77,17 +77,17 @@ struct registered_event_data {
|
||||
|
||||
static bool xlnx_is_error_event(const u32 node_id)
|
||||
{
|
||||
u32 pm_family_code, pm_sub_family_code;
|
||||
u32 pm_family_code;
|
||||
|
||||
zynqmp_pm_get_family_info(&pm_family_code, &pm_sub_family_code);
|
||||
zynqmp_pm_get_family_info(&pm_family_code);
|
||||
|
||||
if (pm_sub_family_code == VERSAL_SUB_FAMILY_CODE) {
|
||||
if (pm_family_code == PM_VERSAL_FAMILY_CODE) {
|
||||
if (node_id == VERSAL_EVENT_ERROR_PMC_ERR1 ||
|
||||
node_id == VERSAL_EVENT_ERROR_PMC_ERR2 ||
|
||||
node_id == VERSAL_EVENT_ERROR_PSM_ERR1 ||
|
||||
node_id == VERSAL_EVENT_ERROR_PSM_ERR2)
|
||||
return true;
|
||||
} else {
|
||||
} else if (pm_family_code == PM_VERSAL_NET_FAMILY_CODE) {
|
||||
if (node_id == VERSAL_NET_EVENT_ERROR_PMC_ERR1 ||
|
||||
node_id == VERSAL_NET_EVENT_ERROR_PMC_ERR2 ||
|
||||
node_id == VERSAL_NET_EVENT_ERROR_PMC_ERR3 ||
|
||||
|
||||
@@ -285,7 +285,7 @@ static int register_event(struct device *dev, const enum pm_api_cb_id cb_type, c
|
||||
static int zynqmp_pm_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret, irq;
|
||||
u32 pm_api_version, pm_family_code, pm_sub_family_code, node_id;
|
||||
u32 pm_api_version, pm_family_code, node_id;
|
||||
struct mbox_client *client;
|
||||
|
||||
ret = zynqmp_pm_get_api_version(&pm_api_version);
|
||||
@@ -315,14 +315,16 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
|
||||
INIT_WORK(&zynqmp_pm_init_suspend_work->callback_work,
|
||||
zynqmp_pm_init_suspend_work_fn);
|
||||
|
||||
ret = zynqmp_pm_get_family_info(&pm_family_code, &pm_sub_family_code);
|
||||
ret = zynqmp_pm_get_family_info(&pm_family_code);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (pm_sub_family_code == VERSALNET_SUB_FAMILY_CODE)
|
||||
if (pm_family_code == PM_VERSAL_NET_FAMILY_CODE)
|
||||
node_id = PM_DEV_ACPU_0_0;
|
||||
else
|
||||
else if (pm_family_code == PM_VERSAL_FAMILY_CODE)
|
||||
node_id = PM_DEV_ACPU_0;
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
ret = register_event(&pdev->dev, PM_NOTIFY_CB, node_id, EVENT_SUBSYSTEM_RESTART,
|
||||
false, subsystem_restart_event_callback);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Xilinx Zynq MPSoC Firmware layer
|
||||
*
|
||||
* Copyright (C) 2014-2021 Xilinx
|
||||
* Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2022 - 2025 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Michal Simek <michal.simek@amd.com>
|
||||
* Davorin Mista <davorin.mista@aggios.com>
|
||||
@@ -51,16 +51,10 @@
|
||||
|
||||
#define PM_PINCTRL_PARAM_SET_VERSION 2
|
||||
|
||||
#define ZYNQMP_FAMILY_CODE 0x23
|
||||
#define VERSAL_FAMILY_CODE 0x26
|
||||
|
||||
/* When all subfamily of platform need to support */
|
||||
#define ALL_SUB_FAMILY_CODE 0x00
|
||||
#define VERSAL_SUB_FAMILY_CODE 0x01
|
||||
#define VERSALNET_SUB_FAMILY_CODE 0x03
|
||||
|
||||
#define FAMILY_CODE_MASK GENMASK(27, 21)
|
||||
#define SUB_FAMILY_CODE_MASK GENMASK(20, 19)
|
||||
/* Family codes */
|
||||
#define PM_ZYNQMP_FAMILY_CODE 0x1 /* ZynqMP family code */
|
||||
#define PM_VERSAL_FAMILY_CODE 0x2 /* Versal family code */
|
||||
#define PM_VERSAL_NET_FAMILY_CODE 0x3 /* Versal NET family code */
|
||||
|
||||
#define API_ID_MASK GENMASK(7, 0)
|
||||
#define MODULE_ID_MASK GENMASK(11, 8)
|
||||
@@ -164,6 +158,7 @@ enum pm_api_cb_id {
|
||||
enum pm_api_id {
|
||||
PM_API_FEATURES = 0,
|
||||
PM_GET_API_VERSION = 1,
|
||||
PM_GET_NODE_STATUS = 3,
|
||||
PM_REGISTER_NOTIFIER = 5,
|
||||
PM_FORCE_POWERDOWN = 8,
|
||||
PM_REQUEST_WAKEUP = 10,
|
||||
@@ -564,7 +559,7 @@ int zynqmp_pm_invoke_fw_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...);
|
||||
#if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE)
|
||||
int zynqmp_pm_get_api_version(u32 *version);
|
||||
int zynqmp_pm_get_chipid(u32 *idcode, u32 *version);
|
||||
int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily);
|
||||
int zynqmp_pm_get_family_info(u32 *family);
|
||||
int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out);
|
||||
int zynqmp_pm_clock_enable(u32 clock_id);
|
||||
int zynqmp_pm_clock_disable(u32 clock_id);
|
||||
@@ -629,6 +624,8 @@ int zynqmp_pm_request_wake(const u32 node,
|
||||
int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mode);
|
||||
int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode);
|
||||
int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode);
|
||||
int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
|
||||
u32 *const requirements, u32 *const usage);
|
||||
int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value);
|
||||
int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
|
||||
u32 value);
|
||||
@@ -643,7 +640,7 @@ static inline int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily)
|
||||
static inline int zynqmp_pm_get_family_info(u32 *family)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -931,6 +928,13 @@ static inline int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mo
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
|
||||
u32 *const requirements,
|
||||
u32 *const usage)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int zynqmp_pm_set_sd_config(u32 node,
|
||||
enum pm_sd_config_type config,
|
||||
u32 value)
|
||||
|
||||
Reference in New Issue
Block a user