xref: /linux/drivers/firmware/xilinx/zynqmp.c (revision fc8f5028eb0cc5aee0501a99f59a04f748fbff1c)
176582671SRajan Vaja // SPDX-License-Identifier: GPL-2.0
276582671SRajan Vaja /*
376582671SRajan Vaja  * Xilinx Zynq MPSoC Firmware layer
476582671SRajan Vaja  *
5acd6510dSTanmay Shah  *  Copyright (C) 2014-2022 Xilinx, Inc.
692fb7133SRonak Jain  *  Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
776582671SRajan Vaja  *
8a5cb804bSMichal Simek  *  Michal Simek <michal.simek@amd.com>
976582671SRajan Vaja  *  Davorin Mista <davorin.mista@aggios.com>
1076582671SRajan Vaja  *  Jolly Shah <jollys@xilinx.com>
1176582671SRajan Vaja  *  Rajan Vaja <rajanv@xilinx.com>
1276582671SRajan Vaja  */
1376582671SRajan Vaja 
1476582671SRajan Vaja #include <linux/arm-smccc.h>
1576582671SRajan Vaja #include <linux/compiler.h>
1676582671SRajan Vaja #include <linux/device.h>
1776582671SRajan Vaja #include <linux/init.h>
18e23d9c6dSJolly Shah #include <linux/mfd/core.h>
1976582671SRajan Vaja #include <linux/module.h>
2076582671SRajan Vaja #include <linux/of.h>
2176582671SRajan Vaja #include <linux/of_platform.h>
225b45759cSRob Herring #include <linux/platform_device.h>
23*29ea3386SUlf Hansson #include <linux/pm_domain.h>
2476582671SRajan Vaja #include <linux/slab.h>
2576582671SRajan Vaja #include <linux/uaccess.h>
26acfdd185SAmit Sunil Dhamne #include <linux/hashtable.h>
2776582671SRajan Vaja 
2876582671SRajan Vaja #include <linux/firmware/xlnx-zynqmp.h>
29a515814eSAbhyuday Godhasara #include <linux/firmware/xlnx-event-manager.h>
30b3217252SRajan Vaja #include "zynqmp-debug.h"
3176582671SRajan Vaja 
32acfdd185SAmit Sunil Dhamne /* Max HashMap Order for PM API feature check (1<<7 = 128) */
33acfdd185SAmit Sunil Dhamne #define PM_API_FEATURE_CHECK_MAX_ORDER  7
34acfdd185SAmit Sunil Dhamne 
3523c64d76SPiyush Mehta /* CRL registers and bitfields */
3623c64d76SPiyush Mehta #define CRL_APB_BASE			0xFF5E0000U
3723c64d76SPiyush Mehta /* BOOT_PIN_CTRL- Used to control the mode pins after boot */
3823c64d76SPiyush Mehta #define CRL_APB_BOOT_PIN_CTRL		(CRL_APB_BASE + (0x250U))
3923c64d76SPiyush Mehta /* BOOT_PIN_CTRL_MASK- out_val[11:8], out_en[3:0] */
4023c64d76SPiyush Mehta #define CRL_APB_BOOTPIN_CTRL_MASK	0xF0FU
4123c64d76SPiyush Mehta 
42f918cfc0SRonak Jain /* IOCTL/QUERY feature payload size */
43f918cfc0SRonak Jain #define FEATURE_PAYLOAD_SIZE		2
44f918cfc0SRonak Jain 
45461011b1SRavi Patel static bool feature_check_enabled;
4669fe24d1SZou Wei static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
47f918cfc0SRonak Jain static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
48f918cfc0SRonak Jain static u32 query_features[FEATURE_PAYLOAD_SIZE];
49acfdd185SAmit Sunil Dhamne 
5092fb7133SRonak Jain static u32 sip_svc_version;
51a515814eSAbhyuday Godhasara static struct platform_device *em_dev;
52a515814eSAbhyuday Godhasara 
53acfdd185SAmit Sunil Dhamne /**
542c5d8f7cSRonak Jain  * struct zynqmp_devinfo - Structure for Zynqmp device instance
552c5d8f7cSRonak Jain  * @dev:		Device Pointer
562c5d8f7cSRonak Jain  * @feature_conf_id:	Feature conf id
572c5d8f7cSRonak Jain  */
582c5d8f7cSRonak Jain struct zynqmp_devinfo {
592c5d8f7cSRonak Jain 	struct device *dev;
602c5d8f7cSRonak Jain 	u32 feature_conf_id;
612c5d8f7cSRonak Jain };
622c5d8f7cSRonak Jain 
632c5d8f7cSRonak Jain /**
64acfdd185SAmit Sunil Dhamne  * struct pm_api_feature_data - PM API Feature data
65acfdd185SAmit Sunil Dhamne  * @pm_api_id:		PM API Id, used as key to index into hashmap
66acfdd185SAmit Sunil Dhamne  * @feature_status:	status of PM API feature: valid, invalid
67acfdd185SAmit Sunil Dhamne  * @hentry:		hlist_node that hooks this entry into hashtable
68acfdd185SAmit Sunil Dhamne  */
69acfdd185SAmit Sunil Dhamne struct pm_api_feature_data {
70acfdd185SAmit Sunil Dhamne 	u32 pm_api_id;
71acfdd185SAmit Sunil Dhamne 	int feature_status;
72acfdd185SAmit Sunil Dhamne 	struct hlist_node hentry;
73acfdd185SAmit Sunil Dhamne };
74461011b1SRavi Patel 
75e23d9c6dSJolly Shah static const struct mfd_cell firmware_devs[] = {
76e23d9c6dSJolly Shah 	{
77e23d9c6dSJolly Shah 		.name = "zynqmp_power_controller",
78e23d9c6dSJolly Shah 	},
79e23d9c6dSJolly Shah };
80e23d9c6dSJolly Shah 
8176582671SRajan Vaja /**
8276582671SRajan Vaja  * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
8376582671SRajan Vaja  * @ret_status:		PMUFW return code
8476582671SRajan Vaja  *
8576582671SRajan Vaja  * Return: corresponding Linux error code
8676582671SRajan Vaja  */
zynqmp_pm_ret_code(u32 ret_status)8776582671SRajan Vaja static int zynqmp_pm_ret_code(u32 ret_status)
8876582671SRajan Vaja {
8976582671SRajan Vaja 	switch (ret_status) {
9076582671SRajan Vaja 	case XST_PM_SUCCESS:
9176582671SRajan Vaja 	case XST_PM_DOUBLE_REQ:
9276582671SRajan Vaja 		return 0;
93461011b1SRavi Patel 	case XST_PM_NO_FEATURE:
94461011b1SRavi Patel 		return -ENOTSUPP;
958c016c80SJay Buddhabhatti 	case XST_PM_INVALID_VERSION:
968c016c80SJay Buddhabhatti 		return -EOPNOTSUPP;
9776582671SRajan Vaja 	case XST_PM_NO_ACCESS:
9876582671SRajan Vaja 		return -EACCES;
9976582671SRajan Vaja 	case XST_PM_ABORT_SUSPEND:
10076582671SRajan Vaja 		return -ECANCELED;
101df2a4d94SRajan Vaja 	case XST_PM_MULT_USER:
102df2a4d94SRajan Vaja 		return -EUSERS;
10376582671SRajan Vaja 	case XST_PM_INTERNAL:
10476582671SRajan Vaja 	case XST_PM_CONFLICT:
10576582671SRajan Vaja 	case XST_PM_INVALID_NODE:
1065dac2a98SJay Buddhabhatti 	case XST_PM_INVALID_CRC:
10776582671SRajan Vaja 	default:
10876582671SRajan Vaja 		return -EINVAL;
10976582671SRajan Vaja 	}
11076582671SRajan Vaja }
11176582671SRajan Vaja 
do_fw_call_fail(u32 * ret_payload,u32 num_args,...)112f922b16aSJay Buddhabhatti static noinline int do_fw_call_fail(u32 *ret_payload, u32 num_args, ...)
11376582671SRajan Vaja {
11476582671SRajan Vaja 	return -ENODEV;
11576582671SRajan Vaja }
11676582671SRajan Vaja 
11776582671SRajan Vaja /*
11876582671SRajan Vaja  * PM function call wrapper
11976582671SRajan Vaja  * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
12076582671SRajan Vaja  */
121f922b16aSJay Buddhabhatti static int (*do_fw_call)(u32 *ret_payload, u32, ...) = do_fw_call_fail;
12276582671SRajan Vaja 
12376582671SRajan Vaja /**
12476582671SRajan Vaja  * do_fw_call_smc() - Call system-level platform management layer (SMC)
125f922b16aSJay Buddhabhatti  * @num_args:		Number of variable arguments should be <= 8
12676582671SRajan Vaja  * @ret_payload:	Returned value array
12776582671SRajan Vaja  *
12876582671SRajan Vaja  * Invoke platform management function via SMC call (no hypervisor present).
12976582671SRajan Vaja  *
13076582671SRajan Vaja  * Return: Returns status, either success or error+reason
13176582671SRajan Vaja  */
do_fw_call_smc(u32 * ret_payload,u32 num_args,...)132f922b16aSJay Buddhabhatti static noinline int do_fw_call_smc(u32 *ret_payload, u32 num_args, ...)
13376582671SRajan Vaja {
13476582671SRajan Vaja 	struct arm_smccc_res res;
135f922b16aSJay Buddhabhatti 	u64 args[8] = {0};
136f922b16aSJay Buddhabhatti 	va_list arg_list;
137f922b16aSJay Buddhabhatti 	u8 i;
13876582671SRajan Vaja 
139f922b16aSJay Buddhabhatti 	if (num_args > 8)
140f922b16aSJay Buddhabhatti 		return -EINVAL;
141f922b16aSJay Buddhabhatti 
142f922b16aSJay Buddhabhatti 	va_start(arg_list, num_args);
143f922b16aSJay Buddhabhatti 
144f922b16aSJay Buddhabhatti 	for (i = 0; i < num_args; i++)
145f922b16aSJay Buddhabhatti 		args[i] = va_arg(arg_list, u64);
146f922b16aSJay Buddhabhatti 
147f922b16aSJay Buddhabhatti 	va_end(arg_list);
148f922b16aSJay Buddhabhatti 
149f922b16aSJay Buddhabhatti 	arm_smccc_smc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
15076582671SRajan Vaja 
15176582671SRajan Vaja 	if (ret_payload) {
15276582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
15376582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
15476582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
15576582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
15692fb7133SRonak Jain 		ret_payload[4] = lower_32_bits(res.a2);
15792fb7133SRonak Jain 		ret_payload[5] = upper_32_bits(res.a2);
15892fb7133SRonak Jain 		ret_payload[6] = lower_32_bits(res.a3);
15976582671SRajan Vaja 	}
16076582671SRajan Vaja 
16176582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
16276582671SRajan Vaja }
16376582671SRajan Vaja 
16476582671SRajan Vaja /**
16576582671SRajan Vaja  * do_fw_call_hvc() - Call system-level platform management layer (HVC)
166f922b16aSJay Buddhabhatti  * @num_args:		Number of variable arguments should be <= 8
16776582671SRajan Vaja  * @ret_payload:	Returned value array
16876582671SRajan Vaja  *
16976582671SRajan Vaja  * Invoke platform management function via HVC
17076582671SRajan Vaja  * HVC-based for communication through hypervisor
17176582671SRajan Vaja  * (no direct communication with ATF).
17276582671SRajan Vaja  *
17376582671SRajan Vaja  * Return: Returns status, either success or error+reason
17476582671SRajan Vaja  */
do_fw_call_hvc(u32 * ret_payload,u32 num_args,...)175f922b16aSJay Buddhabhatti static noinline int do_fw_call_hvc(u32 *ret_payload, u32 num_args, ...)
17676582671SRajan Vaja {
17776582671SRajan Vaja 	struct arm_smccc_res res;
178f922b16aSJay Buddhabhatti 	u64 args[8] = {0};
179f922b16aSJay Buddhabhatti 	va_list arg_list;
180f922b16aSJay Buddhabhatti 	u8 i;
18176582671SRajan Vaja 
182f922b16aSJay Buddhabhatti 	if (num_args > 8)
183f922b16aSJay Buddhabhatti 		return -EINVAL;
184f922b16aSJay Buddhabhatti 
185f922b16aSJay Buddhabhatti 	va_start(arg_list, num_args);
186f922b16aSJay Buddhabhatti 
187f922b16aSJay Buddhabhatti 	for (i = 0; i < num_args; i++)
188f922b16aSJay Buddhabhatti 		args[i] = va_arg(arg_list, u64);
189f922b16aSJay Buddhabhatti 
190f922b16aSJay Buddhabhatti 	va_end(arg_list);
191f922b16aSJay Buddhabhatti 
192f922b16aSJay Buddhabhatti 	arm_smccc_hvc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
19376582671SRajan Vaja 
19476582671SRajan Vaja 	if (ret_payload) {
19576582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
19676582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
19776582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
19876582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
19992fb7133SRonak Jain 		ret_payload[4] = lower_32_bits(res.a2);
20092fb7133SRonak Jain 		ret_payload[5] = upper_32_bits(res.a2);
20192fb7133SRonak Jain 		ret_payload[6] = lower_32_bits(res.a3);
20276582671SRajan Vaja 	}
20376582671SRajan Vaja 
20476582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
20576582671SRajan Vaja }
20676582671SRajan Vaja 
__do_feature_check_call(const u32 api_id,u32 * ret_payload)207218f01a8SRonak Jain static int __do_feature_check_call(const u32 api_id, u32 *ret_payload)
20894ae7f22SRonak Jain {
20994ae7f22SRonak Jain 	int ret;
21094ae7f22SRonak Jain 	u64 smc_arg[2];
211f689a0caSJay Buddhabhatti 	u32 module_id;
212f689a0caSJay Buddhabhatti 	u32 feature_check_api_id;
21394ae7f22SRonak Jain 
214f689a0caSJay Buddhabhatti 	module_id = FIELD_GET(MODULE_ID_MASK, api_id);
215f689a0caSJay Buddhabhatti 
216f689a0caSJay Buddhabhatti 	/*
217f689a0caSJay Buddhabhatti 	 * Feature check of APIs belonging to PM, XSEM, and TF-A are handled by calling
218f689a0caSJay Buddhabhatti 	 * PM_FEATURE_CHECK API. For other modules, call PM_API_FEATURES API.
219f689a0caSJay Buddhabhatti 	 */
220f689a0caSJay Buddhabhatti 	if (module_id == PM_MODULE_ID || module_id == XSEM_MODULE_ID || module_id == TF_A_MODULE_ID)
221f689a0caSJay Buddhabhatti 		feature_check_api_id = PM_FEATURE_CHECK;
222f689a0caSJay Buddhabhatti 	else
223f689a0caSJay Buddhabhatti 		feature_check_api_id = PM_API_FEATURES;
224f689a0caSJay Buddhabhatti 
225f689a0caSJay Buddhabhatti 	/*
226f689a0caSJay Buddhabhatti 	 * Feature check of TF-A APIs is done in the TF-A layer and it expects for
227f689a0caSJay Buddhabhatti 	 * MODULE_ID_MASK bits of SMC's arg[0] to be the same as PM_MODULE_ID.
228f689a0caSJay Buddhabhatti 	 */
22955ed774dSRonak Jain 	if (module_id == TF_A_MODULE_ID) {
230f689a0caSJay Buddhabhatti 		module_id = PM_MODULE_ID;
23155ed774dSRonak Jain 		smc_arg[1] = api_id;
23255ed774dSRonak Jain 	} else {
23355ed774dSRonak Jain 		smc_arg[1] = (api_id & API_ID_MASK);
23455ed774dSRonak Jain 	}
235f689a0caSJay Buddhabhatti 
236f689a0caSJay Buddhabhatti 	smc_arg[0] = PM_SIP_SVC | FIELD_PREP(MODULE_ID_MASK, module_id) | feature_check_api_id;
23794ae7f22SRonak Jain 
238f922b16aSJay Buddhabhatti 	ret = do_fw_call(ret_payload, 2, smc_arg[0], smc_arg[1]);
23994ae7f22SRonak Jain 	if (ret)
24094ae7f22SRonak Jain 		ret = -EOPNOTSUPP;
24194ae7f22SRonak Jain 	else
24294ae7f22SRonak Jain 		ret = ret_payload[1];
24394ae7f22SRonak Jain 
24494ae7f22SRonak Jain 	return ret;
24594ae7f22SRonak Jain }
24694ae7f22SRonak Jain 
do_feature_check_call(const u32 api_id)247218f01a8SRonak Jain static int do_feature_check_call(const u32 api_id)
248461011b1SRavi Patel {
249461011b1SRavi Patel 	int ret;
250461011b1SRavi Patel 	u32 ret_payload[PAYLOAD_ARG_CNT];
251acfdd185SAmit Sunil Dhamne 	struct pm_api_feature_data *feature_data;
252461011b1SRavi Patel 
253acfdd185SAmit Sunil Dhamne 	/* Check for existing entry in hash table for given api */
254acfdd185SAmit Sunil Dhamne 	hash_for_each_possible(pm_api_features_map, feature_data, hentry,
255acfdd185SAmit Sunil Dhamne 			       api_id) {
256acfdd185SAmit Sunil Dhamne 		if (feature_data->pm_api_id == api_id)
257acfdd185SAmit Sunil Dhamne 			return feature_data->feature_status;
258acfdd185SAmit Sunil Dhamne 	}
259f3217d6fSArnd Bergmann 
260acfdd185SAmit Sunil Dhamne 	/* Add new entry if not present */
26138ed310cSRoman Gushchin 	feature_data = kmalloc(sizeof(*feature_data), GFP_ATOMIC);
262acfdd185SAmit Sunil Dhamne 	if (!feature_data)
263acfdd185SAmit Sunil Dhamne 		return -ENOMEM;
264461011b1SRavi Patel 
265acfdd185SAmit Sunil Dhamne 	feature_data->pm_api_id = api_id;
266218f01a8SRonak Jain 	ret = __do_feature_check_call(api_id, ret_payload);
267461011b1SRavi Patel 
268acfdd185SAmit Sunil Dhamne 	feature_data->feature_status = ret;
269acfdd185SAmit Sunil Dhamne 	hash_add(pm_api_features_map, &feature_data->hentry, api_id);
270461011b1SRavi Patel 
271f918cfc0SRonak Jain 	if (api_id == PM_IOCTL)
272f918cfc0SRonak Jain 		/* Store supported IOCTL IDs mask */
273f918cfc0SRonak Jain 		memcpy(ioctl_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
274f918cfc0SRonak Jain 	else if (api_id == PM_QUERY_DATA)
275f918cfc0SRonak Jain 		/* Store supported QUERY IDs mask */
276f918cfc0SRonak Jain 		memcpy(query_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
277f918cfc0SRonak Jain 
278acfdd185SAmit Sunil Dhamne 	return ret;
279461011b1SRavi Patel }
280461011b1SRavi Patel 
281461011b1SRavi Patel /**
282218f01a8SRonak Jain  * zynqmp_pm_feature() - Check whether given feature is supported or not and
283218f01a8SRonak Jain  *			 store supported IOCTL/QUERY ID mask
284218f01a8SRonak Jain  * @api_id:		API ID to check
285218f01a8SRonak Jain  *
286218f01a8SRonak Jain  * Return: Returns status, either success or error+reason
287218f01a8SRonak Jain  */
zynqmp_pm_feature(const u32 api_id)288218f01a8SRonak Jain int zynqmp_pm_feature(const u32 api_id)
289218f01a8SRonak Jain {
290218f01a8SRonak Jain 	int ret;
291218f01a8SRonak Jain 
292218f01a8SRonak Jain 	if (!feature_check_enabled)
293218f01a8SRonak Jain 		return 0;
294218f01a8SRonak Jain 
295218f01a8SRonak Jain 	ret = do_feature_check_call(api_id);
296218f01a8SRonak Jain 
297218f01a8SRonak Jain 	return ret;
298218f01a8SRonak Jain }
29979614953SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
300218f01a8SRonak Jain 
301218f01a8SRonak Jain /**
302f918cfc0SRonak Jain  * zynqmp_pm_is_function_supported() - Check whether given IOCTL/QUERY function
303f918cfc0SRonak Jain  *				       is supported or not
304f918cfc0SRonak Jain  * @api_id:		PM_IOCTL or PM_QUERY_DATA
305f918cfc0SRonak Jain  * @id:			IOCTL or QUERY function IDs
306f918cfc0SRonak Jain  *
307f918cfc0SRonak Jain  * Return: Returns status, either success or error+reason
308f918cfc0SRonak Jain  */
zynqmp_pm_is_function_supported(const u32 api_id,const u32 id)309f918cfc0SRonak Jain int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
310f918cfc0SRonak Jain {
311f918cfc0SRonak Jain 	int ret;
312f918cfc0SRonak Jain 	u32 *bit_mask;
313f918cfc0SRonak Jain 
314f918cfc0SRonak Jain 	/* Input arguments validation */
315f918cfc0SRonak Jain 	if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA))
316f918cfc0SRonak Jain 		return -EINVAL;
317f918cfc0SRonak Jain 
318f918cfc0SRonak Jain 	/* Check feature check API version */
319218f01a8SRonak Jain 	ret = do_feature_check_call(PM_FEATURE_CHECK);
320f918cfc0SRonak Jain 	if (ret < 0)
321f918cfc0SRonak Jain 		return ret;
322f918cfc0SRonak Jain 
323f918cfc0SRonak Jain 	/* Check if feature check version 2 is supported or not */
324f918cfc0SRonak Jain 	if ((ret & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) {
325f918cfc0SRonak Jain 		/*
326f918cfc0SRonak Jain 		 * Call feature check for IOCTL/QUERY API to get IOCTL ID or
327f918cfc0SRonak Jain 		 * QUERY ID feature status.
328f918cfc0SRonak Jain 		 */
329218f01a8SRonak Jain 		ret = do_feature_check_call(api_id);
330f918cfc0SRonak Jain 		if (ret < 0)
331f918cfc0SRonak Jain 			return ret;
332f918cfc0SRonak Jain 
333f918cfc0SRonak Jain 		bit_mask = (api_id == PM_IOCTL) ? ioctl_features : query_features;
334f918cfc0SRonak Jain 
335f918cfc0SRonak Jain 		if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0U)
336f918cfc0SRonak Jain 			return -EOPNOTSUPP;
337f918cfc0SRonak Jain 	} else {
338f918cfc0SRonak Jain 		return -ENODATA;
339f918cfc0SRonak Jain 	}
340f918cfc0SRonak Jain 
341f918cfc0SRonak Jain 	return 0;
342f918cfc0SRonak Jain }
343f918cfc0SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported);
344f918cfc0SRonak Jain 
345f918cfc0SRonak Jain /**
34692fb7133SRonak Jain  * zynqmp_pm_invoke_fw_fn() - Invoke the system-level platform management layer
34792fb7133SRonak Jain  *			caller function depending on the configuration
34892fb7133SRonak Jain  * @pm_api_id:		Requested PM-API call
34992fb7133SRonak Jain  * @ret_payload:	Returned value array
35092fb7133SRonak Jain  * @num_args:		Number of arguments to requested PM-API call
35192fb7133SRonak Jain  *
35292fb7133SRonak Jain  * Invoke platform management function for SMC or HVC call, depending on
35392fb7133SRonak Jain  * configuration.
35492fb7133SRonak Jain  * Following SMC Calling Convention (SMCCC) for SMC64:
35592fb7133SRonak Jain  * Pm Function Identifier,
35692fb7133SRonak Jain  * PM_SIP_SVC + PASS_THROUGH_FW_CMD_ID =
35792fb7133SRonak Jain  *	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
35892fb7133SRonak Jain  *	((SMC_64) << FUNCID_CC_SHIFT)
35992fb7133SRonak Jain  *	((SIP_START) << FUNCID_OEN_SHIFT)
36092fb7133SRonak Jain  *	(PASS_THROUGH_FW_CMD_ID))
36192fb7133SRonak Jain  *
36292fb7133SRonak Jain  * PM_SIP_SVC - Registered ZynqMP SIP Service Call.
36392fb7133SRonak Jain  * PASS_THROUGH_FW_CMD_ID - Fixed SiP SVC call ID for FW specific calls.
36492fb7133SRonak Jain  *
36592fb7133SRonak Jain  * Return: Returns status, either success or error+reason
36692fb7133SRonak Jain  */
zynqmp_pm_invoke_fw_fn(u32 pm_api_id,u32 * ret_payload,u32 num_args,...)36792fb7133SRonak Jain int zynqmp_pm_invoke_fw_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...)
36892fb7133SRonak Jain {
36992fb7133SRonak Jain 	/*
37092fb7133SRonak Jain 	 * Added SIP service call Function Identifier
37192fb7133SRonak Jain 	 * Make sure to stay in x0 register
37292fb7133SRonak Jain 	 */
37392fb7133SRonak Jain 	u64 smc_arg[SMC_ARG_CNT_64];
37492fb7133SRonak Jain 	int ret, i;
37592fb7133SRonak Jain 	va_list arg_list;
37692fb7133SRonak Jain 	u32 args[SMC_ARG_CNT_32] = {0};
37792fb7133SRonak Jain 	u32 module_id;
37892fb7133SRonak Jain 
37992fb7133SRonak Jain 	if (num_args > SMC_ARG_CNT_32)
38092fb7133SRonak Jain 		return -EINVAL;
38192fb7133SRonak Jain 
38292fb7133SRonak Jain 	va_start(arg_list, num_args);
38392fb7133SRonak Jain 
38492fb7133SRonak Jain 	/* Check if feature is supported or not */
38592fb7133SRonak Jain 	ret = zynqmp_pm_feature(pm_api_id);
38692fb7133SRonak Jain 	if (ret < 0)
38792fb7133SRonak Jain 		return ret;
38892fb7133SRonak Jain 
38992fb7133SRonak Jain 	for (i = 0; i < num_args; i++)
39092fb7133SRonak Jain 		args[i] = va_arg(arg_list, u32);
39192fb7133SRonak Jain 
39292fb7133SRonak Jain 	va_end(arg_list);
39392fb7133SRonak Jain 
39492fb7133SRonak Jain 	module_id = FIELD_GET(PLM_MODULE_ID_MASK, pm_api_id);
39592fb7133SRonak Jain 
39692fb7133SRonak Jain 	if (module_id == 0)
39792fb7133SRonak Jain 		module_id = XPM_MODULE_ID;
39892fb7133SRonak Jain 
39992fb7133SRonak Jain 	smc_arg[0] = PM_SIP_SVC | PASS_THROUGH_FW_CMD_ID;
40092fb7133SRonak Jain 	smc_arg[1] = ((u64)args[0] << 32U) | FIELD_PREP(PLM_MODULE_ID_MASK, module_id) |
40192fb7133SRonak Jain 		      (pm_api_id & API_ID_MASK);
40292fb7133SRonak Jain 	for (i = 1; i < (SMC_ARG_CNT_64 - 1); i++)
40392fb7133SRonak Jain 		smc_arg[i + 1] = ((u64)args[(i * 2)] << 32U) | args[(i * 2) - 1];
40492fb7133SRonak Jain 
40592fb7133SRonak Jain 	return do_fw_call(ret_payload, 8, smc_arg[0], smc_arg[1], smc_arg[2], smc_arg[3],
40692fb7133SRonak Jain 			  smc_arg[4], smc_arg[5], smc_arg[6], smc_arg[7]);
40792fb7133SRonak Jain }
40892fb7133SRonak Jain 
40992fb7133SRonak Jain /**
41076582671SRajan Vaja  * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
41176582671SRajan Vaja  *			   caller function depending on the configuration
41276582671SRajan Vaja  * @pm_api_id:		Requested PM-API call
41376582671SRajan Vaja  * @ret_payload:	Returned value array
414f922b16aSJay Buddhabhatti  * @num_args:		Number of arguments to requested PM-API call
41576582671SRajan Vaja  *
41676582671SRajan Vaja  * Invoke platform management function for SMC or HVC call, depending on
41776582671SRajan Vaja  * configuration.
41876582671SRajan Vaja  * Following SMC Calling Convention (SMCCC) for SMC64:
41976582671SRajan Vaja  * Pm Function Identifier,
42076582671SRajan Vaja  * PM_SIP_SVC + PM_API_ID =
42176582671SRajan Vaja  *	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
42276582671SRajan Vaja  *	((SMC_64) << FUNCID_CC_SHIFT)
42376582671SRajan Vaja  *	((SIP_START) << FUNCID_OEN_SHIFT)
42476582671SRajan Vaja  *	((PM_API_ID) & FUNCID_NUM_MASK))
42576582671SRajan Vaja  *
42676582671SRajan Vaja  * PM_SIP_SVC	- Registered ZynqMP SIP Service Call.
42776582671SRajan Vaja  * PM_API_ID	- Platform Management API ID.
42876582671SRajan Vaja  *
42976582671SRajan Vaja  * Return: Returns status, either success or error+reason
43076582671SRajan Vaja  */
zynqmp_pm_invoke_fn(u32 pm_api_id,u32 * ret_payload,u32 num_args,...)431f922b16aSJay Buddhabhatti int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...)
43276582671SRajan Vaja {
43376582671SRajan Vaja 	/*
43476582671SRajan Vaja 	 * Added SIP service call Function Identifier
43576582671SRajan Vaja 	 * Make sure to stay in x0 register
43676582671SRajan Vaja 	 */
437f922b16aSJay Buddhabhatti 	u64 smc_arg[8];
438f922b16aSJay Buddhabhatti 	int ret, i;
439f922b16aSJay Buddhabhatti 	va_list arg_list;
440f922b16aSJay Buddhabhatti 	u32 args[14] = {0};
441f922b16aSJay Buddhabhatti 
442f922b16aSJay Buddhabhatti 	if (num_args > 14)
443f922b16aSJay Buddhabhatti 		return -EINVAL;
444f922b16aSJay Buddhabhatti 
445f922b16aSJay Buddhabhatti 	va_start(arg_list, num_args);
44676582671SRajan Vaja 
447acfdd185SAmit Sunil Dhamne 	/* Check if feature is supported or not */
448acfdd185SAmit Sunil Dhamne 	ret = zynqmp_pm_feature(pm_api_id);
449acfdd185SAmit Sunil Dhamne 	if (ret < 0)
450acfdd185SAmit Sunil Dhamne 		return ret;
451461011b1SRavi Patel 
452f922b16aSJay Buddhabhatti 	for (i = 0; i < num_args; i++)
453f922b16aSJay Buddhabhatti 		args[i] = va_arg(arg_list, u32);
45476582671SRajan Vaja 
455f922b16aSJay Buddhabhatti 	va_end(arg_list);
456f922b16aSJay Buddhabhatti 
457f922b16aSJay Buddhabhatti 	smc_arg[0] = PM_SIP_SVC | pm_api_id;
458f922b16aSJay Buddhabhatti 	for (i = 0; i < 7; i++)
459f922b16aSJay Buddhabhatti 		smc_arg[i + 1] = ((u64)args[(i * 2) + 1] << 32) | args[i * 2];
460f922b16aSJay Buddhabhatti 
461f922b16aSJay Buddhabhatti 	return do_fw_call(ret_payload, 8, smc_arg[0], smc_arg[1], smc_arg[2], smc_arg[3],
462f922b16aSJay Buddhabhatti 			  smc_arg[4], smc_arg[5], smc_arg[6], smc_arg[7]);
46376582671SRajan Vaja }
46476582671SRajan Vaja 
46576582671SRajan Vaja static u32 pm_api_version;
46676582671SRajan Vaja static u32 pm_tz_version;
46703ffa9afSDhaval Shah static u32 pm_family_code;
46803ffa9afSDhaval Shah static u32 pm_sub_family_code;
46976582671SRajan Vaja 
zynqmp_pm_register_sgi(u32 sgi_num,u32 reset)470acd6510dSTanmay Shah int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset)
471acd6510dSTanmay Shah {
472acd6510dSTanmay Shah 	int ret;
473acd6510dSTanmay Shah 
474f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(TF_A_PM_REGISTER_SGI, NULL, 2, sgi_num, reset);
4758c016c80SJay Buddhabhatti 	if (ret != -EOPNOTSUPP && !ret)
476acd6510dSTanmay Shah 		return ret;
477acd6510dSTanmay Shah 
478acd6510dSTanmay Shah 	/* try old implementation as fallback strategy if above fails */
479f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, IOCTL_REGISTER_SGI, sgi_num, reset);
480acd6510dSTanmay Shah }
481acd6510dSTanmay Shah 
48276582671SRajan Vaja /**
48376582671SRajan Vaja  * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
48476582671SRajan Vaja  * @version:	Returned version value
48576582671SRajan Vaja  *
48676582671SRajan Vaja  * Return: Returns status, either success or error+reason
48776582671SRajan Vaja  */
zynqmp_pm_get_api_version(u32 * version)488b9b3a8beSRajan Vaja int zynqmp_pm_get_api_version(u32 *version)
48976582671SRajan Vaja {
49076582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
49176582671SRajan Vaja 	int ret;
49276582671SRajan Vaja 
49376582671SRajan Vaja 	if (!version)
49476582671SRajan Vaja 		return -EINVAL;
49576582671SRajan Vaja 
49676582671SRajan Vaja 	/* Check is PM API version already verified */
49776582671SRajan Vaja 	if (pm_api_version > 0) {
49876582671SRajan Vaja 		*version = pm_api_version;
49976582671SRajan Vaja 		return 0;
50076582671SRajan Vaja 	}
501f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, ret_payload, 0);
50276582671SRajan Vaja 	*version = ret_payload[1];
50376582671SRajan Vaja 
50476582671SRajan Vaja 	return ret;
50576582671SRajan Vaja }
506b9b3a8beSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
50776582671SRajan Vaja 
50876582671SRajan Vaja /**
509fe6f42cfSNava kishore Manne  * zynqmp_pm_get_chipid - Get silicon ID registers
510fe6f42cfSNava kishore Manne  * @idcode:     IDCODE register
511fe6f42cfSNava kishore Manne  * @version:    version register
512fe6f42cfSNava kishore Manne  *
513fe6f42cfSNava kishore Manne  * Return:      Returns the status of the operation and the idcode and version
514fe6f42cfSNava kishore Manne  *              registers in @idcode and @version.
515fe6f42cfSNava kishore Manne  */
zynqmp_pm_get_chipid(u32 * idcode,u32 * version)51621cd93baSRajan Vaja int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
517fe6f42cfSNava kishore Manne {
518fe6f42cfSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
519fe6f42cfSNava kishore Manne 	int ret;
520fe6f42cfSNava kishore Manne 
521fe6f42cfSNava kishore Manne 	if (!idcode || !version)
522fe6f42cfSNava kishore Manne 		return -EINVAL;
523fe6f42cfSNava kishore Manne 
524f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, ret_payload, 0);
525fe6f42cfSNava kishore Manne 	*idcode = ret_payload[1];
526fe6f42cfSNava kishore Manne 	*version = ret_payload[2];
527fe6f42cfSNava kishore Manne 
528fe6f42cfSNava kishore Manne 	return ret;
529fe6f42cfSNava kishore Manne }
53021cd93baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
531fe6f42cfSNava kishore Manne 
532fe6f42cfSNava kishore Manne /**
53303ffa9afSDhaval Shah  * zynqmp_pm_get_family_info() - Get family info of platform
53403ffa9afSDhaval Shah  * @family:	Returned family code value
53503ffa9afSDhaval Shah  * @subfamily:	Returned sub-family code value
53603ffa9afSDhaval Shah  *
53703ffa9afSDhaval Shah  * Return: Returns status, either success or error+reason
53803ffa9afSDhaval Shah  */
zynqmp_pm_get_family_info(u32 * family,u32 * subfamily)5390c4b2255SJay Buddhabhatti int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily)
54003ffa9afSDhaval Shah {
54103ffa9afSDhaval Shah 	u32 ret_payload[PAYLOAD_ARG_CNT];
54203ffa9afSDhaval Shah 	u32 idcode;
54303ffa9afSDhaval Shah 	int ret;
54403ffa9afSDhaval Shah 
54503ffa9afSDhaval Shah 	/* Check is family or sub-family code already received */
54603ffa9afSDhaval Shah 	if (pm_family_code && pm_sub_family_code) {
54703ffa9afSDhaval Shah 		*family = pm_family_code;
54803ffa9afSDhaval Shah 		*subfamily = pm_sub_family_code;
54903ffa9afSDhaval Shah 		return 0;
55003ffa9afSDhaval Shah 	}
55103ffa9afSDhaval Shah 
552f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, ret_payload, 0);
55303ffa9afSDhaval Shah 	if (ret < 0)
55403ffa9afSDhaval Shah 		return ret;
55503ffa9afSDhaval Shah 
55603ffa9afSDhaval Shah 	idcode = ret_payload[1];
55703ffa9afSDhaval Shah 	pm_family_code = FIELD_GET(FAMILY_CODE_MASK, idcode);
55803ffa9afSDhaval Shah 	pm_sub_family_code = FIELD_GET(SUB_FAMILY_CODE_MASK, idcode);
55903ffa9afSDhaval Shah 	*family = pm_family_code;
56003ffa9afSDhaval Shah 	*subfamily = pm_sub_family_code;
56103ffa9afSDhaval Shah 
56203ffa9afSDhaval Shah 	return 0;
56303ffa9afSDhaval Shah }
5640c4b2255SJay Buddhabhatti EXPORT_SYMBOL_GPL(zynqmp_pm_get_family_info);
56503ffa9afSDhaval Shah 
56603ffa9afSDhaval Shah /**
56792fb7133SRonak Jain  * zynqmp_pm_get_sip_svc_version() - Get SiP service call version
56892fb7133SRonak Jain  * @version:	Returned version value
56992fb7133SRonak Jain  *
57092fb7133SRonak Jain  * Return: Returns status, either success or error+reason
57192fb7133SRonak Jain  */
zynqmp_pm_get_sip_svc_version(u32 * version)57292fb7133SRonak Jain static int zynqmp_pm_get_sip_svc_version(u32 *version)
57392fb7133SRonak Jain {
57492fb7133SRonak Jain 	struct arm_smccc_res res;
57592fb7133SRonak Jain 	u64 args[SMC_ARG_CNT_64] = {0};
57692fb7133SRonak Jain 
57792fb7133SRonak Jain 	if (!version)
57892fb7133SRonak Jain 		return -EINVAL;
57992fb7133SRonak Jain 
58092fb7133SRonak Jain 	/* Check if SiP SVC version already verified */
58192fb7133SRonak Jain 	if (sip_svc_version > 0) {
58292fb7133SRonak Jain 		*version = sip_svc_version;
58392fb7133SRonak Jain 		return 0;
58492fb7133SRonak Jain 	}
58592fb7133SRonak Jain 
58692fb7133SRonak Jain 	args[0] = GET_SIP_SVC_VERSION;
58792fb7133SRonak Jain 
58892fb7133SRonak Jain 	arm_smccc_smc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
58992fb7133SRonak Jain 
59092fb7133SRonak Jain 	*version = ((lower_32_bits(res.a0) << 16U) | lower_32_bits(res.a1));
59192fb7133SRonak Jain 
59292fb7133SRonak Jain 	return zynqmp_pm_ret_code(XST_PM_SUCCESS);
59392fb7133SRonak Jain }
59492fb7133SRonak Jain 
59592fb7133SRonak Jain /**
59676582671SRajan Vaja  * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
59776582671SRajan Vaja  * @version:	Returned version value
59876582671SRajan Vaja  *
59976582671SRajan Vaja  * Return: Returns status, either success or error+reason
60076582671SRajan Vaja  */
zynqmp_pm_get_trustzone_version(u32 * version)60176582671SRajan Vaja static int zynqmp_pm_get_trustzone_version(u32 *version)
60276582671SRajan Vaja {
60376582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
60476582671SRajan Vaja 	int ret;
60576582671SRajan Vaja 
60676582671SRajan Vaja 	if (!version)
60776582671SRajan Vaja 		return -EINVAL;
60876582671SRajan Vaja 
60976582671SRajan Vaja 	/* Check is PM trustzone version already verified */
61076582671SRajan Vaja 	if (pm_tz_version > 0) {
61176582671SRajan Vaja 		*version = pm_tz_version;
61276582671SRajan Vaja 		return 0;
61376582671SRajan Vaja 	}
614f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, ret_payload, 0);
61576582671SRajan Vaja 	*version = ret_payload[1];
61676582671SRajan Vaja 
61776582671SRajan Vaja 	return ret;
61876582671SRajan Vaja }
61976582671SRajan Vaja 
62076582671SRajan Vaja /**
62176582671SRajan Vaja  * get_set_conduit_method() - Choose SMC or HVC based communication
62276582671SRajan Vaja  * @np:		Pointer to the device_node structure
62376582671SRajan Vaja  *
62476582671SRajan Vaja  * Use SMC or HVC-based functions to communicate with EL2/EL3.
62576582671SRajan Vaja  *
62676582671SRajan Vaja  * Return: Returns 0 on success or error code
62776582671SRajan Vaja  */
get_set_conduit_method(struct device_node * np)62876582671SRajan Vaja static int get_set_conduit_method(struct device_node *np)
62976582671SRajan Vaja {
63076582671SRajan Vaja 	const char *method;
63176582671SRajan Vaja 
63276582671SRajan Vaja 	if (of_property_read_string(np, "method", &method)) {
63376582671SRajan Vaja 		pr_warn("%s missing \"method\" property\n", __func__);
63476582671SRajan Vaja 		return -ENXIO;
63576582671SRajan Vaja 	}
63676582671SRajan Vaja 
63776582671SRajan Vaja 	if (!strcmp("hvc", method)) {
63876582671SRajan Vaja 		do_fw_call = do_fw_call_hvc;
63976582671SRajan Vaja 	} else if (!strcmp("smc", method)) {
64076582671SRajan Vaja 		do_fw_call = do_fw_call_smc;
64176582671SRajan Vaja 	} else {
64276582671SRajan Vaja 		pr_warn("%s Invalid \"method\" property: %s\n",
64376582671SRajan Vaja 			__func__, method);
64476582671SRajan Vaja 		return -EINVAL;
64576582671SRajan Vaja 	}
64676582671SRajan Vaja 
64776582671SRajan Vaja 	return 0;
64876582671SRajan Vaja }
64976582671SRajan Vaja 
65059ecdd77SRajan Vaja /**
65159ecdd77SRajan Vaja  * zynqmp_pm_query_data() - Get query data from firmware
65259ecdd77SRajan Vaja  * @qdata:	Variable to the zynqmp_pm_query_data structure
65359ecdd77SRajan Vaja  * @out:	Returned output value
65459ecdd77SRajan Vaja  *
65559ecdd77SRajan Vaja  * Return: Returns status, either success or error+reason
65659ecdd77SRajan Vaja  */
zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata,u32 * out)6576366c1baSRajan Vaja int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
65859ecdd77SRajan Vaja {
65992fb7133SRonak Jain 	int ret, i = 0;
66092fb7133SRonak Jain 	u32 ret_payload[PAYLOAD_ARG_CNT] = {0};
661f9627312SRajan Vaja 
66292fb7133SRonak Jain 	if (sip_svc_version >= SIP_SVC_PASSTHROUGH_VERSION) {
66392fb7133SRonak Jain 		ret = zynqmp_pm_invoke_fw_fn(PM_QUERY_DATA, ret_payload, 4,
66492fb7133SRonak Jain 					     qdata.qid, qdata.arg1,
66592fb7133SRonak Jain 					     qdata.arg2, qdata.arg3);
66692fb7133SRonak Jain 		/* To support backward compatibility */
66792fb7133SRonak Jain 		if (!ret && !ret_payload[0]) {
66892fb7133SRonak Jain 			/*
66992fb7133SRonak Jain 			 * TF-A passes return status on 0th index but
67092fb7133SRonak Jain 			 * api to get clock name reads data from 0th
67192fb7133SRonak Jain 			 * index so pass data at 0th index instead of
67292fb7133SRonak Jain 			 * return status
67392fb7133SRonak Jain 			 */
67492fb7133SRonak Jain 			if (qdata.qid == PM_QID_CLOCK_GET_NAME ||
67592fb7133SRonak Jain 			    qdata.qid == PM_QID_PINCTRL_GET_FUNCTION_NAME)
67692fb7133SRonak Jain 				i = 1;
67792fb7133SRonak Jain 
67892fb7133SRonak Jain 			for (; i < PAYLOAD_ARG_CNT; i++, out++)
67992fb7133SRonak Jain 				*out = ret_payload[i];
68092fb7133SRonak Jain 
68192fb7133SRonak Jain 			return ret;
68292fb7133SRonak Jain 		}
68392fb7133SRonak Jain 	}
68492fb7133SRonak Jain 
68592fb7133SRonak Jain 	ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, out, 4, qdata.qid,
68692fb7133SRonak Jain 				  qdata.arg1, qdata.arg2, qdata.arg3);
687f9627312SRajan Vaja 
688f9627312SRajan Vaja 	/*
689f9627312SRajan Vaja 	 * For clock name query, all bytes in SMC response are clock name
690f9627312SRajan Vaja 	 * characters and return code is always success. For invalid clocks,
691f9627312SRajan Vaja 	 * clock name bytes would be zeros.
692f9627312SRajan Vaja 	 */
693f9627312SRajan Vaja 	return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
694f9627312SRajan Vaja }
6956366c1baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
696f9627312SRajan Vaja 
697f9627312SRajan Vaja /**
698f9627312SRajan Vaja  * zynqmp_pm_clock_enable() - Enable the clock for given id
699f9627312SRajan Vaja  * @clock_id:	ID of the clock to be enabled
700f9627312SRajan Vaja  *
701f9627312SRajan Vaja  * This function is used by master to enable the clock
702f9627312SRajan Vaja  * including peripherals and PLL clocks.
703f9627312SRajan Vaja  *
704f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
705f9627312SRajan Vaja  */
zynqmp_pm_clock_enable(u32 clock_id)7063637e84cSRajan Vaja int zynqmp_pm_clock_enable(u32 clock_id)
707f9627312SRajan Vaja {
708f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, NULL, 1, clock_id);
709f9627312SRajan Vaja }
7103637e84cSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
711f9627312SRajan Vaja 
712f9627312SRajan Vaja /**
713f9627312SRajan Vaja  * zynqmp_pm_clock_disable() - Disable the clock for given id
714f9627312SRajan Vaja  * @clock_id:	ID of the clock to be disable
715f9627312SRajan Vaja  *
716f9627312SRajan Vaja  * This function is used by master to disable the clock
717f9627312SRajan Vaja  * including peripherals and PLL clocks.
718f9627312SRajan Vaja  *
719f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
720f9627312SRajan Vaja  */
zynqmp_pm_clock_disable(u32 clock_id)721f5ccd54bSRajan Vaja int zynqmp_pm_clock_disable(u32 clock_id)
722f9627312SRajan Vaja {
723f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, NULL, 1, clock_id);
724f9627312SRajan Vaja }
725f5ccd54bSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
726f9627312SRajan Vaja 
727f9627312SRajan Vaja /**
728f9627312SRajan Vaja  * zynqmp_pm_clock_getstate() - Get the clock state for given id
729f9627312SRajan Vaja  * @clock_id:	ID of the clock to be queried
730f9627312SRajan Vaja  * @state:	1/0 (Enabled/Disabled)
731f9627312SRajan Vaja  *
732f9627312SRajan Vaja  * This function is used by master to get the state of clock
733f9627312SRajan Vaja  * including peripherals and PLL clocks.
734f9627312SRajan Vaja  *
735f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
736f9627312SRajan Vaja  */
zynqmp_pm_clock_getstate(u32 clock_id,u32 * state)7375e76731dSRajan Vaja int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
738f9627312SRajan Vaja {
739f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
740f9627312SRajan Vaja 	int ret;
741f9627312SRajan Vaja 
742f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, ret_payload, 1, clock_id);
743f9627312SRajan Vaja 	*state = ret_payload[1];
744f9627312SRajan Vaja 
745f9627312SRajan Vaja 	return ret;
746f9627312SRajan Vaja }
7475e76731dSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
748f9627312SRajan Vaja 
749f9627312SRajan Vaja /**
750f9627312SRajan Vaja  * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
751f9627312SRajan Vaja  * @clock_id:	ID of the clock
752f9627312SRajan Vaja  * @divider:	divider value
753f9627312SRajan Vaja  *
754f9627312SRajan Vaja  * This function is used by master to set divider for any clock
755f9627312SRajan Vaja  * to achieve desired rate.
756f9627312SRajan Vaja  *
757f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
758f9627312SRajan Vaja  */
zynqmp_pm_clock_setdivider(u32 clock_id,u32 divider)759fc9fb8fbSRajan Vaja int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
760f9627312SRajan Vaja {
761f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, NULL, 2, clock_id, divider);
762f9627312SRajan Vaja }
763fc9fb8fbSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
764f9627312SRajan Vaja 
765f9627312SRajan Vaja /**
766f9627312SRajan Vaja  * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
767f9627312SRajan Vaja  * @clock_id:	ID of the clock
768f9627312SRajan Vaja  * @divider:	divider value
769f9627312SRajan Vaja  *
770f9627312SRajan Vaja  * This function is used by master to get divider values
771f9627312SRajan Vaja  * for any clock.
772f9627312SRajan Vaja  *
773f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
774f9627312SRajan Vaja  */
zynqmp_pm_clock_getdivider(u32 clock_id,u32 * divider)7750667a8d1SRajan Vaja int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
776f9627312SRajan Vaja {
777f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
778f9627312SRajan Vaja 	int ret;
779f9627312SRajan Vaja 
780f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, ret_payload, 1, clock_id);
781f9627312SRajan Vaja 	*divider = ret_payload[1];
782f9627312SRajan Vaja 
783f9627312SRajan Vaja 	return ret;
784f9627312SRajan Vaja }
7850667a8d1SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
786f9627312SRajan Vaja 
787f9627312SRajan Vaja /**
788f9627312SRajan Vaja  * zynqmp_pm_clock_setparent() - Set the clock parent for given id
789f9627312SRajan Vaja  * @clock_id:	ID of the clock
790f9627312SRajan Vaja  * @parent_id:	parent id
791f9627312SRajan Vaja  *
792f9627312SRajan Vaja  * This function is used by master to set parent for any clock.
793f9627312SRajan Vaja  *
794f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
795f9627312SRajan Vaja  */
zynqmp_pm_clock_setparent(u32 clock_id,u32 parent_id)79670c0d364SRajan Vaja int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
797f9627312SRajan Vaja {
798f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, NULL, 2, clock_id, parent_id);
799f9627312SRajan Vaja }
80070c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
801f9627312SRajan Vaja 
802f9627312SRajan Vaja /**
803f9627312SRajan Vaja  * zynqmp_pm_clock_getparent() - Get the clock parent for given id
804f9627312SRajan Vaja  * @clock_id:	ID of the clock
805f9627312SRajan Vaja  * @parent_id:	parent id
806f9627312SRajan Vaja  *
807f9627312SRajan Vaja  * This function is used by master to get parent index
808f9627312SRajan Vaja  * for any clock.
809f9627312SRajan Vaja  *
810f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
811f9627312SRajan Vaja  */
zynqmp_pm_clock_getparent(u32 clock_id,u32 * parent_id)81270c0d364SRajan Vaja int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
813f9627312SRajan Vaja {
814f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
815f9627312SRajan Vaja 	int ret;
816f9627312SRajan Vaja 
817f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, ret_payload, 1, clock_id);
818f9627312SRajan Vaja 	*parent_id = ret_payload[1];
819f9627312SRajan Vaja 
820f9627312SRajan Vaja 	return ret;
82159ecdd77SRajan Vaja }
82270c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
82359ecdd77SRajan Vaja 
8243b0296b8SRajan Vaja /**
825426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
8263b0296b8SRajan Vaja  *
827426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
828426c8d85SRajan Vaja  * @mode:	PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
8293b0296b8SRajan Vaja  *
830426c8d85SRajan Vaja  * This function sets PLL mode
8313b0296b8SRajan Vaja  *
8323b0296b8SRajan Vaja  * Return: Returns status, either success or error+reason
8333b0296b8SRajan Vaja  */
zynqmp_pm_set_pll_frac_mode(u32 clk_id,u32 mode)834426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
8353b0296b8SRajan Vaja {
836f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_PLL_FRAC_MODE, clk_id, mode);
8373b0296b8SRajan Vaja }
838426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
839426c8d85SRajan Vaja 
840426c8d85SRajan Vaja /**
841426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
842426c8d85SRajan Vaja  *
843426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
844426c8d85SRajan Vaja  * @mode:	PLL mode
845426c8d85SRajan Vaja  *
846426c8d85SRajan Vaja  * This function return current PLL mode
847426c8d85SRajan Vaja  *
848426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
849426c8d85SRajan Vaja  */
zynqmp_pm_get_pll_frac_mode(u32 clk_id,u32 * mode)850426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
851426c8d85SRajan Vaja {
852f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, mode, 3, 0, IOCTL_GET_PLL_FRAC_MODE, clk_id);
853426c8d85SRajan Vaja }
854426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
855426c8d85SRajan Vaja 
856426c8d85SRajan Vaja /**
857426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
858426c8d85SRajan Vaja  *
859426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
860426c8d85SRajan Vaja  * @data:	fraction data
861426c8d85SRajan Vaja  *
862426c8d85SRajan Vaja  * This function sets fraction data.
863426c8d85SRajan Vaja  * It is valid for fraction mode only.
864426c8d85SRajan Vaja  *
865426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
866426c8d85SRajan Vaja  */
zynqmp_pm_set_pll_frac_data(u32 clk_id,u32 data)867426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
868426c8d85SRajan Vaja {
869f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_PLL_FRAC_DATA, clk_id, data);
870426c8d85SRajan Vaja }
871426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
872426c8d85SRajan Vaja 
873426c8d85SRajan Vaja /**
874426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
875426c8d85SRajan Vaja  *
876426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
877426c8d85SRajan Vaja  * @data:	fraction data
878426c8d85SRajan Vaja  *
879426c8d85SRajan Vaja  * This function returns fraction data value.
880426c8d85SRajan Vaja  *
881426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
882426c8d85SRajan Vaja  */
zynqmp_pm_get_pll_frac_data(u32 clk_id,u32 * data)883426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
884426c8d85SRajan Vaja {
885f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, data, 3, 0, IOCTL_GET_PLL_FRAC_DATA, clk_id);
886426c8d85SRajan Vaja }
887426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
888426c8d85SRajan Vaja 
889426c8d85SRajan Vaja /**
890426c8d85SRajan Vaja  * zynqmp_pm_set_sd_tapdelay() -  Set tap delay for the SD device
891426c8d85SRajan Vaja  *
892332bee16SMichal Simek  * @node_id:	Node ID of the device
893332bee16SMichal Simek  * @type:	Type of tap delay to set (input/output)
894332bee16SMichal Simek  * @value:	Value to set fot the tap delay
895426c8d85SRajan Vaja  *
896426c8d85SRajan Vaja  * This function sets input/output tap delay for the SD device.
897426c8d85SRajan Vaja  *
898332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
899426c8d85SRajan Vaja  */
zynqmp_pm_set_sd_tapdelay(u32 node_id,u32 type,u32 value)900426c8d85SRajan Vaja int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
901426c8d85SRajan Vaja {
902a4b2e606SMarek Vasut 	u32 reg = (type == PM_TAPDELAY_INPUT) ? SD_ITAPDLY : SD_OTAPDLYSEL;
903a4b2e606SMarek Vasut 	u32 mask = (node_id == NODE_SD_0) ? GENMASK(15, 0) : GENMASK(31, 16);
904a4b2e606SMarek Vasut 
905a4b2e606SMarek Vasut 	if (value) {
906f922b16aSJay Buddhabhatti 		return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, node_id, IOCTL_SET_SD_TAPDELAY, type,
907f922b16aSJay Buddhabhatti 					   value);
908426c8d85SRajan Vaja 	}
909a4b2e606SMarek Vasut 
910a4b2e606SMarek Vasut 	/*
911a4b2e606SMarek Vasut 	 * Work around completely misdesigned firmware API on Xilinx ZynqMP.
912a4b2e606SMarek Vasut 	 * The IOCTL_SET_SD_TAPDELAY firmware call allows the caller to only
913a4b2e606SMarek Vasut 	 * ever set IOU_SLCR SD_ITAPDLY Register SD0_ITAPDLYENA/SD1_ITAPDLYENA
914a4b2e606SMarek Vasut 	 * bits, but there is no matching call to clear those bits. If those
915a4b2e606SMarek Vasut 	 * bits are not cleared, SDMMC tuning may fail.
916a4b2e606SMarek Vasut 	 *
917a4b2e606SMarek Vasut 	 * Luckily, there are PM_MMIO_READ/PM_MMIO_WRITE calls which seem to
918a4b2e606SMarek Vasut 	 * allow complete unrestricted access to all address space, including
919a4b2e606SMarek Vasut 	 * IOU_SLCR SD_ITAPDLY Register and all the other registers, access
920a4b2e606SMarek Vasut 	 * to which was supposed to be protected by the current firmware API.
921a4b2e606SMarek Vasut 	 *
922a4b2e606SMarek Vasut 	 * Use PM_MMIO_READ/PM_MMIO_WRITE to re-implement the missing counter
923a4b2e606SMarek Vasut 	 * part of IOCTL_SET_SD_TAPDELAY which clears SDx_ITAPDLYENA bits.
924a4b2e606SMarek Vasut 	 */
925f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, NULL, 2, reg, mask);
926a4b2e606SMarek Vasut }
927426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
928426c8d85SRajan Vaja 
929426c8d85SRajan Vaja /**
930426c8d85SRajan Vaja  * zynqmp_pm_sd_dll_reset() - Reset DLL logic
931426c8d85SRajan Vaja  *
932332bee16SMichal Simek  * @node_id:	Node ID of the device
933332bee16SMichal Simek  * @type:	Reset type
934426c8d85SRajan Vaja  *
935426c8d85SRajan Vaja  * This function resets DLL logic for the SD device.
936426c8d85SRajan Vaja  *
937332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
938426c8d85SRajan Vaja  */
zynqmp_pm_sd_dll_reset(u32 node_id,u32 type)939426c8d85SRajan Vaja int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
940426c8d85SRajan Vaja {
941f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, node_id, IOCTL_SD_DLL_RESET, type);
942426c8d85SRajan Vaja }
943426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
9443b0296b8SRajan Vaja 
945bc3843d4SNava kishore Manne /**
94674e78adcSSai Krishna Potthuri  * zynqmp_pm_ospi_mux_select() - OSPI Mux selection
94774e78adcSSai Krishna Potthuri  *
94874e78adcSSai Krishna Potthuri  * @dev_id:	Device Id of the OSPI device.
94974e78adcSSai Krishna Potthuri  * @select:	OSPI Mux select value.
95074e78adcSSai Krishna Potthuri  *
95174e78adcSSai Krishna Potthuri  * This function select the OSPI Mux.
95274e78adcSSai Krishna Potthuri  *
95374e78adcSSai Krishna Potthuri  * Return:	Returns status, either success or error+reason
95474e78adcSSai Krishna Potthuri  */
zynqmp_pm_ospi_mux_select(u32 dev_id,u32 select)95574e78adcSSai Krishna Potthuri int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
95674e78adcSSai Krishna Potthuri {
957f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, dev_id, IOCTL_OSPI_MUX_SELECT, select);
95874e78adcSSai Krishna Potthuri }
95974e78adcSSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select);
96074e78adcSSai Krishna Potthuri 
96174e78adcSSai Krishna Potthuri /**
9624f680b72SRajan Vaja  * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
963332bee16SMichal Simek  * @index:	GGS register index
964332bee16SMichal Simek  * @value:	Register value to be written
9654f680b72SRajan Vaja  *
9664f680b72SRajan Vaja  * This function writes value to GGS register.
9674f680b72SRajan Vaja  *
968332bee16SMichal Simek  * Return:      Returns status, either success or error+reason
9694f680b72SRajan Vaja  */
zynqmp_pm_write_ggs(u32 index,u32 value)9704f680b72SRajan Vaja int zynqmp_pm_write_ggs(u32 index, u32 value)
9714f680b72SRajan Vaja {
972f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_WRITE_GGS, index, value);
9734f680b72SRajan Vaja }
9744f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
9754f680b72SRajan Vaja 
9764f680b72SRajan Vaja /**
9772a8faf8dSMichal Simek  * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs)
978332bee16SMichal Simek  * @index:	GGS register index
979332bee16SMichal Simek  * @value:	Register value to be written
9804f680b72SRajan Vaja  *
9814f680b72SRajan Vaja  * This function returns GGS register value.
9824f680b72SRajan Vaja  *
983332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
9844f680b72SRajan Vaja  */
zynqmp_pm_read_ggs(u32 index,u32 * value)9854f680b72SRajan Vaja int zynqmp_pm_read_ggs(u32 index, u32 *value)
9864f680b72SRajan Vaja {
987f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, value, 3, 0, IOCTL_READ_GGS, index);
9884f680b72SRajan Vaja }
9894f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
9904f680b72SRajan Vaja 
9914f680b72SRajan Vaja /**
9924f680b72SRajan Vaja  * zynqmp_pm_write_pggs() - PM API for writing persistent global general
9934f680b72SRajan Vaja  *			     storage (pggs)
994332bee16SMichal Simek  * @index:	PGGS register index
995332bee16SMichal Simek  * @value:	Register value to be written
9964f680b72SRajan Vaja  *
9974f680b72SRajan Vaja  * This function writes value to PGGS register.
9984f680b72SRajan Vaja  *
999332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
10004f680b72SRajan Vaja  */
zynqmp_pm_write_pggs(u32 index,u32 value)10014f680b72SRajan Vaja int zynqmp_pm_write_pggs(u32 index, u32 value)
10024f680b72SRajan Vaja {
1003f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_WRITE_PGGS, index, value);
10044f680b72SRajan Vaja }
10054f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
10064f680b72SRajan Vaja 
10074f680b72SRajan Vaja /**
10082a8faf8dSMichal Simek  * zynqmp_pm_read_pggs() - PM API for reading persistent global general
10094f680b72SRajan Vaja  *			     storage (pggs)
1010332bee16SMichal Simek  * @index:	PGGS register index
1011332bee16SMichal Simek  * @value:	Register value to be written
10124f680b72SRajan Vaja  *
10134f680b72SRajan Vaja  * This function returns PGGS register value.
10144f680b72SRajan Vaja  *
1015332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
10164f680b72SRajan Vaja  */
zynqmp_pm_read_pggs(u32 index,u32 * value)10174f680b72SRajan Vaja int zynqmp_pm_read_pggs(u32 index, u32 *value)
10184f680b72SRajan Vaja {
1019f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, value, 3, 0, IOCTL_READ_PGGS, index);
10204f680b72SRajan Vaja }
10214f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
10224f680b72SRajan Vaja 
zynqmp_pm_set_tapdelay_bypass(u32 index,u32 value)10231e400cb9SRajan Vaja int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value)
10241e400cb9SRajan Vaja {
1025f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_TAPDELAY_BYPASS, index, value);
10261e400cb9SRajan Vaja }
10271e400cb9SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass);
10281e400cb9SRajan Vaja 
10294f680b72SRajan Vaja /**
1030a2cc220aSRajan Vaja  * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
1031332bee16SMichal Simek  * @value:	Status value to be written
1032a2cc220aSRajan Vaja  *
1033a2cc220aSRajan Vaja  * This function sets healthy bit value to indicate boot health status
1034a2cc220aSRajan Vaja  * to firmware.
1035a2cc220aSRajan Vaja  *
1036332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
1037a2cc220aSRajan Vaja  */
zynqmp_pm_set_boot_health_status(u32 value)1038a2cc220aSRajan Vaja int zynqmp_pm_set_boot_health_status(u32 value)
1039a2cc220aSRajan Vaja {
1040f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, 0, IOCTL_SET_BOOT_HEALTH_STATUS, value);
1041a2cc220aSRajan Vaja }
1042a2cc220aSRajan Vaja 
1043a2cc220aSRajan Vaja /**
1044bc3843d4SNava kishore Manne  * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
1045bc3843d4SNava kishore Manne  * @reset:		Reset to be configured
1046bc3843d4SNava kishore Manne  * @assert_flag:	Flag stating should reset be asserted (1) or
1047bc3843d4SNava kishore Manne  *			released (0)
1048bc3843d4SNava kishore Manne  *
1049bc3843d4SNava kishore Manne  * Return: Returns status, either success or error+reason
1050bc3843d4SNava kishore Manne  */
zynqmp_pm_reset_assert(const u32 reset,const enum zynqmp_pm_reset_action assert_flag)1051f33d6099SRonak Jain int zynqmp_pm_reset_assert(const u32 reset,
1052bc3843d4SNava kishore Manne 			   const enum zynqmp_pm_reset_action assert_flag)
1053bc3843d4SNava kishore Manne {
1054f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, NULL, 2, reset, assert_flag);
1055bc3843d4SNava kishore Manne }
1056cf23ec35SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
1057bc3843d4SNava kishore Manne 
1058bc3843d4SNava kishore Manne /**
1059bc3843d4SNava kishore Manne  * zynqmp_pm_reset_get_status - Get status of the reset
1060bc3843d4SNava kishore Manne  * @reset:      Reset whose status should be returned
1061bc3843d4SNava kishore Manne  * @status:     Returned status
1062bc3843d4SNava kishore Manne  *
1063bc3843d4SNava kishore Manne  * Return: Returns status, either success or error+reason
1064bc3843d4SNava kishore Manne  */
zynqmp_pm_reset_get_status(const u32 reset,u32 * status)1065f33d6099SRonak Jain int zynqmp_pm_reset_get_status(const u32 reset, u32 *status)
1066bc3843d4SNava kishore Manne {
1067bc3843d4SNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
1068bc3843d4SNava kishore Manne 	int ret;
1069bc3843d4SNava kishore Manne 
1070bc3843d4SNava kishore Manne 	if (!status)
1071bc3843d4SNava kishore Manne 		return -EINVAL;
1072bc3843d4SNava kishore Manne 
1073f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, ret_payload, 1, reset);
1074bc3843d4SNava kishore Manne 	*status = ret_payload[1];
1075bc3843d4SNava kishore Manne 
1076bc3843d4SNava kishore Manne 	return ret;
1077bc3843d4SNava kishore Manne }
10781b413581SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
1079bc3843d4SNava kishore Manne 
1080e178df31SJolly Shah /**
1081e840deccSNava kishore Manne  * zynqmp_pm_fpga_load - Perform the fpga load
1082e840deccSNava kishore Manne  * @address:	Address to write to
1083e840deccSNava kishore Manne  * @size:	pl bitstream size
1084e840deccSNava kishore Manne  * @flags:	Bitstream type
1085e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
1086e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
1087e840deccSNava kishore Manne  *
1088e840deccSNava kishore Manne  * This function provides access to pmufw. To transfer
1089e840deccSNava kishore Manne  * the required bitstream into PL.
1090e840deccSNava kishore Manne  *
1091e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
1092e840deccSNava kishore Manne  */
zynqmp_pm_fpga_load(const u64 address,const u32 size,const u32 flags)10934db8180fSRajan Vaja int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
1094e840deccSNava kishore Manne {
1095e2ebc05dSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
1096e2ebc05dSNava kishore Manne 	int ret;
1097e2ebc05dSNava kishore Manne 
1098f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_FPGA_LOAD, ret_payload, 4, lower_32_bits(address),
1099f922b16aSJay Buddhabhatti 				  upper_32_bits(address), size, flags);
1100e2ebc05dSNava kishore Manne 	if (ret_payload[0])
1101e2ebc05dSNava kishore Manne 		return -ret_payload[0];
1102e2ebc05dSNava kishore Manne 
1103e2ebc05dSNava kishore Manne 	return ret;
1104e840deccSNava kishore Manne }
110556a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
1106e840deccSNava kishore Manne 
1107e840deccSNava kishore Manne /**
1108e840deccSNava kishore Manne  * zynqmp_pm_fpga_get_status - Read value from PCAP status register
1109e840deccSNava kishore Manne  * @value: Value to read
1110e840deccSNava kishore Manne  *
1111e840deccSNava kishore Manne  * This function provides access to the pmufw to get the PCAP
1112e840deccSNava kishore Manne  * status
1113e840deccSNava kishore Manne  *
1114e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
1115e840deccSNava kishore Manne  */
zynqmp_pm_fpga_get_status(u32 * value)11164db8180fSRajan Vaja int zynqmp_pm_fpga_get_status(u32 *value)
1117e840deccSNava kishore Manne {
1118e840deccSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
1119e840deccSNava kishore Manne 	int ret;
1120e840deccSNava kishore Manne 
1121e840deccSNava kishore Manne 	if (!value)
1122e840deccSNava kishore Manne 		return -EINVAL;
1123e840deccSNava kishore Manne 
1124f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, ret_payload, 0);
1125e840deccSNava kishore Manne 	*value = ret_payload[1];
1126e840deccSNava kishore Manne 
1127e840deccSNava kishore Manne 	return ret;
1128e840deccSNava kishore Manne }
112956a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
1130e840deccSNava kishore Manne 
1131e840deccSNava kishore Manne /**
11328f118f61SNava kishore Manne  * zynqmp_pm_fpga_get_config_status - Get the FPGA configuration status.
11338f118f61SNava kishore Manne  * @value: Buffer to store FPGA configuration status.
11348f118f61SNava kishore Manne  *
11358f118f61SNava kishore Manne  * This function provides access to the pmufw to get the FPGA configuration
11368f118f61SNava kishore Manne  * status
11378f118f61SNava kishore Manne  *
11388f118f61SNava kishore Manne  * Return: 0 on success, a negative value on error
11398f118f61SNava kishore Manne  */
zynqmp_pm_fpga_get_config_status(u32 * value)11408f118f61SNava kishore Manne int zynqmp_pm_fpga_get_config_status(u32 *value)
11418f118f61SNava kishore Manne {
11428f118f61SNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
11438f118f61SNava kishore Manne 	int ret;
11448f118f61SNava kishore Manne 
11458f118f61SNava kishore Manne 	if (!value)
11468f118f61SNava kishore Manne 		return -EINVAL;
11478f118f61SNava kishore Manne 
1148f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_FPGA_READ, ret_payload, 4,
11495abc1740SSiva Durga Prasad Paladugu 				  XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, 0, 0,
1150f922b16aSJay Buddhabhatti 				  XILINX_ZYNQMP_PM_FPGA_READ_CONFIG_REG);
11518f118f61SNava kishore Manne 
11528f118f61SNava kishore Manne 	*value = ret_payload[1];
11538f118f61SNava kishore Manne 
11548f118f61SNava kishore Manne 	return ret;
11558f118f61SNava kishore Manne }
11568f118f61SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_config_status);
11578f118f61SNava kishore Manne 
11588f118f61SNava kishore Manne /**
1159fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_request - Request Pin from firmware
1160fa989ae7SSai Krishna Potthuri  * @pin: Pin number to request
1161fa989ae7SSai Krishna Potthuri  *
1162fa989ae7SSai Krishna Potthuri  * This function requests pin from firmware.
1163fa989ae7SSai Krishna Potthuri  *
1164fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1165fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_request(const u32 pin)1166fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_request(const u32 pin)
1167fa989ae7SSai Krishna Potthuri {
1168f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, NULL, 1, pin);
1169fa989ae7SSai Krishna Potthuri }
1170fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request);
1171fa989ae7SSai Krishna Potthuri 
1172fa989ae7SSai Krishna Potthuri /**
1173fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
1174fa989ae7SSai Krishna Potthuri  * @pin: Pin number to release
1175fa989ae7SSai Krishna Potthuri  *
1176fa989ae7SSai Krishna Potthuri  * This function release pin from firmware.
1177fa989ae7SSai Krishna Potthuri  *
1178fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1179fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_release(const u32 pin)1180fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_release(const u32 pin)
1181fa989ae7SSai Krishna Potthuri {
1182f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, NULL, 1, pin);
1183fa989ae7SSai Krishna Potthuri }
1184fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release);
1185fa989ae7SSai Krishna Potthuri 
1186fa989ae7SSai Krishna Potthuri /**
1187fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
1188fa989ae7SSai Krishna Potthuri  * @pin: Pin number
1189fa989ae7SSai Krishna Potthuri  * @id: Function ID to set
1190fa989ae7SSai Krishna Potthuri  *
1191fa989ae7SSai Krishna Potthuri  * This function sets requested function for the given pin.
1192fa989ae7SSai Krishna Potthuri  *
1193fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1194fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_set_function(const u32 pin,const u32 id)1195fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
1196fa989ae7SSai Krishna Potthuri {
1197f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, NULL, 2, pin, id);
1198fa989ae7SSai Krishna Potthuri }
1199fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function);
1200fa989ae7SSai Krishna Potthuri 
1201fa989ae7SSai Krishna Potthuri /**
1202fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
1203fa989ae7SSai Krishna Potthuri  * @pin: Pin number
1204fa989ae7SSai Krishna Potthuri  * @param: Parameter to get
1205fa989ae7SSai Krishna Potthuri  * @value: Buffer to store parameter value
1206fa989ae7SSai Krishna Potthuri  *
1207fa989ae7SSai Krishna Potthuri  * This function gets requested configuration parameter for the given pin.
1208fa989ae7SSai Krishna Potthuri  *
1209fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1210fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_get_config(const u32 pin,const u32 param,u32 * value)1211fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
1212fa989ae7SSai Krishna Potthuri 				 u32 *value)
1213fa989ae7SSai Krishna Potthuri {
1214fa989ae7SSai Krishna Potthuri 	u32 ret_payload[PAYLOAD_ARG_CNT];
1215fa989ae7SSai Krishna Potthuri 	int ret;
1216fa989ae7SSai Krishna Potthuri 
1217fa989ae7SSai Krishna Potthuri 	if (!value)
1218fa989ae7SSai Krishna Potthuri 		return -EINVAL;
1219fa989ae7SSai Krishna Potthuri 
1220f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, ret_payload, 2, pin, param);
1221fa989ae7SSai Krishna Potthuri 	*value = ret_payload[1];
1222fa989ae7SSai Krishna Potthuri 
1223fa989ae7SSai Krishna Potthuri 	return ret;
1224fa989ae7SSai Krishna Potthuri }
1225fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config);
1226fa989ae7SSai Krishna Potthuri 
1227fa989ae7SSai Krishna Potthuri /**
1228fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
1229fa989ae7SSai Krishna Potthuri  * @pin: Pin number
1230fa989ae7SSai Krishna Potthuri  * @param: Parameter to set
1231fa989ae7SSai Krishna Potthuri  * @value: Parameter value to set
1232fa989ae7SSai Krishna Potthuri  *
1233fa989ae7SSai Krishna Potthuri  * This function sets requested configuration parameter for the given pin.
1234fa989ae7SSai Krishna Potthuri  *
1235fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1236fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_set_config(const u32 pin,const u32 param,u32 value)1237fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
1238fa989ae7SSai Krishna Potthuri 				 u32 value)
1239fa989ae7SSai Krishna Potthuri {
1240aa5ed7b3SSai Krishna Potthuri 	int ret;
1241aa5ed7b3SSai Krishna Potthuri 
1242aa5ed7b3SSai Krishna Potthuri 	if (pm_family_code == ZYNQMP_FAMILY_CODE &&
1243aa5ed7b3SSai Krishna Potthuri 	    param == PM_PINCTRL_CONFIG_TRI_STATE) {
1244aa5ed7b3SSai Krishna Potthuri 		ret = zynqmp_pm_feature(PM_PINCTRL_CONFIG_PARAM_SET);
1245e8415a8aSRonak Jain 		if (ret < PM_PINCTRL_PARAM_SET_VERSION) {
1246e8415a8aSRonak Jain 			pr_warn("The requested pinctrl feature is not supported in the current firmware.\n"
1247e8415a8aSRonak Jain 				"Expected firmware version is 2023.1 and above for this feature to work.\r\n");
1248aa5ed7b3SSai Krishna Potthuri 			return -EOPNOTSUPP;
1249aa5ed7b3SSai Krishna Potthuri 		}
1250e8415a8aSRonak Jain 	}
1251aa5ed7b3SSai Krishna Potthuri 
1252f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, NULL, 3, pin, param, value);
1253fa989ae7SSai Krishna Potthuri }
1254fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config);
1255fa989ae7SSai Krishna Potthuri 
1256fa989ae7SSai Krishna Potthuri /**
125723c64d76SPiyush Mehta  * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status
125823c64d76SPiyush Mehta  * @ps_mode: Returned output value of ps_mode
125923c64d76SPiyush Mehta  *
126023c64d76SPiyush Mehta  * This API function is to be used for notify the power management controller
126123c64d76SPiyush Mehta  * to read bootpin status.
126223c64d76SPiyush Mehta  *
126323c64d76SPiyush Mehta  * Return: status, either success or error+reason
126423c64d76SPiyush Mehta  */
zynqmp_pm_bootmode_read(u32 * ps_mode)126523c64d76SPiyush Mehta unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode)
126623c64d76SPiyush Mehta {
126723c64d76SPiyush Mehta 	unsigned int ret;
126823c64d76SPiyush Mehta 	u32 ret_payload[PAYLOAD_ARG_CNT];
126923c64d76SPiyush Mehta 
1270f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, ret_payload, 1, CRL_APB_BOOT_PIN_CTRL);
127123c64d76SPiyush Mehta 
127223c64d76SPiyush Mehta 	*ps_mode = ret_payload[1];
127323c64d76SPiyush Mehta 
127423c64d76SPiyush Mehta 	return ret;
127523c64d76SPiyush Mehta }
127623c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read);
127723c64d76SPiyush Mehta 
127823c64d76SPiyush Mehta /**
127923c64d76SPiyush Mehta  * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin
128023c64d76SPiyush Mehta  * @ps_mode: Value to be written to the bootpin ctrl register
128123c64d76SPiyush Mehta  *
128223c64d76SPiyush Mehta  * This API function is to be used for notify the power management controller
128323c64d76SPiyush Mehta  * to configure bootpin.
128423c64d76SPiyush Mehta  *
128523c64d76SPiyush Mehta  * Return: Returns status, either success or error+reason
128623c64d76SPiyush Mehta  */
zynqmp_pm_bootmode_write(u32 ps_mode)128723c64d76SPiyush Mehta int zynqmp_pm_bootmode_write(u32 ps_mode)
128823c64d76SPiyush Mehta {
1289f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, NULL, 3, CRL_APB_BOOT_PIN_CTRL,
1290f922b16aSJay Buddhabhatti 				   CRL_APB_BOOTPIN_CTRL_MASK, ps_mode);
129123c64d76SPiyush Mehta }
129223c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write);
129323c64d76SPiyush Mehta 
129423c64d76SPiyush Mehta /**
1295e178df31SJolly Shah  * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
1296e178df31SJolly Shah  *			       master has initialized its own power management
1297e178df31SJolly Shah  *
1298332bee16SMichal Simek  * Return: Returns status, either success or error+reason
1299332bee16SMichal Simek  *
1300e178df31SJolly Shah  * This API function is to be used for notify the power management controller
1301e178df31SJolly Shah  * about the completed power management initialization.
1302e178df31SJolly Shah  */
zynqmp_pm_init_finalize(void)130310086a4fSUlf Hansson static int zynqmp_pm_init_finalize(void)
1304e178df31SJolly Shah {
1305f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, NULL, 0);
1306e178df31SJolly Shah }
1307e178df31SJolly Shah 
1308e178df31SJolly Shah /**
1309e178df31SJolly Shah  * zynqmp_pm_set_suspend_mode()	- Set system suspend mode
1310e178df31SJolly Shah  * @mode:	Mode to set for system suspend
1311e178df31SJolly Shah  *
1312e178df31SJolly Shah  * This API function is used to set mode of system suspend.
1313e178df31SJolly Shah  *
1314e178df31SJolly Shah  * Return: Returns status, either success or error+reason
1315e178df31SJolly Shah  */
zynqmp_pm_set_suspend_mode(u32 mode)1316951d0a97SRajan Vaja int zynqmp_pm_set_suspend_mode(u32 mode)
1317e178df31SJolly Shah {
1318f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, NULL, 1, mode);
1319e178df31SJolly Shah }
1320951d0a97SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
1321e178df31SJolly Shah 
1322c1986ac3SRajan Vaja /**
1323c1986ac3SRajan Vaja  * zynqmp_pm_request_node() - Request a node with specific capabilities
1324c1986ac3SRajan Vaja  * @node:		Node ID of the slave
1325c1986ac3SRajan Vaja  * @capabilities:	Requested capabilities of the slave
1326c1986ac3SRajan Vaja  * @qos:		Quality of service (not supported)
1327c1986ac3SRajan Vaja  * @ack:		Flag to specify whether acknowledge is requested
1328c1986ac3SRajan Vaja  *
1329c1986ac3SRajan Vaja  * This function is used by master to request particular node from firmware.
1330c1986ac3SRajan Vaja  * Every master must request node before using it.
1331c1986ac3SRajan Vaja  *
1332c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1333c1986ac3SRajan Vaja  */
zynqmp_pm_request_node(const u32 node,const u32 capabilities,const u32 qos,const enum zynqmp_pm_request_ack ack)1334bf8b27edSRajan Vaja int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
1335bf8b27edSRajan Vaja 			   const u32 qos, const enum zynqmp_pm_request_ack ack)
1336c1986ac3SRajan Vaja {
1337f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, NULL, 4, node, capabilities, qos, ack);
1338c1986ac3SRajan Vaja }
1339bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
1340c1986ac3SRajan Vaja 
1341c1986ac3SRajan Vaja /**
1342c1986ac3SRajan Vaja  * zynqmp_pm_release_node() - Release a node
1343c1986ac3SRajan Vaja  * @node:	Node ID of the slave
1344c1986ac3SRajan Vaja  *
1345c1986ac3SRajan Vaja  * This function is used by master to inform firmware that master
1346c1986ac3SRajan Vaja  * has released node. Once released, master must not use that node
1347c1986ac3SRajan Vaja  * without re-request.
1348c1986ac3SRajan Vaja  *
1349c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1350c1986ac3SRajan Vaja  */
zynqmp_pm_release_node(const u32 node)135107fb1a46SRajan Vaja int zynqmp_pm_release_node(const u32 node)
1352c1986ac3SRajan Vaja {
1353f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, NULL, 1, node);
1354c1986ac3SRajan Vaja }
135507fb1a46SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
1356c1986ac3SRajan Vaja 
1357c1986ac3SRajan Vaja /**
1358a5e56980SBen Levinsky  * zynqmp_pm_get_rpu_mode() - Get RPU mode
1359a5e56980SBen Levinsky  * @node_id:	Node ID of the device
1360a5e56980SBen Levinsky  * @rpu_mode:	return by reference value
1361a5e56980SBen Levinsky  *		either split or lockstep
1362a5e56980SBen Levinsky  *
1363a5e56980SBen Levinsky  * Return:	return 0 on success or error+reason.
1364a5e56980SBen Levinsky  *		if success, then  rpu_mode will be set
1365a5e56980SBen Levinsky  *		to current rpu mode.
1366a5e56980SBen Levinsky  */
zynqmp_pm_get_rpu_mode(u32 node_id,enum rpu_oper_mode * rpu_mode)1367a5e56980SBen Levinsky int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mode)
1368a5e56980SBen Levinsky {
1369a5e56980SBen Levinsky 	u32 ret_payload[PAYLOAD_ARG_CNT];
1370a5e56980SBen Levinsky 	int ret;
1371a5e56980SBen Levinsky 
1372f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_IOCTL, ret_payload, 2, node_id, IOCTL_GET_RPU_OPER_MODE);
1373a5e56980SBen Levinsky 
1374a5e56980SBen Levinsky 	/* only set rpu_mode if no error */
1375a5e56980SBen Levinsky 	if (ret == XST_PM_SUCCESS)
1376a5e56980SBen Levinsky 		*rpu_mode = ret_payload[0];
1377a5e56980SBen Levinsky 
1378a5e56980SBen Levinsky 	return ret;
1379a5e56980SBen Levinsky }
1380a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_get_rpu_mode);
1381a5e56980SBen Levinsky 
1382a5e56980SBen Levinsky /**
1383a5e56980SBen Levinsky  * zynqmp_pm_set_rpu_mode() - Set RPU mode
1384a5e56980SBen Levinsky  * @node_id:	Node ID of the device
1385a5e56980SBen Levinsky  * @rpu_mode:	Argument 1 to requested IOCTL call. either split or lockstep
1386a5e56980SBen Levinsky  *
1387a5e56980SBen Levinsky  *		This function is used to set RPU mode to split or
1388a5e56980SBen Levinsky  *		lockstep
1389a5e56980SBen Levinsky  *
1390a5e56980SBen Levinsky  * Return:	Returns status, either success or error+reason
1391a5e56980SBen Levinsky  */
zynqmp_pm_set_rpu_mode(u32 node_id,enum rpu_oper_mode rpu_mode)1392a5e56980SBen Levinsky int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode)
1393a5e56980SBen Levinsky {
1394f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, node_id, IOCTL_SET_RPU_OPER_MODE,
1395f922b16aSJay Buddhabhatti 				   (u32)rpu_mode);
1396a5e56980SBen Levinsky }
1397a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_set_rpu_mode);
1398a5e56980SBen Levinsky 
1399a5e56980SBen Levinsky /**
1400a5e56980SBen Levinsky  * zynqmp_pm_set_tcm_config - configure TCM
1401a5e56980SBen Levinsky  * @node_id:	Firmware specific TCM subsystem ID
1402a5e56980SBen Levinsky  * @tcm_mode:	Argument 1 to requested IOCTL call
1403a5e56980SBen Levinsky  *              either PM_RPU_TCM_COMB or PM_RPU_TCM_SPLIT
1404a5e56980SBen Levinsky  *
1405a5e56980SBen Levinsky  * This function is used to set RPU mode to split or combined
1406a5e56980SBen Levinsky  *
1407a5e56980SBen Levinsky  * Return: status: 0 for success, else failure
1408a5e56980SBen Levinsky  */
zynqmp_pm_set_tcm_config(u32 node_id,enum rpu_tcm_comb tcm_mode)1409a5e56980SBen Levinsky int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode)
1410a5e56980SBen Levinsky {
1411f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, node_id, IOCTL_TCM_COMB_CONFIG,
1412f922b16aSJay Buddhabhatti 				   (u32)tcm_mode);
1413a5e56980SBen Levinsky }
1414a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_set_tcm_config);
1415a5e56980SBen Levinsky 
1416a5e56980SBen Levinsky /**
1417da22a04fSBen Levinsky  * zynqmp_pm_force_pwrdwn - PM call to request for another PU or subsystem to
1418da22a04fSBen Levinsky  *             be powered down forcefully
1419da22a04fSBen Levinsky  * @node:  Node ID of the targeted PU or subsystem
1420da22a04fSBen Levinsky  * @ack:   Flag to specify whether acknowledge is requested
1421da22a04fSBen Levinsky  *
1422da22a04fSBen Levinsky  * Return: status, either success or error+reason
1423da22a04fSBen Levinsky  */
zynqmp_pm_force_pwrdwn(const u32 node,const enum zynqmp_pm_request_ack ack)1424da22a04fSBen Levinsky int zynqmp_pm_force_pwrdwn(const u32 node,
1425da22a04fSBen Levinsky 			   const enum zynqmp_pm_request_ack ack)
1426da22a04fSBen Levinsky {
1427f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, NULL, 2, node, ack);
1428da22a04fSBen Levinsky }
1429da22a04fSBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_force_pwrdwn);
1430da22a04fSBen Levinsky 
1431da22a04fSBen Levinsky /**
1432da22a04fSBen Levinsky  * zynqmp_pm_request_wake - PM call to wake up selected master or subsystem
1433da22a04fSBen Levinsky  * @node:  Node ID of the master or subsystem
1434da22a04fSBen Levinsky  * @set_addr:  Specifies whether the address argument is relevant
1435da22a04fSBen Levinsky  * @address:   Address from which to resume when woken up
1436da22a04fSBen Levinsky  * @ack:   Flag to specify whether acknowledge requested
1437da22a04fSBen Levinsky  *
1438da22a04fSBen Levinsky  * Return: status, either success or error+reason
1439da22a04fSBen Levinsky  */
zynqmp_pm_request_wake(const u32 node,const bool set_addr,const u64 address,const enum zynqmp_pm_request_ack ack)1440da22a04fSBen Levinsky int zynqmp_pm_request_wake(const u32 node,
1441da22a04fSBen Levinsky 			   const bool set_addr,
1442da22a04fSBen Levinsky 			   const u64 address,
1443da22a04fSBen Levinsky 			   const enum zynqmp_pm_request_ack ack)
1444da22a04fSBen Levinsky {
1445da22a04fSBen Levinsky 	/* set_addr flag is encoded into 1st bit of address */
1446f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_REQUEST_WAKEUP, NULL, 4, node, address | set_addr,
1447f922b16aSJay Buddhabhatti 				   address >> 32, ack);
1448da22a04fSBen Levinsky }
1449da22a04fSBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake);
1450da22a04fSBen Levinsky 
1451da22a04fSBen Levinsky /**
1452c1986ac3SRajan Vaja  * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
1453c1986ac3SRajan Vaja  * @node:		Node ID of the slave
1454c1986ac3SRajan Vaja  * @capabilities:	Requested capabilities of the slave
1455c1986ac3SRajan Vaja  * @qos:		Quality of service (not supported)
1456c1986ac3SRajan Vaja  * @ack:		Flag to specify whether acknowledge is requested
1457c1986ac3SRajan Vaja  *
1458c1986ac3SRajan Vaja  * This API function is to be used for slaves a PU already has requested
1459c1986ac3SRajan Vaja  * to change its capabilities.
1460c1986ac3SRajan Vaja  *
1461c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1462c1986ac3SRajan Vaja  */
zynqmp_pm_set_requirement(const u32 node,const u32 capabilities,const u32 qos,const enum zynqmp_pm_request_ack ack)1463cbbbda71SRajan Vaja int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
1464c1986ac3SRajan Vaja 			      const u32 qos,
1465c1986ac3SRajan Vaja 			      const enum zynqmp_pm_request_ack ack)
1466c1986ac3SRajan Vaja {
1467f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, NULL, 4, node, capabilities, qos, ack);
1468c1986ac3SRajan Vaja }
1469cbbbda71SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
1470c1986ac3SRajan Vaja 
1471057a0fb6SKalyani Akula /**
14722b9fc773SNava kishore Manne  * zynqmp_pm_load_pdi - Load and process PDI
14732b9fc773SNava kishore Manne  * @src:	Source device where PDI is located
14742b9fc773SNava kishore Manne  * @address:	PDI src address
14752b9fc773SNava kishore Manne  *
14762b9fc773SNava kishore Manne  * This function provides support to load PDI from linux
14772b9fc773SNava kishore Manne  *
14782b9fc773SNava kishore Manne  * Return: Returns status, either success or error+reason
14792b9fc773SNava kishore Manne  */
zynqmp_pm_load_pdi(const u32 src,const u64 address)14802b9fc773SNava kishore Manne int zynqmp_pm_load_pdi(const u32 src, const u64 address)
14812b9fc773SNava kishore Manne {
1482f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_LOAD_PDI, NULL, 3, src, lower_32_bits(address),
1483f922b16aSJay Buddhabhatti 				   upper_32_bits(address));
14842b9fc773SNava kishore Manne }
14852b9fc773SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi);
14862b9fc773SNava kishore Manne 
14872b9fc773SNava kishore Manne /**
14882a8faf8dSMichal Simek  * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
1489057a0fb6SKalyani Akula  * AES-GCM core.
1490057a0fb6SKalyani Akula  * @address:	Address of the AesParams structure.
1491057a0fb6SKalyani Akula  * @out:	Returned output value
1492057a0fb6SKalyani Akula  *
1493057a0fb6SKalyani Akula  * Return:	Returns status, either success or error code.
1494057a0fb6SKalyani Akula  */
zynqmp_pm_aes_engine(const u64 address,u32 * out)1495bc86f9c5SRajan Vaja int zynqmp_pm_aes_engine(const u64 address, u32 *out)
1496057a0fb6SKalyani Akula {
1497057a0fb6SKalyani Akula 	u32 ret_payload[PAYLOAD_ARG_CNT];
1498057a0fb6SKalyani Akula 	int ret;
1499057a0fb6SKalyani Akula 
1500057a0fb6SKalyani Akula 	if (!out)
1501057a0fb6SKalyani Akula 		return -EINVAL;
1502057a0fb6SKalyani Akula 
1503f922b16aSJay Buddhabhatti 	ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, ret_payload, 2, upper_32_bits(address),
1504f922b16aSJay Buddhabhatti 				  lower_32_bits(address));
1505057a0fb6SKalyani Akula 	*out = ret_payload[1];
1506057a0fb6SKalyani Akula 
1507057a0fb6SKalyani Akula 	return ret;
1508057a0fb6SKalyani Akula }
1509bc86f9c5SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
1510057a0fb6SKalyani Akula 
1511fdd2ed88SRajan Vaja /**
1512e34b9430SPraveen Teja Kundanala  * zynqmp_pm_efuse_access - Provides access to efuse memory.
1513e34b9430SPraveen Teja Kundanala  * @address:	Address of the efuse params structure
1514e34b9430SPraveen Teja Kundanala  * @out:		Returned output value
1515e34b9430SPraveen Teja Kundanala  *
1516e34b9430SPraveen Teja Kundanala  * Return:	Returns status, either success or error code.
1517e34b9430SPraveen Teja Kundanala  */
zynqmp_pm_efuse_access(const u64 address,u32 * out)1518e34b9430SPraveen Teja Kundanala int zynqmp_pm_efuse_access(const u64 address, u32 *out)
1519e34b9430SPraveen Teja Kundanala {
1520e34b9430SPraveen Teja Kundanala 	u32 ret_payload[PAYLOAD_ARG_CNT];
1521e34b9430SPraveen Teja Kundanala 	int ret;
1522e34b9430SPraveen Teja Kundanala 
1523e34b9430SPraveen Teja Kundanala 	if (!out)
1524e34b9430SPraveen Teja Kundanala 		return -EINVAL;
1525e34b9430SPraveen Teja Kundanala 
1526e34b9430SPraveen Teja Kundanala 	ret = zynqmp_pm_invoke_fn(PM_EFUSE_ACCESS, ret_payload, 2,
1527e34b9430SPraveen Teja Kundanala 				  upper_32_bits(address),
1528e34b9430SPraveen Teja Kundanala 				  lower_32_bits(address));
1529e34b9430SPraveen Teja Kundanala 	*out = ret_payload[1];
1530e34b9430SPraveen Teja Kundanala 
1531e34b9430SPraveen Teja Kundanala 	return ret;
1532e34b9430SPraveen Teja Kundanala }
1533e34b9430SPraveen Teja Kundanala EXPORT_SYMBOL_GPL(zynqmp_pm_efuse_access);
1534e34b9430SPraveen Teja Kundanala 
1535e34b9430SPraveen Teja Kundanala /**
153680f940efSHarsha  * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
153780f940efSHarsha  * @address:	Address of the data/ Address of output buffer where
153880f940efSHarsha  *		hash should be stored.
153980f940efSHarsha  * @size:	Size of the data.
154080f940efSHarsha  * @flags:
154180f940efSHarsha  *	BIT(0) - for initializing csudma driver and SHA3(Here address
154280f940efSHarsha  *		 and size inputs can be NULL).
154380f940efSHarsha  *	BIT(1) - to call Sha3_Update API which can be called multiple
154480f940efSHarsha  *		 times when data is not contiguous.
154580f940efSHarsha  *	BIT(2) - to get final hash of the whole updated data.
154680f940efSHarsha  *		 Hash will be overwritten at provided address with
154780f940efSHarsha  *		 48 bytes.
154880f940efSHarsha  *
154980f940efSHarsha  * Return:	Returns status, either success or error code.
155080f940efSHarsha  */
zynqmp_pm_sha_hash(const u64 address,const u32 size,const u32 flags)155180f940efSHarsha int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags)
155280f940efSHarsha {
155380f940efSHarsha 	u32 lower_addr = lower_32_bits(address);
155480f940efSHarsha 	u32 upper_addr = upper_32_bits(address);
155580f940efSHarsha 
1556f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_SECURE_SHA, NULL, 4, upper_addr, lower_addr, size, flags);
155780f940efSHarsha }
155880f940efSHarsha EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash);
155980f940efSHarsha 
156080f940efSHarsha /**
15611881eadbSAbhyuday Godhasara  * zynqmp_pm_register_notifier() - PM API for register a subsystem
15621881eadbSAbhyuday Godhasara  *                                to be notified about specific
15631881eadbSAbhyuday Godhasara  *                                event/error.
15641881eadbSAbhyuday Godhasara  * @node:	Node ID to which the event is related.
15651881eadbSAbhyuday Godhasara  * @event:	Event Mask of Error events for which wants to get notified.
15661881eadbSAbhyuday Godhasara  * @wake:	Wake subsystem upon capturing the event if value 1
15671881eadbSAbhyuday Godhasara  * @enable:	Enable the registration for value 1, disable for value 0
15681881eadbSAbhyuday Godhasara  *
15691881eadbSAbhyuday Godhasara  * This function is used to register/un-register for particular node-event
15701881eadbSAbhyuday Godhasara  * combination in firmware.
15711881eadbSAbhyuday Godhasara  *
15721881eadbSAbhyuday Godhasara  * Return: Returns status, either success or error+reason
15731881eadbSAbhyuday Godhasara  */
15741881eadbSAbhyuday Godhasara 
zynqmp_pm_register_notifier(const u32 node,const u32 event,const u32 wake,const u32 enable)15751881eadbSAbhyuday Godhasara int zynqmp_pm_register_notifier(const u32 node, const u32 event,
15761881eadbSAbhyuday Godhasara 				const u32 wake, const u32 enable)
15771881eadbSAbhyuday Godhasara {
1578f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, NULL, 4, node, event, wake, enable);
15791881eadbSAbhyuday Godhasara }
15801881eadbSAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier);
15811881eadbSAbhyuday Godhasara 
15821881eadbSAbhyuday Godhasara /**
1583fdd2ed88SRajan Vaja  * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
1584fdd2ed88SRajan Vaja  * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
1585fdd2ed88SRajan Vaja  * @subtype:	Specifies which system should be restarted or shut down
1586fdd2ed88SRajan Vaja  *
1587fdd2ed88SRajan Vaja  * Return:	Returns status, either success or error+reason
1588fdd2ed88SRajan Vaja  */
zynqmp_pm_system_shutdown(const u32 type,const u32 subtype)1589fdd2ed88SRajan Vaja int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
1590fdd2ed88SRajan Vaja {
1591f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, NULL, 2, type, subtype);
1592fdd2ed88SRajan Vaja }
1593fdd2ed88SRajan Vaja 
1594b3ae24c4SRajan Vaja /**
1595f1d0821bSRonak Jain  * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config
1596f1d0821bSRonak Jain  * @id:         The config ID of the feature to be configured
1597f1d0821bSRonak Jain  * @value:      The config value of the feature to be configured
1598f1d0821bSRonak Jain  *
1599f1d0821bSRonak Jain  * Return:      Returns 0 on success or error value on failure.
1600f1d0821bSRonak Jain  */
zynqmp_pm_set_feature_config(enum pm_feature_config_id id,u32 value)1601f1d0821bSRonak Jain int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value)
1602f1d0821bSRonak Jain {
1603f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_FEATURE_CONFIG, id, value);
1604f1d0821bSRonak Jain }
1605f1d0821bSRonak Jain 
1606f1d0821bSRonak Jain /**
1607f1d0821bSRonak Jain  * zynqmp_pm_get_feature_config - PM call to get value of configured feature
1608f1d0821bSRonak Jain  * @id:         The config id of the feature to be queried
1609f1d0821bSRonak Jain  * @payload:    Returned value array
1610f1d0821bSRonak Jain  *
1611f1d0821bSRonak Jain  * Return:      Returns 0 on success or error value on failure.
1612f1d0821bSRonak Jain  */
zynqmp_pm_get_feature_config(enum pm_feature_config_id id,u32 * payload)1613f1d0821bSRonak Jain int zynqmp_pm_get_feature_config(enum pm_feature_config_id id,
1614f1d0821bSRonak Jain 				 u32 *payload)
1615f1d0821bSRonak Jain {
1616f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, payload, 3, 0, IOCTL_GET_FEATURE_CONFIG, id);
1617f1d0821bSRonak Jain }
1618f1d0821bSRonak Jain 
1619f1d0821bSRonak Jain /**
1620256dea91SRonak Jain  * zynqmp_pm_set_sd_config - PM call to set value of SD config registers
1621256dea91SRonak Jain  * @node:	SD node ID
1622256dea91SRonak Jain  * @config:	The config type of SD registers
1623256dea91SRonak Jain  * @value:	Value to be set
1624256dea91SRonak Jain  *
1625256dea91SRonak Jain  * Return:	Returns 0 on success or error value on failure.
1626256dea91SRonak Jain  */
zynqmp_pm_set_sd_config(u32 node,enum pm_sd_config_type config,u32 value)1627256dea91SRonak Jain int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value)
1628256dea91SRonak Jain {
1629f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, node, IOCTL_SET_SD_CONFIG, config, value);
1630256dea91SRonak Jain }
1631256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_config);
1632256dea91SRonak Jain 
1633256dea91SRonak Jain /**
1634256dea91SRonak Jain  * zynqmp_pm_set_gem_config - PM call to set value of GEM config registers
1635256dea91SRonak Jain  * @node:	GEM node ID
1636256dea91SRonak Jain  * @config:	The config type of GEM registers
1637256dea91SRonak Jain  * @value:	Value to be set
1638256dea91SRonak Jain  *
1639256dea91SRonak Jain  * Return:	Returns 0 on success or error value on failure.
1640256dea91SRonak Jain  */
zynqmp_pm_set_gem_config(u32 node,enum pm_gem_config_type config,u32 value)1641256dea91SRonak Jain int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
1642256dea91SRonak Jain 			     u32 value)
1643256dea91SRonak Jain {
1644f922b16aSJay Buddhabhatti 	return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, node, IOCTL_SET_GEM_CONFIG, config, value);
1645256dea91SRonak Jain }
1646256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_gem_config);
1647256dea91SRonak Jain 
1648256dea91SRonak Jain /**
1649b3ae24c4SRajan Vaja  * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
1650b3ae24c4SRajan Vaja  * @subtype:	Shutdown subtype
1651b3ae24c4SRajan Vaja  * @name:	Matching string for scope argument
1652b3ae24c4SRajan Vaja  *
1653b3ae24c4SRajan Vaja  * This struct encapsulates mapping between shutdown scope ID and string.
1654b3ae24c4SRajan Vaja  */
1655b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope {
1656b3ae24c4SRajan Vaja 	const enum zynqmp_pm_shutdown_subtype subtype;
1657b3ae24c4SRajan Vaja 	const char *name;
1658b3ae24c4SRajan Vaja };
1659b3ae24c4SRajan Vaja 
1660b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
1661b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
1662b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
1663b3ae24c4SRajan Vaja 		.name = "subsystem",
1664b3ae24c4SRajan Vaja 	},
1665b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
1666b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
1667b3ae24c4SRajan Vaja 		.name = "ps_only",
1668b3ae24c4SRajan Vaja 	},
1669b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
1670b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
1671b3ae24c4SRajan Vaja 		.name = "system",
1672b3ae24c4SRajan Vaja 	},
1673b3ae24c4SRajan Vaja };
1674b3ae24c4SRajan Vaja 
1675b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope =
1676b3ae24c4SRajan Vaja 		&shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
1677b3ae24c4SRajan Vaja 
1678b3ae24c4SRajan Vaja /**
1679b3ae24c4SRajan Vaja  * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
1680b3ae24c4SRajan Vaja  * @scope_string:	Shutdown scope string
1681b3ae24c4SRajan Vaja  *
1682b3ae24c4SRajan Vaja  * Return:		Return pointer to matching shutdown scope struct from
1683b3ae24c4SRajan Vaja  *			array of available options in system if string is valid,
1684b3ae24c4SRajan Vaja  *			otherwise returns NULL.
1685b3ae24c4SRajan Vaja  */
1686b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope*
zynqmp_pm_is_shutdown_scope_valid(const char * scope_string)1687b3ae24c4SRajan Vaja 		zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
1688b3ae24c4SRajan Vaja {
1689b3ae24c4SRajan Vaja 	int count;
1690b3ae24c4SRajan Vaja 
1691b3ae24c4SRajan Vaja 	for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
1692b3ae24c4SRajan Vaja 		if (sysfs_streq(scope_string, shutdown_scopes[count].name))
1693b3ae24c4SRajan Vaja 			return &shutdown_scopes[count];
1694b3ae24c4SRajan Vaja 
1695b3ae24c4SRajan Vaja 	return NULL;
1696b3ae24c4SRajan Vaja }
1697b3ae24c4SRajan Vaja 
shutdown_scope_show(struct device * device,struct device_attribute * attr,char * buf)1698b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device,
1699b3ae24c4SRajan Vaja 				   struct device_attribute *attr,
1700b3ae24c4SRajan Vaja 				   char *buf)
1701b3ae24c4SRajan Vaja {
1702b3ae24c4SRajan Vaja 	int i;
1703b3ae24c4SRajan Vaja 
1704b3ae24c4SRajan Vaja 	for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
1705b3ae24c4SRajan Vaja 		if (&shutdown_scopes[i] == selected_scope) {
1706b3ae24c4SRajan Vaja 			strcat(buf, "[");
1707b3ae24c4SRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
1708b3ae24c4SRajan Vaja 			strcat(buf, "]");
1709b3ae24c4SRajan Vaja 		} else {
1710b3ae24c4SRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
1711b3ae24c4SRajan Vaja 		}
1712b3ae24c4SRajan Vaja 		strcat(buf, " ");
1713b3ae24c4SRajan Vaja 	}
1714b3ae24c4SRajan Vaja 	strcat(buf, "\n");
1715b3ae24c4SRajan Vaja 
1716b3ae24c4SRajan Vaja 	return strlen(buf);
1717b3ae24c4SRajan Vaja }
1718b3ae24c4SRajan Vaja 
shutdown_scope_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)1719b3ae24c4SRajan Vaja static ssize_t shutdown_scope_store(struct device *device,
1720b3ae24c4SRajan Vaja 				    struct device_attribute *attr,
1721b3ae24c4SRajan Vaja 				    const char *buf, size_t count)
1722b3ae24c4SRajan Vaja {
1723b3ae24c4SRajan Vaja 	int ret;
1724b3ae24c4SRajan Vaja 	struct zynqmp_pm_shutdown_scope *scope;
1725b3ae24c4SRajan Vaja 
1726b3ae24c4SRajan Vaja 	scope = zynqmp_pm_is_shutdown_scope_valid(buf);
1727b3ae24c4SRajan Vaja 	if (!scope)
1728b3ae24c4SRajan Vaja 		return -EINVAL;
1729b3ae24c4SRajan Vaja 
1730b3ae24c4SRajan Vaja 	ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
1731b3ae24c4SRajan Vaja 					scope->subtype);
1732b3ae24c4SRajan Vaja 	if (ret) {
1733b3ae24c4SRajan Vaja 		pr_err("unable to set shutdown scope %s\n", buf);
1734b3ae24c4SRajan Vaja 		return ret;
1735b3ae24c4SRajan Vaja 	}
1736b3ae24c4SRajan Vaja 
1737b3ae24c4SRajan Vaja 	selected_scope = scope;
1738b3ae24c4SRajan Vaja 
1739b3ae24c4SRajan Vaja 	return count;
1740b3ae24c4SRajan Vaja }
1741b3ae24c4SRajan Vaja 
1742b3ae24c4SRajan Vaja static DEVICE_ATTR_RW(shutdown_scope);
1743b3ae24c4SRajan Vaja 
health_status_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)1744a2cc220aSRajan Vaja static ssize_t health_status_store(struct device *device,
1745a2cc220aSRajan Vaja 				   struct device_attribute *attr,
1746a2cc220aSRajan Vaja 				   const char *buf, size_t count)
1747a2cc220aSRajan Vaja {
1748a2cc220aSRajan Vaja 	int ret;
1749a2cc220aSRajan Vaja 	unsigned int value;
1750a2cc220aSRajan Vaja 
1751a2cc220aSRajan Vaja 	ret = kstrtouint(buf, 10, &value);
1752a2cc220aSRajan Vaja 	if (ret)
1753a2cc220aSRajan Vaja 		return ret;
1754a2cc220aSRajan Vaja 
1755a2cc220aSRajan Vaja 	ret = zynqmp_pm_set_boot_health_status(value);
1756a2cc220aSRajan Vaja 	if (ret) {
1757a2cc220aSRajan Vaja 		dev_err(device, "unable to set healthy bit value to %u\n",
1758a2cc220aSRajan Vaja 			value);
1759a2cc220aSRajan Vaja 		return ret;
1760a2cc220aSRajan Vaja 	}
1761a2cc220aSRajan Vaja 
1762a2cc220aSRajan Vaja 	return count;
1763a2cc220aSRajan Vaja }
1764a2cc220aSRajan Vaja 
1765a2cc220aSRajan Vaja static DEVICE_ATTR_WO(health_status);
1766a2cc220aSRajan Vaja 
ggs_show(struct device * device,struct device_attribute * attr,char * buf,u32 reg)1767ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device,
1768ae5c961dSRajan Vaja 			struct device_attribute *attr,
1769ae5c961dSRajan Vaja 			char *buf,
1770ae5c961dSRajan Vaja 			u32 reg)
1771ae5c961dSRajan Vaja {
1772ae5c961dSRajan Vaja 	int ret;
1773ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1774ae5c961dSRajan Vaja 
1775ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_ggs(reg, ret_payload);
1776ae5c961dSRajan Vaja 	if (ret)
1777ae5c961dSRajan Vaja 		return ret;
1778ae5c961dSRajan Vaja 
1779ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1780ae5c961dSRajan Vaja }
1781ae5c961dSRajan Vaja 
ggs_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count,u32 reg)1782ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device,
1783ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1784ae5c961dSRajan Vaja 			 const char *buf, size_t count,
1785ae5c961dSRajan Vaja 			 u32 reg)
1786ae5c961dSRajan Vaja {
1787ae5c961dSRajan Vaja 	long value;
1788ae5c961dSRajan Vaja 	int ret;
1789ae5c961dSRajan Vaja 
1790ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1791ae5c961dSRajan Vaja 		return -EINVAL;
1792ae5c961dSRajan Vaja 
1793ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1794ae5c961dSRajan Vaja 	if (ret) {
1795ae5c961dSRajan Vaja 		count = -EFAULT;
1796ae5c961dSRajan Vaja 		goto err;
1797ae5c961dSRajan Vaja 	}
1798ae5c961dSRajan Vaja 
1799ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_ggs(reg, value);
1800ae5c961dSRajan Vaja 	if (ret)
1801ae5c961dSRajan Vaja 		count = -EFAULT;
1802ae5c961dSRajan Vaja err:
1803ae5c961dSRajan Vaja 	return count;
1804ae5c961dSRajan Vaja }
1805ae5c961dSRajan Vaja 
1806ae5c961dSRajan Vaja /* GGS register show functions */
1807ae5c961dSRajan Vaja #define GGS0_SHOW(N)						\
1808ae5c961dSRajan Vaja 	ssize_t ggs##N##_show(struct device *device,		\
1809ae5c961dSRajan Vaja 			      struct device_attribute *attr,	\
1810ae5c961dSRajan Vaja 			      char *buf)			\
1811ae5c961dSRajan Vaja 	{							\
1812ae5c961dSRajan Vaja 		return ggs_show(device, attr, buf, N);		\
1813ae5c961dSRajan Vaja 	}
1814ae5c961dSRajan Vaja 
1815ae5c961dSRajan Vaja static GGS0_SHOW(0);
1816ae5c961dSRajan Vaja static GGS0_SHOW(1);
1817ae5c961dSRajan Vaja static GGS0_SHOW(2);
1818ae5c961dSRajan Vaja static GGS0_SHOW(3);
1819ae5c961dSRajan Vaja 
1820ae5c961dSRajan Vaja /* GGS register store function */
1821ae5c961dSRajan Vaja #define GGS0_STORE(N)						\
1822ae5c961dSRajan Vaja 	ssize_t ggs##N##_store(struct device *device,		\
1823ae5c961dSRajan Vaja 			       struct device_attribute *attr,	\
1824ae5c961dSRajan Vaja 			       const char *buf,			\
1825ae5c961dSRajan Vaja 			       size_t count)			\
1826ae5c961dSRajan Vaja 	{							\
1827ae5c961dSRajan Vaja 		return ggs_store(device, attr, buf, count, N);	\
1828ae5c961dSRajan Vaja 	}
1829ae5c961dSRajan Vaja 
1830ae5c961dSRajan Vaja static GGS0_STORE(0);
1831ae5c961dSRajan Vaja static GGS0_STORE(1);
1832ae5c961dSRajan Vaja static GGS0_STORE(2);
1833ae5c961dSRajan Vaja static GGS0_STORE(3);
1834ae5c961dSRajan Vaja 
pggs_show(struct device * device,struct device_attribute * attr,char * buf,u32 reg)1835ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device,
1836ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1837ae5c961dSRajan Vaja 			 char *buf,
1838ae5c961dSRajan Vaja 			 u32 reg)
1839ae5c961dSRajan Vaja {
1840ae5c961dSRajan Vaja 	int ret;
1841ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1842ae5c961dSRajan Vaja 
1843ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_pggs(reg, ret_payload);
1844ae5c961dSRajan Vaja 	if (ret)
1845ae5c961dSRajan Vaja 		return ret;
1846ae5c961dSRajan Vaja 
1847ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1848ae5c961dSRajan Vaja }
1849ae5c961dSRajan Vaja 
pggs_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count,u32 reg)1850ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device,
1851ae5c961dSRajan Vaja 			  struct device_attribute *attr,
1852ae5c961dSRajan Vaja 			  const char *buf, size_t count,
1853ae5c961dSRajan Vaja 			  u32 reg)
1854ae5c961dSRajan Vaja {
1855ae5c961dSRajan Vaja 	long value;
1856ae5c961dSRajan Vaja 	int ret;
1857ae5c961dSRajan Vaja 
1858ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1859ae5c961dSRajan Vaja 		return -EINVAL;
1860ae5c961dSRajan Vaja 
1861ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1862ae5c961dSRajan Vaja 	if (ret) {
1863ae5c961dSRajan Vaja 		count = -EFAULT;
1864ae5c961dSRajan Vaja 		goto err;
1865ae5c961dSRajan Vaja 	}
1866ae5c961dSRajan Vaja 
1867ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_pggs(reg, value);
1868ae5c961dSRajan Vaja 	if (ret)
1869ae5c961dSRajan Vaja 		count = -EFAULT;
1870ae5c961dSRajan Vaja 
1871ae5c961dSRajan Vaja err:
1872ae5c961dSRajan Vaja 	return count;
1873ae5c961dSRajan Vaja }
1874ae5c961dSRajan Vaja 
1875ae5c961dSRajan Vaja #define PGGS0_SHOW(N)						\
1876ae5c961dSRajan Vaja 	ssize_t pggs##N##_show(struct device *device,		\
1877ae5c961dSRajan Vaja 			       struct device_attribute *attr,	\
1878ae5c961dSRajan Vaja 			       char *buf)			\
1879ae5c961dSRajan Vaja 	{							\
1880ae5c961dSRajan Vaja 		return pggs_show(device, attr, buf, N);		\
1881ae5c961dSRajan Vaja 	}
1882ae5c961dSRajan Vaja 
1883ae5c961dSRajan Vaja #define PGGS0_STORE(N)						\
1884ae5c961dSRajan Vaja 	ssize_t pggs##N##_store(struct device *device,		\
1885ae5c961dSRajan Vaja 				struct device_attribute *attr,	\
1886ae5c961dSRajan Vaja 				const char *buf,		\
1887ae5c961dSRajan Vaja 				size_t count)			\
1888ae5c961dSRajan Vaja 	{							\
1889ae5c961dSRajan Vaja 		return pggs_store(device, attr, buf, count, N);	\
1890ae5c961dSRajan Vaja 	}
1891ae5c961dSRajan Vaja 
1892ae5c961dSRajan Vaja /* PGGS register show functions */
1893ae5c961dSRajan Vaja static PGGS0_SHOW(0);
1894ae5c961dSRajan Vaja static PGGS0_SHOW(1);
1895ae5c961dSRajan Vaja static PGGS0_SHOW(2);
1896ae5c961dSRajan Vaja static PGGS0_SHOW(3);
1897ae5c961dSRajan Vaja 
1898ae5c961dSRajan Vaja /* PGGS register store functions */
1899ae5c961dSRajan Vaja static PGGS0_STORE(0);
1900ae5c961dSRajan Vaja static PGGS0_STORE(1);
1901ae5c961dSRajan Vaja static PGGS0_STORE(2);
1902ae5c961dSRajan Vaja static PGGS0_STORE(3);
1903ae5c961dSRajan Vaja 
1904ae5c961dSRajan Vaja /* GGS register attributes */
1905ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs0);
1906ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs1);
1907ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs2);
1908ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs3);
1909ae5c961dSRajan Vaja 
1910ae5c961dSRajan Vaja /* PGGS register attributes */
1911ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs0);
1912ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs1);
1913ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs2);
1914ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs3);
1915ae5c961dSRajan Vaja 
feature_config_id_show(struct device * device,struct device_attribute * attr,char * buf)19162c5d8f7cSRonak Jain static ssize_t feature_config_id_show(struct device *device,
19172c5d8f7cSRonak Jain 				      struct device_attribute *attr,
19182c5d8f7cSRonak Jain 				      char *buf)
19192c5d8f7cSRonak Jain {
19202c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
19212c5d8f7cSRonak Jain 
19222c5d8f7cSRonak Jain 	return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id);
19232c5d8f7cSRonak Jain }
19242c5d8f7cSRonak Jain 
feature_config_id_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)19252c5d8f7cSRonak Jain static ssize_t feature_config_id_store(struct device *device,
19262c5d8f7cSRonak Jain 				       struct device_attribute *attr,
19272c5d8f7cSRonak Jain 				       const char *buf, size_t count)
19282c5d8f7cSRonak Jain {
19292c5d8f7cSRonak Jain 	u32 config_id;
19302c5d8f7cSRonak Jain 	int ret;
19312c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
19322c5d8f7cSRonak Jain 
19332c5d8f7cSRonak Jain 	if (!buf)
19342c5d8f7cSRonak Jain 		return -EINVAL;
19352c5d8f7cSRonak Jain 
19362c5d8f7cSRonak Jain 	ret = kstrtou32(buf, 10, &config_id);
19372c5d8f7cSRonak Jain 	if (ret)
19382c5d8f7cSRonak Jain 		return ret;
19392c5d8f7cSRonak Jain 
19402c5d8f7cSRonak Jain 	devinfo->feature_conf_id = config_id;
19412c5d8f7cSRonak Jain 
19422c5d8f7cSRonak Jain 	return count;
19432c5d8f7cSRonak Jain }
19442c5d8f7cSRonak Jain 
19452c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_id);
19462c5d8f7cSRonak Jain 
feature_config_value_show(struct device * device,struct device_attribute * attr,char * buf)19472c5d8f7cSRonak Jain static ssize_t feature_config_value_show(struct device *device,
19482c5d8f7cSRonak Jain 					 struct device_attribute *attr,
19492c5d8f7cSRonak Jain 					 char *buf)
19502c5d8f7cSRonak Jain {
19512c5d8f7cSRonak Jain 	int ret;
19522c5d8f7cSRonak Jain 	u32 ret_payload[PAYLOAD_ARG_CNT];
19532c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
19542c5d8f7cSRonak Jain 
19552c5d8f7cSRonak Jain 	ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id,
19562c5d8f7cSRonak Jain 					   ret_payload);
19572c5d8f7cSRonak Jain 	if (ret)
19582c5d8f7cSRonak Jain 		return ret;
19592c5d8f7cSRonak Jain 
19602c5d8f7cSRonak Jain 	return sysfs_emit(buf, "%d\n", ret_payload[1]);
19612c5d8f7cSRonak Jain }
19622c5d8f7cSRonak Jain 
feature_config_value_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)19632c5d8f7cSRonak Jain static ssize_t feature_config_value_store(struct device *device,
19642c5d8f7cSRonak Jain 					  struct device_attribute *attr,
19652c5d8f7cSRonak Jain 					  const char *buf, size_t count)
19662c5d8f7cSRonak Jain {
19672c5d8f7cSRonak Jain 	u32 value;
19682c5d8f7cSRonak Jain 	int ret;
19692c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
19702c5d8f7cSRonak Jain 
19712c5d8f7cSRonak Jain 	if (!buf)
19722c5d8f7cSRonak Jain 		return -EINVAL;
19732c5d8f7cSRonak Jain 
19742c5d8f7cSRonak Jain 	ret = kstrtou32(buf, 10, &value);
19752c5d8f7cSRonak Jain 	if (ret)
19762c5d8f7cSRonak Jain 		return ret;
19772c5d8f7cSRonak Jain 
19782c5d8f7cSRonak Jain 	ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id,
19792c5d8f7cSRonak Jain 					   value);
19802c5d8f7cSRonak Jain 	if (ret)
19812c5d8f7cSRonak Jain 		return ret;
19822c5d8f7cSRonak Jain 
19832c5d8f7cSRonak Jain 	return count;
19842c5d8f7cSRonak Jain }
19852c5d8f7cSRonak Jain 
19862c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_value);
19872c5d8f7cSRonak Jain 
1988ae5c961dSRajan Vaja static struct attribute *zynqmp_firmware_attrs[] = {
1989ae5c961dSRajan Vaja 	&dev_attr_ggs0.attr,
1990ae5c961dSRajan Vaja 	&dev_attr_ggs1.attr,
1991ae5c961dSRajan Vaja 	&dev_attr_ggs2.attr,
1992ae5c961dSRajan Vaja 	&dev_attr_ggs3.attr,
1993ae5c961dSRajan Vaja 	&dev_attr_pggs0.attr,
1994ae5c961dSRajan Vaja 	&dev_attr_pggs1.attr,
1995ae5c961dSRajan Vaja 	&dev_attr_pggs2.attr,
1996ae5c961dSRajan Vaja 	&dev_attr_pggs3.attr,
1997b3ae24c4SRajan Vaja 	&dev_attr_shutdown_scope.attr,
1998a2cc220aSRajan Vaja 	&dev_attr_health_status.attr,
19992c5d8f7cSRonak Jain 	&dev_attr_feature_config_id.attr,
20002c5d8f7cSRonak Jain 	&dev_attr_feature_config_value.attr,
2001ae5c961dSRajan Vaja 	NULL,
2002ae5c961dSRajan Vaja };
2003ae5c961dSRajan Vaja 
2004ae5c961dSRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware);
2005ae5c961dSRajan Vaja 
zynqmp_firmware_probe(struct platform_device * pdev)200676582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev)
200776582671SRajan Vaja {
200876582671SRajan Vaja 	struct device *dev = &pdev->dev;
20092c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo;
201076582671SRajan Vaja 	int ret;
201176582671SRajan Vaja 
2012e5052becSRonak Jain 	ret = get_set_conduit_method(dev->of_node);
2013e5052becSRonak Jain 	if (ret)
2014e5052becSRonak Jain 		return ret;
2015e5052becSRonak Jain 
201692fb7133SRonak Jain 	/* Get SiP SVC version number */
201792fb7133SRonak Jain 	ret = zynqmp_pm_get_sip_svc_version(&sip_svc_version);
201892fb7133SRonak Jain 	if (ret)
201992fb7133SRonak Jain 		return ret;
202092fb7133SRonak Jain 
2021e5052becSRonak Jain 	ret = do_feature_check_call(PM_FEATURE_CHECK);
2022f689a0caSJay Buddhabhatti 	if (ret >= 0 && ((ret & FIRMWARE_VERSION_MASK) >= PM_API_VERSION_1))
2023e5052becSRonak Jain 		feature_check_enabled = true;
202476582671SRajan Vaja 
20252c5d8f7cSRonak Jain 	devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL);
20262c5d8f7cSRonak Jain 	if (!devinfo)
20272c5d8f7cSRonak Jain 		return -ENOMEM;
20282c5d8f7cSRonak Jain 
20292c5d8f7cSRonak Jain 	devinfo->dev = dev;
20302c5d8f7cSRonak Jain 
20312c5d8f7cSRonak Jain 	platform_set_drvdata(pdev, devinfo);
20322c5d8f7cSRonak Jain 
203376582671SRajan Vaja 	/* Check PM API version number */
2034168e05c1SRajan Vaja 	ret = zynqmp_pm_get_api_version(&pm_api_version);
2035168e05c1SRajan Vaja 	if (ret)
2036168e05c1SRajan Vaja 		return ret;
2037168e05c1SRajan Vaja 
203876582671SRajan Vaja 	if (pm_api_version < ZYNQMP_PM_VERSION) {
203976582671SRajan Vaja 		panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
204076582671SRajan Vaja 		      __func__,
204176582671SRajan Vaja 		      ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
204276582671SRajan Vaja 		      pm_api_version >> 16, pm_api_version & 0xFFFF);
204376582671SRajan Vaja 	}
204476582671SRajan Vaja 
204576582671SRajan Vaja 	pr_info("%s Platform Management API v%d.%d\n", __func__,
204676582671SRajan Vaja 		pm_api_version >> 16, pm_api_version & 0xFFFF);
204776582671SRajan Vaja 
204803ffa9afSDhaval Shah 	/* Get the Family code and sub family code of platform */
204903ffa9afSDhaval Shah 	ret = zynqmp_pm_get_family_info(&pm_family_code, &pm_sub_family_code);
205003ffa9afSDhaval Shah 	if (ret < 0)
205103ffa9afSDhaval Shah 		return ret;
205203ffa9afSDhaval Shah 
205376582671SRajan Vaja 	/* Check trustzone version number */
205476582671SRajan Vaja 	ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
205576582671SRajan Vaja 	if (ret)
205676582671SRajan Vaja 		panic("Legacy trustzone found without version support\n");
205776582671SRajan Vaja 
205876582671SRajan Vaja 	if (pm_tz_version < ZYNQMP_TZ_VERSION)
205976582671SRajan Vaja 		panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
206076582671SRajan Vaja 		      __func__,
206176582671SRajan Vaja 		      ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
206276582671SRajan Vaja 		      pm_tz_version >> 16, pm_tz_version & 0xFFFF);
206376582671SRajan Vaja 
206476582671SRajan Vaja 	pr_info("%s Trustzone version v%d.%d\n", __func__,
206576582671SRajan Vaja 		pm_tz_version >> 16, pm_tz_version & 0xFFFF);
206676582671SRajan Vaja 
2067e23d9c6dSJolly Shah 	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
2068e23d9c6dSJolly Shah 			      ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
2069e23d9c6dSJolly Shah 	if (ret) {
2070e23d9c6dSJolly Shah 		dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
2071e23d9c6dSJolly Shah 		return ret;
2072e23d9c6dSJolly Shah 	}
2073e23d9c6dSJolly Shah 
207465f0539bSChristophe JAILLET 	zynqmp_pm_api_debugfs_init();
207565f0539bSChristophe JAILLET 
2076a9d06184SJay Buddhabhatti 	if (pm_family_code == VERSAL_FAMILY_CODE) {
2077a515814eSAbhyuday Godhasara 		em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager",
2078a515814eSAbhyuday Godhasara 						       -1, NULL, 0);
2079a515814eSAbhyuday Godhasara 		if (IS_ERR(em_dev))
2080a515814eSAbhyuday Godhasara 			dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n");
2081a515814eSAbhyuday Godhasara 	}
2082a515814eSAbhyuday Godhasara 
208376582671SRajan Vaja 	return of_platform_populate(dev->of_node, NULL, NULL, dev);
208476582671SRajan Vaja }
208576582671SRajan Vaja 
zynqmp_firmware_remove(struct platform_device * pdev)2086408201ebSUwe Kleine-König static void zynqmp_firmware_remove(struct platform_device *pdev)
208776582671SRajan Vaja {
2088acfdd185SAmit Sunil Dhamne 	struct pm_api_feature_data *feature_data;
2089f1f21becSTejas Patel 	struct hlist_node *tmp;
2090acfdd185SAmit Sunil Dhamne 	int i;
2091acfdd185SAmit Sunil Dhamne 
2092e23d9c6dSJolly Shah 	mfd_remove_devices(&pdev->dev);
2093b3217252SRajan Vaja 	zynqmp_pm_api_debugfs_exit();
2094b3217252SRajan Vaja 
2095f1f21becSTejas Patel 	hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) {
2096acfdd185SAmit Sunil Dhamne 		hash_del(&feature_data->hentry);
2097acfdd185SAmit Sunil Dhamne 		kfree(feature_data);
2098acfdd185SAmit Sunil Dhamne 	}
2099acfdd185SAmit Sunil Dhamne 
2100a515814eSAbhyuday Godhasara 	platform_device_unregister(em_dev);
210176582671SRajan Vaja }
210276582671SRajan Vaja 
zynqmp_firmware_sync_state(struct device * dev)21033da405eaSUlf Hansson static void zynqmp_firmware_sync_state(struct device *dev)
21043da405eaSUlf Hansson {
2105*29ea3386SUlf Hansson 	struct device_node *np = dev->of_node;
2106*29ea3386SUlf Hansson 
2107*29ea3386SUlf Hansson 	if (!of_device_is_compatible(np, "xlnx,zynqmp-firmware"))
21083da405eaSUlf Hansson 		return;
21093da405eaSUlf Hansson 
2110*29ea3386SUlf Hansson 	of_genpd_sync_state(np);
2111*29ea3386SUlf Hansson 
21123da405eaSUlf Hansson 	if (zynqmp_pm_init_finalize())
21133da405eaSUlf Hansson 		dev_warn(dev, "failed to release power management to firmware\n");
21143da405eaSUlf Hansson }
21153da405eaSUlf Hansson 
211676582671SRajan Vaja static const struct of_device_id zynqmp_firmware_of_match[] = {
211776582671SRajan Vaja 	{.compatible = "xlnx,zynqmp-firmware"},
2118af3f1afaSJolly Shah 	{.compatible = "xlnx,versal-firmware"},
211976582671SRajan Vaja 	{},
212076582671SRajan Vaja };
212176582671SRajan Vaja MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
212276582671SRajan Vaja 
212376582671SRajan Vaja static struct platform_driver zynqmp_firmware_driver = {
212476582671SRajan Vaja 	.driver = {
212576582671SRajan Vaja 		.name = "zynqmp_firmware",
212676582671SRajan Vaja 		.of_match_table = zynqmp_firmware_of_match,
2127ae5c961dSRajan Vaja 		.dev_groups = zynqmp_firmware_groups,
21283da405eaSUlf Hansson 		.sync_state = zynqmp_firmware_sync_state,
212976582671SRajan Vaja 	},
213076582671SRajan Vaja 	.probe = zynqmp_firmware_probe,
21315770e9f2SUwe Kleine-König 	.remove = zynqmp_firmware_remove,
213276582671SRajan Vaja };
213376582671SRajan Vaja module_platform_driver(zynqmp_firmware_driver);
2134