xref: /openbmc/linux/drivers/firmware/xilinx/zynqmp.c (revision 5b45759c)
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  *
7a5cb804bSMichal Simek  *  Michal Simek <michal.simek@amd.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>
21*5b45759cSRob Herring #include <linux/platform_device.h>
2276582671SRajan Vaja #include <linux/slab.h>
2376582671SRajan Vaja #include <linux/uaccess.h>
24acfdd185SAmit Sunil Dhamne #include <linux/hashtable.h>
2576582671SRajan Vaja 
2676582671SRajan Vaja #include <linux/firmware/xlnx-zynqmp.h>
27a515814eSAbhyuday Godhasara #include <linux/firmware/xlnx-event-manager.h>
28b3217252SRajan Vaja #include "zynqmp-debug.h"
2976582671SRajan Vaja 
30acfdd185SAmit Sunil Dhamne /* Max HashMap Order for PM API feature check (1<<7 = 128) */
31acfdd185SAmit Sunil Dhamne #define PM_API_FEATURE_CHECK_MAX_ORDER  7
32acfdd185SAmit Sunil Dhamne 
3323c64d76SPiyush Mehta /* CRL registers and bitfields */
3423c64d76SPiyush Mehta #define CRL_APB_BASE			0xFF5E0000U
3523c64d76SPiyush Mehta /* BOOT_PIN_CTRL- Used to control the mode pins after boot */
3623c64d76SPiyush Mehta #define CRL_APB_BOOT_PIN_CTRL		(CRL_APB_BASE + (0x250U))
3723c64d76SPiyush Mehta /* BOOT_PIN_CTRL_MASK- out_val[11:8], out_en[3:0] */
3823c64d76SPiyush Mehta #define CRL_APB_BOOTPIN_CTRL_MASK	0xF0FU
3923c64d76SPiyush Mehta 
40f918cfc0SRonak Jain /* IOCTL/QUERY feature payload size */
41f918cfc0SRonak Jain #define FEATURE_PAYLOAD_SIZE		2
42f918cfc0SRonak Jain 
43f918cfc0SRonak Jain /* Firmware feature check version mask */
44f918cfc0SRonak Jain #define FIRMWARE_VERSION_MASK		GENMASK(15, 0)
45f918cfc0SRonak Jain 
46461011b1SRavi Patel static bool feature_check_enabled;
4769fe24d1SZou Wei static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
48f918cfc0SRonak Jain static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
49f918cfc0SRonak Jain static u32 query_features[FEATURE_PAYLOAD_SIZE];
50acfdd185SAmit Sunil Dhamne 
51a515814eSAbhyuday Godhasara static struct platform_device *em_dev;
52a515814eSAbhyuday Godhasara 
53acfdd185SAmit Sunil Dhamne /**
542c5d8f7cSRonak Jain  * struct zynqmp_devinfo - Structure for Zynqmp device instance
552c5d8f7cSRonak Jain  * @dev:		Device Pointer
562c5d8f7cSRonak Jain  * @feature_conf_id:	Feature conf id
572c5d8f7cSRonak Jain  */
582c5d8f7cSRonak Jain struct zynqmp_devinfo {
592c5d8f7cSRonak Jain 	struct device *dev;
602c5d8f7cSRonak Jain 	u32 feature_conf_id;
612c5d8f7cSRonak Jain };
622c5d8f7cSRonak Jain 
632c5d8f7cSRonak Jain /**
64acfdd185SAmit Sunil Dhamne  * struct pm_api_feature_data - PM API Feature data
65acfdd185SAmit Sunil Dhamne  * @pm_api_id:		PM API Id, used as key to index into hashmap
66acfdd185SAmit Sunil Dhamne  * @feature_status:	status of PM API feature: valid, invalid
67acfdd185SAmit Sunil Dhamne  * @hentry:		hlist_node that hooks this entry into hashtable
68acfdd185SAmit Sunil Dhamne  */
69acfdd185SAmit Sunil Dhamne struct pm_api_feature_data {
70acfdd185SAmit Sunil Dhamne 	u32 pm_api_id;
71acfdd185SAmit Sunil Dhamne 	int feature_status;
72acfdd185SAmit Sunil Dhamne 	struct hlist_node hentry;
73acfdd185SAmit Sunil Dhamne };
74461011b1SRavi Patel 
75e23d9c6dSJolly Shah static const struct mfd_cell firmware_devs[] = {
76e23d9c6dSJolly Shah 	{
77e23d9c6dSJolly Shah 		.name = "zynqmp_power_controller",
78e23d9c6dSJolly Shah 	},
79e23d9c6dSJolly Shah };
80e23d9c6dSJolly Shah 
8176582671SRajan Vaja /**
8276582671SRajan Vaja  * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
8376582671SRajan Vaja  * @ret_status:		PMUFW return code
8476582671SRajan Vaja  *
8576582671SRajan Vaja  * Return: corresponding Linux error code
8676582671SRajan Vaja  */
zynqmp_pm_ret_code(u32 ret_status)8776582671SRajan Vaja static int zynqmp_pm_ret_code(u32 ret_status)
8876582671SRajan Vaja {
8976582671SRajan Vaja 	switch (ret_status) {
9076582671SRajan Vaja 	case XST_PM_SUCCESS:
9176582671SRajan Vaja 	case XST_PM_DOUBLE_REQ:
9276582671SRajan Vaja 		return 0;
93461011b1SRavi Patel 	case XST_PM_NO_FEATURE:
94461011b1SRavi Patel 		return -ENOTSUPP;
9576582671SRajan Vaja 	case XST_PM_NO_ACCESS:
9676582671SRajan Vaja 		return -EACCES;
9776582671SRajan Vaja 	case XST_PM_ABORT_SUSPEND:
9876582671SRajan Vaja 		return -ECANCELED;
99df2a4d94SRajan Vaja 	case XST_PM_MULT_USER:
100df2a4d94SRajan Vaja 		return -EUSERS;
10176582671SRajan Vaja 	case XST_PM_INTERNAL:
10276582671SRajan Vaja 	case XST_PM_CONFLICT:
10376582671SRajan Vaja 	case XST_PM_INVALID_NODE:
10476582671SRajan Vaja 	default:
10576582671SRajan Vaja 		return -EINVAL;
10676582671SRajan Vaja 	}
10776582671SRajan Vaja }
10876582671SRajan Vaja 
do_fw_call_fail(u64 arg0,u64 arg1,u64 arg2,u32 * ret_payload)10976582671SRajan Vaja static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2,
11076582671SRajan Vaja 				    u32 *ret_payload)
11176582671SRajan Vaja {
11276582671SRajan Vaja 	return -ENODEV;
11376582671SRajan Vaja }
11476582671SRajan Vaja 
11576582671SRajan Vaja /*
11676582671SRajan Vaja  * PM function call wrapper
11776582671SRajan Vaja  * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
11876582671SRajan Vaja  */
11976582671SRajan Vaja static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail;
12076582671SRajan Vaja 
12176582671SRajan Vaja /**
12276582671SRajan Vaja  * do_fw_call_smc() - Call system-level platform management layer (SMC)
12376582671SRajan Vaja  * @arg0:		Argument 0 to SMC call
12476582671SRajan Vaja  * @arg1:		Argument 1 to SMC call
12576582671SRajan Vaja  * @arg2:		Argument 2 to SMC call
12676582671SRajan Vaja  * @ret_payload:	Returned value array
12776582671SRajan Vaja  *
12876582671SRajan Vaja  * Invoke platform management function via SMC call (no hypervisor present).
12976582671SRajan Vaja  *
13076582671SRajan Vaja  * Return: Returns status, either success or error+reason
13176582671SRajan Vaja  */
do_fw_call_smc(u64 arg0,u64 arg1,u64 arg2,u32 * ret_payload)13276582671SRajan Vaja static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2,
13376582671SRajan Vaja 				   u32 *ret_payload)
13476582671SRajan Vaja {
13576582671SRajan Vaja 	struct arm_smccc_res res;
13676582671SRajan Vaja 
13776582671SRajan Vaja 	arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
13876582671SRajan Vaja 
13976582671SRajan Vaja 	if (ret_payload) {
14076582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
14176582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
14276582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
14376582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
14476582671SRajan Vaja 	}
14576582671SRajan Vaja 
14676582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
14776582671SRajan Vaja }
14876582671SRajan Vaja 
14976582671SRajan Vaja /**
15076582671SRajan Vaja  * do_fw_call_hvc() - Call system-level platform management layer (HVC)
15176582671SRajan Vaja  * @arg0:		Argument 0 to HVC call
15276582671SRajan Vaja  * @arg1:		Argument 1 to HVC call
15376582671SRajan Vaja  * @arg2:		Argument 2 to HVC call
15476582671SRajan Vaja  * @ret_payload:	Returned value array
15576582671SRajan Vaja  *
15676582671SRajan Vaja  * Invoke platform management function via HVC
15776582671SRajan Vaja  * HVC-based for communication through hypervisor
15876582671SRajan Vaja  * (no direct communication with ATF).
15976582671SRajan Vaja  *
16076582671SRajan Vaja  * Return: Returns status, either success or error+reason
16176582671SRajan Vaja  */
do_fw_call_hvc(u64 arg0,u64 arg1,u64 arg2,u32 * ret_payload)16276582671SRajan Vaja static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2,
16376582671SRajan Vaja 				   u32 *ret_payload)
16476582671SRajan Vaja {
16576582671SRajan Vaja 	struct arm_smccc_res res;
16676582671SRajan Vaja 
16776582671SRajan Vaja 	arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
16876582671SRajan Vaja 
16976582671SRajan Vaja 	if (ret_payload) {
17076582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
17176582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
17276582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
17376582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
17476582671SRajan Vaja 	}
17576582671SRajan Vaja 
17676582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
17776582671SRajan Vaja }
17876582671SRajan Vaja 
__do_feature_check_call(const u32 api_id,u32 * ret_payload)179218f01a8SRonak Jain static int __do_feature_check_call(const u32 api_id, u32 *ret_payload)
18094ae7f22SRonak Jain {
18194ae7f22SRonak Jain 	int ret;
18294ae7f22SRonak Jain 	u64 smc_arg[2];
18394ae7f22SRonak Jain 
18494ae7f22SRonak Jain 	smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK;
18594ae7f22SRonak Jain 	smc_arg[1] = api_id;
18694ae7f22SRonak Jain 
18794ae7f22SRonak Jain 	ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload);
18894ae7f22SRonak Jain 	if (ret)
18994ae7f22SRonak Jain 		ret = -EOPNOTSUPP;
19094ae7f22SRonak Jain 	else
19194ae7f22SRonak Jain 		ret = ret_payload[1];
19294ae7f22SRonak Jain 
19394ae7f22SRonak Jain 	return ret;
19494ae7f22SRonak Jain }
19594ae7f22SRonak Jain 
do_feature_check_call(const u32 api_id)196218f01a8SRonak Jain static int do_feature_check_call(const u32 api_id)
197461011b1SRavi Patel {
198461011b1SRavi Patel 	int ret;
199461011b1SRavi Patel 	u32 ret_payload[PAYLOAD_ARG_CNT];
200acfdd185SAmit Sunil Dhamne 	struct pm_api_feature_data *feature_data;
201461011b1SRavi Patel 
202acfdd185SAmit Sunil Dhamne 	/* Check for existing entry in hash table for given api */
203acfdd185SAmit Sunil Dhamne 	hash_for_each_possible(pm_api_features_map, feature_data, hentry,
204acfdd185SAmit Sunil Dhamne 			       api_id) {
205acfdd185SAmit Sunil Dhamne 		if (feature_data->pm_api_id == api_id)
206acfdd185SAmit Sunil Dhamne 			return feature_data->feature_status;
207acfdd185SAmit Sunil Dhamne 	}
208f3217d6fSArnd Bergmann 
209acfdd185SAmit Sunil Dhamne 	/* Add new entry if not present */
21038ed310cSRoman Gushchin 	feature_data = kmalloc(sizeof(*feature_data), GFP_ATOMIC);
211acfdd185SAmit Sunil Dhamne 	if (!feature_data)
212acfdd185SAmit Sunil Dhamne 		return -ENOMEM;
213461011b1SRavi Patel 
214acfdd185SAmit Sunil Dhamne 	feature_data->pm_api_id = api_id;
215218f01a8SRonak Jain 	ret = __do_feature_check_call(api_id, ret_payload);
216461011b1SRavi Patel 
217acfdd185SAmit Sunil Dhamne 	feature_data->feature_status = ret;
218acfdd185SAmit Sunil Dhamne 	hash_add(pm_api_features_map, &feature_data->hentry, api_id);
219461011b1SRavi Patel 
220f918cfc0SRonak Jain 	if (api_id == PM_IOCTL)
221f918cfc0SRonak Jain 		/* Store supported IOCTL IDs mask */
222f918cfc0SRonak Jain 		memcpy(ioctl_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
223f918cfc0SRonak Jain 	else if (api_id == PM_QUERY_DATA)
224f918cfc0SRonak Jain 		/* Store supported QUERY IDs mask */
225f918cfc0SRonak Jain 		memcpy(query_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
226f918cfc0SRonak Jain 
227acfdd185SAmit Sunil Dhamne 	return ret;
228461011b1SRavi Patel }
229f4d77525SAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
230461011b1SRavi Patel 
231461011b1SRavi Patel /**
232218f01a8SRonak Jain  * zynqmp_pm_feature() - Check whether given feature is supported or not and
233218f01a8SRonak Jain  *			 store supported IOCTL/QUERY ID mask
234218f01a8SRonak Jain  * @api_id:		API ID to check
235218f01a8SRonak Jain  *
236218f01a8SRonak Jain  * Return: Returns status, either success or error+reason
237218f01a8SRonak Jain  */
zynqmp_pm_feature(const u32 api_id)238218f01a8SRonak Jain int zynqmp_pm_feature(const u32 api_id)
239218f01a8SRonak Jain {
240218f01a8SRonak Jain 	int ret;
241218f01a8SRonak Jain 
242218f01a8SRonak Jain 	if (!feature_check_enabled)
243218f01a8SRonak Jain 		return 0;
244218f01a8SRonak Jain 
245218f01a8SRonak Jain 	ret = do_feature_check_call(api_id);
246218f01a8SRonak Jain 
247218f01a8SRonak Jain 	return ret;
248218f01a8SRonak Jain }
249218f01a8SRonak Jain 
250218f01a8SRonak Jain /**
251f918cfc0SRonak Jain  * zynqmp_pm_is_function_supported() - Check whether given IOCTL/QUERY function
252f918cfc0SRonak Jain  *				       is supported or not
253f918cfc0SRonak Jain  * @api_id:		PM_IOCTL or PM_QUERY_DATA
254f918cfc0SRonak Jain  * @id:			IOCTL or QUERY function IDs
255f918cfc0SRonak Jain  *
256f918cfc0SRonak Jain  * Return: Returns status, either success or error+reason
257f918cfc0SRonak Jain  */
zynqmp_pm_is_function_supported(const u32 api_id,const u32 id)258f918cfc0SRonak Jain int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
259f918cfc0SRonak Jain {
260f918cfc0SRonak Jain 	int ret;
261f918cfc0SRonak Jain 	u32 *bit_mask;
262f918cfc0SRonak Jain 
263f918cfc0SRonak Jain 	/* Input arguments validation */
264f918cfc0SRonak Jain 	if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA))
265f918cfc0SRonak Jain 		return -EINVAL;
266f918cfc0SRonak Jain 
267f918cfc0SRonak Jain 	/* Check feature check API version */
268218f01a8SRonak Jain 	ret = do_feature_check_call(PM_FEATURE_CHECK);
269f918cfc0SRonak Jain 	if (ret < 0)
270f918cfc0SRonak Jain 		return ret;
271f918cfc0SRonak Jain 
272f918cfc0SRonak Jain 	/* Check if feature check version 2 is supported or not */
273f918cfc0SRonak Jain 	if ((ret & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) {
274f918cfc0SRonak Jain 		/*
275f918cfc0SRonak Jain 		 * Call feature check for IOCTL/QUERY API to get IOCTL ID or
276f918cfc0SRonak Jain 		 * QUERY ID feature status.
277f918cfc0SRonak Jain 		 */
278218f01a8SRonak Jain 		ret = do_feature_check_call(api_id);
279f918cfc0SRonak Jain 		if (ret < 0)
280f918cfc0SRonak Jain 			return ret;
281f918cfc0SRonak Jain 
282f918cfc0SRonak Jain 		bit_mask = (api_id == PM_IOCTL) ? ioctl_features : query_features;
283f918cfc0SRonak Jain 
284f918cfc0SRonak Jain 		if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0U)
285f918cfc0SRonak Jain 			return -EOPNOTSUPP;
286f918cfc0SRonak Jain 	} else {
287f918cfc0SRonak Jain 		return -ENODATA;
288f918cfc0SRonak Jain 	}
289f918cfc0SRonak Jain 
290f918cfc0SRonak Jain 	return 0;
291f918cfc0SRonak Jain }
292f918cfc0SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported);
293f918cfc0SRonak Jain 
294f918cfc0SRonak Jain /**
29576582671SRajan Vaja  * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
29676582671SRajan Vaja  *			   caller function depending on the configuration
29776582671SRajan Vaja  * @pm_api_id:		Requested PM-API call
29876582671SRajan Vaja  * @arg0:		Argument 0 to requested PM-API call
29976582671SRajan Vaja  * @arg1:		Argument 1 to requested PM-API call
30076582671SRajan Vaja  * @arg2:		Argument 2 to requested PM-API call
30176582671SRajan Vaja  * @arg3:		Argument 3 to requested PM-API call
30276582671SRajan Vaja  * @ret_payload:	Returned value array
30376582671SRajan Vaja  *
30476582671SRajan Vaja  * Invoke platform management function for SMC or HVC call, depending on
30576582671SRajan Vaja  * configuration.
30676582671SRajan Vaja  * Following SMC Calling Convention (SMCCC) for SMC64:
30776582671SRajan Vaja  * Pm Function Identifier,
30876582671SRajan Vaja  * PM_SIP_SVC + PM_API_ID =
30976582671SRajan Vaja  *	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
31076582671SRajan Vaja  *	((SMC_64) << FUNCID_CC_SHIFT)
31176582671SRajan Vaja  *	((SIP_START) << FUNCID_OEN_SHIFT)
31276582671SRajan Vaja  *	((PM_API_ID) & FUNCID_NUM_MASK))
31376582671SRajan Vaja  *
31476582671SRajan Vaja  * PM_SIP_SVC	- Registered ZynqMP SIP Service Call.
31576582671SRajan Vaja  * PM_API_ID	- Platform Management API ID.
31676582671SRajan Vaja  *
31776582671SRajan Vaja  * Return: Returns status, either success or error+reason
31876582671SRajan Vaja  */
zynqmp_pm_invoke_fn(u32 pm_api_id,u32 arg0,u32 arg1,u32 arg2,u32 arg3,u32 * ret_payload)31976582671SRajan Vaja int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
32076582671SRajan Vaja 			u32 arg2, u32 arg3, u32 *ret_payload)
32176582671SRajan Vaja {
32276582671SRajan Vaja 	/*
32376582671SRajan Vaja 	 * Added SIP service call Function Identifier
32476582671SRajan Vaja 	 * Make sure to stay in x0 register
32576582671SRajan Vaja 	 */
32676582671SRajan Vaja 	u64 smc_arg[4];
327acfdd185SAmit Sunil Dhamne 	int ret;
32876582671SRajan Vaja 
329acfdd185SAmit Sunil Dhamne 	/* Check if feature is supported or not */
330acfdd185SAmit Sunil Dhamne 	ret = zynqmp_pm_feature(pm_api_id);
331acfdd185SAmit Sunil Dhamne 	if (ret < 0)
332acfdd185SAmit Sunil Dhamne 		return ret;
333461011b1SRavi Patel 
33476582671SRajan Vaja 	smc_arg[0] = PM_SIP_SVC | pm_api_id;
33576582671SRajan Vaja 	smc_arg[1] = ((u64)arg1 << 32) | arg0;
33676582671SRajan Vaja 	smc_arg[2] = ((u64)arg3 << 32) | arg2;
33776582671SRajan Vaja 
33876582671SRajan Vaja 	return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload);
33976582671SRajan Vaja }
34076582671SRajan Vaja 
34176582671SRajan Vaja static u32 pm_api_version;
34276582671SRajan Vaja static u32 pm_tz_version;
34376582671SRajan Vaja static u32 pm_family_code;
344acd6510dSTanmay Shah static u32 pm_sub_family_code;
345acd6510dSTanmay Shah 
zynqmp_pm_register_sgi(u32 sgi_num,u32 reset)346acd6510dSTanmay Shah int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset)
347acd6510dSTanmay Shah {
348acd6510dSTanmay Shah 	int ret;
349acd6510dSTanmay Shah 
350acd6510dSTanmay Shah 	ret = zynqmp_pm_invoke_fn(TF_A_PM_REGISTER_SGI, sgi_num, reset, 0, 0,
351acd6510dSTanmay Shah 				  NULL);
352acd6510dSTanmay Shah 	if (!ret)
353acd6510dSTanmay Shah 		return ret;
354acd6510dSTanmay Shah 
355acd6510dSTanmay Shah 	/* try old implementation as fallback strategy if above fails */
356acd6510dSTanmay Shah 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_REGISTER_SGI, sgi_num,
357acd6510dSTanmay Shah 				   reset, NULL);
35876582671SRajan Vaja }
35976582671SRajan Vaja 
36076582671SRajan Vaja /**
36176582671SRajan Vaja  * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
36276582671SRajan Vaja  * @version:	Returned version value
36376582671SRajan Vaja  *
364b9b3a8beSRajan Vaja  * Return: Returns status, either success or error+reason
36576582671SRajan Vaja  */
zynqmp_pm_get_api_version(u32 * version)36676582671SRajan Vaja int zynqmp_pm_get_api_version(u32 *version)
36776582671SRajan Vaja {
36876582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
36976582671SRajan Vaja 	int ret;
37076582671SRajan Vaja 
37176582671SRajan Vaja 	if (!version)
37276582671SRajan Vaja 		return -EINVAL;
37376582671SRajan Vaja 
37476582671SRajan Vaja 	/* Check is PM API version already verified */
37576582671SRajan Vaja 	if (pm_api_version > 0) {
37676582671SRajan Vaja 		*version = pm_api_version;
37776582671SRajan Vaja 		return 0;
37876582671SRajan Vaja 	}
37976582671SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload);
38076582671SRajan Vaja 	*version = ret_payload[1];
38176582671SRajan Vaja 
382b9b3a8beSRajan Vaja 	return ret;
38376582671SRajan Vaja }
38476582671SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
385fe6f42cfSNava kishore Manne 
386fe6f42cfSNava kishore Manne /**
387fe6f42cfSNava kishore Manne  * zynqmp_pm_get_chipid - Get silicon ID registers
388fe6f42cfSNava kishore Manne  * @idcode:     IDCODE register
389fe6f42cfSNava kishore Manne  * @version:    version register
390fe6f42cfSNava kishore Manne  *
391fe6f42cfSNava kishore Manne  * Return:      Returns the status of the operation and the idcode and version
39221cd93baSRajan Vaja  *              registers in @idcode and @version.
393fe6f42cfSNava kishore Manne  */
zynqmp_pm_get_chipid(u32 * idcode,u32 * version)394fe6f42cfSNava kishore Manne int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
395fe6f42cfSNava kishore Manne {
396fe6f42cfSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
397fe6f42cfSNava kishore Manne 	int ret;
398fe6f42cfSNava kishore Manne 
399fe6f42cfSNava kishore Manne 	if (!idcode || !version)
400fe6f42cfSNava kishore Manne 		return -EINVAL;
401fe6f42cfSNava kishore Manne 
402fe6f42cfSNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
403fe6f42cfSNava kishore Manne 	*idcode = ret_payload[1];
404fe6f42cfSNava kishore Manne 	*version = ret_payload[2];
405fe6f42cfSNava kishore Manne 
40621cd93baSRajan Vaja 	return ret;
407fe6f42cfSNava kishore Manne }
408fe6f42cfSNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
40976582671SRajan Vaja 
41076582671SRajan Vaja /**
41176582671SRajan Vaja  * zynqmp_pm_get_family_info() - Get family info of platform
41276582671SRajan Vaja  * @family:	Returned family code value
41376582671SRajan Vaja  * @subfamily:	Returned sub-family code value
41476582671SRajan Vaja  *
41576582671SRajan Vaja  * Return: Returns status, either success or error+reason
41676582671SRajan Vaja  */
zynqmp_pm_get_family_info(u32 * family,u32 * subfamily)41776582671SRajan Vaja static int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily)
41876582671SRajan Vaja {
41976582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
42076582671SRajan Vaja 	u32 idcode;
42176582671SRajan Vaja 	int ret;
42276582671SRajan Vaja 
42376582671SRajan Vaja 	/* Check is family or sub-family code already received */
42476582671SRajan Vaja 	if (pm_family_code && pm_sub_family_code) {
42576582671SRajan Vaja 		*family = pm_family_code;
42676582671SRajan Vaja 		*subfamily = pm_sub_family_code;
42776582671SRajan Vaja 		return 0;
42876582671SRajan Vaja 	}
42976582671SRajan Vaja 
43076582671SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
43176582671SRajan Vaja 	if (ret < 0)
43276582671SRajan Vaja 		return ret;
43376582671SRajan Vaja 
43476582671SRajan Vaja 	idcode = ret_payload[1];
43576582671SRajan Vaja 	pm_family_code = FIELD_GET(FAMILY_CODE_MASK, idcode);
43676582671SRajan Vaja 	pm_sub_family_code = FIELD_GET(SUB_FAMILY_CODE_MASK, idcode);
43776582671SRajan Vaja 	*family = pm_family_code;
43876582671SRajan Vaja 	*subfamily = pm_sub_family_code;
43976582671SRajan Vaja 
44076582671SRajan Vaja 	return 0;
44176582671SRajan Vaja }
44276582671SRajan Vaja 
44376582671SRajan Vaja /**
44476582671SRajan Vaja  * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
44576582671SRajan Vaja  * @version:	Returned version value
44676582671SRajan Vaja  *
44776582671SRajan Vaja  * Return: Returns status, either success or error+reason
44876582671SRajan Vaja  */
zynqmp_pm_get_trustzone_version(u32 * version)44976582671SRajan Vaja static int zynqmp_pm_get_trustzone_version(u32 *version)
45076582671SRajan Vaja {
45176582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
45276582671SRajan Vaja 	int ret;
45376582671SRajan Vaja 
45476582671SRajan Vaja 	if (!version)
45576582671SRajan Vaja 		return -EINVAL;
45676582671SRajan Vaja 
45776582671SRajan Vaja 	/* Check is PM trustzone version already verified */
45876582671SRajan Vaja 	if (pm_tz_version > 0) {
45976582671SRajan Vaja 		*version = pm_tz_version;
46076582671SRajan Vaja 		return 0;
46176582671SRajan Vaja 	}
46276582671SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0,
46376582671SRajan Vaja 				  0, 0, ret_payload);
46459ecdd77SRajan Vaja 	*version = ret_payload[1];
46559ecdd77SRajan Vaja 
46659ecdd77SRajan Vaja 	return ret;
46759ecdd77SRajan Vaja }
46859ecdd77SRajan Vaja 
46959ecdd77SRajan Vaja /**
47059ecdd77SRajan Vaja  * get_set_conduit_method() - Choose SMC or HVC based communication
4716366c1baSRajan Vaja  * @np:		Pointer to the device_node structure
47259ecdd77SRajan Vaja  *
473f9627312SRajan Vaja  * Use SMC or HVC-based functions to communicate with EL2/EL3.
474f9627312SRajan Vaja  *
475f9627312SRajan Vaja  * Return: Returns 0 on success or error code
47659ecdd77SRajan Vaja  */
get_set_conduit_method(struct device_node * np)477f9627312SRajan Vaja static int get_set_conduit_method(struct device_node *np)
478f9627312SRajan Vaja {
479f9627312SRajan Vaja 	const char *method;
480f9627312SRajan Vaja 
481f9627312SRajan Vaja 	if (of_property_read_string(np, "method", &method)) {
482f9627312SRajan Vaja 		pr_warn("%s missing \"method\" property\n", __func__);
483f9627312SRajan Vaja 		return -ENXIO;
484f9627312SRajan Vaja 	}
4856366c1baSRajan Vaja 
486f9627312SRajan Vaja 	if (!strcmp("hvc", method)) {
487f9627312SRajan Vaja 		do_fw_call = do_fw_call_hvc;
488f9627312SRajan Vaja 	} else if (!strcmp("smc", method)) {
489f9627312SRajan Vaja 		do_fw_call = do_fw_call_smc;
490f9627312SRajan Vaja 	} else {
491f9627312SRajan Vaja 		pr_warn("%s Invalid \"method\" property: %s\n",
492f9627312SRajan Vaja 			__func__, method);
493f9627312SRajan Vaja 		return -EINVAL;
494f9627312SRajan Vaja 	}
495f9627312SRajan Vaja 
4963637e84cSRajan Vaja 	return 0;
497f9627312SRajan Vaja }
498f9627312SRajan Vaja 
499f9627312SRajan Vaja /**
5003637e84cSRajan Vaja  * zynqmp_pm_query_data() - Get query data from firmware
501f9627312SRajan Vaja  * @qdata:	Variable to the zynqmp_pm_query_data structure
502f9627312SRajan Vaja  * @out:	Returned output value
503f9627312SRajan Vaja  *
504f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
505f9627312SRajan Vaja  */
zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata,u32 * out)506f9627312SRajan Vaja int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
507f9627312SRajan Vaja {
508f9627312SRajan Vaja 	int ret;
509f9627312SRajan Vaja 
510f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1,
511f5ccd54bSRajan Vaja 				  qdata.arg2, qdata.arg3, out);
512f9627312SRajan Vaja 
513f9627312SRajan Vaja 	/*
514f9627312SRajan Vaja 	 * For clock name query, all bytes in SMC response are clock name
515f5ccd54bSRajan Vaja 	 * characters and return code is always success. For invalid clocks,
516f9627312SRajan Vaja 	 * clock name bytes would be zeros.
517f9627312SRajan Vaja 	 */
518f9627312SRajan Vaja 	return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
519f9627312SRajan Vaja }
520f9627312SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
521f9627312SRajan Vaja 
522f9627312SRajan Vaja /**
523f9627312SRajan Vaja  * zynqmp_pm_clock_enable() - Enable the clock for given id
524f9627312SRajan Vaja  * @clock_id:	ID of the clock to be enabled
525f9627312SRajan Vaja  *
526f9627312SRajan Vaja  * This function is used by master to enable the clock
5275e76731dSRajan Vaja  * including peripherals and PLL clocks.
528f9627312SRajan Vaja  *
529f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
530f9627312SRajan Vaja  */
zynqmp_pm_clock_enable(u32 clock_id)531f9627312SRajan Vaja int zynqmp_pm_clock_enable(u32 clock_id)
532f9627312SRajan Vaja {
533f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
534f9627312SRajan Vaja }
535f9627312SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
536f9627312SRajan Vaja 
537f9627312SRajan Vaja /**
5385e76731dSRajan Vaja  * zynqmp_pm_clock_disable() - Disable the clock for given id
539f9627312SRajan Vaja  * @clock_id:	ID of the clock to be disable
540f9627312SRajan Vaja  *
541f9627312SRajan Vaja  * This function is used by master to disable the clock
542f9627312SRajan Vaja  * including peripherals and PLL clocks.
543f9627312SRajan Vaja  *
544f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
545f9627312SRajan Vaja  */
zynqmp_pm_clock_disable(u32 clock_id)546f9627312SRajan Vaja int zynqmp_pm_clock_disable(u32 clock_id)
547f9627312SRajan Vaja {
548f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
549f9627312SRajan Vaja }
550fc9fb8fbSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
551f9627312SRajan Vaja 
552f9627312SRajan Vaja /**
553f9627312SRajan Vaja  * zynqmp_pm_clock_getstate() - Get the clock state for given id
554f9627312SRajan Vaja  * @clock_id:	ID of the clock to be queried
555fc9fb8fbSRajan Vaja  * @state:	1/0 (Enabled/Disabled)
556f9627312SRajan Vaja  *
557f9627312SRajan Vaja  * This function is used by master to get the state of clock
558f9627312SRajan Vaja  * including peripherals and PLL clocks.
559f9627312SRajan Vaja  *
560f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
561f9627312SRajan Vaja  */
zynqmp_pm_clock_getstate(u32 clock_id,u32 * state)562f9627312SRajan Vaja int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
563f9627312SRajan Vaja {
564f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
565f9627312SRajan Vaja 	int ret;
566f9627312SRajan Vaja 
5670667a8d1SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0,
568f9627312SRajan Vaja 				  0, 0, ret_payload);
569f9627312SRajan Vaja 	*state = ret_payload[1];
570f9627312SRajan Vaja 
571f9627312SRajan Vaja 	return ret;
572f9627312SRajan Vaja }
573f9627312SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
574f9627312SRajan Vaja 
575f9627312SRajan Vaja /**
576f9627312SRajan Vaja  * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
577f9627312SRajan Vaja  * @clock_id:	ID of the clock
5780667a8d1SRajan Vaja  * @divider:	divider value
579f9627312SRajan Vaja  *
580f9627312SRajan Vaja  * This function is used by master to set divider for any clock
581f9627312SRajan Vaja  * to achieve desired rate.
582f9627312SRajan Vaja  *
583f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
584f9627312SRajan Vaja  */
zynqmp_pm_clock_setdivider(u32 clock_id,u32 divider)585f9627312SRajan Vaja int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
586f9627312SRajan Vaja {
587f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
588f9627312SRajan Vaja 				   0, 0, NULL);
5897a1e1062SRajan Vaja }
590f9627312SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
591f9627312SRajan Vaja 
592f9627312SRajan Vaja /**
593f9627312SRajan Vaja  * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
594f9627312SRajan Vaja  * @clock_id:	ID of the clock
595f9627312SRajan Vaja  * @divider:	divider value
5967a1e1062SRajan Vaja  *
597f9627312SRajan Vaja  * This function is used by master to get divider values
598f9627312SRajan Vaja  * for any clock.
599f9627312SRajan Vaja  *
600f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
601f9627312SRajan Vaja  */
zynqmp_pm_clock_getdivider(u32 clock_id,u32 * divider)602f9627312SRajan Vaja int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
603f9627312SRajan Vaja {
604f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
605f9627312SRajan Vaja 	int ret;
606f9627312SRajan Vaja 
607f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0,
6087a1e1062SRajan Vaja 				  0, 0, ret_payload);
609f9627312SRajan Vaja 	*divider = ret_payload[1];
610f9627312SRajan Vaja 
611f9627312SRajan Vaja 	return ret;
612f9627312SRajan Vaja }
613f9627312SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
614f9627312SRajan Vaja 
615f9627312SRajan Vaja /**
616f9627312SRajan Vaja  * zynqmp_pm_clock_setrate() - Set the clock rate for given id
617f9627312SRajan Vaja  * @clock_id:	ID of the clock
618f9627312SRajan Vaja  * @rate:	rate value in hz
6197a1e1062SRajan Vaja  *
620f9627312SRajan Vaja  * This function is used by master to set rate for any clock.
621f9627312SRajan Vaja  *
622f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
623f9627312SRajan Vaja  */
zynqmp_pm_clock_setrate(u32 clock_id,u64 rate)624f9627312SRajan Vaja int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
625f9627312SRajan Vaja {
626f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
627f9627312SRajan Vaja 				   lower_32_bits(rate),
628f9627312SRajan Vaja 				   upper_32_bits(rate),
629f9627312SRajan Vaja 				   0, NULL);
63070c0d364SRajan Vaja }
631f9627312SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate);
632f9627312SRajan Vaja 
633f9627312SRajan Vaja /**
634f9627312SRajan Vaja  * zynqmp_pm_clock_getrate() - Get the clock rate for given id
63570c0d364SRajan Vaja  * @clock_id:	ID of the clock
636f9627312SRajan Vaja  * @rate:	rate value in hz
637f9627312SRajan Vaja  *
638f9627312SRajan Vaja  * This function is used by master to get rate
639f9627312SRajan Vaja  * for any clock.
640f9627312SRajan Vaja  *
641f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
642f9627312SRajan Vaja  */
zynqmp_pm_clock_getrate(u32 clock_id,u64 * rate)643f9627312SRajan Vaja int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
644f9627312SRajan Vaja {
645f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
646f9627312SRajan Vaja 	int ret;
64770c0d364SRajan Vaja 
648f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0,
649f9627312SRajan Vaja 				  0, 0, ret_payload);
650f9627312SRajan Vaja 	*rate = ((u64)ret_payload[2] << 32) | ret_payload[1];
651f9627312SRajan Vaja 
652f9627312SRajan Vaja 	return ret;
653f9627312SRajan Vaja }
654f9627312SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate);
655f9627312SRajan Vaja 
656f9627312SRajan Vaja /**
65759ecdd77SRajan Vaja  * zynqmp_pm_clock_setparent() - Set the clock parent for given id
65870c0d364SRajan Vaja  * @clock_id:	ID of the clock
65959ecdd77SRajan Vaja  * @parent_id:	parent id
6603b0296b8SRajan Vaja  *
661426c8d85SRajan Vaja  * This function is used by master to set parent for any clock.
6623b0296b8SRajan Vaja  *
663426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
664426c8d85SRajan Vaja  */
zynqmp_pm_clock_setparent(u32 clock_id,u32 parent_id)6653b0296b8SRajan Vaja int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
666426c8d85SRajan Vaja {
6673b0296b8SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
6683b0296b8SRajan Vaja 				   parent_id, 0, 0, NULL);
6693b0296b8SRajan Vaja }
670426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
6713b0296b8SRajan Vaja 
672426c8d85SRajan Vaja /**
673426c8d85SRajan Vaja  * zynqmp_pm_clock_getparent() - Get the clock parent for given id
6743b0296b8SRajan Vaja  * @clock_id:	ID of the clock
675426c8d85SRajan Vaja  * @parent_id:	parent id
676426c8d85SRajan Vaja  *
677426c8d85SRajan Vaja  * This function is used by master to get parent index
678426c8d85SRajan Vaja  * for any clock.
679426c8d85SRajan Vaja  *
680426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
681426c8d85SRajan Vaja  */
zynqmp_pm_clock_getparent(u32 clock_id,u32 * parent_id)682426c8d85SRajan Vaja int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
683426c8d85SRajan Vaja {
684426c8d85SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
685426c8d85SRajan Vaja 	int ret;
686426c8d85SRajan Vaja 
687426c8d85SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0,
688426c8d85SRajan Vaja 				  0, 0, ret_payload);
689426c8d85SRajan Vaja 	*parent_id = ret_payload[1];
690426c8d85SRajan Vaja 
691426c8d85SRajan Vaja 	return ret;
692426c8d85SRajan Vaja }
693426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
694426c8d85SRajan Vaja 
695426c8d85SRajan Vaja /**
696426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
697426c8d85SRajan Vaja  *
698426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
699426c8d85SRajan Vaja  * @mode:	PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
700426c8d85SRajan Vaja  *
701426c8d85SRajan Vaja  * This function sets PLL mode
702426c8d85SRajan Vaja  *
703426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
704426c8d85SRajan Vaja  */
zynqmp_pm_set_pll_frac_mode(u32 clk_id,u32 mode)705426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
706426c8d85SRajan Vaja {
707426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE,
708426c8d85SRajan Vaja 				   clk_id, mode, NULL);
709426c8d85SRajan Vaja }
710426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
711426c8d85SRajan Vaja 
712426c8d85SRajan Vaja /**
713426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
714426c8d85SRajan Vaja  *
715426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
716426c8d85SRajan Vaja  * @mode:	PLL mode
717426c8d85SRajan Vaja  *
718426c8d85SRajan Vaja  * This function return current PLL mode
719426c8d85SRajan Vaja  *
720426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
721426c8d85SRajan Vaja  */
zynqmp_pm_get_pll_frac_mode(u32 clk_id,u32 * mode)722426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
723426c8d85SRajan Vaja {
724426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE,
725426c8d85SRajan Vaja 				   clk_id, 0, mode);
726426c8d85SRajan Vaja }
727426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
728426c8d85SRajan Vaja 
729426c8d85SRajan Vaja /**
730426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
731426c8d85SRajan Vaja  *
732332bee16SMichal Simek  * @clk_id:	PLL clock ID
733332bee16SMichal Simek  * @data:	fraction data
734332bee16SMichal Simek  *
735426c8d85SRajan Vaja  * This function sets fraction data.
736426c8d85SRajan Vaja  * It is valid for fraction mode only.
737426c8d85SRajan Vaja  *
738332bee16SMichal Simek  * Return: Returns status, either success or error+reason
739426c8d85SRajan Vaja  */
zynqmp_pm_set_pll_frac_data(u32 clk_id,u32 data)740426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
741426c8d85SRajan Vaja {
742a4b2e606SMarek Vasut 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA,
743a4b2e606SMarek Vasut 				   clk_id, data, NULL);
744a4b2e606SMarek Vasut }
745a4b2e606SMarek Vasut EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
746a4b2e606SMarek Vasut 
747a4b2e606SMarek Vasut /**
748426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
749426c8d85SRajan Vaja  *
750a4b2e606SMarek Vasut  * @clk_id:	PLL clock ID
751a4b2e606SMarek Vasut  * @data:	fraction data
752a4b2e606SMarek Vasut  *
753a4b2e606SMarek Vasut  * This function returns fraction data value.
754a4b2e606SMarek Vasut  *
755a4b2e606SMarek Vasut  * Return: Returns status, either success or error+reason
756a4b2e606SMarek Vasut  */
zynqmp_pm_get_pll_frac_data(u32 clk_id,u32 * data)757a4b2e606SMarek Vasut int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
758a4b2e606SMarek Vasut {
759a4b2e606SMarek Vasut 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA,
760a4b2e606SMarek Vasut 				   clk_id, 0, data);
761a4b2e606SMarek Vasut }
762a4b2e606SMarek Vasut EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
763a4b2e606SMarek Vasut 
764a4b2e606SMarek Vasut /**
765a4b2e606SMarek Vasut  * zynqmp_pm_set_sd_tapdelay() -  Set tap delay for the SD device
766a4b2e606SMarek Vasut  *
767a4b2e606SMarek Vasut  * @node_id:	Node ID of the device
768426c8d85SRajan Vaja  * @type:	Type of tap delay to set (input/output)
769426c8d85SRajan Vaja  * @value:	Value to set fot the tap delay
770426c8d85SRajan Vaja  *
771426c8d85SRajan Vaja  * This function sets input/output tap delay for the SD device.
772426c8d85SRajan Vaja  *
773332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
774332bee16SMichal Simek  */
zynqmp_pm_set_sd_tapdelay(u32 node_id,u32 type,u32 value)775426c8d85SRajan Vaja int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
776426c8d85SRajan Vaja {
777426c8d85SRajan Vaja 	u32 reg = (type == PM_TAPDELAY_INPUT) ? SD_ITAPDLY : SD_OTAPDLYSEL;
778332bee16SMichal Simek 	u32 mask = (node_id == NODE_SD_0) ? GENMASK(15, 0) : GENMASK(31, 16);
779426c8d85SRajan Vaja 
780426c8d85SRajan Vaja 	if (value) {
781426c8d85SRajan Vaja 		return zynqmp_pm_invoke_fn(PM_IOCTL, node_id,
782f4426311SManish Narani 					   IOCTL_SET_SD_TAPDELAY,
783426c8d85SRajan Vaja 					   type, value, NULL);
784426c8d85SRajan Vaja 	}
785426c8d85SRajan Vaja 
7863b0296b8SRajan Vaja 	/*
787bc3843d4SNava kishore Manne 	 * Work around completely misdesigned firmware API on Xilinx ZynqMP.
78874e78adcSSai Krishna Potthuri 	 * The IOCTL_SET_SD_TAPDELAY firmware call allows the caller to only
78974e78adcSSai Krishna Potthuri 	 * ever set IOU_SLCR SD_ITAPDLY Register SD0_ITAPDLYENA/SD1_ITAPDLYENA
79074e78adcSSai Krishna Potthuri 	 * bits, but there is no matching call to clear those bits. If those
79174e78adcSSai Krishna Potthuri 	 * bits are not cleared, SDMMC tuning may fail.
79274e78adcSSai Krishna Potthuri 	 *
79374e78adcSSai Krishna Potthuri 	 * Luckily, there are PM_MMIO_READ/PM_MMIO_WRITE calls which seem to
79474e78adcSSai Krishna Potthuri 	 * allow complete unrestricted access to all address space, including
79574e78adcSSai Krishna Potthuri 	 * IOU_SLCR SD_ITAPDLY Register and all the other registers, access
79674e78adcSSai Krishna Potthuri 	 * to which was supposed to be protected by the current firmware API.
79774e78adcSSai Krishna Potthuri 	 *
79874e78adcSSai Krishna Potthuri 	 * Use PM_MMIO_READ/PM_MMIO_WRITE to re-implement the missing counter
79974e78adcSSai Krishna Potthuri 	 * part of IOCTL_SET_SD_TAPDELAY which clears SDx_ITAPDLYENA bits.
80074e78adcSSai Krishna Potthuri 	 */
80174e78adcSSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, reg, mask, 0, 0, NULL);
80274e78adcSSai Krishna Potthuri }
80374e78adcSSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
80474e78adcSSai Krishna Potthuri 
8054f680b72SRajan Vaja /**
806332bee16SMichal Simek  * zynqmp_pm_sd_dll_reset() - Reset DLL logic
807332bee16SMichal Simek  *
8084f680b72SRajan Vaja  * @node_id:	Node ID of the device
8094f680b72SRajan Vaja  * @type:	Reset type
8104f680b72SRajan Vaja  *
811332bee16SMichal Simek  * This function resets DLL logic for the SD device.
8124f680b72SRajan Vaja  *
8134f680b72SRajan Vaja  * Return:	Returns status, either success or error+reason
8144f680b72SRajan Vaja  */
zynqmp_pm_sd_dll_reset(u32 node_id,u32 type)8154f680b72SRajan Vaja int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
8164f680b72SRajan Vaja {
8174f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET,
8184f680b72SRajan Vaja 				   type, 0, NULL);
8194f680b72SRajan Vaja }
8204f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
8212a8faf8dSMichal Simek 
822332bee16SMichal Simek /**
823332bee16SMichal Simek  * zynqmp_pm_ospi_mux_select() - OSPI Mux selection
8244f680b72SRajan Vaja  *
8254f680b72SRajan Vaja  * @dev_id:	Device Id of the OSPI device.
8264f680b72SRajan Vaja  * @select:	OSPI Mux select value.
827332bee16SMichal Simek  *
8284f680b72SRajan Vaja  * This function select the OSPI Mux.
8294f680b72SRajan Vaja  *
8304f680b72SRajan Vaja  * Return:	Returns status, either success or error+reason
8314f680b72SRajan Vaja  */
zynqmp_pm_ospi_mux_select(u32 dev_id,u32 select)8324f680b72SRajan Vaja int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
8334f680b72SRajan Vaja {
8344f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, dev_id, IOCTL_OSPI_MUX_SELECT,
8354f680b72SRajan Vaja 				   select, 0, NULL);
8364f680b72SRajan Vaja }
8374f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select);
8384f680b72SRajan Vaja 
839332bee16SMichal Simek /**
840332bee16SMichal Simek  * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
8414f680b72SRajan Vaja  * @index:	GGS register index
8424f680b72SRajan Vaja  * @value:	Register value to be written
8434f680b72SRajan Vaja  *
844332bee16SMichal Simek  * This function writes value to GGS register.
8454f680b72SRajan Vaja  *
8464f680b72SRajan Vaja  * Return:      Returns status, either success or error+reason
8474f680b72SRajan Vaja  */
zynqmp_pm_write_ggs(u32 index,u32 value)8484f680b72SRajan Vaja int zynqmp_pm_write_ggs(u32 index, u32 value)
8494f680b72SRajan Vaja {
8504f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS,
8514f680b72SRajan Vaja 				   index, value, NULL);
8524f680b72SRajan Vaja }
8534f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
8542a8faf8dSMichal Simek 
8554f680b72SRajan Vaja /**
856332bee16SMichal Simek  * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs)
857332bee16SMichal Simek  * @index:	GGS register index
8584f680b72SRajan Vaja  * @value:	Register value to be written
8594f680b72SRajan Vaja  *
8604f680b72SRajan Vaja  * This function returns GGS register value.
861332bee16SMichal Simek  *
8624f680b72SRajan Vaja  * Return:	Returns status, either success or error+reason
8634f680b72SRajan Vaja  */
zynqmp_pm_read_ggs(u32 index,u32 * value)8644f680b72SRajan Vaja int zynqmp_pm_read_ggs(u32 index, u32 *value)
8654f680b72SRajan Vaja {
8664f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS,
8674f680b72SRajan Vaja 				   index, 0, value);
8684f680b72SRajan Vaja }
8694f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
8701e400cb9SRajan Vaja 
8711e400cb9SRajan Vaja /**
8721e400cb9SRajan Vaja  * zynqmp_pm_write_pggs() - PM API for writing persistent global general
8731e400cb9SRajan Vaja  *			     storage (pggs)
8741e400cb9SRajan Vaja  * @index:	PGGS register index
8751e400cb9SRajan Vaja  * @value:	Register value to be written
8761e400cb9SRajan Vaja  *
8774f680b72SRajan Vaja  * This function writes value to PGGS register.
878a2cc220aSRajan Vaja  *
879332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
880a2cc220aSRajan Vaja  */
zynqmp_pm_write_pggs(u32 index,u32 value)881a2cc220aSRajan Vaja int zynqmp_pm_write_pggs(u32 index, u32 value)
882a2cc220aSRajan Vaja {
883a2cc220aSRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value,
884332bee16SMichal Simek 				   NULL);
885a2cc220aSRajan Vaja }
886a2cc220aSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
887a2cc220aSRajan Vaja 
888a2cc220aSRajan Vaja /**
889a2cc220aSRajan Vaja  * zynqmp_pm_read_pggs() - PM API for reading persistent global general
890a2cc220aSRajan Vaja  *			     storage (pggs)
891a2cc220aSRajan Vaja  * @index:	PGGS register index
892a2cc220aSRajan Vaja  * @value:	Register value to be written
893bc3843d4SNava kishore Manne  *
894bc3843d4SNava kishore Manne  * This function returns PGGS register value.
895bc3843d4SNava kishore Manne  *
896bc3843d4SNava kishore Manne  * Return:	Returns status, either success or error+reason
897bc3843d4SNava kishore Manne  */
zynqmp_pm_read_pggs(u32 index,u32 * value)898bc3843d4SNava kishore Manne int zynqmp_pm_read_pggs(u32 index, u32 *value)
899bc3843d4SNava kishore Manne {
900cf23ec35SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0,
901bc3843d4SNava kishore Manne 				   value);
902bc3843d4SNava kishore Manne }
903bc3843d4SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
904bc3843d4SNava kishore Manne 
zynqmp_pm_set_tapdelay_bypass(u32 index,u32 value)905bc3843d4SNava kishore Manne int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value)
906cf23ec35SRajan Vaja {
907bc3843d4SNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_TAPDELAY_BYPASS,
908bc3843d4SNava kishore Manne 				   index, value, NULL);
909bc3843d4SNava kishore Manne }
910bc3843d4SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass);
911bc3843d4SNava kishore Manne 
912bc3843d4SNava kishore Manne /**
913bc3843d4SNava kishore Manne  * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
914bc3843d4SNava kishore Manne  * @value:	Status value to be written
9151b413581SRajan Vaja  *
916bc3843d4SNava kishore Manne  * This function sets healthy bit value to indicate boot health status
917bc3843d4SNava kishore Manne  * to firmware.
918bc3843d4SNava kishore Manne  *
919bc3843d4SNava kishore Manne  * Return:	Returns status, either success or error+reason
920bc3843d4SNava kishore Manne  */
zynqmp_pm_set_boot_health_status(u32 value)921bc3843d4SNava kishore Manne int zynqmp_pm_set_boot_health_status(u32 value)
922bc3843d4SNava kishore Manne {
923bc3843d4SNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS,
924bc3843d4SNava kishore Manne 				   value, 0, NULL);
925bc3843d4SNava kishore Manne }
926bc3843d4SNava kishore Manne 
927bc3843d4SNava kishore Manne /**
928bc3843d4SNava kishore Manne  * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
9291b413581SRajan Vaja  * @reset:		Reset to be configured
930bc3843d4SNava kishore Manne  * @assert_flag:	Flag stating should reset be asserted (1) or
931e178df31SJolly Shah  *			released (0)
932e840deccSNava kishore Manne  *
933e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
934e840deccSNava kishore Manne  */
zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,const enum zynqmp_pm_reset_action assert_flag)935e840deccSNava kishore Manne int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
936e840deccSNava kishore Manne 			   const enum zynqmp_pm_reset_action assert_flag)
937e840deccSNava kishore Manne {
938e840deccSNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
939e840deccSNava kishore Manne 				   0, 0, NULL);
940e840deccSNava kishore Manne }
941e840deccSNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
942e840deccSNava kishore Manne 
943e840deccSNava kishore Manne /**
9444db8180fSRajan Vaja  * zynqmp_pm_reset_get_status - Get status of the reset
945e840deccSNava kishore Manne  * @reset:      Reset whose status should be returned
946e2ebc05dSNava kishore Manne  * @status:     Returned status
947e2ebc05dSNava kishore Manne  *
948e2ebc05dSNava kishore Manne  * Return: Returns status, either success or error+reason
949e2ebc05dSNava kishore Manne  */
zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,u32 * status)950e2ebc05dSNava kishore Manne int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
951e2ebc05dSNava kishore Manne {
952e2ebc05dSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
953e2ebc05dSNava kishore Manne 	int ret;
954e2ebc05dSNava kishore Manne 
955e2ebc05dSNava kishore Manne 	if (!status)
956e840deccSNava kishore Manne 		return -EINVAL;
95756a9a806SNathan Chancellor 
958e840deccSNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
959e840deccSNava kishore Manne 				  0, 0, ret_payload);
960e840deccSNava kishore Manne 	*status = ret_payload[1];
961e840deccSNava kishore Manne 
962e840deccSNava kishore Manne 	return ret;
963e840deccSNava kishore Manne }
964e840deccSNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
965e840deccSNava kishore Manne 
966e840deccSNava kishore Manne /**
967e840deccSNava kishore Manne  * zynqmp_pm_fpga_load - Perform the fpga load
9684db8180fSRajan Vaja  * @address:	Address to write to
969e840deccSNava kishore Manne  * @size:	pl bitstream size
970e840deccSNava kishore Manne  * @flags:	Bitstream type
971e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
972e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
973e840deccSNava kishore Manne  *
974e840deccSNava kishore Manne  * This function provides access to pmufw. To transfer
975e840deccSNava kishore Manne  * the required bitstream into PL.
976e840deccSNava kishore Manne  *
977e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
978e840deccSNava kishore Manne  */
zynqmp_pm_fpga_load(const u64 address,const u32 size,const u32 flags)979e840deccSNava kishore Manne int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
980e840deccSNava kishore Manne {
98156a9a806SNathan Chancellor 	u32 ret_payload[PAYLOAD_ARG_CNT];
982e840deccSNava kishore Manne 	int ret;
983e840deccSNava kishore Manne 
9848f118f61SNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
9858f118f61SNava kishore Manne 				  upper_32_bits(address), size, flags,
9868f118f61SNava kishore Manne 				  ret_payload);
9878f118f61SNava kishore Manne 	if (ret_payload[0])
9888f118f61SNava kishore Manne 		return -ret_payload[0];
9898f118f61SNava kishore Manne 
9908f118f61SNava kishore Manne 	return ret;
9918f118f61SNava kishore Manne }
9928f118f61SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
9938f118f61SNava kishore Manne 
9948f118f61SNava kishore Manne /**
9958f118f61SNava kishore Manne  * zynqmp_pm_fpga_get_status - Read value from PCAP status register
9968f118f61SNava kishore Manne  * @value: Value to read
9978f118f61SNava kishore Manne  *
9988f118f61SNava kishore Manne  * This function provides access to the pmufw to get the PCAP
9998f118f61SNava kishore Manne  * status
10008f118f61SNava kishore Manne  *
10018f118f61SNava kishore Manne  * Return: Returns status, either success or error+reason
10028f118f61SNava kishore Manne  */
zynqmp_pm_fpga_get_status(u32 * value)10038f118f61SNava kishore Manne int zynqmp_pm_fpga_get_status(u32 *value)
10048f118f61SNava kishore Manne {
10058f118f61SNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
10068f118f61SNava kishore Manne 	int ret;
10078f118f61SNava kishore Manne 
10088f118f61SNava kishore Manne 	if (!value)
10098f118f61SNava kishore Manne 		return -EINVAL;
10108f118f61SNava kishore Manne 
10118f118f61SNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
10128f118f61SNava kishore Manne 	*value = ret_payload[1];
10138f118f61SNava kishore Manne 
10148f118f61SNava kishore Manne 	return ret;
10158f118f61SNava kishore Manne }
10168f118f61SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
1017fa989ae7SSai Krishna Potthuri 
1018fa989ae7SSai Krishna Potthuri /**
1019fa989ae7SSai Krishna Potthuri  * zynqmp_pm_fpga_get_config_status - Get the FPGA configuration status.
1020fa989ae7SSai Krishna Potthuri  * @value: Buffer to store FPGA configuration status.
1021fa989ae7SSai Krishna Potthuri  *
1022fa989ae7SSai Krishna Potthuri  * This function provides access to the pmufw to get the FPGA configuration
1023fa989ae7SSai Krishna Potthuri  * status
1024fa989ae7SSai Krishna Potthuri  *
1025fa989ae7SSai Krishna Potthuri  * Return: 0 on success, a negative value on error
1026fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_fpga_get_config_status(u32 * value)1027fa989ae7SSai Krishna Potthuri int zynqmp_pm_fpga_get_config_status(u32 *value)
1028fa989ae7SSai Krishna Potthuri {
1029fa989ae7SSai Krishna Potthuri 	u32 ret_payload[PAYLOAD_ARG_CNT];
1030fa989ae7SSai Krishna Potthuri 	u32 buf, lower_addr, upper_addr;
1031fa989ae7SSai Krishna Potthuri 	int ret;
1032fa989ae7SSai Krishna Potthuri 
1033fa989ae7SSai Krishna Potthuri 	if (!value)
1034fa989ae7SSai Krishna Potthuri 		return -EINVAL;
1035fa989ae7SSai Krishna Potthuri 
1036fa989ae7SSai Krishna Potthuri 	lower_addr = lower_32_bits((u64)&buf);
1037fa989ae7SSai Krishna Potthuri 	upper_addr = upper_32_bits((u64)&buf);
1038fa989ae7SSai Krishna Potthuri 
1039fa989ae7SSai Krishna Potthuri 	ret = zynqmp_pm_invoke_fn(PM_FPGA_READ,
1040fa989ae7SSai Krishna Potthuri 				  XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET,
1041fa989ae7SSai Krishna Potthuri 				  lower_addr, upper_addr,
1042fa989ae7SSai Krishna Potthuri 				  XILINX_ZYNQMP_PM_FPGA_READ_CONFIG_REG,
1043fa989ae7SSai Krishna Potthuri 				  ret_payload);
1044fa989ae7SSai Krishna Potthuri 
1045fa989ae7SSai Krishna Potthuri 	*value = ret_payload[1];
1046fa989ae7SSai Krishna Potthuri 
1047fa989ae7SSai Krishna Potthuri 	return ret;
1048fa989ae7SSai Krishna Potthuri }
1049fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_config_status);
1050fa989ae7SSai Krishna Potthuri 
1051fa989ae7SSai Krishna Potthuri /**
1052fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_request - Request Pin from firmware
1053fa989ae7SSai Krishna Potthuri  * @pin: Pin number to request
1054fa989ae7SSai Krishna Potthuri  *
1055fa989ae7SSai Krishna Potthuri  * This function requests pin from firmware.
1056fa989ae7SSai Krishna Potthuri  *
1057fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1058fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_request(const u32 pin)1059fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_request(const u32 pin)
1060fa989ae7SSai Krishna Potthuri {
1061fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
1062fa989ae7SSai Krishna Potthuri }
1063fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request);
1064fa989ae7SSai Krishna Potthuri 
1065fa989ae7SSai Krishna Potthuri /**
1066fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
1067fa989ae7SSai Krishna Potthuri  * @pin: Pin number to release
1068fa989ae7SSai Krishna Potthuri  *
1069fa989ae7SSai Krishna Potthuri  * This function release pin from firmware.
1070fa989ae7SSai Krishna Potthuri  *
1071fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1072fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_release(const u32 pin)1073fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_release(const u32 pin)
1074fa989ae7SSai Krishna Potthuri {
1075fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL);
1076fa989ae7SSai Krishna Potthuri }
1077fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release);
1078fa989ae7SSai Krishna Potthuri 
1079fa989ae7SSai Krishna Potthuri /**
1080fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin
1081fa989ae7SSai Krishna Potthuri  * @pin: Pin number
1082fa989ae7SSai Krishna Potthuri  * @id: Buffer to store function ID
1083fa989ae7SSai Krishna Potthuri  *
1084fa989ae7SSai Krishna Potthuri  * This function provides the function currently set for the given pin.
1085fa989ae7SSai Krishna Potthuri  *
1086fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason
1087fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_get_function(const u32 pin,u32 * id)1088fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id)
1089fa989ae7SSai Krishna Potthuri {
1090fa989ae7SSai Krishna Potthuri 	u32 ret_payload[PAYLOAD_ARG_CNT];
1091fa989ae7SSai Krishna Potthuri 	int ret;
1092fa989ae7SSai Krishna Potthuri 
1093fa989ae7SSai Krishna Potthuri 	if (!id)
1094fa989ae7SSai Krishna Potthuri 		return -EINVAL;
1095fa989ae7SSai Krishna Potthuri 
1096fa989ae7SSai Krishna Potthuri 	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0,
1097fa989ae7SSai Krishna Potthuri 				  0, 0, ret_payload);
1098fa989ae7SSai Krishna Potthuri 	*id = ret_payload[1];
1099fa989ae7SSai Krishna Potthuri 
1100fa989ae7SSai Krishna Potthuri 	return ret;
1101fa989ae7SSai Krishna Potthuri }
1102fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_function);
1103fa989ae7SSai Krishna Potthuri 
1104fa989ae7SSai Krishna Potthuri /**
1105fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
1106fa989ae7SSai Krishna Potthuri  * @pin: Pin number
1107fa989ae7SSai Krishna Potthuri  * @id: Function ID to set
1108fa989ae7SSai Krishna Potthuri  *
1109fa989ae7SSai Krishna Potthuri  * This function sets requested function for the given pin.
1110fa989ae7SSai Krishna Potthuri  *
1111fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1112fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_set_function(const u32 pin,const u32 id)1113fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
1114fa989ae7SSai Krishna Potthuri {
1115fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id,
1116fa989ae7SSai Krishna Potthuri 				   0, 0, NULL);
1117fa989ae7SSai Krishna Potthuri }
1118fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function);
1119fa989ae7SSai Krishna Potthuri 
1120fa989ae7SSai Krishna Potthuri /**
1121fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
1122fa989ae7SSai Krishna Potthuri  * @pin: Pin number
1123fa989ae7SSai Krishna Potthuri  * @param: Parameter to get
1124fa989ae7SSai Krishna Potthuri  * @value: Buffer to store parameter value
1125fa989ae7SSai Krishna Potthuri  *
1126fa989ae7SSai Krishna Potthuri  * This function gets requested configuration parameter for the given pin.
1127fa989ae7SSai Krishna Potthuri  *
1128fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
1129fa989ae7SSai Krishna Potthuri  */
zynqmp_pm_pinctrl_get_config(const u32 pin,const u32 param,u32 * value)1130fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
113123c64d76SPiyush Mehta 				 u32 *value)
113223c64d76SPiyush Mehta {
113323c64d76SPiyush Mehta 	u32 ret_payload[PAYLOAD_ARG_CNT];
113423c64d76SPiyush Mehta 	int ret;
113523c64d76SPiyush Mehta 
113623c64d76SPiyush Mehta 	if (!value)
113723c64d76SPiyush Mehta 		return -EINVAL;
113823c64d76SPiyush Mehta 
113923c64d76SPiyush Mehta 	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param,
114023c64d76SPiyush Mehta 				  0, 0, ret_payload);
114123c64d76SPiyush Mehta 	*value = ret_payload[1];
114223c64d76SPiyush Mehta 
114323c64d76SPiyush Mehta 	return ret;
114423c64d76SPiyush Mehta }
114523c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config);
114623c64d76SPiyush Mehta 
114723c64d76SPiyush Mehta /**
114823c64d76SPiyush Mehta  * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
114923c64d76SPiyush Mehta  * @pin: Pin number
115023c64d76SPiyush Mehta  * @param: Parameter to set
115123c64d76SPiyush Mehta  * @value: Parameter value to set
115223c64d76SPiyush Mehta  *
115323c64d76SPiyush Mehta  * This function sets requested configuration parameter for the given pin.
115423c64d76SPiyush Mehta  *
115523c64d76SPiyush Mehta  * Return: Returns status, either success or error+reason.
115623c64d76SPiyush Mehta  */
zynqmp_pm_pinctrl_set_config(const u32 pin,const u32 param,u32 value)115723c64d76SPiyush Mehta int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
115823c64d76SPiyush Mehta 				 u32 value)
115923c64d76SPiyush Mehta {
116023c64d76SPiyush Mehta 	int ret;
116123c64d76SPiyush Mehta 
116223c64d76SPiyush Mehta 	if (pm_family_code == ZYNQMP_FAMILY_CODE &&
116323c64d76SPiyush Mehta 	    param == PM_PINCTRL_CONFIG_TRI_STATE) {
116423c64d76SPiyush Mehta 		ret = zynqmp_pm_feature(PM_PINCTRL_CONFIG_PARAM_SET);
116523c64d76SPiyush Mehta 		if (ret < PM_PINCTRL_PARAM_SET_VERSION)
116623c64d76SPiyush Mehta 			return -EOPNOTSUPP;
116723c64d76SPiyush Mehta 	}
116823c64d76SPiyush Mehta 
116923c64d76SPiyush Mehta 	return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin,
1170e178df31SJolly Shah 				   param, value, 0, NULL);
1171e178df31SJolly Shah }
1172e178df31SJolly Shah EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config);
1173332bee16SMichal Simek 
1174332bee16SMichal Simek /**
1175e178df31SJolly Shah  * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status
1176e178df31SJolly Shah  * @ps_mode: Returned output value of ps_mode
1177e178df31SJolly Shah  *
11789474da95SRajan Vaja  * This API function is to be used for notify the power management controller
1179e178df31SJolly Shah  * to read bootpin status.
1180e178df31SJolly Shah  *
1181e178df31SJolly Shah  * Return: status, either success or error+reason
11829474da95SRajan Vaja  */
zynqmp_pm_bootmode_read(u32 * ps_mode)1183e178df31SJolly Shah unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode)
1184e178df31SJolly Shah {
1185e178df31SJolly Shah 	unsigned int ret;
1186e178df31SJolly Shah 	u32 ret_payload[PAYLOAD_ARG_CNT];
1187e178df31SJolly Shah 
1188e178df31SJolly Shah 	ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, CRL_APB_BOOT_PIN_CTRL, 0,
1189e178df31SJolly Shah 				  0, 0, ret_payload);
1190e178df31SJolly Shah 
1191e178df31SJolly Shah 	*ps_mode = ret_payload[1];
1192951d0a97SRajan Vaja 
1193e178df31SJolly Shah 	return ret;
1194e178df31SJolly Shah }
1195e178df31SJolly Shah EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read);
1196951d0a97SRajan Vaja 
1197e178df31SJolly Shah /**
1198c1986ac3SRajan Vaja  * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin
1199c1986ac3SRajan Vaja  * @ps_mode: Value to be written to the bootpin ctrl register
1200c1986ac3SRajan Vaja  *
1201c1986ac3SRajan Vaja  * This API function is to be used for notify the power management controller
1202c1986ac3SRajan Vaja  * to configure bootpin.
1203c1986ac3SRajan Vaja  *
1204c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1205c1986ac3SRajan Vaja  */
zynqmp_pm_bootmode_write(u32 ps_mode)1206c1986ac3SRajan Vaja int zynqmp_pm_bootmode_write(u32 ps_mode)
1207c1986ac3SRajan Vaja {
1208c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, CRL_APB_BOOT_PIN_CTRL,
1209c1986ac3SRajan Vaja 				   CRL_APB_BOOTPIN_CTRL_MASK, ps_mode, 0, NULL);
1210bf8b27edSRajan Vaja }
1211bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write);
1212c1986ac3SRajan Vaja 
1213c1986ac3SRajan Vaja /**
1214c1986ac3SRajan Vaja  * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
1215c1986ac3SRajan Vaja  *			       master has initialized its own power management
1216bf8b27edSRajan Vaja  *
1217c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1218c1986ac3SRajan Vaja  *
1219c1986ac3SRajan Vaja  * This API function is to be used for notify the power management controller
1220c1986ac3SRajan Vaja  * about the completed power management initialization.
1221c1986ac3SRajan Vaja  */
zynqmp_pm_init_finalize(void)1222c1986ac3SRajan Vaja int zynqmp_pm_init_finalize(void)
1223c1986ac3SRajan Vaja {
1224c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
1225c1986ac3SRajan Vaja }
1226c1986ac3SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize);
1227c1986ac3SRajan Vaja 
122807fb1a46SRajan Vaja /**
1229c1986ac3SRajan Vaja  * zynqmp_pm_set_suspend_mode()	- Set system suspend mode
1230c1986ac3SRajan Vaja  * @mode:	Mode to set for system suspend
1231c1986ac3SRajan Vaja  *
123207fb1a46SRajan Vaja  * This API function is used to set mode of system suspend.
1233c1986ac3SRajan Vaja  *
1234c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1235a5e56980SBen Levinsky  */
zynqmp_pm_set_suspend_mode(u32 mode)1236a5e56980SBen Levinsky int zynqmp_pm_set_suspend_mode(u32 mode)
1237a5e56980SBen Levinsky {
1238a5e56980SBen Levinsky 	return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
1239a5e56980SBen Levinsky }
1240a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
1241a5e56980SBen Levinsky 
1242a5e56980SBen Levinsky /**
1243a5e56980SBen Levinsky  * zynqmp_pm_request_node() - Request a node with specific capabilities
1244a5e56980SBen Levinsky  * @node:		Node ID of the slave
1245a5e56980SBen Levinsky  * @capabilities:	Requested capabilities of the slave
1246a5e56980SBen Levinsky  * @qos:		Quality of service (not supported)
1247a5e56980SBen Levinsky  * @ack:		Flag to specify whether acknowledge is requested
1248a5e56980SBen Levinsky  *
1249a5e56980SBen Levinsky  * This function is used by master to request particular node from firmware.
1250a5e56980SBen Levinsky  * Every master must request node before using it.
1251a5e56980SBen Levinsky  *
1252a5e56980SBen Levinsky  * Return: Returns status, either success or error+reason
1253a5e56980SBen Levinsky  */
zynqmp_pm_request_node(const u32 node,const u32 capabilities,const u32 qos,const enum zynqmp_pm_request_ack ack)1254a5e56980SBen Levinsky int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
1255a5e56980SBen Levinsky 			   const u32 qos, const enum zynqmp_pm_request_ack ack)
1256a5e56980SBen Levinsky {
1257a5e56980SBen Levinsky 	return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
1258a5e56980SBen Levinsky 				   qos, ack, NULL);
1259a5e56980SBen Levinsky }
1260a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
1261a5e56980SBen Levinsky 
1262a5e56980SBen Levinsky /**
1263a5e56980SBen Levinsky  * zynqmp_pm_release_node() - Release a node
1264a5e56980SBen Levinsky  * @node:	Node ID of the slave
1265a5e56980SBen Levinsky  *
1266a5e56980SBen Levinsky  * This function is used by master to inform firmware that master
1267a5e56980SBen Levinsky  * has released node. Once released, master must not use that node
1268a5e56980SBen Levinsky  * without re-request.
1269a5e56980SBen Levinsky  *
1270a5e56980SBen Levinsky  * Return: Returns status, either success or error+reason
1271a5e56980SBen Levinsky  */
zynqmp_pm_release_node(const u32 node)1272a5e56980SBen Levinsky int zynqmp_pm_release_node(const u32 node)
1273a5e56980SBen Levinsky {
1274a5e56980SBen Levinsky 	return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
1275a5e56980SBen Levinsky }
1276a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
1277a5e56980SBen Levinsky 
1278a5e56980SBen Levinsky /**
1279a5e56980SBen Levinsky  * zynqmp_pm_get_rpu_mode() - Get RPU mode
1280a5e56980SBen Levinsky  * @node_id:	Node ID of the device
1281a5e56980SBen Levinsky  * @rpu_mode:	return by reference value
1282a5e56980SBen Levinsky  *		either split or lockstep
1283a5e56980SBen Levinsky  *
1284a5e56980SBen Levinsky  * Return:	return 0 on success or error+reason.
1285a5e56980SBen Levinsky  *		if success, then  rpu_mode will be set
1286a5e56980SBen Levinsky  *		to current rpu mode.
1287a5e56980SBen Levinsky  */
zynqmp_pm_get_rpu_mode(u32 node_id,enum rpu_oper_mode * rpu_mode)1288a5e56980SBen Levinsky int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mode)
1289a5e56980SBen Levinsky {
1290a5e56980SBen Levinsky 	u32 ret_payload[PAYLOAD_ARG_CNT];
1291a5e56980SBen Levinsky 	int ret;
1292a5e56980SBen Levinsky 
1293a5e56980SBen Levinsky 	ret = zynqmp_pm_invoke_fn(PM_IOCTL, node_id,
1294a5e56980SBen Levinsky 				  IOCTL_GET_RPU_OPER_MODE, 0, 0, ret_payload);
1295a5e56980SBen Levinsky 
1296a5e56980SBen Levinsky 	/* only set rpu_mode if no error */
1297da22a04fSBen Levinsky 	if (ret == XST_PM_SUCCESS)
1298da22a04fSBen Levinsky 		*rpu_mode = ret_payload[0];
1299da22a04fSBen Levinsky 
1300da22a04fSBen Levinsky 	return ret;
1301da22a04fSBen Levinsky }
1302da22a04fSBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_get_rpu_mode);
1303da22a04fSBen Levinsky 
1304da22a04fSBen Levinsky /**
1305da22a04fSBen Levinsky  * zynqmp_pm_set_rpu_mode() - Set RPU mode
1306da22a04fSBen Levinsky  * @node_id:	Node ID of the device
1307da22a04fSBen Levinsky  * @rpu_mode:	Argument 1 to requested IOCTL call. either split or lockstep
1308da22a04fSBen Levinsky  *
1309da22a04fSBen Levinsky  *		This function is used to set RPU mode to split or
1310da22a04fSBen Levinsky  *		lockstep
1311da22a04fSBen Levinsky  *
1312da22a04fSBen Levinsky  * Return:	Returns status, either success or error+reason
1313da22a04fSBen Levinsky  */
zynqmp_pm_set_rpu_mode(u32 node_id,enum rpu_oper_mode rpu_mode)1314da22a04fSBen Levinsky int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode)
1315da22a04fSBen Levinsky {
1316da22a04fSBen Levinsky 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id,
1317da22a04fSBen Levinsky 				   IOCTL_SET_RPU_OPER_MODE, (u32)rpu_mode,
1318da22a04fSBen Levinsky 				   0, NULL);
1319da22a04fSBen Levinsky }
1320da22a04fSBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_set_rpu_mode);
1321da22a04fSBen Levinsky 
1322da22a04fSBen Levinsky /**
1323da22a04fSBen Levinsky  * zynqmp_pm_set_tcm_config - configure TCM
1324da22a04fSBen Levinsky  * @node_id:	Firmware specific TCM subsystem ID
1325da22a04fSBen Levinsky  * @tcm_mode:	Argument 1 to requested IOCTL call
1326da22a04fSBen Levinsky  *              either PM_RPU_TCM_COMB or PM_RPU_TCM_SPLIT
1327da22a04fSBen Levinsky  *
1328da22a04fSBen Levinsky  * This function is used to set RPU mode to split or combined
1329da22a04fSBen Levinsky  *
1330da22a04fSBen Levinsky  * Return: status: 0 for success, else failure
1331da22a04fSBen Levinsky  */
zynqmp_pm_set_tcm_config(u32 node_id,enum rpu_tcm_comb tcm_mode)1332c1986ac3SRajan Vaja int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode)
1333c1986ac3SRajan Vaja {
1334c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id,
1335c1986ac3SRajan Vaja 				   IOCTL_TCM_COMB_CONFIG, (u32)tcm_mode, 0,
1336c1986ac3SRajan Vaja 				   NULL);
1337c1986ac3SRajan Vaja }
1338c1986ac3SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_tcm_config);
1339c1986ac3SRajan Vaja 
1340c1986ac3SRajan Vaja /**
1341c1986ac3SRajan Vaja  * zynqmp_pm_force_pwrdwn - PM call to request for another PU or subsystem to
1342c1986ac3SRajan Vaja  *             be powered down forcefully
1343cbbbda71SRajan Vaja  * @node:  Node ID of the targeted PU or subsystem
1344c1986ac3SRajan Vaja  * @ack:   Flag to specify whether acknowledge is requested
1345c1986ac3SRajan Vaja  *
1346c1986ac3SRajan Vaja  * Return: status, either success or error+reason
1347c1986ac3SRajan Vaja  */
zynqmp_pm_force_pwrdwn(const u32 node,const enum zynqmp_pm_request_ack ack)1348c1986ac3SRajan Vaja int zynqmp_pm_force_pwrdwn(const u32 node,
1349c1986ac3SRajan Vaja 			   const enum zynqmp_pm_request_ack ack)
1350cbbbda71SRajan Vaja {
1351c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, node, ack, 0, 0, NULL);
1352057a0fb6SKalyani Akula }
13532b9fc773SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_force_pwrdwn);
13542b9fc773SNava kishore Manne 
13552b9fc773SNava kishore Manne /**
13562b9fc773SNava kishore Manne  * zynqmp_pm_request_wake - PM call to wake up selected master or subsystem
13572b9fc773SNava kishore Manne  * @node:  Node ID of the master or subsystem
13582b9fc773SNava kishore Manne  * @set_addr:  Specifies whether the address argument is relevant
13592b9fc773SNava kishore Manne  * @address:   Address from which to resume when woken up
13602b9fc773SNava kishore Manne  * @ack:   Flag to specify whether acknowledge requested
13612b9fc773SNava kishore Manne  *
13622b9fc773SNava kishore Manne  * Return: status, either success or error+reason
13632b9fc773SNava kishore Manne  */
zynqmp_pm_request_wake(const u32 node,const bool set_addr,const u64 address,const enum zynqmp_pm_request_ack ack)13642b9fc773SNava kishore Manne int zynqmp_pm_request_wake(const u32 node,
13652b9fc773SNava kishore Manne 			   const bool set_addr,
13662b9fc773SNava kishore Manne 			   const u64 address,
13672b9fc773SNava kishore Manne 			   const enum zynqmp_pm_request_ack ack)
13682b9fc773SNava kishore Manne {
13692b9fc773SNava kishore Manne 	/* set_addr flag is encoded into 1st bit of address */
13702a8faf8dSMichal Simek 	return zynqmp_pm_invoke_fn(PM_REQUEST_WAKEUP, node, address | set_addr,
1371057a0fb6SKalyani Akula 				   address >> 32, ack, NULL);
1372057a0fb6SKalyani Akula }
1373057a0fb6SKalyani Akula EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake);
1374057a0fb6SKalyani Akula 
1375057a0fb6SKalyani Akula /**
1376057a0fb6SKalyani Akula  * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
1377bc86f9c5SRajan Vaja  * @node:		Node ID of the slave
1378057a0fb6SKalyani Akula  * @capabilities:	Requested capabilities of the slave
1379057a0fb6SKalyani Akula  * @qos:		Quality of service (not supported)
1380057a0fb6SKalyani Akula  * @ack:		Flag to specify whether acknowledge is requested
1381057a0fb6SKalyani Akula  *
1382057a0fb6SKalyani Akula  * This API function is to be used for slaves a PU already has requested
1383057a0fb6SKalyani Akula  * to change its capabilities.
1384057a0fb6SKalyani Akula  *
1385057a0fb6SKalyani Akula  * Return: Returns status, either success or error+reason
1386057a0fb6SKalyani Akula  */
zynqmp_pm_set_requirement(const u32 node,const u32 capabilities,const u32 qos,const enum zynqmp_pm_request_ack ack)1387057a0fb6SKalyani Akula int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
1388057a0fb6SKalyani Akula 			      const u32 qos,
1389057a0fb6SKalyani Akula 			      const enum zynqmp_pm_request_ack ack)
1390057a0fb6SKalyani Akula {
1391057a0fb6SKalyani Akula 	return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
1392bc86f9c5SRajan Vaja 				   qos, ack, NULL);
1393057a0fb6SKalyani Akula }
1394fdd2ed88SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
139580f940efSHarsha 
139680f940efSHarsha /**
139780f940efSHarsha  * zynqmp_pm_load_pdi - Load and process PDI
139880f940efSHarsha  * @src:       Source device where PDI is located
139980f940efSHarsha  * @address:   PDI src address
140080f940efSHarsha  *
140180f940efSHarsha  * This function provides support to load PDI from linux
140280f940efSHarsha  *
140380f940efSHarsha  * Return: Returns status, either success or error+reason
140480f940efSHarsha  */
zynqmp_pm_load_pdi(const u32 src,const u64 address)140580f940efSHarsha int zynqmp_pm_load_pdi(const u32 src, const u64 address)
140680f940efSHarsha {
140780f940efSHarsha 	return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src,
140880f940efSHarsha 				   lower_32_bits(address),
140980f940efSHarsha 				   upper_32_bits(address), 0, NULL);
141080f940efSHarsha }
141180f940efSHarsha EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi);
141280f940efSHarsha 
141380f940efSHarsha /**
141480f940efSHarsha  * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
141580f940efSHarsha  * AES-GCM core.
141680f940efSHarsha  * @address:	Address of the AesParams structure.
141780f940efSHarsha  * @out:	Returned output value
141880f940efSHarsha  *
141980f940efSHarsha  * Return:	Returns status, either success or error code.
142080f940efSHarsha  */
zynqmp_pm_aes_engine(const u64 address,u32 * out)14211881eadbSAbhyuday Godhasara int zynqmp_pm_aes_engine(const u64 address, u32 *out)
14221881eadbSAbhyuday Godhasara {
14231881eadbSAbhyuday Godhasara 	u32 ret_payload[PAYLOAD_ARG_CNT];
14241881eadbSAbhyuday Godhasara 	int ret;
14251881eadbSAbhyuday Godhasara 
14261881eadbSAbhyuday Godhasara 	if (!out)
14271881eadbSAbhyuday Godhasara 		return -EINVAL;
14281881eadbSAbhyuday Godhasara 
14291881eadbSAbhyuday Godhasara 	ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address),
14301881eadbSAbhyuday Godhasara 				  lower_32_bits(address),
14311881eadbSAbhyuday Godhasara 				  0, 0, ret_payload);
14321881eadbSAbhyuday Godhasara 	*out = ret_payload[1];
14331881eadbSAbhyuday Godhasara 
14341881eadbSAbhyuday Godhasara 	return ret;
14351881eadbSAbhyuday Godhasara }
14361881eadbSAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
14371881eadbSAbhyuday Godhasara 
14381881eadbSAbhyuday Godhasara /**
14391881eadbSAbhyuday Godhasara  * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
14401881eadbSAbhyuday Godhasara  * @address:	Address of the data/ Address of output buffer where
14411881eadbSAbhyuday Godhasara  *		hash should be stored.
14421881eadbSAbhyuday Godhasara  * @size:	Size of the data.
14431881eadbSAbhyuday Godhasara  * @flags:
1444fdd2ed88SRajan Vaja  *	BIT(0) - for initializing csudma driver and SHA3(Here address
1445fdd2ed88SRajan Vaja  *		 and size inputs can be NULL).
1446fdd2ed88SRajan Vaja  *	BIT(1) - to call Sha3_Update API which can be called multiple
1447fdd2ed88SRajan Vaja  *		 times when data is not contiguous.
1448fdd2ed88SRajan Vaja  *	BIT(2) - to get final hash of the whole updated data.
1449fdd2ed88SRajan Vaja  *		 Hash will be overwritten at provided address with
1450fdd2ed88SRajan Vaja  *		 48 bytes.
1451fdd2ed88SRajan Vaja  *
1452fdd2ed88SRajan Vaja  * Return:	Returns status, either success or error code.
1453fdd2ed88SRajan Vaja  */
zynqmp_pm_sha_hash(const u64 address,const u32 size,const u32 flags)1454fdd2ed88SRajan Vaja int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags)
1455fdd2ed88SRajan Vaja {
1456b3ae24c4SRajan Vaja 	u32 lower_addr = lower_32_bits(address);
1457f1d0821bSRonak Jain 	u32 upper_addr = upper_32_bits(address);
1458f1d0821bSRonak Jain 
1459f1d0821bSRonak Jain 	return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_addr, lower_addr,
1460f1d0821bSRonak Jain 				   size, flags, NULL);
1461f1d0821bSRonak Jain }
1462f1d0821bSRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash);
1463f1d0821bSRonak Jain 
1464f1d0821bSRonak Jain /**
1465f1d0821bSRonak Jain  * zynqmp_pm_register_notifier() - PM API for register a subsystem
1466f1d0821bSRonak Jain  *                                to be notified about specific
1467f1d0821bSRonak Jain  *                                event/error.
1468f1d0821bSRonak Jain  * @node:	Node ID to which the event is related.
1469f1d0821bSRonak Jain  * @event:	Event Mask of Error events for which wants to get notified.
1470f1d0821bSRonak Jain  * @wake:	Wake subsystem upon capturing the event if value 1
1471f1d0821bSRonak Jain  * @enable:	Enable the registration for value 1, disable for value 0
1472f1d0821bSRonak Jain  *
1473f1d0821bSRonak Jain  * This function is used to register/un-register for particular node-event
1474f1d0821bSRonak Jain  * combination in firmware.
1475f1d0821bSRonak Jain  *
1476f1d0821bSRonak Jain  * Return: Returns status, either success or error+reason
1477f1d0821bSRonak Jain  */
1478f1d0821bSRonak Jain 
zynqmp_pm_register_notifier(const u32 node,const u32 event,const u32 wake,const u32 enable)1479f1d0821bSRonak Jain int zynqmp_pm_register_notifier(const u32 node, const u32 event,
1480f1d0821bSRonak Jain 				const u32 wake, const u32 enable)
1481f1d0821bSRonak Jain {
1482f1d0821bSRonak Jain 	return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event,
1483f1d0821bSRonak Jain 				   wake, enable, NULL);
1484256dea91SRonak Jain }
1485256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier);
1486256dea91SRonak Jain 
1487256dea91SRonak Jain /**
1488256dea91SRonak Jain  * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
1489256dea91SRonak Jain  * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
1490256dea91SRonak Jain  * @subtype:	Specifies which system should be restarted or shut down
1491256dea91SRonak Jain  *
1492256dea91SRonak Jain  * Return:	Returns status, either success or error+reason
1493256dea91SRonak Jain  */
zynqmp_pm_system_shutdown(const u32 type,const u32 subtype)1494256dea91SRonak Jain int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
1495256dea91SRonak Jain {
1496256dea91SRonak Jain 	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
1497256dea91SRonak Jain 				   0, 0, NULL);
1498256dea91SRonak Jain }
1499256dea91SRonak Jain 
1500256dea91SRonak Jain /**
1501256dea91SRonak Jain  * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config
1502256dea91SRonak Jain  * @id:         The config ID of the feature to be configured
1503256dea91SRonak Jain  * @value:      The config value of the feature to be configured
1504256dea91SRonak Jain  *
1505256dea91SRonak Jain  * Return:      Returns 0 on success or error value on failure.
1506256dea91SRonak Jain  */
zynqmp_pm_set_feature_config(enum pm_feature_config_id id,u32 value)1507256dea91SRonak Jain int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value)
1508256dea91SRonak Jain {
1509256dea91SRonak Jain 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_FEATURE_CONFIG,
1510256dea91SRonak Jain 				   id, value, NULL);
1511256dea91SRonak Jain }
1512256dea91SRonak Jain 
1513256dea91SRonak Jain /**
1514256dea91SRonak Jain  * zynqmp_pm_get_feature_config - PM call to get value of configured feature
1515b3ae24c4SRajan Vaja  * @id:         The config id of the feature to be queried
1516b3ae24c4SRajan Vaja  * @payload:    Returned value array
1517b3ae24c4SRajan Vaja  *
1518b3ae24c4SRajan Vaja  * Return:      Returns 0 on success or error value on failure.
1519b3ae24c4SRajan Vaja  */
zynqmp_pm_get_feature_config(enum pm_feature_config_id id,u32 * payload)1520b3ae24c4SRajan Vaja int zynqmp_pm_get_feature_config(enum pm_feature_config_id id,
1521b3ae24c4SRajan Vaja 				 u32 *payload)
1522b3ae24c4SRajan Vaja {
1523b3ae24c4SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_FEATURE_CONFIG,
1524b3ae24c4SRajan Vaja 				   id, 0, payload);
1525b3ae24c4SRajan Vaja }
1526b3ae24c4SRajan Vaja 
1527b3ae24c4SRajan Vaja /**
1528b3ae24c4SRajan Vaja  * zynqmp_pm_set_sd_config - PM call to set value of SD config registers
1529b3ae24c4SRajan Vaja  * @node:	SD node ID
1530b3ae24c4SRajan Vaja  * @config:	The config type of SD registers
1531b3ae24c4SRajan Vaja  * @value:	Value to be set
1532b3ae24c4SRajan Vaja  *
1533b3ae24c4SRajan Vaja  * Return:	Returns 0 on success or error value on failure.
1534b3ae24c4SRajan Vaja  */
zynqmp_pm_set_sd_config(u32 node,enum pm_sd_config_type config,u32 value)1535b3ae24c4SRajan Vaja int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value)
1536b3ae24c4SRajan Vaja {
1537b3ae24c4SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_SD_CONFIG,
1538b3ae24c4SRajan Vaja 				   config, value, NULL);
1539b3ae24c4SRajan Vaja }
1540b3ae24c4SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_config);
1541b3ae24c4SRajan Vaja 
1542b3ae24c4SRajan Vaja /**
1543b3ae24c4SRajan Vaja  * zynqmp_pm_set_gem_config - PM call to set value of GEM config registers
1544b3ae24c4SRajan Vaja  * @node:	GEM node ID
1545b3ae24c4SRajan Vaja  * @config:	The config type of GEM registers
1546b3ae24c4SRajan Vaja  * @value:	Value to be set
1547b3ae24c4SRajan Vaja  *
1548b3ae24c4SRajan Vaja  * Return:	Returns 0 on success or error value on failure.
1549b3ae24c4SRajan Vaja  */
zynqmp_pm_set_gem_config(u32 node,enum pm_gem_config_type config,u32 value)1550b3ae24c4SRajan Vaja int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
1551b3ae24c4SRajan Vaja 			     u32 value)
1552b3ae24c4SRajan Vaja {
1553b3ae24c4SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, node, IOCTL_SET_GEM_CONFIG,
1554b3ae24c4SRajan Vaja 				   config, value, NULL);
1555b3ae24c4SRajan Vaja }
1556b3ae24c4SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_gem_config);
1557b3ae24c4SRajan Vaja 
1558b3ae24c4SRajan Vaja /**
1559b3ae24c4SRajan Vaja  * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
1560b3ae24c4SRajan Vaja  * @subtype:	Shutdown subtype
1561b3ae24c4SRajan Vaja  * @name:	Matching string for scope argument
1562b3ae24c4SRajan Vaja  *
1563b3ae24c4SRajan Vaja  * This struct encapsulates mapping between shutdown scope ID and string.
1564b3ae24c4SRajan Vaja  */
1565b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope {
1566b3ae24c4SRajan Vaja 	const enum zynqmp_pm_shutdown_subtype subtype;
1567b3ae24c4SRajan Vaja 	const char *name;
1568b3ae24c4SRajan Vaja };
1569b3ae24c4SRajan Vaja 
1570b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
1571b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
1572b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
1573b3ae24c4SRajan Vaja 		.name = "subsystem",
1574b3ae24c4SRajan Vaja 	},
1575b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
1576b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
1577b3ae24c4SRajan Vaja 		.name = "ps_only",
1578b3ae24c4SRajan Vaja 	},
1579b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
1580b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
1581b3ae24c4SRajan Vaja 		.name = "system",
1582b3ae24c4SRajan Vaja 	},
1583b3ae24c4SRajan Vaja };
1584b3ae24c4SRajan Vaja 
1585b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope =
1586b3ae24c4SRajan Vaja 		&shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
1587b3ae24c4SRajan Vaja 
1588b3ae24c4SRajan Vaja /**
1589b3ae24c4SRajan Vaja  * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
1590b3ae24c4SRajan Vaja  * @scope_string:	Shutdown scope string
1591b3ae24c4SRajan Vaja  *
1592b3ae24c4SRajan Vaja  * Return:		Return pointer to matching shutdown scope struct from
1593b3ae24c4SRajan Vaja  *			array of available options in system if string is valid,
1594b3ae24c4SRajan Vaja  *			otherwise returns NULL.
1595b3ae24c4SRajan Vaja  */
1596b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope*
zynqmp_pm_is_shutdown_scope_valid(const char * scope_string)1597b3ae24c4SRajan Vaja 		zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
1598b3ae24c4SRajan Vaja {
1599b3ae24c4SRajan Vaja 	int count;
1600b3ae24c4SRajan Vaja 
1601b3ae24c4SRajan Vaja 	for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
1602b3ae24c4SRajan Vaja 		if (sysfs_streq(scope_string, shutdown_scopes[count].name))
1603b3ae24c4SRajan Vaja 			return &shutdown_scopes[count];
1604b3ae24c4SRajan Vaja 
1605b3ae24c4SRajan Vaja 	return NULL;
1606b3ae24c4SRajan Vaja }
1607b3ae24c4SRajan Vaja 
shutdown_scope_show(struct device * device,struct device_attribute * attr,char * buf)1608b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device,
1609b3ae24c4SRajan Vaja 				   struct device_attribute *attr,
1610a2cc220aSRajan Vaja 				   char *buf)
1611a2cc220aSRajan Vaja {
1612a2cc220aSRajan Vaja 	int i;
1613a2cc220aSRajan Vaja 
1614a2cc220aSRajan Vaja 	for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
1615a2cc220aSRajan Vaja 		if (&shutdown_scopes[i] == selected_scope) {
1616a2cc220aSRajan Vaja 			strcat(buf, "[");
1617a2cc220aSRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
1618a2cc220aSRajan Vaja 			strcat(buf, "]");
1619a2cc220aSRajan Vaja 		} else {
1620a2cc220aSRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
1621a2cc220aSRajan Vaja 		}
1622a2cc220aSRajan Vaja 		strcat(buf, " ");
1623a2cc220aSRajan Vaja 	}
1624a2cc220aSRajan Vaja 	strcat(buf, "\n");
1625a2cc220aSRajan Vaja 
1626a2cc220aSRajan Vaja 	return strlen(buf);
1627a2cc220aSRajan Vaja }
1628a2cc220aSRajan Vaja 
shutdown_scope_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)1629a2cc220aSRajan Vaja static ssize_t shutdown_scope_store(struct device *device,
1630a2cc220aSRajan Vaja 				    struct device_attribute *attr,
1631a2cc220aSRajan Vaja 				    const char *buf, size_t count)
1632a2cc220aSRajan Vaja {
1633ae5c961dSRajan Vaja 	int ret;
1634ae5c961dSRajan Vaja 	struct zynqmp_pm_shutdown_scope *scope;
1635ae5c961dSRajan Vaja 
1636ae5c961dSRajan Vaja 	scope = zynqmp_pm_is_shutdown_scope_valid(buf);
1637ae5c961dSRajan Vaja 	if (!scope)
1638ae5c961dSRajan Vaja 		return -EINVAL;
1639ae5c961dSRajan Vaja 
1640ae5c961dSRajan Vaja 	ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
1641ae5c961dSRajan Vaja 					scope->subtype);
1642ae5c961dSRajan Vaja 	if (ret) {
1643ae5c961dSRajan Vaja 		pr_err("unable to set shutdown scope %s\n", buf);
1644ae5c961dSRajan Vaja 		return ret;
1645ae5c961dSRajan Vaja 	}
1646ae5c961dSRajan Vaja 
1647ae5c961dSRajan Vaja 	selected_scope = scope;
1648ae5c961dSRajan Vaja 
1649ae5c961dSRajan Vaja 	return count;
1650ae5c961dSRajan Vaja }
1651ae5c961dSRajan Vaja 
1652ae5c961dSRajan Vaja static DEVICE_ATTR_RW(shutdown_scope);
1653ae5c961dSRajan Vaja 
health_status_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)1654ae5c961dSRajan Vaja static ssize_t health_status_store(struct device *device,
1655ae5c961dSRajan Vaja 				   struct device_attribute *attr,
1656ae5c961dSRajan Vaja 				   const char *buf, size_t count)
1657ae5c961dSRajan Vaja {
1658ae5c961dSRajan Vaja 	int ret;
1659ae5c961dSRajan Vaja 	unsigned int value;
1660ae5c961dSRajan Vaja 
1661ae5c961dSRajan Vaja 	ret = kstrtouint(buf, 10, &value);
1662ae5c961dSRajan Vaja 	if (ret)
1663ae5c961dSRajan Vaja 		return ret;
1664ae5c961dSRajan Vaja 
1665ae5c961dSRajan Vaja 	ret = zynqmp_pm_set_boot_health_status(value);
1666ae5c961dSRajan Vaja 	if (ret) {
1667ae5c961dSRajan Vaja 		dev_err(device, "unable to set healthy bit value to %u\n",
1668ae5c961dSRajan Vaja 			value);
1669ae5c961dSRajan Vaja 		return ret;
1670ae5c961dSRajan Vaja 	}
1671ae5c961dSRajan Vaja 
1672ae5c961dSRajan Vaja 	return count;
1673ae5c961dSRajan Vaja }
1674ae5c961dSRajan Vaja 
1675ae5c961dSRajan Vaja static DEVICE_ATTR_WO(health_status);
1676ae5c961dSRajan Vaja 
ggs_show(struct device * device,struct device_attribute * attr,char * buf,u32 reg)1677ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device,
1678ae5c961dSRajan Vaja 			struct device_attribute *attr,
1679ae5c961dSRajan Vaja 			char *buf,
1680ae5c961dSRajan Vaja 			u32 reg)
1681ae5c961dSRajan Vaja {
1682ae5c961dSRajan Vaja 	int ret;
1683ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1684ae5c961dSRajan Vaja 
1685ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_ggs(reg, ret_payload);
1686ae5c961dSRajan Vaja 	if (ret)
1687ae5c961dSRajan Vaja 		return ret;
1688ae5c961dSRajan Vaja 
1689ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1690ae5c961dSRajan Vaja }
1691ae5c961dSRajan Vaja 
ggs_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count,u32 reg)1692ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device,
1693ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1694ae5c961dSRajan Vaja 			 const char *buf, size_t count,
1695ae5c961dSRajan Vaja 			 u32 reg)
1696ae5c961dSRajan Vaja {
1697ae5c961dSRajan Vaja 	long value;
1698ae5c961dSRajan Vaja 	int ret;
1699ae5c961dSRajan Vaja 
1700ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1701ae5c961dSRajan Vaja 		return -EINVAL;
1702ae5c961dSRajan Vaja 
1703ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1704ae5c961dSRajan Vaja 	if (ret) {
1705ae5c961dSRajan Vaja 		count = -EFAULT;
1706ae5c961dSRajan Vaja 		goto err;
1707ae5c961dSRajan Vaja 	}
1708ae5c961dSRajan Vaja 
1709ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_ggs(reg, value);
1710ae5c961dSRajan Vaja 	if (ret)
1711ae5c961dSRajan Vaja 		count = -EFAULT;
1712ae5c961dSRajan Vaja err:
1713ae5c961dSRajan Vaja 	return count;
1714ae5c961dSRajan Vaja }
1715ae5c961dSRajan Vaja 
1716ae5c961dSRajan Vaja /* GGS register show functions */
1717ae5c961dSRajan Vaja #define GGS0_SHOW(N)						\
1718ae5c961dSRajan Vaja 	ssize_t ggs##N##_show(struct device *device,		\
1719ae5c961dSRajan Vaja 			      struct device_attribute *attr,	\
1720ae5c961dSRajan Vaja 			      char *buf)			\
1721ae5c961dSRajan Vaja 	{							\
1722ae5c961dSRajan Vaja 		return ggs_show(device, attr, buf, N);		\
1723ae5c961dSRajan Vaja 	}
1724ae5c961dSRajan Vaja 
1725ae5c961dSRajan Vaja static GGS0_SHOW(0);
1726ae5c961dSRajan Vaja static GGS0_SHOW(1);
1727ae5c961dSRajan Vaja static GGS0_SHOW(2);
1728ae5c961dSRajan Vaja static GGS0_SHOW(3);
1729ae5c961dSRajan Vaja 
1730ae5c961dSRajan Vaja /* GGS register store function */
1731ae5c961dSRajan Vaja #define GGS0_STORE(N)						\
1732ae5c961dSRajan Vaja 	ssize_t ggs##N##_store(struct device *device,		\
1733ae5c961dSRajan Vaja 			       struct device_attribute *attr,	\
1734ae5c961dSRajan Vaja 			       const char *buf,			\
1735ae5c961dSRajan Vaja 			       size_t count)			\
1736ae5c961dSRajan Vaja 	{							\
1737ae5c961dSRajan Vaja 		return ggs_store(device, attr, buf, count, N);	\
1738ae5c961dSRajan Vaja 	}
1739ae5c961dSRajan Vaja 
1740ae5c961dSRajan Vaja static GGS0_STORE(0);
1741ae5c961dSRajan Vaja static GGS0_STORE(1);
1742ae5c961dSRajan Vaja static GGS0_STORE(2);
1743ae5c961dSRajan Vaja static GGS0_STORE(3);
1744ae5c961dSRajan Vaja 
pggs_show(struct device * device,struct device_attribute * attr,char * buf,u32 reg)1745ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device,
1746ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1747ae5c961dSRajan Vaja 			 char *buf,
1748ae5c961dSRajan Vaja 			 u32 reg)
1749ae5c961dSRajan Vaja {
1750ae5c961dSRajan Vaja 	int ret;
1751ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1752ae5c961dSRajan Vaja 
1753ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_pggs(reg, ret_payload);
1754ae5c961dSRajan Vaja 	if (ret)
1755ae5c961dSRajan Vaja 		return ret;
1756ae5c961dSRajan Vaja 
1757ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1758ae5c961dSRajan Vaja }
1759ae5c961dSRajan Vaja 
pggs_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count,u32 reg)1760ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device,
1761ae5c961dSRajan Vaja 			  struct device_attribute *attr,
1762ae5c961dSRajan Vaja 			  const char *buf, size_t count,
1763ae5c961dSRajan Vaja 			  u32 reg)
1764ae5c961dSRajan Vaja {
1765ae5c961dSRajan Vaja 	long value;
1766ae5c961dSRajan Vaja 	int ret;
1767ae5c961dSRajan Vaja 
1768ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1769ae5c961dSRajan Vaja 		return -EINVAL;
1770ae5c961dSRajan Vaja 
1771ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1772ae5c961dSRajan Vaja 	if (ret) {
1773ae5c961dSRajan Vaja 		count = -EFAULT;
1774ae5c961dSRajan Vaja 		goto err;
1775ae5c961dSRajan Vaja 	}
1776ae5c961dSRajan Vaja 
1777ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_pggs(reg, value);
1778ae5c961dSRajan Vaja 	if (ret)
1779ae5c961dSRajan Vaja 		count = -EFAULT;
1780ae5c961dSRajan Vaja 
1781ae5c961dSRajan Vaja err:
17822c5d8f7cSRonak Jain 	return count;
17832c5d8f7cSRonak Jain }
17842c5d8f7cSRonak Jain 
17852c5d8f7cSRonak Jain #define PGGS0_SHOW(N)						\
17862c5d8f7cSRonak Jain 	ssize_t pggs##N##_show(struct device *device,		\
17872c5d8f7cSRonak Jain 			       struct device_attribute *attr,	\
17882c5d8f7cSRonak Jain 			       char *buf)			\
17892c5d8f7cSRonak Jain 	{							\
17902c5d8f7cSRonak Jain 		return pggs_show(device, attr, buf, N);		\
17912c5d8f7cSRonak Jain 	}
17922c5d8f7cSRonak Jain 
17932c5d8f7cSRonak Jain #define PGGS0_STORE(N)						\
17942c5d8f7cSRonak Jain 	ssize_t pggs##N##_store(struct device *device,		\
17952c5d8f7cSRonak Jain 				struct device_attribute *attr,	\
17962c5d8f7cSRonak Jain 				const char *buf,		\
17972c5d8f7cSRonak Jain 				size_t count)			\
17982c5d8f7cSRonak Jain 	{							\
17992c5d8f7cSRonak Jain 		return pggs_store(device, attr, buf, count, N);	\
18002c5d8f7cSRonak Jain 	}
18012c5d8f7cSRonak Jain 
18022c5d8f7cSRonak Jain /* PGGS register show functions */
18032c5d8f7cSRonak Jain static PGGS0_SHOW(0);
18042c5d8f7cSRonak Jain static PGGS0_SHOW(1);
18052c5d8f7cSRonak Jain static PGGS0_SHOW(2);
18062c5d8f7cSRonak Jain static PGGS0_SHOW(3);
18072c5d8f7cSRonak Jain 
18082c5d8f7cSRonak Jain /* PGGS register store functions */
18092c5d8f7cSRonak Jain static PGGS0_STORE(0);
18102c5d8f7cSRonak Jain static PGGS0_STORE(1);
18112c5d8f7cSRonak Jain static PGGS0_STORE(2);
18122c5d8f7cSRonak Jain static PGGS0_STORE(3);
18132c5d8f7cSRonak Jain 
18142c5d8f7cSRonak Jain /* GGS register attributes */
18152c5d8f7cSRonak Jain static DEVICE_ATTR_RW(ggs0);
18162c5d8f7cSRonak Jain static DEVICE_ATTR_RW(ggs1);
18172c5d8f7cSRonak Jain static DEVICE_ATTR_RW(ggs2);
18182c5d8f7cSRonak Jain static DEVICE_ATTR_RW(ggs3);
18192c5d8f7cSRonak Jain 
18202c5d8f7cSRonak Jain /* PGGS register attributes */
18212c5d8f7cSRonak Jain static DEVICE_ATTR_RW(pggs0);
18222c5d8f7cSRonak Jain static DEVICE_ATTR_RW(pggs1);
18232c5d8f7cSRonak Jain static DEVICE_ATTR_RW(pggs2);
18242c5d8f7cSRonak Jain static DEVICE_ATTR_RW(pggs3);
18252c5d8f7cSRonak Jain 
feature_config_id_show(struct device * device,struct device_attribute * attr,char * buf)18262c5d8f7cSRonak Jain static ssize_t feature_config_id_show(struct device *device,
18272c5d8f7cSRonak Jain 				      struct device_attribute *attr,
18282c5d8f7cSRonak Jain 				      char *buf)
18292c5d8f7cSRonak Jain {
18302c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
18312c5d8f7cSRonak Jain 
18322c5d8f7cSRonak Jain 	return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id);
18332c5d8f7cSRonak Jain }
18342c5d8f7cSRonak Jain 
feature_config_id_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)18352c5d8f7cSRonak Jain static ssize_t feature_config_id_store(struct device *device,
18362c5d8f7cSRonak Jain 				       struct device_attribute *attr,
18372c5d8f7cSRonak Jain 				       const char *buf, size_t count)
18382c5d8f7cSRonak Jain {
18392c5d8f7cSRonak Jain 	u32 config_id;
18402c5d8f7cSRonak Jain 	int ret;
18412c5d8f7cSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
18422c5d8f7cSRonak Jain 
18432c5d8f7cSRonak Jain 	if (!buf)
18442c5d8f7cSRonak Jain 		return -EINVAL;
18452c5d8f7cSRonak Jain 
18462c5d8f7cSRonak Jain 	ret = kstrtou32(buf, 10, &config_id);
18472c5d8f7cSRonak Jain 	if (ret)
18482c5d8f7cSRonak Jain 		return ret;
18492c5d8f7cSRonak Jain 
18502c5d8f7cSRonak Jain 	devinfo->feature_conf_id = config_id;
18512c5d8f7cSRonak Jain 
18522c5d8f7cSRonak Jain 	return count;
18532c5d8f7cSRonak Jain }
1854ae5c961dSRajan Vaja 
1855ae5c961dSRajan Vaja static DEVICE_ATTR_RW(feature_config_id);
1856ae5c961dSRajan Vaja 
feature_config_value_show(struct device * device,struct device_attribute * attr,char * buf)1857ae5c961dSRajan Vaja static ssize_t feature_config_value_show(struct device *device,
1858ae5c961dSRajan Vaja 					 struct device_attribute *attr,
1859ae5c961dSRajan Vaja 					 char *buf)
1860ae5c961dSRajan Vaja {
1861ae5c961dSRajan Vaja 	int ret;
1862ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1863b3ae24c4SRajan Vaja 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1864a2cc220aSRajan Vaja 
18652c5d8f7cSRonak Jain 	ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id,
18662c5d8f7cSRonak Jain 					   ret_payload);
1867ae5c961dSRajan Vaja 	if (ret)
1868ae5c961dSRajan Vaja 		return ret;
1869ae5c961dSRajan Vaja 
1870ae5c961dSRajan Vaja 	return sysfs_emit(buf, "%d\n", ret_payload[1]);
1871ae5c961dSRajan Vaja }
187276582671SRajan Vaja 
feature_config_value_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)187376582671SRajan Vaja static ssize_t feature_config_value_store(struct device *device,
187476582671SRajan Vaja 					  struct device_attribute *attr,
187576582671SRajan Vaja 					  const char *buf, size_t count)
18762c5d8f7cSRonak Jain {
187776582671SRajan Vaja 	u32 value;
187876582671SRajan Vaja 	int ret;
1879e5052becSRonak Jain 	struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1880e5052becSRonak Jain 
1881e5052becSRonak Jain 	if (!buf)
1882e5052becSRonak Jain 		return -EINVAL;
188376582671SRajan Vaja 
1884af3f1afaSJolly Shah 	ret = kstrtou32(buf, 10, &value);
1885af3f1afaSJolly Shah 	if (ret)
188676582671SRajan Vaja 		return ret;
188776582671SRajan Vaja 
1888461011b1SRavi Patel 	ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id,
1889461011b1SRavi Patel 					   value);
1890af3f1afaSJolly Shah 	if (ret)
189176582671SRajan Vaja 		return ret;
1892e5052becSRonak Jain 
1893e5052becSRonak Jain 	return count;
1894e5052becSRonak Jain }
1895e5052becSRonak Jain 
1896e5052becSRonak Jain static DEVICE_ATTR_RW(feature_config_value);
1897e5052becSRonak Jain 
1898e5052becSRonak Jain static struct attribute *zynqmp_firmware_attrs[] = {
189976582671SRajan Vaja 	&dev_attr_ggs0.attr,
19002c5d8f7cSRonak Jain 	&dev_attr_ggs1.attr,
19012c5d8f7cSRonak Jain 	&dev_attr_ggs2.attr,
19022c5d8f7cSRonak Jain 	&dev_attr_ggs3.attr,
19032c5d8f7cSRonak Jain 	&dev_attr_pggs0.attr,
19042c5d8f7cSRonak Jain 	&dev_attr_pggs1.attr,
19052c5d8f7cSRonak Jain 	&dev_attr_pggs2.attr,
19062c5d8f7cSRonak Jain 	&dev_attr_pggs3.attr,
19072c5d8f7cSRonak Jain 	&dev_attr_shutdown_scope.attr,
190876582671SRajan Vaja 	&dev_attr_health_status.attr,
1909168e05c1SRajan Vaja 	&dev_attr_feature_config_id.attr,
1910168e05c1SRajan Vaja 	&dev_attr_feature_config_value.attr,
1911168e05c1SRajan Vaja 	NULL,
1912168e05c1SRajan Vaja };
191376582671SRajan Vaja 
191476582671SRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware);
191576582671SRajan Vaja 
zynqmp_firmware_probe(struct platform_device * pdev)191676582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev)
191776582671SRajan Vaja {
191876582671SRajan Vaja 	struct device *dev = &pdev->dev;
191976582671SRajan Vaja 	struct device_node *np;
192076582671SRajan Vaja 	struct zynqmp_devinfo *devinfo;
192176582671SRajan Vaja 	int ret;
192276582671SRajan Vaja 
192376582671SRajan Vaja 	ret = get_set_conduit_method(dev->of_node);
192476582671SRajan Vaja 	if (ret)
192576582671SRajan Vaja 		return ret;
192676582671SRajan Vaja 
192776582671SRajan Vaja 	np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp");
192876582671SRajan Vaja 	if (!np) {
192976582671SRajan Vaja 		np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
193076582671SRajan Vaja 		if (!np)
193176582671SRajan Vaja 			return 0;
193276582671SRajan Vaja 
193376582671SRajan Vaja 		feature_check_enabled = true;
193476582671SRajan Vaja 	}
193576582671SRajan Vaja 
193676582671SRajan Vaja 	if (!feature_check_enabled) {
1937e23d9c6dSJolly Shah 		ret = do_feature_check_call(PM_FEATURE_CHECK);
1938e23d9c6dSJolly Shah 		if (ret >= 0)
1939e23d9c6dSJolly Shah 			feature_check_enabled = true;
1940e23d9c6dSJolly Shah 	}
1941e23d9c6dSJolly Shah 
1942e23d9c6dSJolly Shah 	of_node_put(np);
1943e23d9c6dSJolly Shah 
194465f0539bSChristophe JAILLET 	devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL);
194565f0539bSChristophe JAILLET 	if (!devinfo)
1946a515814eSAbhyuday Godhasara 		return -ENOMEM;
1947a515814eSAbhyuday Godhasara 
1948a515814eSAbhyuday Godhasara 	devinfo->dev = dev;
1949a515814eSAbhyuday Godhasara 
1950a515814eSAbhyuday Godhasara 	platform_set_drvdata(pdev, devinfo);
1951a515814eSAbhyuday Godhasara 
1952a515814eSAbhyuday Godhasara 	/* Check PM API version number */
1953a515814eSAbhyuday Godhasara 	ret = zynqmp_pm_get_api_version(&pm_api_version);
1954a515814eSAbhyuday Godhasara 	if (ret)
195576582671SRajan Vaja 		return ret;
195676582671SRajan Vaja 
195776582671SRajan Vaja 	if (pm_api_version < ZYNQMP_PM_VERSION) {
195876582671SRajan Vaja 		panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
195976582671SRajan Vaja 		      __func__,
1960acfdd185SAmit Sunil Dhamne 		      ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
1961f1f21becSTejas Patel 		      pm_api_version >> 16, pm_api_version & 0xFFFF);
1962acfdd185SAmit Sunil Dhamne 	}
1963acfdd185SAmit Sunil Dhamne 
1964e23d9c6dSJolly Shah 	pr_info("%s Platform Management API v%d.%d\n", __func__,
1965b3217252SRajan Vaja 		pm_api_version >> 16, pm_api_version & 0xFFFF);
1966b3217252SRajan Vaja 
1967f1f21becSTejas Patel 	/* Get the Family code and sub family code of platform */
1968acfdd185SAmit Sunil Dhamne 	ret = zynqmp_pm_get_family_info(&pm_family_code, &pm_sub_family_code);
1969acfdd185SAmit Sunil Dhamne 	if (ret < 0)
1970acfdd185SAmit Sunil Dhamne 		return ret;
1971acfdd185SAmit Sunil Dhamne 
1972a515814eSAbhyuday Godhasara 	/* Check trustzone version number */
1973a515814eSAbhyuday Godhasara 	ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
197476582671SRajan Vaja 	if (ret)
197576582671SRajan Vaja 		panic("Legacy trustzone found without version support\n");
197676582671SRajan Vaja 
197776582671SRajan Vaja 	if (pm_tz_version < ZYNQMP_TZ_VERSION)
197876582671SRajan Vaja 		panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
1979af3f1afaSJolly Shah 		      __func__,
198076582671SRajan Vaja 		      ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
198176582671SRajan Vaja 		      pm_tz_version >> 16, pm_tz_version & 0xFFFF);
198276582671SRajan Vaja 
198376582671SRajan Vaja 	pr_info("%s Trustzone version v%d.%d\n", __func__,
198476582671SRajan Vaja 		pm_tz_version >> 16, pm_tz_version & 0xFFFF);
198576582671SRajan Vaja 
198676582671SRajan Vaja 	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
198776582671SRajan Vaja 			      ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
1988ae5c961dSRajan Vaja 	if (ret) {
198976582671SRajan Vaja 		dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
199076582671SRajan Vaja 		return ret;
199176582671SRajan Vaja 	}
199276582671SRajan Vaja 
199376582671SRajan Vaja 	zynqmp_pm_api_debugfs_init();
1994 
1995 	np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
1996 	if (np) {
1997 		em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager",
1998 						       -1, NULL, 0);
1999 		if (IS_ERR(em_dev))
2000 			dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n");
2001 	}
2002 	of_node_put(np);
2003 
2004 	return of_platform_populate(dev->of_node, NULL, NULL, dev);
2005 }
2006 
zynqmp_firmware_remove(struct platform_device * pdev)2007 static int zynqmp_firmware_remove(struct platform_device *pdev)
2008 {
2009 	struct pm_api_feature_data *feature_data;
2010 	struct hlist_node *tmp;
2011 	int i;
2012 
2013 	mfd_remove_devices(&pdev->dev);
2014 	zynqmp_pm_api_debugfs_exit();
2015 
2016 	hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) {
2017 		hash_del(&feature_data->hentry);
2018 		kfree(feature_data);
2019 	}
2020 
2021 	platform_device_unregister(em_dev);
2022 
2023 	return 0;
2024 }
2025 
2026 static const struct of_device_id zynqmp_firmware_of_match[] = {
2027 	{.compatible = "xlnx,zynqmp-firmware"},
2028 	{.compatible = "xlnx,versal-firmware"},
2029 	{},
2030 };
2031 MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
2032 
2033 static struct platform_driver zynqmp_firmware_driver = {
2034 	.driver = {
2035 		.name = "zynqmp_firmware",
2036 		.of_match_table = zynqmp_firmware_of_match,
2037 		.dev_groups = zynqmp_firmware_groups,
2038 	},
2039 	.probe = zynqmp_firmware_probe,
2040 	.remove = zynqmp_firmware_remove,
2041 };
2042 module_platform_driver(zynqmp_firmware_driver);
2043