xref: /openbmc/linux/drivers/firmware/xilinx/zynqmp.c (revision 1e400cb9)
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.
676582671SRajan Vaja  *
776582671SRajan Vaja  *  Michal Simek <michal.simek@xilinx.com>
876582671SRajan Vaja  *  Davorin Mista <davorin.mista@aggios.com>
976582671SRajan Vaja  *  Jolly Shah <jollys@xilinx.com>
1076582671SRajan Vaja  *  Rajan Vaja <rajanv@xilinx.com>
1176582671SRajan Vaja  */
1276582671SRajan Vaja 
1376582671SRajan Vaja #include <linux/arm-smccc.h>
1476582671SRajan Vaja #include <linux/compiler.h>
1576582671SRajan Vaja #include <linux/device.h>
1676582671SRajan Vaja #include <linux/init.h>
17e23d9c6dSJolly Shah #include <linux/mfd/core.h>
1876582671SRajan Vaja #include <linux/module.h>
1976582671SRajan Vaja #include <linux/of.h>
2076582671SRajan Vaja #include <linux/of_platform.h>
2176582671SRajan Vaja #include <linux/slab.h>
2276582671SRajan Vaja #include <linux/uaccess.h>
23acfdd185SAmit Sunil Dhamne #include <linux/hashtable.h>
2476582671SRajan Vaja 
2576582671SRajan Vaja #include <linux/firmware/xlnx-zynqmp.h>
26a515814eSAbhyuday Godhasara #include <linux/firmware/xlnx-event-manager.h>
27b3217252SRajan Vaja #include "zynqmp-debug.h"
2876582671SRajan Vaja 
29acfdd185SAmit Sunil Dhamne /* Max HashMap Order for PM API feature check (1<<7 = 128) */
30acfdd185SAmit Sunil Dhamne #define PM_API_FEATURE_CHECK_MAX_ORDER  7
31acfdd185SAmit Sunil Dhamne 
3223c64d76SPiyush Mehta /* CRL registers and bitfields */
3323c64d76SPiyush Mehta #define CRL_APB_BASE			0xFF5E0000U
3423c64d76SPiyush Mehta /* BOOT_PIN_CTRL- Used to control the mode pins after boot */
3523c64d76SPiyush Mehta #define CRL_APB_BOOT_PIN_CTRL		(CRL_APB_BASE + (0x250U))
3623c64d76SPiyush Mehta /* BOOT_PIN_CTRL_MASK- out_val[11:8], out_en[3:0] */
3723c64d76SPiyush Mehta #define CRL_APB_BOOTPIN_CTRL_MASK	0xF0FU
3823c64d76SPiyush Mehta 
39f918cfc0SRonak Jain /* IOCTL/QUERY feature payload size */
40f918cfc0SRonak Jain #define FEATURE_PAYLOAD_SIZE		2
41f918cfc0SRonak Jain 
42f918cfc0SRonak Jain /* Firmware feature check version mask */
43f918cfc0SRonak Jain #define FIRMWARE_VERSION_MASK		GENMASK(15, 0)
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 
50a515814eSAbhyuday Godhasara static struct platform_device *em_dev;
51a515814eSAbhyuday Godhasara 
52acfdd185SAmit Sunil Dhamne /**
532c5d8f7cSRonak Jain  * struct zynqmp_devinfo - Structure for Zynqmp device instance
542c5d8f7cSRonak Jain  * @dev:		Device Pointer
552c5d8f7cSRonak Jain  * @feature_conf_id:	Feature conf id
562c5d8f7cSRonak Jain  */
572c5d8f7cSRonak Jain struct zynqmp_devinfo {
582c5d8f7cSRonak Jain 	struct device *dev;
592c5d8f7cSRonak Jain 	u32 feature_conf_id;
602c5d8f7cSRonak Jain };
612c5d8f7cSRonak Jain 
622c5d8f7cSRonak Jain /**
63acfdd185SAmit Sunil Dhamne  * struct pm_api_feature_data - PM API Feature data
64acfdd185SAmit Sunil Dhamne  * @pm_api_id:		PM API Id, used as key to index into hashmap
65acfdd185SAmit Sunil Dhamne  * @feature_status:	status of PM API feature: valid, invalid
66acfdd185SAmit Sunil Dhamne  * @hentry:		hlist_node that hooks this entry into hashtable
67acfdd185SAmit Sunil Dhamne  */
68acfdd185SAmit Sunil Dhamne struct pm_api_feature_data {
69acfdd185SAmit Sunil Dhamne 	u32 pm_api_id;
70acfdd185SAmit Sunil Dhamne 	int feature_status;
71acfdd185SAmit Sunil Dhamne 	struct hlist_node hentry;
72acfdd185SAmit Sunil Dhamne };
73461011b1SRavi Patel 
74e23d9c6dSJolly Shah static const struct mfd_cell firmware_devs[] = {
75e23d9c6dSJolly Shah 	{
76e23d9c6dSJolly Shah 		.name = "zynqmp_power_controller",
77e23d9c6dSJolly Shah 	},
78e23d9c6dSJolly Shah };
79e23d9c6dSJolly Shah 
8076582671SRajan Vaja /**
8176582671SRajan Vaja  * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
8276582671SRajan Vaja  * @ret_status:		PMUFW return code
8376582671SRajan Vaja  *
8476582671SRajan Vaja  * Return: corresponding Linux error code
8576582671SRajan Vaja  */
8676582671SRajan Vaja static int zynqmp_pm_ret_code(u32 ret_status)
8776582671SRajan Vaja {
8876582671SRajan Vaja 	switch (ret_status) {
8976582671SRajan Vaja 	case XST_PM_SUCCESS:
9076582671SRajan Vaja 	case XST_PM_DOUBLE_REQ:
9176582671SRajan Vaja 		return 0;
92461011b1SRavi Patel 	case XST_PM_NO_FEATURE:
93461011b1SRavi Patel 		return -ENOTSUPP;
9476582671SRajan Vaja 	case XST_PM_NO_ACCESS:
9576582671SRajan Vaja 		return -EACCES;
9676582671SRajan Vaja 	case XST_PM_ABORT_SUSPEND:
9776582671SRajan Vaja 		return -ECANCELED;
98df2a4d94SRajan Vaja 	case XST_PM_MULT_USER:
99df2a4d94SRajan Vaja 		return -EUSERS;
10076582671SRajan Vaja 	case XST_PM_INTERNAL:
10176582671SRajan Vaja 	case XST_PM_CONFLICT:
10276582671SRajan Vaja 	case XST_PM_INVALID_NODE:
10376582671SRajan Vaja 	default:
10476582671SRajan Vaja 		return -EINVAL;
10576582671SRajan Vaja 	}
10676582671SRajan Vaja }
10776582671SRajan Vaja 
10876582671SRajan Vaja static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2,
10976582671SRajan Vaja 				    u32 *ret_payload)
11076582671SRajan Vaja {
11176582671SRajan Vaja 	return -ENODEV;
11276582671SRajan Vaja }
11376582671SRajan Vaja 
11476582671SRajan Vaja /*
11576582671SRajan Vaja  * PM function call wrapper
11676582671SRajan Vaja  * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
11776582671SRajan Vaja  */
11876582671SRajan Vaja static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail;
11976582671SRajan Vaja 
12076582671SRajan Vaja /**
12176582671SRajan Vaja  * do_fw_call_smc() - Call system-level platform management layer (SMC)
12276582671SRajan Vaja  * @arg0:		Argument 0 to SMC call
12376582671SRajan Vaja  * @arg1:		Argument 1 to SMC call
12476582671SRajan Vaja  * @arg2:		Argument 2 to SMC call
12576582671SRajan Vaja  * @ret_payload:	Returned value array
12676582671SRajan Vaja  *
12776582671SRajan Vaja  * Invoke platform management function via SMC call (no hypervisor present).
12876582671SRajan Vaja  *
12976582671SRajan Vaja  * Return: Returns status, either success or error+reason
13076582671SRajan Vaja  */
13176582671SRajan Vaja static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2,
13276582671SRajan Vaja 				   u32 *ret_payload)
13376582671SRajan Vaja {
13476582671SRajan Vaja 	struct arm_smccc_res res;
13576582671SRajan Vaja 
13676582671SRajan Vaja 	arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
13776582671SRajan Vaja 
13876582671SRajan Vaja 	if (ret_payload) {
13976582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
14076582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
14176582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
14276582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
14376582671SRajan Vaja 	}
14476582671SRajan Vaja 
14576582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
14676582671SRajan Vaja }
14776582671SRajan Vaja 
14876582671SRajan Vaja /**
14976582671SRajan Vaja  * do_fw_call_hvc() - Call system-level platform management layer (HVC)
15076582671SRajan Vaja  * @arg0:		Argument 0 to HVC call
15176582671SRajan Vaja  * @arg1:		Argument 1 to HVC call
15276582671SRajan Vaja  * @arg2:		Argument 2 to HVC call
15376582671SRajan Vaja  * @ret_payload:	Returned value array
15476582671SRajan Vaja  *
15576582671SRajan Vaja  * Invoke platform management function via HVC
15676582671SRajan Vaja  * HVC-based for communication through hypervisor
15776582671SRajan Vaja  * (no direct communication with ATF).
15876582671SRajan Vaja  *
15976582671SRajan Vaja  * Return: Returns status, either success or error+reason
16076582671SRajan Vaja  */
16176582671SRajan Vaja static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2,
16276582671SRajan Vaja 				   u32 *ret_payload)
16376582671SRajan Vaja {
16476582671SRajan Vaja 	struct arm_smccc_res res;
16576582671SRajan Vaja 
16676582671SRajan Vaja 	arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
16776582671SRajan Vaja 
16876582671SRajan Vaja 	if (ret_payload) {
16976582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
17076582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
17176582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
17276582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
17376582671SRajan Vaja 	}
17476582671SRajan Vaja 
17576582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
17676582671SRajan Vaja }
17776582671SRajan Vaja 
178218f01a8SRonak Jain static int __do_feature_check_call(const u32 api_id, u32 *ret_payload)
17994ae7f22SRonak Jain {
18094ae7f22SRonak Jain 	int ret;
18194ae7f22SRonak Jain 	u64 smc_arg[2];
18294ae7f22SRonak Jain 
18394ae7f22SRonak Jain 	smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK;
18494ae7f22SRonak Jain 	smc_arg[1] = api_id;
18594ae7f22SRonak Jain 
18694ae7f22SRonak Jain 	ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload);
18794ae7f22SRonak Jain 	if (ret)
18894ae7f22SRonak Jain 		ret = -EOPNOTSUPP;
18994ae7f22SRonak Jain 	else
19094ae7f22SRonak Jain 		ret = ret_payload[1];
19194ae7f22SRonak Jain 
19294ae7f22SRonak Jain 	return ret;
19394ae7f22SRonak Jain }
19494ae7f22SRonak Jain 
195218f01a8SRonak Jain static int do_feature_check_call(const u32 api_id)
196461011b1SRavi Patel {
197461011b1SRavi Patel 	int ret;
198461011b1SRavi Patel 	u32 ret_payload[PAYLOAD_ARG_CNT];
199acfdd185SAmit Sunil Dhamne 	struct pm_api_feature_data *feature_data;
200461011b1SRavi Patel 
201acfdd185SAmit Sunil Dhamne 	/* Check for existing entry in hash table for given api */
202acfdd185SAmit Sunil Dhamne 	hash_for_each_possible(pm_api_features_map, feature_data, hentry,
203acfdd185SAmit Sunil Dhamne 			       api_id) {
204acfdd185SAmit Sunil Dhamne 		if (feature_data->pm_api_id == api_id)
205acfdd185SAmit Sunil Dhamne 			return feature_data->feature_status;
206acfdd185SAmit Sunil Dhamne 	}
207f3217d6fSArnd Bergmann 
208acfdd185SAmit Sunil Dhamne 	/* Add new entry if not present */
209acfdd185SAmit Sunil Dhamne 	feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL);
210acfdd185SAmit Sunil Dhamne 	if (!feature_data)
211acfdd185SAmit Sunil Dhamne 		return -ENOMEM;
212461011b1SRavi Patel 
213acfdd185SAmit Sunil Dhamne 	feature_data->pm_api_id = api_id;
214218f01a8SRonak Jain 	ret = __do_feature_check_call(api_id, ret_payload);
215461011b1SRavi Patel 
216acfdd185SAmit Sunil Dhamne 	feature_data->feature_status = ret;
217acfdd185SAmit Sunil Dhamne 	hash_add(pm_api_features_map, &feature_data->hentry, api_id);
218461011b1SRavi Patel 
219f918cfc0SRonak Jain 	if (api_id == PM_IOCTL)
220f918cfc0SRonak Jain 		/* Store supported IOCTL IDs mask */
221f918cfc0SRonak Jain 		memcpy(ioctl_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
222f918cfc0SRonak Jain 	else if (api_id == PM_QUERY_DATA)
223f918cfc0SRonak Jain 		/* Store supported QUERY IDs mask */
224f918cfc0SRonak Jain 		memcpy(query_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
225f918cfc0SRonak Jain 
226acfdd185SAmit Sunil Dhamne 	return ret;
227461011b1SRavi Patel }
228f4d77525SAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
229461011b1SRavi Patel 
230461011b1SRavi Patel /**
231218f01a8SRonak Jain  * zynqmp_pm_feature() - Check whether given feature is supported or not and
232218f01a8SRonak Jain  *			 store supported IOCTL/QUERY ID mask
233218f01a8SRonak Jain  * @api_id:		API ID to check
234218f01a8SRonak Jain  *
235218f01a8SRonak Jain  * Return: Returns status, either success or error+reason
236218f01a8SRonak Jain  */
237218f01a8SRonak Jain int zynqmp_pm_feature(const u32 api_id)
238218f01a8SRonak Jain {
239218f01a8SRonak Jain 	int ret;
240218f01a8SRonak Jain 
241218f01a8SRonak Jain 	if (!feature_check_enabled)
242218f01a8SRonak Jain 		return 0;
243218f01a8SRonak Jain 
244218f01a8SRonak Jain 	ret = do_feature_check_call(api_id);
245218f01a8SRonak Jain 
246218f01a8SRonak Jain 	return ret;
247218f01a8SRonak Jain }
248218f01a8SRonak Jain 
249218f01a8SRonak Jain /**
250f918cfc0SRonak Jain  * zynqmp_pm_is_function_supported() - Check whether given IOCTL/QUERY function
251f918cfc0SRonak Jain  *				       is supported or not
252f918cfc0SRonak Jain  * @api_id:		PM_IOCTL or PM_QUERY_DATA
253f918cfc0SRonak Jain  * @id:			IOCTL or QUERY function IDs
254f918cfc0SRonak Jain  *
255f918cfc0SRonak Jain  * Return: Returns status, either success or error+reason
256f918cfc0SRonak Jain  */
257f918cfc0SRonak Jain int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
258f918cfc0SRonak Jain {
259f918cfc0SRonak Jain 	int ret;
260f918cfc0SRonak Jain 	u32 *bit_mask;
261f918cfc0SRonak Jain 
262f918cfc0SRonak Jain 	/* Input arguments validation */
263f918cfc0SRonak Jain 	if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA))
264f918cfc0SRonak Jain 		return -EINVAL;
265f918cfc0SRonak Jain 
266f918cfc0SRonak Jain 	/* Check feature check API version */
267218f01a8SRonak Jain 	ret = do_feature_check_call(PM_FEATURE_CHECK);
268f918cfc0SRonak Jain 	if (ret < 0)
269f918cfc0SRonak Jain 		return ret;
270f918cfc0SRonak Jain 
271f918cfc0SRonak Jain 	/* Check if feature check version 2 is supported or not */
272f918cfc0SRonak Jain 	if ((ret & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) {
273f918cfc0SRonak Jain 		/*
274f918cfc0SRonak Jain 		 * Call feature check for IOCTL/QUERY API to get IOCTL ID or
275f918cfc0SRonak Jain 		 * QUERY ID feature status.
276f918cfc0SRonak Jain 		 */
277218f01a8SRonak Jain 		ret = do_feature_check_call(api_id);
278f918cfc0SRonak Jain 		if (ret < 0)
279f918cfc0SRonak Jain 			return ret;
280f918cfc0SRonak Jain 
281f918cfc0SRonak Jain 		bit_mask = (api_id == PM_IOCTL) ? ioctl_features : query_features;
282f918cfc0SRonak Jain 
283f918cfc0SRonak Jain 		if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0U)
284f918cfc0SRonak Jain 			return -EOPNOTSUPP;
285f918cfc0SRonak Jain 	} else {
286f918cfc0SRonak Jain 		return -ENODATA;
287f918cfc0SRonak Jain 	}
288f918cfc0SRonak Jain 
289f918cfc0SRonak Jain 	return 0;
290f918cfc0SRonak Jain }
291f918cfc0SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported);
292f918cfc0SRonak Jain 
293f918cfc0SRonak Jain /**
29476582671SRajan Vaja  * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
29576582671SRajan Vaja  *			   caller function depending on the configuration
29676582671SRajan Vaja  * @pm_api_id:		Requested PM-API call
29776582671SRajan Vaja  * @arg0:		Argument 0 to requested PM-API call
29876582671SRajan Vaja  * @arg1:		Argument 1 to requested PM-API call
29976582671SRajan Vaja  * @arg2:		Argument 2 to requested PM-API call
30076582671SRajan Vaja  * @arg3:		Argument 3 to requested PM-API call
30176582671SRajan Vaja  * @ret_payload:	Returned value array
30276582671SRajan Vaja  *
30376582671SRajan Vaja  * Invoke platform management function for SMC or HVC call, depending on
30476582671SRajan Vaja  * configuration.
30576582671SRajan Vaja  * Following SMC Calling Convention (SMCCC) for SMC64:
30676582671SRajan Vaja  * Pm Function Identifier,
30776582671SRajan Vaja  * PM_SIP_SVC + PM_API_ID =
30876582671SRajan Vaja  *	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
30976582671SRajan Vaja  *	((SMC_64) << FUNCID_CC_SHIFT)
31076582671SRajan Vaja  *	((SIP_START) << FUNCID_OEN_SHIFT)
31176582671SRajan Vaja  *	((PM_API_ID) & FUNCID_NUM_MASK))
31276582671SRajan Vaja  *
31376582671SRajan Vaja  * PM_SIP_SVC	- Registered ZynqMP SIP Service Call.
31476582671SRajan Vaja  * PM_API_ID	- Platform Management API ID.
31576582671SRajan Vaja  *
31676582671SRajan Vaja  * Return: Returns status, either success or error+reason
31776582671SRajan Vaja  */
31876582671SRajan Vaja int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
31976582671SRajan Vaja 			u32 arg2, u32 arg3, u32 *ret_payload)
32076582671SRajan Vaja {
32176582671SRajan Vaja 	/*
32276582671SRajan Vaja 	 * Added SIP service call Function Identifier
32376582671SRajan Vaja 	 * Make sure to stay in x0 register
32476582671SRajan Vaja 	 */
32576582671SRajan Vaja 	u64 smc_arg[4];
326acfdd185SAmit Sunil Dhamne 	int ret;
32776582671SRajan Vaja 
328acfdd185SAmit Sunil Dhamne 	/* Check if feature is supported or not */
329acfdd185SAmit Sunil Dhamne 	ret = zynqmp_pm_feature(pm_api_id);
330acfdd185SAmit Sunil Dhamne 	if (ret < 0)
331acfdd185SAmit Sunil Dhamne 		return ret;
332461011b1SRavi Patel 
33376582671SRajan Vaja 	smc_arg[0] = PM_SIP_SVC | pm_api_id;
33476582671SRajan Vaja 	smc_arg[1] = ((u64)arg1 << 32) | arg0;
33576582671SRajan Vaja 	smc_arg[2] = ((u64)arg3 << 32) | arg2;
33676582671SRajan Vaja 
33776582671SRajan Vaja 	return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload);
33876582671SRajan Vaja }
33976582671SRajan Vaja 
34076582671SRajan Vaja static u32 pm_api_version;
34176582671SRajan Vaja static u32 pm_tz_version;
34276582671SRajan Vaja 
343acd6510dSTanmay Shah int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset)
344acd6510dSTanmay Shah {
345acd6510dSTanmay Shah 	int ret;
346acd6510dSTanmay Shah 
347acd6510dSTanmay Shah 	ret = zynqmp_pm_invoke_fn(TF_A_PM_REGISTER_SGI, sgi_num, reset, 0, 0,
348acd6510dSTanmay Shah 				  NULL);
349acd6510dSTanmay Shah 	if (!ret)
350acd6510dSTanmay Shah 		return ret;
351acd6510dSTanmay Shah 
352acd6510dSTanmay Shah 	/* try old implementation as fallback strategy if above fails */
353acd6510dSTanmay Shah 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_REGISTER_SGI, sgi_num,
354acd6510dSTanmay Shah 				   reset, NULL);
355acd6510dSTanmay Shah }
356acd6510dSTanmay Shah 
35776582671SRajan Vaja /**
35876582671SRajan Vaja  * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
35976582671SRajan Vaja  * @version:	Returned version value
36076582671SRajan Vaja  *
36176582671SRajan Vaja  * Return: Returns status, either success or error+reason
36276582671SRajan Vaja  */
363b9b3a8beSRajan Vaja int zynqmp_pm_get_api_version(u32 *version)
36476582671SRajan Vaja {
36576582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
36676582671SRajan Vaja 	int ret;
36776582671SRajan Vaja 
36876582671SRajan Vaja 	if (!version)
36976582671SRajan Vaja 		return -EINVAL;
37076582671SRajan Vaja 
37176582671SRajan Vaja 	/* Check is PM API version already verified */
37276582671SRajan Vaja 	if (pm_api_version > 0) {
37376582671SRajan Vaja 		*version = pm_api_version;
37476582671SRajan Vaja 		return 0;
37576582671SRajan Vaja 	}
37676582671SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload);
37776582671SRajan Vaja 	*version = ret_payload[1];
37876582671SRajan Vaja 
37976582671SRajan Vaja 	return ret;
38076582671SRajan Vaja }
381b9b3a8beSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
38276582671SRajan Vaja 
38376582671SRajan Vaja /**
384fe6f42cfSNava kishore Manne  * zynqmp_pm_get_chipid - Get silicon ID registers
385fe6f42cfSNava kishore Manne  * @idcode:     IDCODE register
386fe6f42cfSNava kishore Manne  * @version:    version register
387fe6f42cfSNava kishore Manne  *
388fe6f42cfSNava kishore Manne  * Return:      Returns the status of the operation and the idcode and version
389fe6f42cfSNava kishore Manne  *              registers in @idcode and @version.
390fe6f42cfSNava kishore Manne  */
39121cd93baSRajan Vaja int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
392fe6f42cfSNava kishore Manne {
393fe6f42cfSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
394fe6f42cfSNava kishore Manne 	int ret;
395fe6f42cfSNava kishore Manne 
396fe6f42cfSNava kishore Manne 	if (!idcode || !version)
397fe6f42cfSNava kishore Manne 		return -EINVAL;
398fe6f42cfSNava kishore Manne 
399fe6f42cfSNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
400fe6f42cfSNava kishore Manne 	*idcode = ret_payload[1];
401fe6f42cfSNava kishore Manne 	*version = ret_payload[2];
402fe6f42cfSNava kishore Manne 
403fe6f42cfSNava kishore Manne 	return ret;
404fe6f42cfSNava kishore Manne }
40521cd93baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
406fe6f42cfSNava kishore Manne 
407fe6f42cfSNava kishore Manne /**
40876582671SRajan Vaja  * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
40976582671SRajan Vaja  * @version:	Returned version value
41076582671SRajan Vaja  *
41176582671SRajan Vaja  * Return: Returns status, either success or error+reason
41276582671SRajan Vaja  */
41376582671SRajan Vaja static int zynqmp_pm_get_trustzone_version(u32 *version)
41476582671SRajan Vaja {
41576582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
41676582671SRajan Vaja 	int ret;
41776582671SRajan Vaja 
41876582671SRajan Vaja 	if (!version)
41976582671SRajan Vaja 		return -EINVAL;
42076582671SRajan Vaja 
42176582671SRajan Vaja 	/* Check is PM trustzone version already verified */
42276582671SRajan Vaja 	if (pm_tz_version > 0) {
42376582671SRajan Vaja 		*version = pm_tz_version;
42476582671SRajan Vaja 		return 0;
42576582671SRajan Vaja 	}
42676582671SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0,
42776582671SRajan Vaja 				  0, 0, ret_payload);
42876582671SRajan Vaja 	*version = ret_payload[1];
42976582671SRajan Vaja 
43076582671SRajan Vaja 	return ret;
43176582671SRajan Vaja }
43276582671SRajan Vaja 
43376582671SRajan Vaja /**
43476582671SRajan Vaja  * get_set_conduit_method() - Choose SMC or HVC based communication
43576582671SRajan Vaja  * @np:		Pointer to the device_node structure
43676582671SRajan Vaja  *
43776582671SRajan Vaja  * Use SMC or HVC-based functions to communicate with EL2/EL3.
43876582671SRajan Vaja  *
43976582671SRajan Vaja  * Return: Returns 0 on success or error code
44076582671SRajan Vaja  */
44176582671SRajan Vaja static int get_set_conduit_method(struct device_node *np)
44276582671SRajan Vaja {
44376582671SRajan Vaja 	const char *method;
44476582671SRajan Vaja 
44576582671SRajan Vaja 	if (of_property_read_string(np, "method", &method)) {
44676582671SRajan Vaja 		pr_warn("%s missing \"method\" property\n", __func__);
44776582671SRajan Vaja 		return -ENXIO;
44876582671SRajan Vaja 	}
44976582671SRajan Vaja 
45076582671SRajan Vaja 	if (!strcmp("hvc", method)) {
45176582671SRajan Vaja 		do_fw_call = do_fw_call_hvc;
45276582671SRajan Vaja 	} else if (!strcmp("smc", method)) {
45376582671SRajan Vaja 		do_fw_call = do_fw_call_smc;
45476582671SRajan Vaja 	} else {
45576582671SRajan Vaja 		pr_warn("%s Invalid \"method\" property: %s\n",
45676582671SRajan Vaja 			__func__, method);
45776582671SRajan Vaja 		return -EINVAL;
45876582671SRajan Vaja 	}
45976582671SRajan Vaja 
46076582671SRajan Vaja 	return 0;
46176582671SRajan Vaja }
46276582671SRajan Vaja 
46359ecdd77SRajan Vaja /**
46459ecdd77SRajan Vaja  * zynqmp_pm_query_data() - Get query data from firmware
46559ecdd77SRajan Vaja  * @qdata:	Variable to the zynqmp_pm_query_data structure
46659ecdd77SRajan Vaja  * @out:	Returned output value
46759ecdd77SRajan Vaja  *
46859ecdd77SRajan Vaja  * Return: Returns status, either success or error+reason
46959ecdd77SRajan Vaja  */
4706366c1baSRajan Vaja int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
47159ecdd77SRajan Vaja {
472f9627312SRajan Vaja 	int ret;
473f9627312SRajan Vaja 
474f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1,
47559ecdd77SRajan Vaja 				  qdata.arg2, qdata.arg3, out);
476f9627312SRajan Vaja 
477f9627312SRajan Vaja 	/*
478f9627312SRajan Vaja 	 * For clock name query, all bytes in SMC response are clock name
479f9627312SRajan Vaja 	 * characters and return code is always success. For invalid clocks,
480f9627312SRajan Vaja 	 * clock name bytes would be zeros.
481f9627312SRajan Vaja 	 */
482f9627312SRajan Vaja 	return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
483f9627312SRajan Vaja }
4846366c1baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
485f9627312SRajan Vaja 
486f9627312SRajan Vaja /**
487f9627312SRajan Vaja  * zynqmp_pm_clock_enable() - Enable the clock for given id
488f9627312SRajan Vaja  * @clock_id:	ID of the clock to be enabled
489f9627312SRajan Vaja  *
490f9627312SRajan Vaja  * This function is used by master to enable the clock
491f9627312SRajan Vaja  * including peripherals and PLL clocks.
492f9627312SRajan Vaja  *
493f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
494f9627312SRajan Vaja  */
4953637e84cSRajan Vaja int zynqmp_pm_clock_enable(u32 clock_id)
496f9627312SRajan Vaja {
497f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
498f9627312SRajan Vaja }
4993637e84cSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
500f9627312SRajan Vaja 
501f9627312SRajan Vaja /**
502f9627312SRajan Vaja  * zynqmp_pm_clock_disable() - Disable the clock for given id
503f9627312SRajan Vaja  * @clock_id:	ID of the clock to be disable
504f9627312SRajan Vaja  *
505f9627312SRajan Vaja  * This function is used by master to disable the clock
506f9627312SRajan Vaja  * including peripherals and PLL clocks.
507f9627312SRajan Vaja  *
508f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
509f9627312SRajan Vaja  */
510f5ccd54bSRajan Vaja int zynqmp_pm_clock_disable(u32 clock_id)
511f9627312SRajan Vaja {
512f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
513f9627312SRajan Vaja }
514f5ccd54bSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
515f9627312SRajan Vaja 
516f9627312SRajan Vaja /**
517f9627312SRajan Vaja  * zynqmp_pm_clock_getstate() - Get the clock state for given id
518f9627312SRajan Vaja  * @clock_id:	ID of the clock to be queried
519f9627312SRajan Vaja  * @state:	1/0 (Enabled/Disabled)
520f9627312SRajan Vaja  *
521f9627312SRajan Vaja  * This function is used by master to get the state of clock
522f9627312SRajan Vaja  * including peripherals and PLL clocks.
523f9627312SRajan Vaja  *
524f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
525f9627312SRajan Vaja  */
5265e76731dSRajan Vaja int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
527f9627312SRajan Vaja {
528f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
529f9627312SRajan Vaja 	int ret;
530f9627312SRajan Vaja 
531f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0,
532f9627312SRajan Vaja 				  0, 0, ret_payload);
533f9627312SRajan Vaja 	*state = ret_payload[1];
534f9627312SRajan Vaja 
535f9627312SRajan Vaja 	return ret;
536f9627312SRajan Vaja }
5375e76731dSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
538f9627312SRajan Vaja 
539f9627312SRajan Vaja /**
540f9627312SRajan Vaja  * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
541f9627312SRajan Vaja  * @clock_id:	ID of the clock
542f9627312SRajan Vaja  * @divider:	divider value
543f9627312SRajan Vaja  *
544f9627312SRajan Vaja  * This function is used by master to set divider for any clock
545f9627312SRajan Vaja  * to achieve desired rate.
546f9627312SRajan Vaja  *
547f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
548f9627312SRajan Vaja  */
549fc9fb8fbSRajan Vaja int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
550f9627312SRajan Vaja {
551f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
552f9627312SRajan Vaja 				   0, 0, NULL);
553f9627312SRajan Vaja }
554fc9fb8fbSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
555f9627312SRajan Vaja 
556f9627312SRajan Vaja /**
557f9627312SRajan Vaja  * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
558f9627312SRajan Vaja  * @clock_id:	ID of the clock
559f9627312SRajan Vaja  * @divider:	divider value
560f9627312SRajan Vaja  *
561f9627312SRajan Vaja  * This function is used by master to get divider values
562f9627312SRajan Vaja  * for any clock.
563f9627312SRajan Vaja  *
564f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
565f9627312SRajan Vaja  */
5660667a8d1SRajan Vaja int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
567f9627312SRajan Vaja {
568f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
569f9627312SRajan Vaja 	int ret;
570f9627312SRajan Vaja 
571f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0,
572f9627312SRajan Vaja 				  0, 0, ret_payload);
573f9627312SRajan Vaja 	*divider = ret_payload[1];
574f9627312SRajan Vaja 
575f9627312SRajan Vaja 	return ret;
576f9627312SRajan Vaja }
5770667a8d1SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
578f9627312SRajan Vaja 
579f9627312SRajan Vaja /**
580f9627312SRajan Vaja  * zynqmp_pm_clock_setrate() - Set the clock rate for given id
581f9627312SRajan Vaja  * @clock_id:	ID of the clock
582f9627312SRajan Vaja  * @rate:	rate value in hz
583f9627312SRajan Vaja  *
584f9627312SRajan Vaja  * This function is used by master to set rate for any clock.
585f9627312SRajan Vaja  *
586f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
587f9627312SRajan Vaja  */
5887a1e1062SRajan Vaja int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
589f9627312SRajan Vaja {
590f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
591f9627312SRajan Vaja 				   lower_32_bits(rate),
592f9627312SRajan Vaja 				   upper_32_bits(rate),
593f9627312SRajan Vaja 				   0, NULL);
594f9627312SRajan Vaja }
5957a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate);
596f9627312SRajan Vaja 
597f9627312SRajan Vaja /**
598f9627312SRajan Vaja  * zynqmp_pm_clock_getrate() - Get the clock rate for given id
599f9627312SRajan Vaja  * @clock_id:	ID of the clock
600f9627312SRajan Vaja  * @rate:	rate value in hz
601f9627312SRajan Vaja  *
602f9627312SRajan Vaja  * This function is used by master to get rate
603f9627312SRajan Vaja  * for any clock.
604f9627312SRajan Vaja  *
605f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
606f9627312SRajan Vaja  */
6077a1e1062SRajan Vaja int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
608f9627312SRajan Vaja {
609f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
610f9627312SRajan Vaja 	int ret;
611f9627312SRajan Vaja 
612f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0,
613f9627312SRajan Vaja 				  0, 0, ret_payload);
614f9627312SRajan Vaja 	*rate = ((u64)ret_payload[2] << 32) | ret_payload[1];
615f9627312SRajan Vaja 
616f9627312SRajan Vaja 	return ret;
617f9627312SRajan Vaja }
6187a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate);
619f9627312SRajan Vaja 
620f9627312SRajan Vaja /**
621f9627312SRajan Vaja  * zynqmp_pm_clock_setparent() - Set the clock parent for given id
622f9627312SRajan Vaja  * @clock_id:	ID of the clock
623f9627312SRajan Vaja  * @parent_id:	parent id
624f9627312SRajan Vaja  *
625f9627312SRajan Vaja  * This function is used by master to set parent for any clock.
626f9627312SRajan Vaja  *
627f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
628f9627312SRajan Vaja  */
62970c0d364SRajan Vaja int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
630f9627312SRajan Vaja {
631f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
632f9627312SRajan Vaja 				   parent_id, 0, 0, NULL);
633f9627312SRajan Vaja }
63470c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
635f9627312SRajan Vaja 
636f9627312SRajan Vaja /**
637f9627312SRajan Vaja  * zynqmp_pm_clock_getparent() - Get the clock parent for given id
638f9627312SRajan Vaja  * @clock_id:	ID of the clock
639f9627312SRajan Vaja  * @parent_id:	parent id
640f9627312SRajan Vaja  *
641f9627312SRajan Vaja  * This function is used by master to get parent index
642f9627312SRajan Vaja  * for any clock.
643f9627312SRajan Vaja  *
644f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
645f9627312SRajan Vaja  */
64670c0d364SRajan Vaja int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
647f9627312SRajan Vaja {
648f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
649f9627312SRajan Vaja 	int ret;
650f9627312SRajan Vaja 
651f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0,
652f9627312SRajan Vaja 				  0, 0, ret_payload);
653f9627312SRajan Vaja 	*parent_id = ret_payload[1];
654f9627312SRajan Vaja 
655f9627312SRajan Vaja 	return ret;
65659ecdd77SRajan Vaja }
65770c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
65859ecdd77SRajan Vaja 
6593b0296b8SRajan Vaja /**
660426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
6613b0296b8SRajan Vaja  *
662426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
663426c8d85SRajan Vaja  * @mode:	PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
6643b0296b8SRajan Vaja  *
665426c8d85SRajan Vaja  * This function sets PLL mode
6663b0296b8SRajan Vaja  *
6673b0296b8SRajan Vaja  * Return: Returns status, either success or error+reason
6683b0296b8SRajan Vaja  */
669426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
6703b0296b8SRajan Vaja {
671426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE,
672426c8d85SRajan Vaja 				   clk_id, mode, NULL);
6733b0296b8SRajan Vaja }
674426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
675426c8d85SRajan Vaja 
676426c8d85SRajan Vaja /**
677426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
678426c8d85SRajan Vaja  *
679426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
680426c8d85SRajan Vaja  * @mode:	PLL mode
681426c8d85SRajan Vaja  *
682426c8d85SRajan Vaja  * This function return current PLL mode
683426c8d85SRajan Vaja  *
684426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
685426c8d85SRajan Vaja  */
686426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
687426c8d85SRajan Vaja {
688426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE,
689426c8d85SRajan Vaja 				   clk_id, 0, mode);
690426c8d85SRajan Vaja }
691426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
692426c8d85SRajan Vaja 
693426c8d85SRajan Vaja /**
694426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
695426c8d85SRajan Vaja  *
696426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
697426c8d85SRajan Vaja  * @data:	fraction data
698426c8d85SRajan Vaja  *
699426c8d85SRajan Vaja  * This function sets fraction data.
700426c8d85SRajan Vaja  * It is valid for fraction mode only.
701426c8d85SRajan Vaja  *
702426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
703426c8d85SRajan Vaja  */
704426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
705426c8d85SRajan Vaja {
706426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA,
707426c8d85SRajan Vaja 				   clk_id, data, NULL);
708426c8d85SRajan Vaja }
709426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
710426c8d85SRajan Vaja 
711426c8d85SRajan Vaja /**
712426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
713426c8d85SRajan Vaja  *
714426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
715426c8d85SRajan Vaja  * @data:	fraction data
716426c8d85SRajan Vaja  *
717426c8d85SRajan Vaja  * This function returns fraction data value.
718426c8d85SRajan Vaja  *
719426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
720426c8d85SRajan Vaja  */
721426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
722426c8d85SRajan Vaja {
723426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA,
724426c8d85SRajan Vaja 				   clk_id, 0, data);
725426c8d85SRajan Vaja }
726426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
727426c8d85SRajan Vaja 
728426c8d85SRajan Vaja /**
729426c8d85SRajan Vaja  * zynqmp_pm_set_sd_tapdelay() -  Set tap delay for the SD device
730426c8d85SRajan Vaja  *
731332bee16SMichal Simek  * @node_id:	Node ID of the device
732332bee16SMichal Simek  * @type:	Type of tap delay to set (input/output)
733332bee16SMichal Simek  * @value:	Value to set fot the tap delay
734426c8d85SRajan Vaja  *
735426c8d85SRajan Vaja  * This function sets input/output tap delay for the SD device.
736426c8d85SRajan Vaja  *
737332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
738426c8d85SRajan Vaja  */
739426c8d85SRajan Vaja int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
740426c8d85SRajan Vaja {
741426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
742426c8d85SRajan Vaja 				   type, value, NULL);
743426c8d85SRajan Vaja }
744426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
745426c8d85SRajan Vaja 
746426c8d85SRajan Vaja /**
747426c8d85SRajan Vaja  * zynqmp_pm_sd_dll_reset() - Reset DLL logic
748426c8d85SRajan Vaja  *
749332bee16SMichal Simek  * @node_id:	Node ID of the device
750332bee16SMichal Simek  * @type:	Reset type
751426c8d85SRajan Vaja  *
752426c8d85SRajan Vaja  * This function resets DLL logic for the SD device.
753426c8d85SRajan Vaja  *
754332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
755426c8d85SRajan Vaja  */
756426c8d85SRajan Vaja int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
757426c8d85SRajan Vaja {
758f4426311SManish Narani 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET,
759426c8d85SRajan Vaja 				   type, 0, NULL);
760426c8d85SRajan Vaja }
761426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
7623b0296b8SRajan Vaja 
763bc3843d4SNava kishore Manne /**
76474e78adcSSai Krishna Potthuri  * zynqmp_pm_ospi_mux_select() - OSPI Mux selection
76574e78adcSSai Krishna Potthuri  *
76674e78adcSSai Krishna Potthuri  * @dev_id:	Device Id of the OSPI device.
76774e78adcSSai Krishna Potthuri  * @select:	OSPI Mux select value.
76874e78adcSSai Krishna Potthuri  *
76974e78adcSSai Krishna Potthuri  * This function select the OSPI Mux.
77074e78adcSSai Krishna Potthuri  *
77174e78adcSSai Krishna Potthuri  * Return:	Returns status, either success or error+reason
77274e78adcSSai Krishna Potthuri  */
77374e78adcSSai Krishna Potthuri int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
77474e78adcSSai Krishna Potthuri {
77574e78adcSSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_IOCTL, dev_id, IOCTL_OSPI_MUX_SELECT,
77674e78adcSSai Krishna Potthuri 				   select, 0, NULL);
77774e78adcSSai Krishna Potthuri }
77874e78adcSSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select);
77974e78adcSSai Krishna Potthuri 
78074e78adcSSai Krishna Potthuri /**
7814f680b72SRajan Vaja  * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
782332bee16SMichal Simek  * @index:	GGS register index
783332bee16SMichal Simek  * @value:	Register value to be written
7844f680b72SRajan Vaja  *
7854f680b72SRajan Vaja  * This function writes value to GGS register.
7864f680b72SRajan Vaja  *
787332bee16SMichal Simek  * Return:      Returns status, either success or error+reason
7884f680b72SRajan Vaja  */
7894f680b72SRajan Vaja int zynqmp_pm_write_ggs(u32 index, u32 value)
7904f680b72SRajan Vaja {
7914f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS,
7924f680b72SRajan Vaja 				   index, value, NULL);
7934f680b72SRajan Vaja }
7944f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
7954f680b72SRajan Vaja 
7964f680b72SRajan Vaja /**
7972a8faf8dSMichal Simek  * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs)
798332bee16SMichal Simek  * @index:	GGS register index
799332bee16SMichal Simek  * @value:	Register value to be written
8004f680b72SRajan Vaja  *
8014f680b72SRajan Vaja  * This function returns GGS register value.
8024f680b72SRajan Vaja  *
803332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
8044f680b72SRajan Vaja  */
8054f680b72SRajan Vaja int zynqmp_pm_read_ggs(u32 index, u32 *value)
8064f680b72SRajan Vaja {
8074f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS,
8084f680b72SRajan Vaja 				   index, 0, value);
8094f680b72SRajan Vaja }
8104f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
8114f680b72SRajan Vaja 
8124f680b72SRajan Vaja /**
8134f680b72SRajan Vaja  * zynqmp_pm_write_pggs() - PM API for writing persistent global general
8144f680b72SRajan Vaja  *			     storage (pggs)
815332bee16SMichal Simek  * @index:	PGGS register index
816332bee16SMichal Simek  * @value:	Register value to be written
8174f680b72SRajan Vaja  *
8184f680b72SRajan Vaja  * This function writes value to PGGS register.
8194f680b72SRajan Vaja  *
820332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
8214f680b72SRajan Vaja  */
8224f680b72SRajan Vaja int zynqmp_pm_write_pggs(u32 index, u32 value)
8234f680b72SRajan Vaja {
8244f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value,
8254f680b72SRajan Vaja 				   NULL);
8264f680b72SRajan Vaja }
8274f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
8284f680b72SRajan Vaja 
8294f680b72SRajan Vaja /**
8302a8faf8dSMichal Simek  * zynqmp_pm_read_pggs() - PM API for reading persistent global general
8314f680b72SRajan Vaja  *			     storage (pggs)
832332bee16SMichal Simek  * @index:	PGGS register index
833332bee16SMichal Simek  * @value:	Register value to be written
8344f680b72SRajan Vaja  *
8354f680b72SRajan Vaja  * This function returns PGGS register value.
8364f680b72SRajan Vaja  *
837332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
8384f680b72SRajan Vaja  */
8394f680b72SRajan Vaja int zynqmp_pm_read_pggs(u32 index, u32 *value)
8404f680b72SRajan Vaja {
8414f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0,
8424f680b72SRajan Vaja 				   value);
8434f680b72SRajan Vaja }
8444f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
8454f680b72SRajan Vaja 
846*1e400cb9SRajan Vaja int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value)
847*1e400cb9SRajan Vaja {
848*1e400cb9SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_TAPDELAY_BYPASS,
849*1e400cb9SRajan Vaja 				   index, value, NULL);
850*1e400cb9SRajan Vaja }
851*1e400cb9SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass);
852*1e400cb9SRajan Vaja 
8534f680b72SRajan Vaja /**
854a2cc220aSRajan Vaja  * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
855332bee16SMichal Simek  * @value:	Status value to be written
856a2cc220aSRajan Vaja  *
857a2cc220aSRajan Vaja  * This function sets healthy bit value to indicate boot health status
858a2cc220aSRajan Vaja  * to firmware.
859a2cc220aSRajan Vaja  *
860332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
861a2cc220aSRajan Vaja  */
862a2cc220aSRajan Vaja int zynqmp_pm_set_boot_health_status(u32 value)
863a2cc220aSRajan Vaja {
864a2cc220aSRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS,
865a2cc220aSRajan Vaja 				   value, 0, NULL);
866a2cc220aSRajan Vaja }
867a2cc220aSRajan Vaja 
868a2cc220aSRajan Vaja /**
869bc3843d4SNava kishore Manne  * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
870bc3843d4SNava kishore Manne  * @reset:		Reset to be configured
871bc3843d4SNava kishore Manne  * @assert_flag:	Flag stating should reset be asserted (1) or
872bc3843d4SNava kishore Manne  *			released (0)
873bc3843d4SNava kishore Manne  *
874bc3843d4SNava kishore Manne  * Return: Returns status, either success or error+reason
875bc3843d4SNava kishore Manne  */
876cf23ec35SRajan Vaja int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
877bc3843d4SNava kishore Manne 			   const enum zynqmp_pm_reset_action assert_flag)
878bc3843d4SNava kishore Manne {
879bc3843d4SNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
880bc3843d4SNava kishore Manne 				   0, 0, NULL);
881bc3843d4SNava kishore Manne }
882cf23ec35SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
883bc3843d4SNava kishore Manne 
884bc3843d4SNava kishore Manne /**
885bc3843d4SNava kishore Manne  * zynqmp_pm_reset_get_status - Get status of the reset
886bc3843d4SNava kishore Manne  * @reset:      Reset whose status should be returned
887bc3843d4SNava kishore Manne  * @status:     Returned status
888bc3843d4SNava kishore Manne  *
889bc3843d4SNava kishore Manne  * Return: Returns status, either success or error+reason
890bc3843d4SNava kishore Manne  */
8911b413581SRajan Vaja int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
892bc3843d4SNava kishore Manne {
893bc3843d4SNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
894bc3843d4SNava kishore Manne 	int ret;
895bc3843d4SNava kishore Manne 
896bc3843d4SNava kishore Manne 	if (!status)
897bc3843d4SNava kishore Manne 		return -EINVAL;
898bc3843d4SNava kishore Manne 
899bc3843d4SNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
900bc3843d4SNava kishore Manne 				  0, 0, ret_payload);
901bc3843d4SNava kishore Manne 	*status = ret_payload[1];
902bc3843d4SNava kishore Manne 
903bc3843d4SNava kishore Manne 	return ret;
904bc3843d4SNava kishore Manne }
9051b413581SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
906bc3843d4SNava kishore Manne 
907e178df31SJolly Shah /**
908e840deccSNava kishore Manne  * zynqmp_pm_fpga_load - Perform the fpga load
909e840deccSNava kishore Manne  * @address:	Address to write to
910e840deccSNava kishore Manne  * @size:	pl bitstream size
911e840deccSNava kishore Manne  * @flags:	Bitstream type
912e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
913e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
914e840deccSNava kishore Manne  *
915e840deccSNava kishore Manne  * This function provides access to pmufw. To transfer
916e840deccSNava kishore Manne  * the required bitstream into PL.
917e840deccSNava kishore Manne  *
918e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
919e840deccSNava kishore Manne  */
9204db8180fSRajan Vaja int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
921e840deccSNava kishore Manne {
922e840deccSNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
923e840deccSNava kishore Manne 				   upper_32_bits(address), size, flags, NULL);
924e840deccSNava kishore Manne }
92556a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
926e840deccSNava kishore Manne 
927e840deccSNava kishore Manne /**
928e840deccSNava kishore Manne  * zynqmp_pm_fpga_get_status - Read value from PCAP status register
929e840deccSNava kishore Manne  * @value: Value to read
930e840deccSNava kishore Manne  *
931e840deccSNava kishore Manne  * This function provides access to the pmufw to get the PCAP
932e840deccSNava kishore Manne  * status
933e840deccSNava kishore Manne  *
934e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
935e840deccSNava kishore Manne  */
9364db8180fSRajan Vaja int zynqmp_pm_fpga_get_status(u32 *value)
937e840deccSNava kishore Manne {
938e840deccSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
939e840deccSNava kishore Manne 	int ret;
940e840deccSNava kishore Manne 
941e840deccSNava kishore Manne 	if (!value)
942e840deccSNava kishore Manne 		return -EINVAL;
943e840deccSNava kishore Manne 
944e840deccSNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
945e840deccSNava kishore Manne 	*value = ret_payload[1];
946e840deccSNava kishore Manne 
947e840deccSNava kishore Manne 	return ret;
948e840deccSNava kishore Manne }
94956a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
950e840deccSNava kishore Manne 
951e840deccSNava kishore Manne /**
952fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_request - Request Pin from firmware
953fa989ae7SSai Krishna Potthuri  * @pin: Pin number to request
954fa989ae7SSai Krishna Potthuri  *
955fa989ae7SSai Krishna Potthuri  * This function requests pin from firmware.
956fa989ae7SSai Krishna Potthuri  *
957fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
958fa989ae7SSai Krishna Potthuri  */
959fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_request(const u32 pin)
960fa989ae7SSai Krishna Potthuri {
961fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
962fa989ae7SSai Krishna Potthuri }
963fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request);
964fa989ae7SSai Krishna Potthuri 
965fa989ae7SSai Krishna Potthuri /**
966fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
967fa989ae7SSai Krishna Potthuri  * @pin: Pin number to release
968fa989ae7SSai Krishna Potthuri  *
969fa989ae7SSai Krishna Potthuri  * This function release pin from firmware.
970fa989ae7SSai Krishna Potthuri  *
971fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
972fa989ae7SSai Krishna Potthuri  */
973fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_release(const u32 pin)
974fa989ae7SSai Krishna Potthuri {
975fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL);
976fa989ae7SSai Krishna Potthuri }
977fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release);
978fa989ae7SSai Krishna Potthuri 
979fa989ae7SSai Krishna Potthuri /**
980fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin
981fa989ae7SSai Krishna Potthuri  * @pin: Pin number
982fa989ae7SSai Krishna Potthuri  * @id: Buffer to store function ID
983fa989ae7SSai Krishna Potthuri  *
984fa989ae7SSai Krishna Potthuri  * This function provides the function currently set for the given pin.
985fa989ae7SSai Krishna Potthuri  *
986fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason
987fa989ae7SSai Krishna Potthuri  */
988fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id)
989fa989ae7SSai Krishna Potthuri {
990fa989ae7SSai Krishna Potthuri 	u32 ret_payload[PAYLOAD_ARG_CNT];
991fa989ae7SSai Krishna Potthuri 	int ret;
992fa989ae7SSai Krishna Potthuri 
993fa989ae7SSai Krishna Potthuri 	if (!id)
994fa989ae7SSai Krishna Potthuri 		return -EINVAL;
995fa989ae7SSai Krishna Potthuri 
996fa989ae7SSai Krishna Potthuri 	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0,
997fa989ae7SSai Krishna Potthuri 				  0, 0, ret_payload);
998fa989ae7SSai Krishna Potthuri 	*id = ret_payload[1];
999fa989ae7SSai Krishna Potthuri 
1000fa989ae7SSai Krishna Potthuri 	return ret;
1001fa989ae7SSai Krishna Potthuri }
1002fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_function);
1003fa989ae7SSai Krishna Potthuri 
1004fa989ae7SSai Krishna Potthuri /**
1005fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
1006fa989ae7SSai Krishna Potthuri  * @pin: Pin number
1007fa989ae7SSai Krishna Potthuri  * @id: Function ID to set
1008fa989ae7SSai Krishna Potthuri  *
1009fa989ae7SSai Krishna Potthuri  * This function sets requested function for the given pin.
1010fa989ae7SSai Krishna Potthuri  *
1011fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1012fa989ae7SSai Krishna Potthuri  */
1013fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
1014fa989ae7SSai Krishna Potthuri {
1015fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id,
1016fa989ae7SSai Krishna Potthuri 				   0, 0, NULL);
1017fa989ae7SSai Krishna Potthuri }
1018fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function);
1019fa989ae7SSai Krishna Potthuri 
1020fa989ae7SSai Krishna Potthuri /**
1021fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
1022fa989ae7SSai Krishna Potthuri  * @pin: Pin number
1023fa989ae7SSai Krishna Potthuri  * @param: Parameter to get
1024fa989ae7SSai Krishna Potthuri  * @value: Buffer to store parameter value
1025fa989ae7SSai Krishna Potthuri  *
1026fa989ae7SSai Krishna Potthuri  * This function gets requested configuration parameter for the given pin.
1027fa989ae7SSai Krishna Potthuri  *
1028fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1029fa989ae7SSai Krishna Potthuri  */
1030fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
1031fa989ae7SSai Krishna Potthuri 				 u32 *value)
1032fa989ae7SSai Krishna Potthuri {
1033fa989ae7SSai Krishna Potthuri 	u32 ret_payload[PAYLOAD_ARG_CNT];
1034fa989ae7SSai Krishna Potthuri 	int ret;
1035fa989ae7SSai Krishna Potthuri 
1036fa989ae7SSai Krishna Potthuri 	if (!value)
1037fa989ae7SSai Krishna Potthuri 		return -EINVAL;
1038fa989ae7SSai Krishna Potthuri 
1039fa989ae7SSai Krishna Potthuri 	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param,
1040fa989ae7SSai Krishna Potthuri 				  0, 0, ret_payload);
1041fa989ae7SSai Krishna Potthuri 	*value = ret_payload[1];
1042fa989ae7SSai Krishna Potthuri 
1043fa989ae7SSai Krishna Potthuri 	return ret;
1044fa989ae7SSai Krishna Potthuri }
1045fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config);
1046fa989ae7SSai Krishna Potthuri 
1047fa989ae7SSai Krishna Potthuri /**
1048fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
1049fa989ae7SSai Krishna Potthuri  * @pin: Pin number
1050fa989ae7SSai Krishna Potthuri  * @param: Parameter to set
1051fa989ae7SSai Krishna Potthuri  * @value: Parameter value to set
1052fa989ae7SSai Krishna Potthuri  *
1053fa989ae7SSai Krishna Potthuri  * This function sets requested configuration parameter for the given pin.
1054fa989ae7SSai Krishna Potthuri  *
1055fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1056fa989ae7SSai Krishna Potthuri  */
1057fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
1058fa989ae7SSai Krishna Potthuri 				 u32 value)
1059fa989ae7SSai Krishna Potthuri {
1060fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin,
1061fa989ae7SSai Krishna Potthuri 				   param, value, 0, NULL);
1062fa989ae7SSai Krishna Potthuri }
1063fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config);
1064fa989ae7SSai Krishna Potthuri 
1065fa989ae7SSai Krishna Potthuri /**
106623c64d76SPiyush Mehta  * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status
106723c64d76SPiyush Mehta  * @ps_mode: Returned output value of ps_mode
106823c64d76SPiyush Mehta  *
106923c64d76SPiyush Mehta  * This API function is to be used for notify the power management controller
107023c64d76SPiyush Mehta  * to read bootpin status.
107123c64d76SPiyush Mehta  *
107223c64d76SPiyush Mehta  * Return: status, either success or error+reason
107323c64d76SPiyush Mehta  */
107423c64d76SPiyush Mehta unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode)
107523c64d76SPiyush Mehta {
107623c64d76SPiyush Mehta 	unsigned int ret;
107723c64d76SPiyush Mehta 	u32 ret_payload[PAYLOAD_ARG_CNT];
107823c64d76SPiyush Mehta 
107923c64d76SPiyush Mehta 	ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, CRL_APB_BOOT_PIN_CTRL, 0,
108023c64d76SPiyush Mehta 				  0, 0, ret_payload);
108123c64d76SPiyush Mehta 
108223c64d76SPiyush Mehta 	*ps_mode = ret_payload[1];
108323c64d76SPiyush Mehta 
108423c64d76SPiyush Mehta 	return ret;
108523c64d76SPiyush Mehta }
108623c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read);
108723c64d76SPiyush Mehta 
108823c64d76SPiyush Mehta /**
108923c64d76SPiyush Mehta  * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin
109023c64d76SPiyush Mehta  * @ps_mode: Value to be written to the bootpin ctrl register
109123c64d76SPiyush Mehta  *
109223c64d76SPiyush Mehta  * This API function is to be used for notify the power management controller
109323c64d76SPiyush Mehta  * to configure bootpin.
109423c64d76SPiyush Mehta  *
109523c64d76SPiyush Mehta  * Return: Returns status, either success or error+reason
109623c64d76SPiyush Mehta  */
109723c64d76SPiyush Mehta int zynqmp_pm_bootmode_write(u32 ps_mode)
109823c64d76SPiyush Mehta {
109923c64d76SPiyush Mehta 	return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, CRL_APB_BOOT_PIN_CTRL,
110023c64d76SPiyush Mehta 				   CRL_APB_BOOTPIN_CTRL_MASK, ps_mode, 0, NULL);
110123c64d76SPiyush Mehta }
110223c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write);
110323c64d76SPiyush Mehta 
110423c64d76SPiyush Mehta /**
1105e178df31SJolly Shah  * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
1106e178df31SJolly Shah  *			       master has initialized its own power management
1107e178df31SJolly Shah  *
1108332bee16SMichal Simek  * Return: Returns status, either success or error+reason
1109332bee16SMichal Simek  *
1110e178df31SJolly Shah  * This API function is to be used for notify the power management controller
1111e178df31SJolly Shah  * about the completed power management initialization.
1112e178df31SJolly Shah  */
11139474da95SRajan Vaja int zynqmp_pm_init_finalize(void)
1114e178df31SJolly Shah {
1115e178df31SJolly Shah 	return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
1116e178df31SJolly Shah }
11179474da95SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize);
1118e178df31SJolly Shah 
1119e178df31SJolly Shah /**
1120e178df31SJolly Shah  * zynqmp_pm_set_suspend_mode()	- Set system suspend mode
1121e178df31SJolly Shah  * @mode:	Mode to set for system suspend
1122e178df31SJolly Shah  *
1123e178df31SJolly Shah  * This API function is used to set mode of system suspend.
1124e178df31SJolly Shah  *
1125e178df31SJolly Shah  * Return: Returns status, either success or error+reason
1126e178df31SJolly Shah  */
1127951d0a97SRajan Vaja int zynqmp_pm_set_suspend_mode(u32 mode)
1128e178df31SJolly Shah {
1129e178df31SJolly Shah 	return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
1130e178df31SJolly Shah }
1131951d0a97SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
1132e178df31SJolly Shah 
1133c1986ac3SRajan Vaja /**
1134c1986ac3SRajan Vaja  * zynqmp_pm_request_node() - Request a node with specific capabilities
1135c1986ac3SRajan Vaja  * @node:		Node ID of the slave
1136c1986ac3SRajan Vaja  * @capabilities:	Requested capabilities of the slave
1137c1986ac3SRajan Vaja  * @qos:		Quality of service (not supported)
1138c1986ac3SRajan Vaja  * @ack:		Flag to specify whether acknowledge is requested
1139c1986ac3SRajan Vaja  *
1140c1986ac3SRajan Vaja  * This function is used by master to request particular node from firmware.
1141c1986ac3SRajan Vaja  * Every master must request node before using it.
1142c1986ac3SRajan Vaja  *
1143c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1144c1986ac3SRajan Vaja  */
1145bf8b27edSRajan Vaja int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
1146bf8b27edSRajan Vaja 			   const u32 qos, const enum zynqmp_pm_request_ack ack)
1147c1986ac3SRajan Vaja {
1148c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
1149c1986ac3SRajan Vaja 				   qos, ack, NULL);
1150c1986ac3SRajan Vaja }
1151bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
1152c1986ac3SRajan Vaja 
1153c1986ac3SRajan Vaja /**
1154c1986ac3SRajan Vaja  * zynqmp_pm_release_node() - Release a node
1155c1986ac3SRajan Vaja  * @node:	Node ID of the slave
1156c1986ac3SRajan Vaja  *
1157c1986ac3SRajan Vaja  * This function is used by master to inform firmware that master
1158c1986ac3SRajan Vaja  * has released node. Once released, master must not use that node
1159c1986ac3SRajan Vaja  * without re-request.
1160c1986ac3SRajan Vaja  *
1161c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1162c1986ac3SRajan Vaja  */
116307fb1a46SRajan Vaja int zynqmp_pm_release_node(const u32 node)
1164c1986ac3SRajan Vaja {
1165c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
1166c1986ac3SRajan Vaja }
116707fb1a46SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
1168c1986ac3SRajan Vaja 
1169c1986ac3SRajan Vaja /**
1170c1986ac3SRajan Vaja  * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
1171c1986ac3SRajan Vaja  * @node:		Node ID of the slave
1172c1986ac3SRajan Vaja  * @capabilities:	Requested capabilities of the slave
1173c1986ac3SRajan Vaja  * @qos:		Quality of service (not supported)
1174c1986ac3SRajan Vaja  * @ack:		Flag to specify whether acknowledge is requested
1175c1986ac3SRajan Vaja  *
1176c1986ac3SRajan Vaja  * This API function is to be used for slaves a PU already has requested
1177c1986ac3SRajan Vaja  * to change its capabilities.
1178c1986ac3SRajan Vaja  *
1179c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1180c1986ac3SRajan Vaja  */
1181cbbbda71SRajan Vaja int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
1182c1986ac3SRajan Vaja 			      const u32 qos,
1183c1986ac3SRajan Vaja 			      const enum zynqmp_pm_request_ack ack)
1184c1986ac3SRajan Vaja {
1185c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
1186c1986ac3SRajan Vaja 				   qos, ack, NULL);
1187c1986ac3SRajan Vaja }
1188cbbbda71SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
1189c1986ac3SRajan Vaja 
1190057a0fb6SKalyani Akula /**
11912b9fc773SNava kishore Manne  * zynqmp_pm_load_pdi - Load and process PDI
11922b9fc773SNava kishore Manne  * @src:       Source device where PDI is located
11932b9fc773SNava kishore Manne  * @address:   PDI src address
11942b9fc773SNava kishore Manne  *
11952b9fc773SNava kishore Manne  * This function provides support to load PDI from linux
11962b9fc773SNava kishore Manne  *
11972b9fc773SNava kishore Manne  * Return: Returns status, either success or error+reason
11982b9fc773SNava kishore Manne  */
11992b9fc773SNava kishore Manne int zynqmp_pm_load_pdi(const u32 src, const u64 address)
12002b9fc773SNava kishore Manne {
12012b9fc773SNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src,
12022b9fc773SNava kishore Manne 				   lower_32_bits(address),
12032b9fc773SNava kishore Manne 				   upper_32_bits(address), 0, NULL);
12042b9fc773SNava kishore Manne }
12052b9fc773SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi);
12062b9fc773SNava kishore Manne 
12072b9fc773SNava kishore Manne /**
12082a8faf8dSMichal Simek  * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
1209057a0fb6SKalyani Akula  * AES-GCM core.
1210057a0fb6SKalyani Akula  * @address:	Address of the AesParams structure.
1211057a0fb6SKalyani Akula  * @out:	Returned output value
1212057a0fb6SKalyani Akula  *
1213057a0fb6SKalyani Akula  * Return:	Returns status, either success or error code.
1214057a0fb6SKalyani Akula  */
1215bc86f9c5SRajan Vaja int zynqmp_pm_aes_engine(const u64 address, u32 *out)
1216057a0fb6SKalyani Akula {
1217057a0fb6SKalyani Akula 	u32 ret_payload[PAYLOAD_ARG_CNT];
1218057a0fb6SKalyani Akula 	int ret;
1219057a0fb6SKalyani Akula 
1220057a0fb6SKalyani Akula 	if (!out)
1221057a0fb6SKalyani Akula 		return -EINVAL;
1222057a0fb6SKalyani Akula 
1223057a0fb6SKalyani Akula 	ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address),
1224057a0fb6SKalyani Akula 				  lower_32_bits(address),
1225057a0fb6SKalyani Akula 				  0, 0, ret_payload);
1226057a0fb6SKalyani Akula 	*out = ret_payload[1];
1227057a0fb6SKalyani Akula 
1228057a0fb6SKalyani Akula 	return ret;
1229057a0fb6SKalyani Akula }
1230bc86f9c5SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
1231057a0fb6SKalyani Akula 
1232fdd2ed88SRajan Vaja /**
123380f940efSHarsha  * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
123480f940efSHarsha  * @address:	Address of the data/ Address of output buffer where
123580f940efSHarsha  *		hash should be stored.
123680f940efSHarsha  * @size:	Size of the data.
123780f940efSHarsha  * @flags:
123880f940efSHarsha  *	BIT(0) - for initializing csudma driver and SHA3(Here address
123980f940efSHarsha  *		 and size inputs can be NULL).
124080f940efSHarsha  *	BIT(1) - to call Sha3_Update API which can be called multiple
124180f940efSHarsha  *		 times when data is not contiguous.
124280f940efSHarsha  *	BIT(2) - to get final hash of the whole updated data.
124380f940efSHarsha  *		 Hash will be overwritten at provided address with
124480f940efSHarsha  *		 48 bytes.
124580f940efSHarsha  *
124680f940efSHarsha  * Return:	Returns status, either success or error code.
124780f940efSHarsha  */
124880f940efSHarsha int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags)
124980f940efSHarsha {
125080f940efSHarsha 	u32 lower_addr = lower_32_bits(address);
125180f940efSHarsha 	u32 upper_addr = upper_32_bits(address);
125280f940efSHarsha 
125380f940efSHarsha 	return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_addr, lower_addr,
125480f940efSHarsha 				   size, flags, NULL);
125580f940efSHarsha }
125680f940efSHarsha EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash);
125780f940efSHarsha 
125880f940efSHarsha /**
12591881eadbSAbhyuday Godhasara  * zynqmp_pm_register_notifier() - PM API for register a subsystem
12601881eadbSAbhyuday Godhasara  *                                to be notified about specific
12611881eadbSAbhyuday Godhasara  *                                event/error.
12621881eadbSAbhyuday Godhasara  * @node:	Node ID to which the event is related.
12631881eadbSAbhyuday Godhasara  * @event:	Event Mask of Error events for which wants to get notified.
12641881eadbSAbhyuday Godhasara  * @wake:	Wake subsystem upon capturing the event if value 1
12651881eadbSAbhyuday Godhasara  * @enable:	Enable the registration for value 1, disable for value 0
12661881eadbSAbhyuday Godhasara  *
12671881eadbSAbhyuday Godhasara  * This function is used to register/un-register for particular node-event
12681881eadbSAbhyuday Godhasara  * combination in firmware.
12691881eadbSAbhyuday Godhasara  *
12701881eadbSAbhyuday Godhasara  * Return: Returns status, either success or error+reason
12711881eadbSAbhyuday Godhasara  */
12721881eadbSAbhyuday Godhasara 
12731881eadbSAbhyuday Godhasara int zynqmp_pm_register_notifier(const u32 node, const u32 event,
12741881eadbSAbhyuday Godhasara 				const u32 wake, const u32 enable)
12751881eadbSAbhyuday Godhasara {
12761881eadbSAbhyuday Godhasara 	return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event,
12771881eadbSAbhyuday Godhasara 				   wake, enable, NULL);
12781881eadbSAbhyuday Godhasara }
12791881eadbSAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier);
12801881eadbSAbhyuday Godhasara 
12811881eadbSAbhyuday Godhasara /**
1282fdd2ed88SRajan Vaja  * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
1283fdd2ed88SRajan Vaja  * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
1284fdd2ed88SRajan Vaja  * @subtype:	Specifies which system should be restarted or shut down
1285fdd2ed88SRajan Vaja  *
1286fdd2ed88SRajan Vaja  * Return:	Returns status, either success or error+reason
1287fdd2ed88SRajan Vaja  */
1288fdd2ed88SRajan Vaja int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
1289fdd2ed88SRajan Vaja {
1290fdd2ed88SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
1291fdd2ed88SRajan Vaja 				   0, 0, NULL);
1292fdd2ed88SRajan Vaja }
1293fdd2ed88SRajan Vaja 
1294b3ae24c4SRajan Vaja /**
1295f1d0821bSRonak Jain  * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config
1296f1d0821bSRonak Jain  * @id:         The config ID of the feature to be configured
1297f1d0821bSRonak Jain  * @value:      The config value of the feature to be configured
1298f1d0821bSRonak Jain  *
1299f1d0821bSRonak Jain  * Return:      Returns 0 on success or error value on failure.
1300f1d0821bSRonak Jain  */
1301f1d0821bSRonak Jain int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value)
1302f1d0821bSRonak Jain {
1303f1d0821bSRonak Jain 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_FEATURE_CONFIG,
1304f1d0821bSRonak Jain 				   id, value, NULL);
1305f1d0821bSRonak Jain }
1306f1d0821bSRonak Jain 
1307f1d0821bSRonak Jain /**
1308f1d0821bSRonak Jain  * zynqmp_pm_get_feature_config - PM call to get value of configured feature
1309f1d0821bSRonak Jain  * @id:         The config id of the feature to be queried
1310f1d0821bSRonak Jain  * @payload:    Returned value array
1311f1d0821bSRonak Jain  *
1312f1d0821bSRonak Jain  * Return:      Returns 0 on success or error value on failure.
1313f1d0821bSRonak Jain  */
1314f1d0821bSRonak Jain int zynqmp_pm_get_feature_config(enum pm_feature_config_id id,
1315f1d0821bSRonak Jain 				 u32 *payload)
1316f1d0821bSRonak Jain {
1317f1d0821bSRonak Jain 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_FEATURE_CONFIG,
1318f1d0821bSRonak Jain 				   id, 0, payload);
1319f1d0821bSRonak Jain }
1320f1d0821bSRonak Jain 
1321f1d0821bSRonak Jain /**
1322256dea91SRonak Jain  * zynqmp_pm_set_sd_config - PM call to set value of SD config registers
1323256dea91SRonak Jain  * @node:	SD node ID
1324256dea91SRonak Jain  * @config:	The config type of SD registers
1325256dea91SRonak Jain  * @value:	Value to be set
1326256dea91SRonak Jain  *
1327256dea91SRonak Jain  * Return:	Returns 0 on success or error value on failure.
1328256dea91SRonak Jain  */
1329256dea91SRonak Jain int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value)
1330256dea91SRonak Jain {
1331256dea91SRonak Jain 	return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_SD_CONFIG,
1332256dea91SRonak Jain 				   config, value, NULL);
1333256dea91SRonak Jain }
1334256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_config);
1335256dea91SRonak Jain 
1336256dea91SRonak Jain /**
1337256dea91SRonak Jain  * zynqmp_pm_set_gem_config - PM call to set value of GEM config registers
1338256dea91SRonak Jain  * @node:	GEM node ID
1339256dea91SRonak Jain  * @config:	The config type of GEM registers
1340256dea91SRonak Jain  * @value:	Value to be set
1341256dea91SRonak Jain  *
1342256dea91SRonak Jain  * Return:	Returns 0 on success or error value on failure.
1343256dea91SRonak Jain  */
1344256dea91SRonak Jain int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
1345256dea91SRonak Jain 			     u32 value)
1346256dea91SRonak Jain {
1347256dea91SRonak Jain 	return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_GEM_CONFIG,
1348256dea91SRonak Jain 				   config, value, NULL);
1349256dea91SRonak Jain }
1350256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_gem_config);
1351256dea91SRonak Jain 
1352256dea91SRonak Jain /**
1353b3ae24c4SRajan Vaja  * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
1354b3ae24c4SRajan Vaja  * @subtype:	Shutdown subtype
1355b3ae24c4SRajan Vaja  * @name:	Matching string for scope argument
1356b3ae24c4SRajan Vaja  *
1357b3ae24c4SRajan Vaja  * This struct encapsulates mapping between shutdown scope ID and string.
1358b3ae24c4SRajan Vaja  */
1359b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope {
1360b3ae24c4SRajan Vaja 	const enum zynqmp_pm_shutdown_subtype subtype;
1361b3ae24c4SRajan Vaja 	const char *name;
1362b3ae24c4SRajan Vaja };
1363b3ae24c4SRajan Vaja 
1364b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
1365b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
1366b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
1367b3ae24c4SRajan Vaja 		.name = "subsystem",
1368b3ae24c4SRajan Vaja 	},
1369b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
1370b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
1371b3ae24c4SRajan Vaja 		.name = "ps_only",
1372b3ae24c4SRajan Vaja 	},
1373b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
1374b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
1375b3ae24c4SRajan Vaja 		.name = "system",
1376b3ae24c4SRajan Vaja 	},
1377b3ae24c4SRajan Vaja };
1378b3ae24c4SRajan Vaja 
1379b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope =
1380b3ae24c4SRajan Vaja 		&shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
1381b3ae24c4SRajan Vaja 
1382b3ae24c4SRajan Vaja /**
1383b3ae24c4SRajan Vaja  * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
1384b3ae24c4SRajan Vaja  * @scope_string:	Shutdown scope string
1385b3ae24c4SRajan Vaja  *
1386b3ae24c4SRajan Vaja  * Return:		Return pointer to matching shutdown scope struct from
1387b3ae24c4SRajan Vaja  *			array of available options in system if string is valid,
1388b3ae24c4SRajan Vaja  *			otherwise returns NULL.
1389b3ae24c4SRajan Vaja  */
1390b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope*
1391b3ae24c4SRajan Vaja 		zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
1392b3ae24c4SRajan Vaja {
1393b3ae24c4SRajan Vaja 	int count;
1394b3ae24c4SRajan Vaja 
1395b3ae24c4SRajan Vaja 	for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
1396b3ae24c4SRajan Vaja 		if (sysfs_streq(scope_string, shutdown_scopes[count].name))
1397b3ae24c4SRajan Vaja 			return &shutdown_scopes[count];
1398b3ae24c4SRajan Vaja 
1399b3ae24c4SRajan Vaja 	return NULL;
1400b3ae24c4SRajan Vaja }
1401b3ae24c4SRajan Vaja 
1402b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device,
1403b3ae24c4SRajan Vaja 				   struct device_attribute *attr,
1404b3ae24c4SRajan Vaja 				   char *buf)
1405b3ae24c4SRajan Vaja {
1406b3ae24c4SRajan Vaja 	int i;
1407b3ae24c4SRajan Vaja 
1408b3ae24c4SRajan Vaja 	for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
1409b3ae24c4SRajan Vaja 		if (&shutdown_scopes[i] == selected_scope) {
1410b3ae24c4SRajan Vaja 			strcat(buf, "[");
1411b3ae24c4SRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
1412b3ae24c4SRajan Vaja 			strcat(buf, "]");
1413b3ae24c4SRajan Vaja 		} else {
1414b3ae24c4SRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
1415b3ae24c4SRajan Vaja 		}
1416b3ae24c4SRajan Vaja 		strcat(buf, " ");
1417b3ae24c4SRajan Vaja 	}
1418b3ae24c4SRajan Vaja 	strcat(buf, "\n");
1419b3ae24c4SRajan Vaja 
1420b3ae24c4SRajan Vaja 	return strlen(buf);
1421b3ae24c4SRajan Vaja }
1422b3ae24c4SRajan Vaja 
1423b3ae24c4SRajan Vaja static ssize_t shutdown_scope_store(struct device *device,
1424b3ae24c4SRajan Vaja 				    struct device_attribute *attr,
1425b3ae24c4SRajan Vaja 				    const char *buf, size_t count)
1426b3ae24c4SRajan Vaja {
1427b3ae24c4SRajan Vaja 	int ret;
1428b3ae24c4SRajan Vaja 	struct zynqmp_pm_shutdown_scope *scope;
1429b3ae24c4SRajan Vaja 
1430b3ae24c4SRajan Vaja 	scope = zynqmp_pm_is_shutdown_scope_valid(buf);
1431b3ae24c4SRajan Vaja 	if (!scope)
1432b3ae24c4SRajan Vaja 		return -EINVAL;
1433b3ae24c4SRajan Vaja 
1434b3ae24c4SRajan Vaja 	ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
1435b3ae24c4SRajan Vaja 					scope->subtype);
1436b3ae24c4SRajan Vaja 	if (ret) {
1437b3ae24c4SRajan Vaja 		pr_err("unable to set shutdown scope %s\n", buf);
1438b3ae24c4SRajan Vaja 		return ret;
1439b3ae24c4SRajan Vaja 	}
1440b3ae24c4SRajan Vaja 
1441b3ae24c4SRajan Vaja 	selected_scope = scope;
1442b3ae24c4SRajan Vaja 
1443b3ae24c4SRajan Vaja 	return count;
1444b3ae24c4SRajan Vaja }
1445b3ae24c4SRajan Vaja 
1446b3ae24c4SRajan Vaja static DEVICE_ATTR_RW(shutdown_scope);
1447b3ae24c4SRajan Vaja 
1448a2cc220aSRajan Vaja static ssize_t health_status_store(struct device *device,
1449a2cc220aSRajan Vaja 				   struct device_attribute *attr,
1450a2cc220aSRajan Vaja 				   const char *buf, size_t count)
1451a2cc220aSRajan Vaja {
1452a2cc220aSRajan Vaja 	int ret;
1453a2cc220aSRajan Vaja 	unsigned int value;
1454a2cc220aSRajan Vaja 
1455a2cc220aSRajan Vaja 	ret = kstrtouint(buf, 10, &value);
1456a2cc220aSRajan Vaja 	if (ret)
1457a2cc220aSRajan Vaja 		return ret;
1458a2cc220aSRajan Vaja 
1459a2cc220aSRajan Vaja 	ret = zynqmp_pm_set_boot_health_status(value);
1460a2cc220aSRajan Vaja 	if (ret) {
1461a2cc220aSRajan Vaja 		dev_err(device, "unable to set healthy bit value to %u\n",
1462a2cc220aSRajan Vaja 			value);
1463a2cc220aSRajan Vaja 		return ret;
1464a2cc220aSRajan Vaja 	}
1465a2cc220aSRajan Vaja 
1466a2cc220aSRajan Vaja 	return count;
1467a2cc220aSRajan Vaja }
1468a2cc220aSRajan Vaja 
1469a2cc220aSRajan Vaja static DEVICE_ATTR_WO(health_status);
1470a2cc220aSRajan Vaja 
1471ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device,
1472ae5c961dSRajan Vaja 			struct device_attribute *attr,
1473ae5c961dSRajan Vaja 			char *buf,
1474ae5c961dSRajan Vaja 			u32 reg)
1475ae5c961dSRajan Vaja {
1476ae5c961dSRajan Vaja 	int ret;
1477ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1478ae5c961dSRajan Vaja 
1479ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_ggs(reg, ret_payload);
1480ae5c961dSRajan Vaja 	if (ret)
1481ae5c961dSRajan Vaja 		return ret;
1482ae5c961dSRajan Vaja 
1483ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1484ae5c961dSRajan Vaja }
1485ae5c961dSRajan Vaja 
1486ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device,
1487ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1488ae5c961dSRajan Vaja 			 const char *buf, size_t count,
1489ae5c961dSRajan Vaja 			 u32 reg)
1490ae5c961dSRajan Vaja {
1491ae5c961dSRajan Vaja 	long value;
1492ae5c961dSRajan Vaja 	int ret;
1493ae5c961dSRajan Vaja 
1494ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1495ae5c961dSRajan Vaja 		return -EINVAL;
1496ae5c961dSRajan Vaja 
1497ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1498ae5c961dSRajan Vaja 	if (ret) {
1499ae5c961dSRajan Vaja 		count = -EFAULT;
1500ae5c961dSRajan Vaja 		goto err;
1501ae5c961dSRajan Vaja 	}
1502ae5c961dSRajan Vaja 
1503ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_ggs(reg, value);
1504ae5c961dSRajan Vaja 	if (ret)
1505ae5c961dSRajan Vaja 		count = -EFAULT;
1506ae5c961dSRajan Vaja err:
1507ae5c961dSRajan Vaja 	return count;
1508ae5c961dSRajan Vaja }
1509ae5c961dSRajan Vaja 
1510ae5c961dSRajan Vaja /* GGS register show functions */
1511ae5c961dSRajan Vaja #define GGS0_SHOW(N)						\
1512ae5c961dSRajan Vaja 	ssize_t ggs##N##_show(struct device *device,		\
1513ae5c961dSRajan Vaja 			      struct device_attribute *attr,	\
1514ae5c961dSRajan Vaja 			      char *buf)			\
1515ae5c961dSRajan Vaja 	{							\
1516ae5c961dSRajan Vaja 		return ggs_show(device, attr, buf, N);		\
1517ae5c961dSRajan Vaja 	}
1518ae5c961dSRajan Vaja 
1519ae5c961dSRajan Vaja static GGS0_SHOW(0);
1520ae5c961dSRajan Vaja static GGS0_SHOW(1);
1521ae5c961dSRajan Vaja static GGS0_SHOW(2);
1522ae5c961dSRajan Vaja static GGS0_SHOW(3);
1523ae5c961dSRajan Vaja 
1524ae5c961dSRajan Vaja /* GGS register store function */
1525ae5c961dSRajan Vaja #define GGS0_STORE(N)						\
1526ae5c961dSRajan Vaja 	ssize_t ggs##N##_store(struct device *device,		\
1527ae5c961dSRajan Vaja 			       struct device_attribute *attr,	\
1528ae5c961dSRajan Vaja 			       const char *buf,			\
1529ae5c961dSRajan Vaja 			       size_t count)			\
1530ae5c961dSRajan Vaja 	{							\
1531ae5c961dSRajan Vaja 		return ggs_store(device, attr, buf, count, N);	\
1532ae5c961dSRajan Vaja 	}
1533ae5c961dSRajan Vaja 
1534ae5c961dSRajan Vaja static GGS0_STORE(0);
1535ae5c961dSRajan Vaja static GGS0_STORE(1);
1536ae5c961dSRajan Vaja static GGS0_STORE(2);
1537ae5c961dSRajan Vaja static GGS0_STORE(3);
1538ae5c961dSRajan Vaja 
1539ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device,
1540ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1541ae5c961dSRajan Vaja 			 char *buf,
1542ae5c961dSRajan Vaja 			 u32 reg)
1543ae5c961dSRajan Vaja {
1544ae5c961dSRajan Vaja 	int ret;
1545ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1546ae5c961dSRajan Vaja 
1547ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_pggs(reg, ret_payload);
1548ae5c961dSRajan Vaja 	if (ret)
1549ae5c961dSRajan Vaja 		return ret;
1550ae5c961dSRajan Vaja 
1551ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1552ae5c961dSRajan Vaja }
1553ae5c961dSRajan Vaja 
1554ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device,
1555ae5c961dSRajan Vaja 			  struct device_attribute *attr,
1556ae5c961dSRajan Vaja 			  const char *buf, size_t count,
1557ae5c961dSRajan Vaja 			  u32 reg)
1558ae5c961dSRajan Vaja {
1559ae5c961dSRajan Vaja 	long value;
1560ae5c961dSRajan Vaja 	int ret;
1561ae5c961dSRajan Vaja 
1562ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1563ae5c961dSRajan Vaja 		return -EINVAL;
1564ae5c961dSRajan Vaja 
1565ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1566ae5c961dSRajan Vaja 	if (ret) {
1567ae5c961dSRajan Vaja 		count = -EFAULT;
1568ae5c961dSRajan Vaja 		goto err;
1569ae5c961dSRajan Vaja 	}
1570ae5c961dSRajan Vaja 
1571ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_pggs(reg, value);
1572ae5c961dSRajan Vaja 	if (ret)
1573ae5c961dSRajan Vaja 		count = -EFAULT;
1574ae5c961dSRajan Vaja 
1575ae5c961dSRajan Vaja err:
1576ae5c961dSRajan Vaja 	return count;
1577ae5c961dSRajan Vaja }
1578ae5c961dSRajan Vaja 
1579ae5c961dSRajan Vaja #define PGGS0_SHOW(N)						\
1580ae5c961dSRajan Vaja 	ssize_t pggs##N##_show(struct device *device,		\
1581ae5c961dSRajan Vaja 			       struct device_attribute *attr,	\
1582ae5c961dSRajan Vaja 			       char *buf)			\
1583ae5c961dSRajan Vaja 	{							\
1584ae5c961dSRajan Vaja 		return pggs_show(device, attr, buf, N);		\
1585ae5c961dSRajan Vaja 	}
1586ae5c961dSRajan Vaja 
1587ae5c961dSRajan Vaja #define PGGS0_STORE(N)						\
1588ae5c961dSRajan Vaja 	ssize_t pggs##N##_store(struct device *device,		\
1589ae5c961dSRajan Vaja 				struct device_attribute *attr,	\
1590ae5c961dSRajan Vaja 				const char *buf,		\
1591ae5c961dSRajan Vaja 				size_t count)			\
1592ae5c961dSRajan Vaja 	{							\
1593ae5c961dSRajan Vaja 		return pggs_store(device, attr, buf, count, N);	\
1594ae5c961dSRajan Vaja 	}
1595ae5c961dSRajan Vaja 
1596ae5c961dSRajan Vaja /* PGGS register show functions */
1597ae5c961dSRajan Vaja static PGGS0_SHOW(0);
1598ae5c961dSRajan Vaja static PGGS0_SHOW(1);
1599ae5c961dSRajan Vaja static PGGS0_SHOW(2);
1600ae5c961dSRajan Vaja static PGGS0_SHOW(3);
1601ae5c961dSRajan Vaja 
1602ae5c961dSRajan Vaja /* PGGS register store functions */
1603ae5c961dSRajan Vaja static PGGS0_STORE(0);
1604ae5c961dSRajan Vaja static PGGS0_STORE(1);
1605ae5c961dSRajan Vaja static PGGS0_STORE(2);
1606ae5c961dSRajan Vaja static PGGS0_STORE(3);
1607ae5c961dSRajan Vaja 
1608ae5c961dSRajan Vaja /* GGS register attributes */
1609ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs0);
1610ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs1);
1611ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs2);
1612ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs3);
1613ae5c961dSRajan Vaja 
1614ae5c961dSRajan Vaja /* PGGS register attributes */
1615ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs0);
1616ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs1);
1617ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs2);
1618ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs3);
1619ae5c961dSRajan Vaja 
16202c5d8f7cSRonak Jain static ssize_t feature_config_id_show(struct device *device,
16212c5d8f7cSRonak Jain 				      struct device_attribute *attr,
16222c5d8f7cSRonak Jain 				      char *buf)
16232c5d8f7cSRonak Jain {
16242c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
16252c5d8f7cSRonak Jain 
16262c5d8f7cSRonak Jain 	return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id);
16272c5d8f7cSRonak Jain }
16282c5d8f7cSRonak Jain 
16292c5d8f7cSRonak Jain static ssize_t feature_config_id_store(struct device *device,
16302c5d8f7cSRonak Jain 				       struct device_attribute *attr,
16312c5d8f7cSRonak Jain 				       const char *buf, size_t count)
16322c5d8f7cSRonak Jain {
16332c5d8f7cSRonak Jain 	u32 config_id;
16342c5d8f7cSRonak Jain 	int ret;
16352c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
16362c5d8f7cSRonak Jain 
16372c5d8f7cSRonak Jain 	if (!buf)
16382c5d8f7cSRonak Jain 		return -EINVAL;
16392c5d8f7cSRonak Jain 
16402c5d8f7cSRonak Jain 	ret = kstrtou32(buf, 10, &config_id);
16412c5d8f7cSRonak Jain 	if (ret)
16422c5d8f7cSRonak Jain 		return ret;
16432c5d8f7cSRonak Jain 
16442c5d8f7cSRonak Jain 	devinfo->feature_conf_id = config_id;
16452c5d8f7cSRonak Jain 
16462c5d8f7cSRonak Jain 	return count;
16472c5d8f7cSRonak Jain }
16482c5d8f7cSRonak Jain 
16492c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_id);
16502c5d8f7cSRonak Jain 
16512c5d8f7cSRonak Jain static ssize_t feature_config_value_show(struct device *device,
16522c5d8f7cSRonak Jain 					 struct device_attribute *attr,
16532c5d8f7cSRonak Jain 					 char *buf)
16542c5d8f7cSRonak Jain {
16552c5d8f7cSRonak Jain 	int ret;
16562c5d8f7cSRonak Jain 	u32 ret_payload[PAYLOAD_ARG_CNT];
16572c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
16582c5d8f7cSRonak Jain 
16592c5d8f7cSRonak Jain 	ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id,
16602c5d8f7cSRonak Jain 					   ret_payload);
16612c5d8f7cSRonak Jain 	if (ret)
16622c5d8f7cSRonak Jain 		return ret;
16632c5d8f7cSRonak Jain 
16642c5d8f7cSRonak Jain 	return sysfs_emit(buf, "%d\n", ret_payload[1]);
16652c5d8f7cSRonak Jain }
16662c5d8f7cSRonak Jain 
16672c5d8f7cSRonak Jain static ssize_t feature_config_value_store(struct device *device,
16682c5d8f7cSRonak Jain 					  struct device_attribute *attr,
16692c5d8f7cSRonak Jain 					  const char *buf, size_t count)
16702c5d8f7cSRonak Jain {
16712c5d8f7cSRonak Jain 	u32 value;
16722c5d8f7cSRonak Jain 	int ret;
16732c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
16742c5d8f7cSRonak Jain 
16752c5d8f7cSRonak Jain 	if (!buf)
16762c5d8f7cSRonak Jain 		return -EINVAL;
16772c5d8f7cSRonak Jain 
16782c5d8f7cSRonak Jain 	ret = kstrtou32(buf, 10, &value);
16792c5d8f7cSRonak Jain 	if (ret)
16802c5d8f7cSRonak Jain 		return ret;
16812c5d8f7cSRonak Jain 
16822c5d8f7cSRonak Jain 	ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id,
16832c5d8f7cSRonak Jain 					   value);
16842c5d8f7cSRonak Jain 	if (ret)
16852c5d8f7cSRonak Jain 		return ret;
16862c5d8f7cSRonak Jain 
16872c5d8f7cSRonak Jain 	return count;
16882c5d8f7cSRonak Jain }
16892c5d8f7cSRonak Jain 
16902c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_value);
16912c5d8f7cSRonak Jain 
1692ae5c961dSRajan Vaja static struct attribute *zynqmp_firmware_attrs[] = {
1693ae5c961dSRajan Vaja 	&dev_attr_ggs0.attr,
1694ae5c961dSRajan Vaja 	&dev_attr_ggs1.attr,
1695ae5c961dSRajan Vaja 	&dev_attr_ggs2.attr,
1696ae5c961dSRajan Vaja 	&dev_attr_ggs3.attr,
1697ae5c961dSRajan Vaja 	&dev_attr_pggs0.attr,
1698ae5c961dSRajan Vaja 	&dev_attr_pggs1.attr,
1699ae5c961dSRajan Vaja 	&dev_attr_pggs2.attr,
1700ae5c961dSRajan Vaja 	&dev_attr_pggs3.attr,
1701b3ae24c4SRajan Vaja 	&dev_attr_shutdown_scope.attr,
1702a2cc220aSRajan Vaja 	&dev_attr_health_status.attr,
17032c5d8f7cSRonak Jain 	&dev_attr_feature_config_id.attr,
17042c5d8f7cSRonak Jain 	&dev_attr_feature_config_value.attr,
1705ae5c961dSRajan Vaja 	NULL,
1706ae5c961dSRajan Vaja };
1707ae5c961dSRajan Vaja 
1708ae5c961dSRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware);
1709ae5c961dSRajan Vaja 
171076582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev)
171176582671SRajan Vaja {
171276582671SRajan Vaja 	struct device *dev = &pdev->dev;
171376582671SRajan Vaja 	struct device_node *np;
17142c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo;
171576582671SRajan Vaja 	int ret;
171676582671SRajan Vaja 
1717e5052becSRonak Jain 	ret = get_set_conduit_method(dev->of_node);
1718e5052becSRonak Jain 	if (ret)
1719e5052becSRonak Jain 		return ret;
1720e5052becSRonak Jain 
172176582671SRajan Vaja 	np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp");
1722af3f1afaSJolly Shah 	if (!np) {
1723af3f1afaSJolly Shah 		np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
172476582671SRajan Vaja 		if (!np)
172576582671SRajan Vaja 			return 0;
1726461011b1SRavi Patel 
1727461011b1SRavi Patel 		feature_check_enabled = true;
1728af3f1afaSJolly Shah 	}
172976582671SRajan Vaja 
1730e5052becSRonak Jain 	if (!feature_check_enabled) {
1731e5052becSRonak Jain 		ret = do_feature_check_call(PM_FEATURE_CHECK);
1732e5052becSRonak Jain 		if (ret >= 0)
1733e5052becSRonak Jain 			feature_check_enabled = true;
1734e5052becSRonak Jain 	}
1735e5052becSRonak Jain 
1736e5052becSRonak Jain 	of_node_put(np);
173776582671SRajan Vaja 
17382c5d8f7cSRonak Jain 	devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL);
17392c5d8f7cSRonak Jain 	if (!devinfo)
17402c5d8f7cSRonak Jain 		return -ENOMEM;
17412c5d8f7cSRonak Jain 
17422c5d8f7cSRonak Jain 	devinfo->dev = dev;
17432c5d8f7cSRonak Jain 
17442c5d8f7cSRonak Jain 	platform_set_drvdata(pdev, devinfo);
17452c5d8f7cSRonak Jain 
174676582671SRajan Vaja 	/* Check PM API version number */
1747168e05c1SRajan Vaja 	ret = zynqmp_pm_get_api_version(&pm_api_version);
1748168e05c1SRajan Vaja 	if (ret)
1749168e05c1SRajan Vaja 		return ret;
1750168e05c1SRajan Vaja 
175176582671SRajan Vaja 	if (pm_api_version < ZYNQMP_PM_VERSION) {
175276582671SRajan Vaja 		panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
175376582671SRajan Vaja 		      __func__,
175476582671SRajan Vaja 		      ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
175576582671SRajan Vaja 		      pm_api_version >> 16, pm_api_version & 0xFFFF);
175676582671SRajan Vaja 	}
175776582671SRajan Vaja 
175876582671SRajan Vaja 	pr_info("%s Platform Management API v%d.%d\n", __func__,
175976582671SRajan Vaja 		pm_api_version >> 16, pm_api_version & 0xFFFF);
176076582671SRajan Vaja 
176176582671SRajan Vaja 	/* Check trustzone version number */
176276582671SRajan Vaja 	ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
176376582671SRajan Vaja 	if (ret)
176476582671SRajan Vaja 		panic("Legacy trustzone found without version support\n");
176576582671SRajan Vaja 
176676582671SRajan Vaja 	if (pm_tz_version < ZYNQMP_TZ_VERSION)
176776582671SRajan Vaja 		panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
176876582671SRajan Vaja 		      __func__,
176976582671SRajan Vaja 		      ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
177076582671SRajan Vaja 		      pm_tz_version >> 16, pm_tz_version & 0xFFFF);
177176582671SRajan Vaja 
177276582671SRajan Vaja 	pr_info("%s Trustzone version v%d.%d\n", __func__,
177376582671SRajan Vaja 		pm_tz_version >> 16, pm_tz_version & 0xFFFF);
177476582671SRajan Vaja 
1775e23d9c6dSJolly Shah 	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
1776e23d9c6dSJolly Shah 			      ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
1777e23d9c6dSJolly Shah 	if (ret) {
1778e23d9c6dSJolly Shah 		dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
1779e23d9c6dSJolly Shah 		return ret;
1780e23d9c6dSJolly Shah 	}
1781e23d9c6dSJolly Shah 
178265f0539bSChristophe JAILLET 	zynqmp_pm_api_debugfs_init();
178365f0539bSChristophe JAILLET 
1784a515814eSAbhyuday Godhasara 	np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
1785a515814eSAbhyuday Godhasara 	if (np) {
1786a515814eSAbhyuday Godhasara 		em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager",
1787a515814eSAbhyuday Godhasara 						       -1, NULL, 0);
1788a515814eSAbhyuday Godhasara 		if (IS_ERR(em_dev))
1789a515814eSAbhyuday Godhasara 			dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n");
1790a515814eSAbhyuday Godhasara 	}
1791a515814eSAbhyuday Godhasara 	of_node_put(np);
1792a515814eSAbhyuday Godhasara 
179376582671SRajan Vaja 	return of_platform_populate(dev->of_node, NULL, NULL, dev);
179476582671SRajan Vaja }
179576582671SRajan Vaja 
179676582671SRajan Vaja static int zynqmp_firmware_remove(struct platform_device *pdev)
179776582671SRajan Vaja {
1798acfdd185SAmit Sunil Dhamne 	struct pm_api_feature_data *feature_data;
1799f1f21becSTejas Patel 	struct hlist_node *tmp;
1800acfdd185SAmit Sunil Dhamne 	int i;
1801acfdd185SAmit Sunil Dhamne 
1802e23d9c6dSJolly Shah 	mfd_remove_devices(&pdev->dev);
1803b3217252SRajan Vaja 	zynqmp_pm_api_debugfs_exit();
1804b3217252SRajan Vaja 
1805f1f21becSTejas Patel 	hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) {
1806acfdd185SAmit Sunil Dhamne 		hash_del(&feature_data->hentry);
1807acfdd185SAmit Sunil Dhamne 		kfree(feature_data);
1808acfdd185SAmit Sunil Dhamne 	}
1809acfdd185SAmit Sunil Dhamne 
1810a515814eSAbhyuday Godhasara 	platform_device_unregister(em_dev);
1811a515814eSAbhyuday Godhasara 
181276582671SRajan Vaja 	return 0;
181376582671SRajan Vaja }
181476582671SRajan Vaja 
181576582671SRajan Vaja static const struct of_device_id zynqmp_firmware_of_match[] = {
181676582671SRajan Vaja 	{.compatible = "xlnx,zynqmp-firmware"},
1817af3f1afaSJolly Shah 	{.compatible = "xlnx,versal-firmware"},
181876582671SRajan Vaja 	{},
181976582671SRajan Vaja };
182076582671SRajan Vaja MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
182176582671SRajan Vaja 
182276582671SRajan Vaja static struct platform_driver zynqmp_firmware_driver = {
182376582671SRajan Vaja 	.driver = {
182476582671SRajan Vaja 		.name = "zynqmp_firmware",
182576582671SRajan Vaja 		.of_match_table = zynqmp_firmware_of_match,
1826ae5c961dSRajan Vaja 		.dev_groups = zynqmp_firmware_groups,
182776582671SRajan Vaja 	},
182876582671SRajan Vaja 	.probe = zynqmp_firmware_probe,
182976582671SRajan Vaja 	.remove = zynqmp_firmware_remove,
183076582671SRajan Vaja };
183176582671SRajan Vaja module_platform_driver(zynqmp_firmware_driver);
1832