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