xref: /openbmc/linux/drivers/firmware/xilinx/zynqmp.c (revision 80f940ef)
176582671SRajan Vaja // SPDX-License-Identifier: GPL-2.0
276582671SRajan Vaja /*
376582671SRajan Vaja  * Xilinx Zynq MPSoC Firmware layer
476582671SRajan Vaja  *
5f1f21becSTejas Patel  *  Copyright (C) 2014-2021 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 
39461011b1SRavi Patel static bool feature_check_enabled;
4069fe24d1SZou Wei static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
41acfdd185SAmit Sunil Dhamne 
42a515814eSAbhyuday Godhasara static struct platform_device *em_dev;
43a515814eSAbhyuday Godhasara 
44acfdd185SAmit Sunil Dhamne /**
45acfdd185SAmit Sunil Dhamne  * struct pm_api_feature_data - PM API Feature data
46acfdd185SAmit Sunil Dhamne  * @pm_api_id:		PM API Id, used as key to index into hashmap
47acfdd185SAmit Sunil Dhamne  * @feature_status:	status of PM API feature: valid, invalid
48acfdd185SAmit Sunil Dhamne  * @hentry:		hlist_node that hooks this entry into hashtable
49acfdd185SAmit Sunil Dhamne  */
50acfdd185SAmit Sunil Dhamne struct pm_api_feature_data {
51acfdd185SAmit Sunil Dhamne 	u32 pm_api_id;
52acfdd185SAmit Sunil Dhamne 	int feature_status;
53acfdd185SAmit Sunil Dhamne 	struct hlist_node hentry;
54acfdd185SAmit Sunil Dhamne };
55461011b1SRavi Patel 
56e23d9c6dSJolly Shah static const struct mfd_cell firmware_devs[] = {
57e23d9c6dSJolly Shah 	{
58e23d9c6dSJolly Shah 		.name = "zynqmp_power_controller",
59e23d9c6dSJolly Shah 	},
60e23d9c6dSJolly Shah };
61e23d9c6dSJolly Shah 
6276582671SRajan Vaja /**
6376582671SRajan Vaja  * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
6476582671SRajan Vaja  * @ret_status:		PMUFW return code
6576582671SRajan Vaja  *
6676582671SRajan Vaja  * Return: corresponding Linux error code
6776582671SRajan Vaja  */
6876582671SRajan Vaja static int zynqmp_pm_ret_code(u32 ret_status)
6976582671SRajan Vaja {
7076582671SRajan Vaja 	switch (ret_status) {
7176582671SRajan Vaja 	case XST_PM_SUCCESS:
7276582671SRajan Vaja 	case XST_PM_DOUBLE_REQ:
7376582671SRajan Vaja 		return 0;
74461011b1SRavi Patel 	case XST_PM_NO_FEATURE:
75461011b1SRavi Patel 		return -ENOTSUPP;
7676582671SRajan Vaja 	case XST_PM_NO_ACCESS:
7776582671SRajan Vaja 		return -EACCES;
7876582671SRajan Vaja 	case XST_PM_ABORT_SUSPEND:
7976582671SRajan Vaja 		return -ECANCELED;
80df2a4d94SRajan Vaja 	case XST_PM_MULT_USER:
81df2a4d94SRajan Vaja 		return -EUSERS;
8276582671SRajan Vaja 	case XST_PM_INTERNAL:
8376582671SRajan Vaja 	case XST_PM_CONFLICT:
8476582671SRajan Vaja 	case XST_PM_INVALID_NODE:
8576582671SRajan Vaja 	default:
8676582671SRajan Vaja 		return -EINVAL;
8776582671SRajan Vaja 	}
8876582671SRajan Vaja }
8976582671SRajan Vaja 
9076582671SRajan Vaja static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2,
9176582671SRajan Vaja 				    u32 *ret_payload)
9276582671SRajan Vaja {
9376582671SRajan Vaja 	return -ENODEV;
9476582671SRajan Vaja }
9576582671SRajan Vaja 
9676582671SRajan Vaja /*
9776582671SRajan Vaja  * PM function call wrapper
9876582671SRajan Vaja  * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
9976582671SRajan Vaja  */
10076582671SRajan Vaja static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail;
10176582671SRajan Vaja 
10276582671SRajan Vaja /**
10376582671SRajan Vaja  * do_fw_call_smc() - Call system-level platform management layer (SMC)
10476582671SRajan Vaja  * @arg0:		Argument 0 to SMC call
10576582671SRajan Vaja  * @arg1:		Argument 1 to SMC call
10676582671SRajan Vaja  * @arg2:		Argument 2 to SMC call
10776582671SRajan Vaja  * @ret_payload:	Returned value array
10876582671SRajan Vaja  *
10976582671SRajan Vaja  * Invoke platform management function via SMC call (no hypervisor present).
11076582671SRajan Vaja  *
11176582671SRajan Vaja  * Return: Returns status, either success or error+reason
11276582671SRajan Vaja  */
11376582671SRajan Vaja static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2,
11476582671SRajan Vaja 				   u32 *ret_payload)
11576582671SRajan Vaja {
11676582671SRajan Vaja 	struct arm_smccc_res res;
11776582671SRajan Vaja 
11876582671SRajan Vaja 	arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
11976582671SRajan Vaja 
12076582671SRajan Vaja 	if (ret_payload) {
12176582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
12276582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
12376582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
12476582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
12576582671SRajan Vaja 	}
12676582671SRajan Vaja 
12776582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
12876582671SRajan Vaja }
12976582671SRajan Vaja 
13076582671SRajan Vaja /**
13176582671SRajan Vaja  * do_fw_call_hvc() - Call system-level platform management layer (HVC)
13276582671SRajan Vaja  * @arg0:		Argument 0 to HVC call
13376582671SRajan Vaja  * @arg1:		Argument 1 to HVC call
13476582671SRajan Vaja  * @arg2:		Argument 2 to HVC call
13576582671SRajan Vaja  * @ret_payload:	Returned value array
13676582671SRajan Vaja  *
13776582671SRajan Vaja  * Invoke platform management function via HVC
13876582671SRajan Vaja  * HVC-based for communication through hypervisor
13976582671SRajan Vaja  * (no direct communication with ATF).
14076582671SRajan Vaja  *
14176582671SRajan Vaja  * Return: Returns status, either success or error+reason
14276582671SRajan Vaja  */
14376582671SRajan Vaja static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2,
14476582671SRajan Vaja 				   u32 *ret_payload)
14576582671SRajan Vaja {
14676582671SRajan Vaja 	struct arm_smccc_res res;
14776582671SRajan Vaja 
14876582671SRajan Vaja 	arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
14976582671SRajan Vaja 
15076582671SRajan Vaja 	if (ret_payload) {
15176582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
15276582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
15376582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
15476582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
15576582671SRajan Vaja 	}
15676582671SRajan Vaja 
15776582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
15876582671SRajan Vaja }
15976582671SRajan Vaja 
16076582671SRajan Vaja /**
161461011b1SRavi Patel  * zynqmp_pm_feature() - Check weather given feature is supported or not
162461011b1SRavi Patel  * @api_id:		API ID to check
163461011b1SRavi Patel  *
164461011b1SRavi Patel  * Return: Returns status, either success or error+reason
165461011b1SRavi Patel  */
166f4d77525SAbhyuday Godhasara int zynqmp_pm_feature(const u32 api_id)
167461011b1SRavi Patel {
168461011b1SRavi Patel 	int ret;
169461011b1SRavi Patel 	u32 ret_payload[PAYLOAD_ARG_CNT];
170461011b1SRavi Patel 	u64 smc_arg[2];
171acfdd185SAmit Sunil Dhamne 	struct pm_api_feature_data *feature_data;
172461011b1SRavi Patel 
173461011b1SRavi Patel 	if (!feature_check_enabled)
174461011b1SRavi Patel 		return 0;
175461011b1SRavi Patel 
176acfdd185SAmit Sunil Dhamne 	/* Check for existing entry in hash table for given api */
177acfdd185SAmit Sunil Dhamne 	hash_for_each_possible(pm_api_features_map, feature_data, hentry,
178acfdd185SAmit Sunil Dhamne 			       api_id) {
179acfdd185SAmit Sunil Dhamne 		if (feature_data->pm_api_id == api_id)
180acfdd185SAmit Sunil Dhamne 			return feature_data->feature_status;
181acfdd185SAmit Sunil Dhamne 	}
182f3217d6fSArnd Bergmann 
183acfdd185SAmit Sunil Dhamne 	/* Add new entry if not present */
184acfdd185SAmit Sunil Dhamne 	feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL);
185acfdd185SAmit Sunil Dhamne 	if (!feature_data)
186acfdd185SAmit Sunil Dhamne 		return -ENOMEM;
187461011b1SRavi Patel 
188acfdd185SAmit Sunil Dhamne 	feature_data->pm_api_id = api_id;
189461011b1SRavi Patel 	smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK;
190461011b1SRavi Patel 	smc_arg[1] = api_id;
191461011b1SRavi Patel 
192461011b1SRavi Patel 	ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload);
193acfdd185SAmit Sunil Dhamne 	if (ret)
194acfdd185SAmit Sunil Dhamne 		ret = -EOPNOTSUPP;
195acfdd185SAmit Sunil Dhamne 	else
196acfdd185SAmit Sunil Dhamne 		ret = ret_payload[1];
197461011b1SRavi Patel 
198acfdd185SAmit Sunil Dhamne 	feature_data->feature_status = ret;
199acfdd185SAmit Sunil Dhamne 	hash_add(pm_api_features_map, &feature_data->hentry, api_id);
200461011b1SRavi Patel 
201acfdd185SAmit Sunil Dhamne 	return ret;
202461011b1SRavi Patel }
203f4d77525SAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
204461011b1SRavi Patel 
205461011b1SRavi Patel /**
20676582671SRajan Vaja  * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
20776582671SRajan Vaja  *			   caller function depending on the configuration
20876582671SRajan Vaja  * @pm_api_id:		Requested PM-API call
20976582671SRajan Vaja  * @arg0:		Argument 0 to requested PM-API call
21076582671SRajan Vaja  * @arg1:		Argument 1 to requested PM-API call
21176582671SRajan Vaja  * @arg2:		Argument 2 to requested PM-API call
21276582671SRajan Vaja  * @arg3:		Argument 3 to requested PM-API call
21376582671SRajan Vaja  * @ret_payload:	Returned value array
21476582671SRajan Vaja  *
21576582671SRajan Vaja  * Invoke platform management function for SMC or HVC call, depending on
21676582671SRajan Vaja  * configuration.
21776582671SRajan Vaja  * Following SMC Calling Convention (SMCCC) for SMC64:
21876582671SRajan Vaja  * Pm Function Identifier,
21976582671SRajan Vaja  * PM_SIP_SVC + PM_API_ID =
22076582671SRajan Vaja  *	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
22176582671SRajan Vaja  *	((SMC_64) << FUNCID_CC_SHIFT)
22276582671SRajan Vaja  *	((SIP_START) << FUNCID_OEN_SHIFT)
22376582671SRajan Vaja  *	((PM_API_ID) & FUNCID_NUM_MASK))
22476582671SRajan Vaja  *
22576582671SRajan Vaja  * PM_SIP_SVC	- Registered ZynqMP SIP Service Call.
22676582671SRajan Vaja  * PM_API_ID	- Platform Management API ID.
22776582671SRajan Vaja  *
22876582671SRajan Vaja  * Return: Returns status, either success or error+reason
22976582671SRajan Vaja  */
23076582671SRajan Vaja int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
23176582671SRajan Vaja 			u32 arg2, u32 arg3, u32 *ret_payload)
23276582671SRajan Vaja {
23376582671SRajan Vaja 	/*
23476582671SRajan Vaja 	 * Added SIP service call Function Identifier
23576582671SRajan Vaja 	 * Make sure to stay in x0 register
23676582671SRajan Vaja 	 */
23776582671SRajan Vaja 	u64 smc_arg[4];
238acfdd185SAmit Sunil Dhamne 	int ret;
23976582671SRajan Vaja 
240acfdd185SAmit Sunil Dhamne 	/* Check if feature is supported or not */
241acfdd185SAmit Sunil Dhamne 	ret = zynqmp_pm_feature(pm_api_id);
242acfdd185SAmit Sunil Dhamne 	if (ret < 0)
243acfdd185SAmit Sunil Dhamne 		return ret;
244461011b1SRavi Patel 
24576582671SRajan Vaja 	smc_arg[0] = PM_SIP_SVC | pm_api_id;
24676582671SRajan Vaja 	smc_arg[1] = ((u64)arg1 << 32) | arg0;
24776582671SRajan Vaja 	smc_arg[2] = ((u64)arg3 << 32) | arg2;
24876582671SRajan Vaja 
24976582671SRajan Vaja 	return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload);
25076582671SRajan Vaja }
25176582671SRajan Vaja 
25276582671SRajan Vaja static u32 pm_api_version;
25376582671SRajan Vaja static u32 pm_tz_version;
25476582671SRajan Vaja 
25576582671SRajan Vaja /**
25676582671SRajan Vaja  * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
25776582671SRajan Vaja  * @version:	Returned version value
25876582671SRajan Vaja  *
25976582671SRajan Vaja  * Return: Returns status, either success or error+reason
26076582671SRajan Vaja  */
261b9b3a8beSRajan Vaja int zynqmp_pm_get_api_version(u32 *version)
26276582671SRajan Vaja {
26376582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
26476582671SRajan Vaja 	int ret;
26576582671SRajan Vaja 
26676582671SRajan Vaja 	if (!version)
26776582671SRajan Vaja 		return -EINVAL;
26876582671SRajan Vaja 
26976582671SRajan Vaja 	/* Check is PM API version already verified */
27076582671SRajan Vaja 	if (pm_api_version > 0) {
27176582671SRajan Vaja 		*version = pm_api_version;
27276582671SRajan Vaja 		return 0;
27376582671SRajan Vaja 	}
27476582671SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload);
27576582671SRajan Vaja 	*version = ret_payload[1];
27676582671SRajan Vaja 
27776582671SRajan Vaja 	return ret;
27876582671SRajan Vaja }
279b9b3a8beSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
28076582671SRajan Vaja 
28176582671SRajan Vaja /**
282fe6f42cfSNava kishore Manne  * zynqmp_pm_get_chipid - Get silicon ID registers
283fe6f42cfSNava kishore Manne  * @idcode:     IDCODE register
284fe6f42cfSNava kishore Manne  * @version:    version register
285fe6f42cfSNava kishore Manne  *
286fe6f42cfSNava kishore Manne  * Return:      Returns the status of the operation and the idcode and version
287fe6f42cfSNava kishore Manne  *              registers in @idcode and @version.
288fe6f42cfSNava kishore Manne  */
28921cd93baSRajan Vaja int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
290fe6f42cfSNava kishore Manne {
291fe6f42cfSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
292fe6f42cfSNava kishore Manne 	int ret;
293fe6f42cfSNava kishore Manne 
294fe6f42cfSNava kishore Manne 	if (!idcode || !version)
295fe6f42cfSNava kishore Manne 		return -EINVAL;
296fe6f42cfSNava kishore Manne 
297fe6f42cfSNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
298fe6f42cfSNava kishore Manne 	*idcode = ret_payload[1];
299fe6f42cfSNava kishore Manne 	*version = ret_payload[2];
300fe6f42cfSNava kishore Manne 
301fe6f42cfSNava kishore Manne 	return ret;
302fe6f42cfSNava kishore Manne }
30321cd93baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
304fe6f42cfSNava kishore Manne 
305fe6f42cfSNava kishore Manne /**
30676582671SRajan Vaja  * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
30776582671SRajan Vaja  * @version:	Returned version value
30876582671SRajan Vaja  *
30976582671SRajan Vaja  * Return: Returns status, either success or error+reason
31076582671SRajan Vaja  */
31176582671SRajan Vaja static int zynqmp_pm_get_trustzone_version(u32 *version)
31276582671SRajan Vaja {
31376582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
31476582671SRajan Vaja 	int ret;
31576582671SRajan Vaja 
31676582671SRajan Vaja 	if (!version)
31776582671SRajan Vaja 		return -EINVAL;
31876582671SRajan Vaja 
31976582671SRajan Vaja 	/* Check is PM trustzone version already verified */
32076582671SRajan Vaja 	if (pm_tz_version > 0) {
32176582671SRajan Vaja 		*version = pm_tz_version;
32276582671SRajan Vaja 		return 0;
32376582671SRajan Vaja 	}
32476582671SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0,
32576582671SRajan Vaja 				  0, 0, ret_payload);
32676582671SRajan Vaja 	*version = ret_payload[1];
32776582671SRajan Vaja 
32876582671SRajan Vaja 	return ret;
32976582671SRajan Vaja }
33076582671SRajan Vaja 
33176582671SRajan Vaja /**
33276582671SRajan Vaja  * get_set_conduit_method() - Choose SMC or HVC based communication
33376582671SRajan Vaja  * @np:		Pointer to the device_node structure
33476582671SRajan Vaja  *
33576582671SRajan Vaja  * Use SMC or HVC-based functions to communicate with EL2/EL3.
33676582671SRajan Vaja  *
33776582671SRajan Vaja  * Return: Returns 0 on success or error code
33876582671SRajan Vaja  */
33976582671SRajan Vaja static int get_set_conduit_method(struct device_node *np)
34076582671SRajan Vaja {
34176582671SRajan Vaja 	const char *method;
34276582671SRajan Vaja 
34376582671SRajan Vaja 	if (of_property_read_string(np, "method", &method)) {
34476582671SRajan Vaja 		pr_warn("%s missing \"method\" property\n", __func__);
34576582671SRajan Vaja 		return -ENXIO;
34676582671SRajan Vaja 	}
34776582671SRajan Vaja 
34876582671SRajan Vaja 	if (!strcmp("hvc", method)) {
34976582671SRajan Vaja 		do_fw_call = do_fw_call_hvc;
35076582671SRajan Vaja 	} else if (!strcmp("smc", method)) {
35176582671SRajan Vaja 		do_fw_call = do_fw_call_smc;
35276582671SRajan Vaja 	} else {
35376582671SRajan Vaja 		pr_warn("%s Invalid \"method\" property: %s\n",
35476582671SRajan Vaja 			__func__, method);
35576582671SRajan Vaja 		return -EINVAL;
35676582671SRajan Vaja 	}
35776582671SRajan Vaja 
35876582671SRajan Vaja 	return 0;
35976582671SRajan Vaja }
36076582671SRajan Vaja 
36159ecdd77SRajan Vaja /**
36259ecdd77SRajan Vaja  * zynqmp_pm_query_data() - Get query data from firmware
36359ecdd77SRajan Vaja  * @qdata:	Variable to the zynqmp_pm_query_data structure
36459ecdd77SRajan Vaja  * @out:	Returned output value
36559ecdd77SRajan Vaja  *
36659ecdd77SRajan Vaja  * Return: Returns status, either success or error+reason
36759ecdd77SRajan Vaja  */
3686366c1baSRajan Vaja int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
36959ecdd77SRajan Vaja {
370f9627312SRajan Vaja 	int ret;
371f9627312SRajan Vaja 
372f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1,
37359ecdd77SRajan Vaja 				  qdata.arg2, qdata.arg3, out);
374f9627312SRajan Vaja 
375f9627312SRajan Vaja 	/*
376f9627312SRajan Vaja 	 * For clock name query, all bytes in SMC response are clock name
377f9627312SRajan Vaja 	 * characters and return code is always success. For invalid clocks,
378f9627312SRajan Vaja 	 * clock name bytes would be zeros.
379f9627312SRajan Vaja 	 */
380f9627312SRajan Vaja 	return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
381f9627312SRajan Vaja }
3826366c1baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
383f9627312SRajan Vaja 
384f9627312SRajan Vaja /**
385f9627312SRajan Vaja  * zynqmp_pm_clock_enable() - Enable the clock for given id
386f9627312SRajan Vaja  * @clock_id:	ID of the clock to be enabled
387f9627312SRajan Vaja  *
388f9627312SRajan Vaja  * This function is used by master to enable the clock
389f9627312SRajan Vaja  * including peripherals and PLL clocks.
390f9627312SRajan Vaja  *
391f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
392f9627312SRajan Vaja  */
3933637e84cSRajan Vaja int zynqmp_pm_clock_enable(u32 clock_id)
394f9627312SRajan Vaja {
395f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
396f9627312SRajan Vaja }
3973637e84cSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
398f9627312SRajan Vaja 
399f9627312SRajan Vaja /**
400f9627312SRajan Vaja  * zynqmp_pm_clock_disable() - Disable the clock for given id
401f9627312SRajan Vaja  * @clock_id:	ID of the clock to be disable
402f9627312SRajan Vaja  *
403f9627312SRajan Vaja  * This function is used by master to disable the clock
404f9627312SRajan Vaja  * including peripherals and PLL clocks.
405f9627312SRajan Vaja  *
406f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
407f9627312SRajan Vaja  */
408f5ccd54bSRajan Vaja int zynqmp_pm_clock_disable(u32 clock_id)
409f9627312SRajan Vaja {
410f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
411f9627312SRajan Vaja }
412f5ccd54bSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
413f9627312SRajan Vaja 
414f9627312SRajan Vaja /**
415f9627312SRajan Vaja  * zynqmp_pm_clock_getstate() - Get the clock state for given id
416f9627312SRajan Vaja  * @clock_id:	ID of the clock to be queried
417f9627312SRajan Vaja  * @state:	1/0 (Enabled/Disabled)
418f9627312SRajan Vaja  *
419f9627312SRajan Vaja  * This function is used by master to get the state of clock
420f9627312SRajan Vaja  * including peripherals and PLL clocks.
421f9627312SRajan Vaja  *
422f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
423f9627312SRajan Vaja  */
4245e76731dSRajan Vaja int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
425f9627312SRajan Vaja {
426f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
427f9627312SRajan Vaja 	int ret;
428f9627312SRajan Vaja 
429f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0,
430f9627312SRajan Vaja 				  0, 0, ret_payload);
431f9627312SRajan Vaja 	*state = ret_payload[1];
432f9627312SRajan Vaja 
433f9627312SRajan Vaja 	return ret;
434f9627312SRajan Vaja }
4355e76731dSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
436f9627312SRajan Vaja 
437f9627312SRajan Vaja /**
438f9627312SRajan Vaja  * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
439f9627312SRajan Vaja  * @clock_id:	ID of the clock
440f9627312SRajan Vaja  * @divider:	divider value
441f9627312SRajan Vaja  *
442f9627312SRajan Vaja  * This function is used by master to set divider for any clock
443f9627312SRajan Vaja  * to achieve desired rate.
444f9627312SRajan Vaja  *
445f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
446f9627312SRajan Vaja  */
447fc9fb8fbSRajan Vaja int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
448f9627312SRajan Vaja {
449f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
450f9627312SRajan Vaja 				   0, 0, NULL);
451f9627312SRajan Vaja }
452fc9fb8fbSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
453f9627312SRajan Vaja 
454f9627312SRajan Vaja /**
455f9627312SRajan Vaja  * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
456f9627312SRajan Vaja  * @clock_id:	ID of the clock
457f9627312SRajan Vaja  * @divider:	divider value
458f9627312SRajan Vaja  *
459f9627312SRajan Vaja  * This function is used by master to get divider values
460f9627312SRajan Vaja  * for any clock.
461f9627312SRajan Vaja  *
462f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
463f9627312SRajan Vaja  */
4640667a8d1SRajan Vaja int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
465f9627312SRajan Vaja {
466f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
467f9627312SRajan Vaja 	int ret;
468f9627312SRajan Vaja 
469f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0,
470f9627312SRajan Vaja 				  0, 0, ret_payload);
471f9627312SRajan Vaja 	*divider = ret_payload[1];
472f9627312SRajan Vaja 
473f9627312SRajan Vaja 	return ret;
474f9627312SRajan Vaja }
4750667a8d1SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
476f9627312SRajan Vaja 
477f9627312SRajan Vaja /**
478f9627312SRajan Vaja  * zynqmp_pm_clock_setrate() - Set the clock rate for given id
479f9627312SRajan Vaja  * @clock_id:	ID of the clock
480f9627312SRajan Vaja  * @rate:	rate value in hz
481f9627312SRajan Vaja  *
482f9627312SRajan Vaja  * This function is used by master to set rate for any clock.
483f9627312SRajan Vaja  *
484f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
485f9627312SRajan Vaja  */
4867a1e1062SRajan Vaja int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
487f9627312SRajan Vaja {
488f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
489f9627312SRajan Vaja 				   lower_32_bits(rate),
490f9627312SRajan Vaja 				   upper_32_bits(rate),
491f9627312SRajan Vaja 				   0, NULL);
492f9627312SRajan Vaja }
4937a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate);
494f9627312SRajan Vaja 
495f9627312SRajan Vaja /**
496f9627312SRajan Vaja  * zynqmp_pm_clock_getrate() - Get the clock rate for given id
497f9627312SRajan Vaja  * @clock_id:	ID of the clock
498f9627312SRajan Vaja  * @rate:	rate value in hz
499f9627312SRajan Vaja  *
500f9627312SRajan Vaja  * This function is used by master to get rate
501f9627312SRajan Vaja  * for any clock.
502f9627312SRajan Vaja  *
503f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
504f9627312SRajan Vaja  */
5057a1e1062SRajan Vaja int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
506f9627312SRajan Vaja {
507f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
508f9627312SRajan Vaja 	int ret;
509f9627312SRajan Vaja 
510f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0,
511f9627312SRajan Vaja 				  0, 0, ret_payload);
512f9627312SRajan Vaja 	*rate = ((u64)ret_payload[2] << 32) | ret_payload[1];
513f9627312SRajan Vaja 
514f9627312SRajan Vaja 	return ret;
515f9627312SRajan Vaja }
5167a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate);
517f9627312SRajan Vaja 
518f9627312SRajan Vaja /**
519f9627312SRajan Vaja  * zynqmp_pm_clock_setparent() - Set the clock parent for given id
520f9627312SRajan Vaja  * @clock_id:	ID of the clock
521f9627312SRajan Vaja  * @parent_id:	parent id
522f9627312SRajan Vaja  *
523f9627312SRajan Vaja  * This function is used by master to set parent for any clock.
524f9627312SRajan Vaja  *
525f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
526f9627312SRajan Vaja  */
52770c0d364SRajan Vaja int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
528f9627312SRajan Vaja {
529f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
530f9627312SRajan Vaja 				   parent_id, 0, 0, NULL);
531f9627312SRajan Vaja }
53270c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
533f9627312SRajan Vaja 
534f9627312SRajan Vaja /**
535f9627312SRajan Vaja  * zynqmp_pm_clock_getparent() - Get the clock parent for given id
536f9627312SRajan Vaja  * @clock_id:	ID of the clock
537f9627312SRajan Vaja  * @parent_id:	parent id
538f9627312SRajan Vaja  *
539f9627312SRajan Vaja  * This function is used by master to get parent index
540f9627312SRajan Vaja  * for any clock.
541f9627312SRajan Vaja  *
542f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
543f9627312SRajan Vaja  */
54470c0d364SRajan Vaja int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
545f9627312SRajan Vaja {
546f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
547f9627312SRajan Vaja 	int ret;
548f9627312SRajan Vaja 
549f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0,
550f9627312SRajan Vaja 				  0, 0, ret_payload);
551f9627312SRajan Vaja 	*parent_id = ret_payload[1];
552f9627312SRajan Vaja 
553f9627312SRajan Vaja 	return ret;
55459ecdd77SRajan Vaja }
55570c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
55659ecdd77SRajan Vaja 
5573b0296b8SRajan Vaja /**
558426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
5593b0296b8SRajan Vaja  *
560426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
561426c8d85SRajan Vaja  * @mode:	PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
5623b0296b8SRajan Vaja  *
563426c8d85SRajan Vaja  * This function sets PLL mode
5643b0296b8SRajan Vaja  *
5653b0296b8SRajan Vaja  * Return: Returns status, either success or error+reason
5663b0296b8SRajan Vaja  */
567426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
5683b0296b8SRajan Vaja {
569426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE,
570426c8d85SRajan Vaja 				   clk_id, mode, NULL);
5713b0296b8SRajan Vaja }
572426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
573426c8d85SRajan Vaja 
574426c8d85SRajan Vaja /**
575426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
576426c8d85SRajan Vaja  *
577426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
578426c8d85SRajan Vaja  * @mode:	PLL mode
579426c8d85SRajan Vaja  *
580426c8d85SRajan Vaja  * This function return current PLL mode
581426c8d85SRajan Vaja  *
582426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
583426c8d85SRajan Vaja  */
584426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
585426c8d85SRajan Vaja {
586426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE,
587426c8d85SRajan Vaja 				   clk_id, 0, mode);
588426c8d85SRajan Vaja }
589426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
590426c8d85SRajan Vaja 
591426c8d85SRajan Vaja /**
592426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
593426c8d85SRajan Vaja  *
594426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
595426c8d85SRajan Vaja  * @data:	fraction data
596426c8d85SRajan Vaja  *
597426c8d85SRajan Vaja  * This function sets fraction data.
598426c8d85SRajan Vaja  * It is valid for fraction mode only.
599426c8d85SRajan Vaja  *
600426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
601426c8d85SRajan Vaja  */
602426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
603426c8d85SRajan Vaja {
604426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA,
605426c8d85SRajan Vaja 				   clk_id, data, NULL);
606426c8d85SRajan Vaja }
607426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
608426c8d85SRajan Vaja 
609426c8d85SRajan Vaja /**
610426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
611426c8d85SRajan Vaja  *
612426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
613426c8d85SRajan Vaja  * @data:	fraction data
614426c8d85SRajan Vaja  *
615426c8d85SRajan Vaja  * This function returns fraction data value.
616426c8d85SRajan Vaja  *
617426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
618426c8d85SRajan Vaja  */
619426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
620426c8d85SRajan Vaja {
621426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA,
622426c8d85SRajan Vaja 				   clk_id, 0, data);
623426c8d85SRajan Vaja }
624426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
625426c8d85SRajan Vaja 
626426c8d85SRajan Vaja /**
627426c8d85SRajan Vaja  * zynqmp_pm_set_sd_tapdelay() -  Set tap delay for the SD device
628426c8d85SRajan Vaja  *
629332bee16SMichal Simek  * @node_id:	Node ID of the device
630332bee16SMichal Simek  * @type:	Type of tap delay to set (input/output)
631332bee16SMichal Simek  * @value:	Value to set fot the tap delay
632426c8d85SRajan Vaja  *
633426c8d85SRajan Vaja  * This function sets input/output tap delay for the SD device.
634426c8d85SRajan Vaja  *
635332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
636426c8d85SRajan Vaja  */
637426c8d85SRajan Vaja int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
638426c8d85SRajan Vaja {
639426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
640426c8d85SRajan Vaja 				   type, value, NULL);
641426c8d85SRajan Vaja }
642426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
643426c8d85SRajan Vaja 
644426c8d85SRajan Vaja /**
645426c8d85SRajan Vaja  * zynqmp_pm_sd_dll_reset() - Reset DLL logic
646426c8d85SRajan Vaja  *
647332bee16SMichal Simek  * @node_id:	Node ID of the device
648332bee16SMichal Simek  * @type:	Reset type
649426c8d85SRajan Vaja  *
650426c8d85SRajan Vaja  * This function resets DLL logic for the SD device.
651426c8d85SRajan Vaja  *
652332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
653426c8d85SRajan Vaja  */
654426c8d85SRajan Vaja int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
655426c8d85SRajan Vaja {
656f4426311SManish Narani 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET,
657426c8d85SRajan Vaja 				   type, 0, NULL);
658426c8d85SRajan Vaja }
659426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
6603b0296b8SRajan Vaja 
661bc3843d4SNava kishore Manne /**
66274e78adcSSai Krishna Potthuri  * zynqmp_pm_ospi_mux_select() - OSPI Mux selection
66374e78adcSSai Krishna Potthuri  *
66474e78adcSSai Krishna Potthuri  * @dev_id:	Device Id of the OSPI device.
66574e78adcSSai Krishna Potthuri  * @select:	OSPI Mux select value.
66674e78adcSSai Krishna Potthuri  *
66774e78adcSSai Krishna Potthuri  * This function select the OSPI Mux.
66874e78adcSSai Krishna Potthuri  *
66974e78adcSSai Krishna Potthuri  * Return:	Returns status, either success or error+reason
67074e78adcSSai Krishna Potthuri  */
67174e78adcSSai Krishna Potthuri int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
67274e78adcSSai Krishna Potthuri {
67374e78adcSSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_IOCTL, dev_id, IOCTL_OSPI_MUX_SELECT,
67474e78adcSSai Krishna Potthuri 				   select, 0, NULL);
67574e78adcSSai Krishna Potthuri }
67674e78adcSSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select);
67774e78adcSSai Krishna Potthuri 
67874e78adcSSai Krishna Potthuri /**
6794f680b72SRajan Vaja  * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
680332bee16SMichal Simek  * @index:	GGS register index
681332bee16SMichal Simek  * @value:	Register value to be written
6824f680b72SRajan Vaja  *
6834f680b72SRajan Vaja  * This function writes value to GGS register.
6844f680b72SRajan Vaja  *
685332bee16SMichal Simek  * Return:      Returns status, either success or error+reason
6864f680b72SRajan Vaja  */
6874f680b72SRajan Vaja int zynqmp_pm_write_ggs(u32 index, u32 value)
6884f680b72SRajan Vaja {
6894f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS,
6904f680b72SRajan Vaja 				   index, value, NULL);
6914f680b72SRajan Vaja }
6924f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
6934f680b72SRajan Vaja 
6944f680b72SRajan Vaja /**
6952a8faf8dSMichal Simek  * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs)
696332bee16SMichal Simek  * @index:	GGS register index
697332bee16SMichal Simek  * @value:	Register value to be written
6984f680b72SRajan Vaja  *
6994f680b72SRajan Vaja  * This function returns GGS register value.
7004f680b72SRajan Vaja  *
701332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
7024f680b72SRajan Vaja  */
7034f680b72SRajan Vaja int zynqmp_pm_read_ggs(u32 index, u32 *value)
7044f680b72SRajan Vaja {
7054f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS,
7064f680b72SRajan Vaja 				   index, 0, value);
7074f680b72SRajan Vaja }
7084f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
7094f680b72SRajan Vaja 
7104f680b72SRajan Vaja /**
7114f680b72SRajan Vaja  * zynqmp_pm_write_pggs() - PM API for writing persistent global general
7124f680b72SRajan Vaja  *			     storage (pggs)
713332bee16SMichal Simek  * @index:	PGGS register index
714332bee16SMichal Simek  * @value:	Register value to be written
7154f680b72SRajan Vaja  *
7164f680b72SRajan Vaja  * This function writes value to PGGS register.
7174f680b72SRajan Vaja  *
718332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
7194f680b72SRajan Vaja  */
7204f680b72SRajan Vaja int zynqmp_pm_write_pggs(u32 index, u32 value)
7214f680b72SRajan Vaja {
7224f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value,
7234f680b72SRajan Vaja 				   NULL);
7244f680b72SRajan Vaja }
7254f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
7264f680b72SRajan Vaja 
7274f680b72SRajan Vaja /**
7282a8faf8dSMichal Simek  * zynqmp_pm_read_pggs() - PM API for reading persistent global general
7294f680b72SRajan Vaja  *			     storage (pggs)
730332bee16SMichal Simek  * @index:	PGGS register index
731332bee16SMichal Simek  * @value:	Register value to be written
7324f680b72SRajan Vaja  *
7334f680b72SRajan Vaja  * This function returns PGGS register value.
7344f680b72SRajan Vaja  *
735332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
7364f680b72SRajan Vaja  */
7374f680b72SRajan Vaja int zynqmp_pm_read_pggs(u32 index, u32 *value)
7384f680b72SRajan Vaja {
7394f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0,
7404f680b72SRajan Vaja 				   value);
7414f680b72SRajan Vaja }
7424f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
7434f680b72SRajan Vaja 
7444f680b72SRajan Vaja /**
745a2cc220aSRajan Vaja  * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
746332bee16SMichal Simek  * @value:	Status value to be written
747a2cc220aSRajan Vaja  *
748a2cc220aSRajan Vaja  * This function sets healthy bit value to indicate boot health status
749a2cc220aSRajan Vaja  * to firmware.
750a2cc220aSRajan Vaja  *
751332bee16SMichal Simek  * Return:	Returns status, either success or error+reason
752a2cc220aSRajan Vaja  */
753a2cc220aSRajan Vaja int zynqmp_pm_set_boot_health_status(u32 value)
754a2cc220aSRajan Vaja {
755a2cc220aSRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS,
756a2cc220aSRajan Vaja 				   value, 0, NULL);
757a2cc220aSRajan Vaja }
758a2cc220aSRajan Vaja 
759a2cc220aSRajan Vaja /**
760bc3843d4SNava kishore Manne  * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
761bc3843d4SNava kishore Manne  * @reset:		Reset to be configured
762bc3843d4SNava kishore Manne  * @assert_flag:	Flag stating should reset be asserted (1) or
763bc3843d4SNava kishore Manne  *			released (0)
764bc3843d4SNava kishore Manne  *
765bc3843d4SNava kishore Manne  * Return: Returns status, either success or error+reason
766bc3843d4SNava kishore Manne  */
767cf23ec35SRajan Vaja int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
768bc3843d4SNava kishore Manne 			   const enum zynqmp_pm_reset_action assert_flag)
769bc3843d4SNava kishore Manne {
770bc3843d4SNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
771bc3843d4SNava kishore Manne 				   0, 0, NULL);
772bc3843d4SNava kishore Manne }
773cf23ec35SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
774bc3843d4SNava kishore Manne 
775bc3843d4SNava kishore Manne /**
776bc3843d4SNava kishore Manne  * zynqmp_pm_reset_get_status - Get status of the reset
777bc3843d4SNava kishore Manne  * @reset:      Reset whose status should be returned
778bc3843d4SNava kishore Manne  * @status:     Returned status
779bc3843d4SNava kishore Manne  *
780bc3843d4SNava kishore Manne  * Return: Returns status, either success or error+reason
781bc3843d4SNava kishore Manne  */
7821b413581SRajan Vaja int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
783bc3843d4SNava kishore Manne {
784bc3843d4SNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
785bc3843d4SNava kishore Manne 	int ret;
786bc3843d4SNava kishore Manne 
787bc3843d4SNava kishore Manne 	if (!status)
788bc3843d4SNava kishore Manne 		return -EINVAL;
789bc3843d4SNava kishore Manne 
790bc3843d4SNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
791bc3843d4SNava kishore Manne 				  0, 0, ret_payload);
792bc3843d4SNava kishore Manne 	*status = ret_payload[1];
793bc3843d4SNava kishore Manne 
794bc3843d4SNava kishore Manne 	return ret;
795bc3843d4SNava kishore Manne }
7961b413581SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
797bc3843d4SNava kishore Manne 
798e178df31SJolly Shah /**
799e840deccSNava kishore Manne  * zynqmp_pm_fpga_load - Perform the fpga load
800e840deccSNava kishore Manne  * @address:	Address to write to
801e840deccSNava kishore Manne  * @size:	pl bitstream size
802e840deccSNava kishore Manne  * @flags:	Bitstream type
803e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
804e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
805e840deccSNava kishore Manne  *
806e840deccSNava kishore Manne  * This function provides access to pmufw. To transfer
807e840deccSNava kishore Manne  * the required bitstream into PL.
808e840deccSNava kishore Manne  *
809e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
810e840deccSNava kishore Manne  */
8114db8180fSRajan Vaja int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
812e840deccSNava kishore Manne {
813e840deccSNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
814e840deccSNava kishore Manne 				   upper_32_bits(address), size, flags, NULL);
815e840deccSNava kishore Manne }
81656a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
817e840deccSNava kishore Manne 
818e840deccSNava kishore Manne /**
819e840deccSNava kishore Manne  * zynqmp_pm_fpga_get_status - Read value from PCAP status register
820e840deccSNava kishore Manne  * @value: Value to read
821e840deccSNava kishore Manne  *
822e840deccSNava kishore Manne  * This function provides access to the pmufw to get the PCAP
823e840deccSNava kishore Manne  * status
824e840deccSNava kishore Manne  *
825e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
826e840deccSNava kishore Manne  */
8274db8180fSRajan Vaja int zynqmp_pm_fpga_get_status(u32 *value)
828e840deccSNava kishore Manne {
829e840deccSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
830e840deccSNava kishore Manne 	int ret;
831e840deccSNava kishore Manne 
832e840deccSNava kishore Manne 	if (!value)
833e840deccSNava kishore Manne 		return -EINVAL;
834e840deccSNava kishore Manne 
835e840deccSNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
836e840deccSNava kishore Manne 	*value = ret_payload[1];
837e840deccSNava kishore Manne 
838e840deccSNava kishore Manne 	return ret;
839e840deccSNava kishore Manne }
84056a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
841e840deccSNava kishore Manne 
842e840deccSNava kishore Manne /**
843fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_request - Request Pin from firmware
844fa989ae7SSai Krishna Potthuri  * @pin: Pin number to request
845fa989ae7SSai Krishna Potthuri  *
846fa989ae7SSai Krishna Potthuri  * This function requests pin from firmware.
847fa989ae7SSai Krishna Potthuri  *
848fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
849fa989ae7SSai Krishna Potthuri  */
850fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_request(const u32 pin)
851fa989ae7SSai Krishna Potthuri {
852fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
853fa989ae7SSai Krishna Potthuri }
854fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request);
855fa989ae7SSai Krishna Potthuri 
856fa989ae7SSai Krishna Potthuri /**
857fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
858fa989ae7SSai Krishna Potthuri  * @pin: Pin number to release
859fa989ae7SSai Krishna Potthuri  *
860fa989ae7SSai Krishna Potthuri  * This function release pin from firmware.
861fa989ae7SSai Krishna Potthuri  *
862fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
863fa989ae7SSai Krishna Potthuri  */
864fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_release(const u32 pin)
865fa989ae7SSai Krishna Potthuri {
866fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL);
867fa989ae7SSai Krishna Potthuri }
868fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release);
869fa989ae7SSai Krishna Potthuri 
870fa989ae7SSai Krishna Potthuri /**
871fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin
872fa989ae7SSai Krishna Potthuri  * @pin: Pin number
873fa989ae7SSai Krishna Potthuri  * @id: Buffer to store function ID
874fa989ae7SSai Krishna Potthuri  *
875fa989ae7SSai Krishna Potthuri  * This function provides the function currently set for the given pin.
876fa989ae7SSai Krishna Potthuri  *
877fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason
878fa989ae7SSai Krishna Potthuri  */
879fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id)
880fa989ae7SSai Krishna Potthuri {
881fa989ae7SSai Krishna Potthuri 	u32 ret_payload[PAYLOAD_ARG_CNT];
882fa989ae7SSai Krishna Potthuri 	int ret;
883fa989ae7SSai Krishna Potthuri 
884fa989ae7SSai Krishna Potthuri 	if (!id)
885fa989ae7SSai Krishna Potthuri 		return -EINVAL;
886fa989ae7SSai Krishna Potthuri 
887fa989ae7SSai Krishna Potthuri 	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0,
888fa989ae7SSai Krishna Potthuri 				  0, 0, ret_payload);
889fa989ae7SSai Krishna Potthuri 	*id = ret_payload[1];
890fa989ae7SSai Krishna Potthuri 
891fa989ae7SSai Krishna Potthuri 	return ret;
892fa989ae7SSai Krishna Potthuri }
893fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_function);
894fa989ae7SSai Krishna Potthuri 
895fa989ae7SSai Krishna Potthuri /**
896fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
897fa989ae7SSai Krishna Potthuri  * @pin: Pin number
898fa989ae7SSai Krishna Potthuri  * @id: Function ID to set
899fa989ae7SSai Krishna Potthuri  *
900fa989ae7SSai Krishna Potthuri  * This function sets requested function for the given pin.
901fa989ae7SSai Krishna Potthuri  *
902fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
903fa989ae7SSai Krishna Potthuri  */
904fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
905fa989ae7SSai Krishna Potthuri {
906fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id,
907fa989ae7SSai Krishna Potthuri 				   0, 0, NULL);
908fa989ae7SSai Krishna Potthuri }
909fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function);
910fa989ae7SSai Krishna Potthuri 
911fa989ae7SSai Krishna Potthuri /**
912fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
913fa989ae7SSai Krishna Potthuri  * @pin: Pin number
914fa989ae7SSai Krishna Potthuri  * @param: Parameter to get
915fa989ae7SSai Krishna Potthuri  * @value: Buffer to store parameter value
916fa989ae7SSai Krishna Potthuri  *
917fa989ae7SSai Krishna Potthuri  * This function gets requested configuration parameter for the given pin.
918fa989ae7SSai Krishna Potthuri  *
919fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
920fa989ae7SSai Krishna Potthuri  */
921fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
922fa989ae7SSai Krishna Potthuri 				 u32 *value)
923fa989ae7SSai Krishna Potthuri {
924fa989ae7SSai Krishna Potthuri 	u32 ret_payload[PAYLOAD_ARG_CNT];
925fa989ae7SSai Krishna Potthuri 	int ret;
926fa989ae7SSai Krishna Potthuri 
927fa989ae7SSai Krishna Potthuri 	if (!value)
928fa989ae7SSai Krishna Potthuri 		return -EINVAL;
929fa989ae7SSai Krishna Potthuri 
930fa989ae7SSai Krishna Potthuri 	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param,
931fa989ae7SSai Krishna Potthuri 				  0, 0, ret_payload);
932fa989ae7SSai Krishna Potthuri 	*value = ret_payload[1];
933fa989ae7SSai Krishna Potthuri 
934fa989ae7SSai Krishna Potthuri 	return ret;
935fa989ae7SSai Krishna Potthuri }
936fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config);
937fa989ae7SSai Krishna Potthuri 
938fa989ae7SSai Krishna Potthuri /**
939fa989ae7SSai Krishna Potthuri  * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
940fa989ae7SSai Krishna Potthuri  * @pin: Pin number
941fa989ae7SSai Krishna Potthuri  * @param: Parameter to set
942fa989ae7SSai Krishna Potthuri  * @value: Parameter value to set
943fa989ae7SSai Krishna Potthuri  *
944fa989ae7SSai Krishna Potthuri  * This function sets requested configuration parameter for the given pin.
945fa989ae7SSai Krishna Potthuri  *
946fa989ae7SSai Krishna Potthuri  * Return: Returns status, either success or error+reason.
947fa989ae7SSai Krishna Potthuri  */
948fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
949fa989ae7SSai Krishna Potthuri 				 u32 value)
950fa989ae7SSai Krishna Potthuri {
951fa989ae7SSai Krishna Potthuri 	return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin,
952fa989ae7SSai Krishna Potthuri 				   param, value, 0, NULL);
953fa989ae7SSai Krishna Potthuri }
954fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config);
955fa989ae7SSai Krishna Potthuri 
956fa989ae7SSai Krishna Potthuri /**
95723c64d76SPiyush Mehta  * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status
95823c64d76SPiyush Mehta  * @ps_mode: Returned output value of ps_mode
95923c64d76SPiyush Mehta  *
96023c64d76SPiyush Mehta  * This API function is to be used for notify the power management controller
96123c64d76SPiyush Mehta  * to read bootpin status.
96223c64d76SPiyush Mehta  *
96323c64d76SPiyush Mehta  * Return: status, either success or error+reason
96423c64d76SPiyush Mehta  */
96523c64d76SPiyush Mehta unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode)
96623c64d76SPiyush Mehta {
96723c64d76SPiyush Mehta 	unsigned int ret;
96823c64d76SPiyush Mehta 	u32 ret_payload[PAYLOAD_ARG_CNT];
96923c64d76SPiyush Mehta 
97023c64d76SPiyush Mehta 	ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, CRL_APB_BOOT_PIN_CTRL, 0,
97123c64d76SPiyush Mehta 				  0, 0, ret_payload);
97223c64d76SPiyush Mehta 
97323c64d76SPiyush Mehta 	*ps_mode = ret_payload[1];
97423c64d76SPiyush Mehta 
97523c64d76SPiyush Mehta 	return ret;
97623c64d76SPiyush Mehta }
97723c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read);
97823c64d76SPiyush Mehta 
97923c64d76SPiyush Mehta /**
98023c64d76SPiyush Mehta  * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin
98123c64d76SPiyush Mehta  * @ps_mode: Value to be written to the bootpin ctrl register
98223c64d76SPiyush Mehta  *
98323c64d76SPiyush Mehta  * This API function is to be used for notify the power management controller
98423c64d76SPiyush Mehta  * to configure bootpin.
98523c64d76SPiyush Mehta  *
98623c64d76SPiyush Mehta  * Return: Returns status, either success or error+reason
98723c64d76SPiyush Mehta  */
98823c64d76SPiyush Mehta int zynqmp_pm_bootmode_write(u32 ps_mode)
98923c64d76SPiyush Mehta {
99023c64d76SPiyush Mehta 	return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, CRL_APB_BOOT_PIN_CTRL,
99123c64d76SPiyush Mehta 				   CRL_APB_BOOTPIN_CTRL_MASK, ps_mode, 0, NULL);
99223c64d76SPiyush Mehta }
99323c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write);
99423c64d76SPiyush Mehta 
99523c64d76SPiyush Mehta /**
996e178df31SJolly Shah  * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
997e178df31SJolly Shah  *			       master has initialized its own power management
998e178df31SJolly Shah  *
999332bee16SMichal Simek  * Return: Returns status, either success or error+reason
1000332bee16SMichal Simek  *
1001e178df31SJolly Shah  * This API function is to be used for notify the power management controller
1002e178df31SJolly Shah  * about the completed power management initialization.
1003e178df31SJolly Shah  */
10049474da95SRajan Vaja int zynqmp_pm_init_finalize(void)
1005e178df31SJolly Shah {
1006e178df31SJolly Shah 	return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
1007e178df31SJolly Shah }
10089474da95SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize);
1009e178df31SJolly Shah 
1010e178df31SJolly Shah /**
1011e178df31SJolly Shah  * zynqmp_pm_set_suspend_mode()	- Set system suspend mode
1012e178df31SJolly Shah  * @mode:	Mode to set for system suspend
1013e178df31SJolly Shah  *
1014e178df31SJolly Shah  * This API function is used to set mode of system suspend.
1015e178df31SJolly Shah  *
1016e178df31SJolly Shah  * Return: Returns status, either success or error+reason
1017e178df31SJolly Shah  */
1018951d0a97SRajan Vaja int zynqmp_pm_set_suspend_mode(u32 mode)
1019e178df31SJolly Shah {
1020e178df31SJolly Shah 	return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
1021e178df31SJolly Shah }
1022951d0a97SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
1023e178df31SJolly Shah 
1024c1986ac3SRajan Vaja /**
1025c1986ac3SRajan Vaja  * zynqmp_pm_request_node() - Request a node with specific capabilities
1026c1986ac3SRajan Vaja  * @node:		Node ID of the slave
1027c1986ac3SRajan Vaja  * @capabilities:	Requested capabilities of the slave
1028c1986ac3SRajan Vaja  * @qos:		Quality of service (not supported)
1029c1986ac3SRajan Vaja  * @ack:		Flag to specify whether acknowledge is requested
1030c1986ac3SRajan Vaja  *
1031c1986ac3SRajan Vaja  * This function is used by master to request particular node from firmware.
1032c1986ac3SRajan Vaja  * Every master must request node before using it.
1033c1986ac3SRajan Vaja  *
1034c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1035c1986ac3SRajan Vaja  */
1036bf8b27edSRajan Vaja int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
1037bf8b27edSRajan Vaja 			   const u32 qos, const enum zynqmp_pm_request_ack ack)
1038c1986ac3SRajan Vaja {
1039c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
1040c1986ac3SRajan Vaja 				   qos, ack, NULL);
1041c1986ac3SRajan Vaja }
1042bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
1043c1986ac3SRajan Vaja 
1044c1986ac3SRajan Vaja /**
1045c1986ac3SRajan Vaja  * zynqmp_pm_release_node() - Release a node
1046c1986ac3SRajan Vaja  * @node:	Node ID of the slave
1047c1986ac3SRajan Vaja  *
1048c1986ac3SRajan Vaja  * This function is used by master to inform firmware that master
1049c1986ac3SRajan Vaja  * has released node. Once released, master must not use that node
1050c1986ac3SRajan Vaja  * without re-request.
1051c1986ac3SRajan Vaja  *
1052c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1053c1986ac3SRajan Vaja  */
105407fb1a46SRajan Vaja int zynqmp_pm_release_node(const u32 node)
1055c1986ac3SRajan Vaja {
1056c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
1057c1986ac3SRajan Vaja }
105807fb1a46SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
1059c1986ac3SRajan Vaja 
1060c1986ac3SRajan Vaja /**
1061c1986ac3SRajan Vaja  * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
1062c1986ac3SRajan Vaja  * @node:		Node ID of the slave
1063c1986ac3SRajan Vaja  * @capabilities:	Requested capabilities of the slave
1064c1986ac3SRajan Vaja  * @qos:		Quality of service (not supported)
1065c1986ac3SRajan Vaja  * @ack:		Flag to specify whether acknowledge is requested
1066c1986ac3SRajan Vaja  *
1067c1986ac3SRajan Vaja  * This API function is to be used for slaves a PU already has requested
1068c1986ac3SRajan Vaja  * to change its capabilities.
1069c1986ac3SRajan Vaja  *
1070c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
1071c1986ac3SRajan Vaja  */
1072cbbbda71SRajan Vaja int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
1073c1986ac3SRajan Vaja 			      const u32 qos,
1074c1986ac3SRajan Vaja 			      const enum zynqmp_pm_request_ack ack)
1075c1986ac3SRajan Vaja {
1076c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
1077c1986ac3SRajan Vaja 				   qos, ack, NULL);
1078c1986ac3SRajan Vaja }
1079cbbbda71SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
1080c1986ac3SRajan Vaja 
1081057a0fb6SKalyani Akula /**
10822b9fc773SNava kishore Manne  * zynqmp_pm_load_pdi - Load and process PDI
10832b9fc773SNava kishore Manne  * @src:       Source device where PDI is located
10842b9fc773SNava kishore Manne  * @address:   PDI src address
10852b9fc773SNava kishore Manne  *
10862b9fc773SNava kishore Manne  * This function provides support to load PDI from linux
10872b9fc773SNava kishore Manne  *
10882b9fc773SNava kishore Manne  * Return: Returns status, either success or error+reason
10892b9fc773SNava kishore Manne  */
10902b9fc773SNava kishore Manne int zynqmp_pm_load_pdi(const u32 src, const u64 address)
10912b9fc773SNava kishore Manne {
10922b9fc773SNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src,
10932b9fc773SNava kishore Manne 				   lower_32_bits(address),
10942b9fc773SNava kishore Manne 				   upper_32_bits(address), 0, NULL);
10952b9fc773SNava kishore Manne }
10962b9fc773SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi);
10972b9fc773SNava kishore Manne 
10982b9fc773SNava kishore Manne /**
10992a8faf8dSMichal Simek  * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
1100057a0fb6SKalyani Akula  * AES-GCM core.
1101057a0fb6SKalyani Akula  * @address:	Address of the AesParams structure.
1102057a0fb6SKalyani Akula  * @out:	Returned output value
1103057a0fb6SKalyani Akula  *
1104057a0fb6SKalyani Akula  * Return:	Returns status, either success or error code.
1105057a0fb6SKalyani Akula  */
1106bc86f9c5SRajan Vaja int zynqmp_pm_aes_engine(const u64 address, u32 *out)
1107057a0fb6SKalyani Akula {
1108057a0fb6SKalyani Akula 	u32 ret_payload[PAYLOAD_ARG_CNT];
1109057a0fb6SKalyani Akula 	int ret;
1110057a0fb6SKalyani Akula 
1111057a0fb6SKalyani Akula 	if (!out)
1112057a0fb6SKalyani Akula 		return -EINVAL;
1113057a0fb6SKalyani Akula 
1114057a0fb6SKalyani Akula 	ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address),
1115057a0fb6SKalyani Akula 				  lower_32_bits(address),
1116057a0fb6SKalyani Akula 				  0, 0, ret_payload);
1117057a0fb6SKalyani Akula 	*out = ret_payload[1];
1118057a0fb6SKalyani Akula 
1119057a0fb6SKalyani Akula 	return ret;
1120057a0fb6SKalyani Akula }
1121bc86f9c5SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
1122057a0fb6SKalyani Akula 
1123fdd2ed88SRajan Vaja /**
1124*80f940efSHarsha  * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
1125*80f940efSHarsha  * @address:	Address of the data/ Address of output buffer where
1126*80f940efSHarsha  *		hash should be stored.
1127*80f940efSHarsha  * @size:	Size of the data.
1128*80f940efSHarsha  * @flags:
1129*80f940efSHarsha  *	BIT(0) - for initializing csudma driver and SHA3(Here address
1130*80f940efSHarsha  *		 and size inputs can be NULL).
1131*80f940efSHarsha  *	BIT(1) - to call Sha3_Update API which can be called multiple
1132*80f940efSHarsha  *		 times when data is not contiguous.
1133*80f940efSHarsha  *	BIT(2) - to get final hash of the whole updated data.
1134*80f940efSHarsha  *		 Hash will be overwritten at provided address with
1135*80f940efSHarsha  *		 48 bytes.
1136*80f940efSHarsha  *
1137*80f940efSHarsha  * Return:	Returns status, either success or error code.
1138*80f940efSHarsha  */
1139*80f940efSHarsha int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags)
1140*80f940efSHarsha {
1141*80f940efSHarsha 	u32 lower_addr = lower_32_bits(address);
1142*80f940efSHarsha 	u32 upper_addr = upper_32_bits(address);
1143*80f940efSHarsha 
1144*80f940efSHarsha 	return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_addr, lower_addr,
1145*80f940efSHarsha 				   size, flags, NULL);
1146*80f940efSHarsha }
1147*80f940efSHarsha EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash);
1148*80f940efSHarsha 
1149*80f940efSHarsha /**
11501881eadbSAbhyuday Godhasara  * zynqmp_pm_register_notifier() - PM API for register a subsystem
11511881eadbSAbhyuday Godhasara  *                                to be notified about specific
11521881eadbSAbhyuday Godhasara  *                                event/error.
11531881eadbSAbhyuday Godhasara  * @node:	Node ID to which the event is related.
11541881eadbSAbhyuday Godhasara  * @event:	Event Mask of Error events for which wants to get notified.
11551881eadbSAbhyuday Godhasara  * @wake:	Wake subsystem upon capturing the event if value 1
11561881eadbSAbhyuday Godhasara  * @enable:	Enable the registration for value 1, disable for value 0
11571881eadbSAbhyuday Godhasara  *
11581881eadbSAbhyuday Godhasara  * This function is used to register/un-register for particular node-event
11591881eadbSAbhyuday Godhasara  * combination in firmware.
11601881eadbSAbhyuday Godhasara  *
11611881eadbSAbhyuday Godhasara  * Return: Returns status, either success or error+reason
11621881eadbSAbhyuday Godhasara  */
11631881eadbSAbhyuday Godhasara 
11641881eadbSAbhyuday Godhasara int zynqmp_pm_register_notifier(const u32 node, const u32 event,
11651881eadbSAbhyuday Godhasara 				const u32 wake, const u32 enable)
11661881eadbSAbhyuday Godhasara {
11671881eadbSAbhyuday Godhasara 	return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event,
11681881eadbSAbhyuday Godhasara 				   wake, enable, NULL);
11691881eadbSAbhyuday Godhasara }
11701881eadbSAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier);
11711881eadbSAbhyuday Godhasara 
11721881eadbSAbhyuday Godhasara /**
1173fdd2ed88SRajan Vaja  * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
1174fdd2ed88SRajan Vaja  * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
1175fdd2ed88SRajan Vaja  * @subtype:	Specifies which system should be restarted or shut down
1176fdd2ed88SRajan Vaja  *
1177fdd2ed88SRajan Vaja  * Return:	Returns status, either success or error+reason
1178fdd2ed88SRajan Vaja  */
1179fdd2ed88SRajan Vaja int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
1180fdd2ed88SRajan Vaja {
1181fdd2ed88SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
1182fdd2ed88SRajan Vaja 				   0, 0, NULL);
1183fdd2ed88SRajan Vaja }
1184fdd2ed88SRajan Vaja 
1185b3ae24c4SRajan Vaja /**
1186b3ae24c4SRajan Vaja  * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
1187b3ae24c4SRajan Vaja  * @subtype:	Shutdown subtype
1188b3ae24c4SRajan Vaja  * @name:	Matching string for scope argument
1189b3ae24c4SRajan Vaja  *
1190b3ae24c4SRajan Vaja  * This struct encapsulates mapping between shutdown scope ID and string.
1191b3ae24c4SRajan Vaja  */
1192b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope {
1193b3ae24c4SRajan Vaja 	const enum zynqmp_pm_shutdown_subtype subtype;
1194b3ae24c4SRajan Vaja 	const char *name;
1195b3ae24c4SRajan Vaja };
1196b3ae24c4SRajan Vaja 
1197b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
1198b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
1199b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
1200b3ae24c4SRajan Vaja 		.name = "subsystem",
1201b3ae24c4SRajan Vaja 	},
1202b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
1203b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
1204b3ae24c4SRajan Vaja 		.name = "ps_only",
1205b3ae24c4SRajan Vaja 	},
1206b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
1207b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
1208b3ae24c4SRajan Vaja 		.name = "system",
1209b3ae24c4SRajan Vaja 	},
1210b3ae24c4SRajan Vaja };
1211b3ae24c4SRajan Vaja 
1212b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope =
1213b3ae24c4SRajan Vaja 		&shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
1214b3ae24c4SRajan Vaja 
1215b3ae24c4SRajan Vaja /**
1216b3ae24c4SRajan Vaja  * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
1217b3ae24c4SRajan Vaja  * @scope_string:	Shutdown scope string
1218b3ae24c4SRajan Vaja  *
1219b3ae24c4SRajan Vaja  * Return:		Return pointer to matching shutdown scope struct from
1220b3ae24c4SRajan Vaja  *			array of available options in system if string is valid,
1221b3ae24c4SRajan Vaja  *			otherwise returns NULL.
1222b3ae24c4SRajan Vaja  */
1223b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope*
1224b3ae24c4SRajan Vaja 		zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
1225b3ae24c4SRajan Vaja {
1226b3ae24c4SRajan Vaja 	int count;
1227b3ae24c4SRajan Vaja 
1228b3ae24c4SRajan Vaja 	for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
1229b3ae24c4SRajan Vaja 		if (sysfs_streq(scope_string, shutdown_scopes[count].name))
1230b3ae24c4SRajan Vaja 			return &shutdown_scopes[count];
1231b3ae24c4SRajan Vaja 
1232b3ae24c4SRajan Vaja 	return NULL;
1233b3ae24c4SRajan Vaja }
1234b3ae24c4SRajan Vaja 
1235b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device,
1236b3ae24c4SRajan Vaja 				   struct device_attribute *attr,
1237b3ae24c4SRajan Vaja 				   char *buf)
1238b3ae24c4SRajan Vaja {
1239b3ae24c4SRajan Vaja 	int i;
1240b3ae24c4SRajan Vaja 
1241b3ae24c4SRajan Vaja 	for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
1242b3ae24c4SRajan Vaja 		if (&shutdown_scopes[i] == selected_scope) {
1243b3ae24c4SRajan Vaja 			strcat(buf, "[");
1244b3ae24c4SRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
1245b3ae24c4SRajan Vaja 			strcat(buf, "]");
1246b3ae24c4SRajan Vaja 		} else {
1247b3ae24c4SRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
1248b3ae24c4SRajan Vaja 		}
1249b3ae24c4SRajan Vaja 		strcat(buf, " ");
1250b3ae24c4SRajan Vaja 	}
1251b3ae24c4SRajan Vaja 	strcat(buf, "\n");
1252b3ae24c4SRajan Vaja 
1253b3ae24c4SRajan Vaja 	return strlen(buf);
1254b3ae24c4SRajan Vaja }
1255b3ae24c4SRajan Vaja 
1256b3ae24c4SRajan Vaja static ssize_t shutdown_scope_store(struct device *device,
1257b3ae24c4SRajan Vaja 				    struct device_attribute *attr,
1258b3ae24c4SRajan Vaja 				    const char *buf, size_t count)
1259b3ae24c4SRajan Vaja {
1260b3ae24c4SRajan Vaja 	int ret;
1261b3ae24c4SRajan Vaja 	struct zynqmp_pm_shutdown_scope *scope;
1262b3ae24c4SRajan Vaja 
1263b3ae24c4SRajan Vaja 	scope = zynqmp_pm_is_shutdown_scope_valid(buf);
1264b3ae24c4SRajan Vaja 	if (!scope)
1265b3ae24c4SRajan Vaja 		return -EINVAL;
1266b3ae24c4SRajan Vaja 
1267b3ae24c4SRajan Vaja 	ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
1268b3ae24c4SRajan Vaja 					scope->subtype);
1269b3ae24c4SRajan Vaja 	if (ret) {
1270b3ae24c4SRajan Vaja 		pr_err("unable to set shutdown scope %s\n", buf);
1271b3ae24c4SRajan Vaja 		return ret;
1272b3ae24c4SRajan Vaja 	}
1273b3ae24c4SRajan Vaja 
1274b3ae24c4SRajan Vaja 	selected_scope = scope;
1275b3ae24c4SRajan Vaja 
1276b3ae24c4SRajan Vaja 	return count;
1277b3ae24c4SRajan Vaja }
1278b3ae24c4SRajan Vaja 
1279b3ae24c4SRajan Vaja static DEVICE_ATTR_RW(shutdown_scope);
1280b3ae24c4SRajan Vaja 
1281a2cc220aSRajan Vaja static ssize_t health_status_store(struct device *device,
1282a2cc220aSRajan Vaja 				   struct device_attribute *attr,
1283a2cc220aSRajan Vaja 				   const char *buf, size_t count)
1284a2cc220aSRajan Vaja {
1285a2cc220aSRajan Vaja 	int ret;
1286a2cc220aSRajan Vaja 	unsigned int value;
1287a2cc220aSRajan Vaja 
1288a2cc220aSRajan Vaja 	ret = kstrtouint(buf, 10, &value);
1289a2cc220aSRajan Vaja 	if (ret)
1290a2cc220aSRajan Vaja 		return ret;
1291a2cc220aSRajan Vaja 
1292a2cc220aSRajan Vaja 	ret = zynqmp_pm_set_boot_health_status(value);
1293a2cc220aSRajan Vaja 	if (ret) {
1294a2cc220aSRajan Vaja 		dev_err(device, "unable to set healthy bit value to %u\n",
1295a2cc220aSRajan Vaja 			value);
1296a2cc220aSRajan Vaja 		return ret;
1297a2cc220aSRajan Vaja 	}
1298a2cc220aSRajan Vaja 
1299a2cc220aSRajan Vaja 	return count;
1300a2cc220aSRajan Vaja }
1301a2cc220aSRajan Vaja 
1302a2cc220aSRajan Vaja static DEVICE_ATTR_WO(health_status);
1303a2cc220aSRajan Vaja 
1304ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device,
1305ae5c961dSRajan Vaja 			struct device_attribute *attr,
1306ae5c961dSRajan Vaja 			char *buf,
1307ae5c961dSRajan Vaja 			u32 reg)
1308ae5c961dSRajan Vaja {
1309ae5c961dSRajan Vaja 	int ret;
1310ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1311ae5c961dSRajan Vaja 
1312ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_ggs(reg, ret_payload);
1313ae5c961dSRajan Vaja 	if (ret)
1314ae5c961dSRajan Vaja 		return ret;
1315ae5c961dSRajan Vaja 
1316ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1317ae5c961dSRajan Vaja }
1318ae5c961dSRajan Vaja 
1319ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device,
1320ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1321ae5c961dSRajan Vaja 			 const char *buf, size_t count,
1322ae5c961dSRajan Vaja 			 u32 reg)
1323ae5c961dSRajan Vaja {
1324ae5c961dSRajan Vaja 	long value;
1325ae5c961dSRajan Vaja 	int ret;
1326ae5c961dSRajan Vaja 
1327ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1328ae5c961dSRajan Vaja 		return -EINVAL;
1329ae5c961dSRajan Vaja 
1330ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1331ae5c961dSRajan Vaja 	if (ret) {
1332ae5c961dSRajan Vaja 		count = -EFAULT;
1333ae5c961dSRajan Vaja 		goto err;
1334ae5c961dSRajan Vaja 	}
1335ae5c961dSRajan Vaja 
1336ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_ggs(reg, value);
1337ae5c961dSRajan Vaja 	if (ret)
1338ae5c961dSRajan Vaja 		count = -EFAULT;
1339ae5c961dSRajan Vaja err:
1340ae5c961dSRajan Vaja 	return count;
1341ae5c961dSRajan Vaja }
1342ae5c961dSRajan Vaja 
1343ae5c961dSRajan Vaja /* GGS register show functions */
1344ae5c961dSRajan Vaja #define GGS0_SHOW(N)						\
1345ae5c961dSRajan Vaja 	ssize_t ggs##N##_show(struct device *device,		\
1346ae5c961dSRajan Vaja 			      struct device_attribute *attr,	\
1347ae5c961dSRajan Vaja 			      char *buf)			\
1348ae5c961dSRajan Vaja 	{							\
1349ae5c961dSRajan Vaja 		return ggs_show(device, attr, buf, N);		\
1350ae5c961dSRajan Vaja 	}
1351ae5c961dSRajan Vaja 
1352ae5c961dSRajan Vaja static GGS0_SHOW(0);
1353ae5c961dSRajan Vaja static GGS0_SHOW(1);
1354ae5c961dSRajan Vaja static GGS0_SHOW(2);
1355ae5c961dSRajan Vaja static GGS0_SHOW(3);
1356ae5c961dSRajan Vaja 
1357ae5c961dSRajan Vaja /* GGS register store function */
1358ae5c961dSRajan Vaja #define GGS0_STORE(N)						\
1359ae5c961dSRajan Vaja 	ssize_t ggs##N##_store(struct device *device,		\
1360ae5c961dSRajan Vaja 			       struct device_attribute *attr,	\
1361ae5c961dSRajan Vaja 			       const char *buf,			\
1362ae5c961dSRajan Vaja 			       size_t count)			\
1363ae5c961dSRajan Vaja 	{							\
1364ae5c961dSRajan Vaja 		return ggs_store(device, attr, buf, count, N);	\
1365ae5c961dSRajan Vaja 	}
1366ae5c961dSRajan Vaja 
1367ae5c961dSRajan Vaja static GGS0_STORE(0);
1368ae5c961dSRajan Vaja static GGS0_STORE(1);
1369ae5c961dSRajan Vaja static GGS0_STORE(2);
1370ae5c961dSRajan Vaja static GGS0_STORE(3);
1371ae5c961dSRajan Vaja 
1372ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device,
1373ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1374ae5c961dSRajan Vaja 			 char *buf,
1375ae5c961dSRajan Vaja 			 u32 reg)
1376ae5c961dSRajan Vaja {
1377ae5c961dSRajan Vaja 	int ret;
1378ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1379ae5c961dSRajan Vaja 
1380ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_pggs(reg, ret_payload);
1381ae5c961dSRajan Vaja 	if (ret)
1382ae5c961dSRajan Vaja 		return ret;
1383ae5c961dSRajan Vaja 
1384ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1385ae5c961dSRajan Vaja }
1386ae5c961dSRajan Vaja 
1387ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device,
1388ae5c961dSRajan Vaja 			  struct device_attribute *attr,
1389ae5c961dSRajan Vaja 			  const char *buf, size_t count,
1390ae5c961dSRajan Vaja 			  u32 reg)
1391ae5c961dSRajan Vaja {
1392ae5c961dSRajan Vaja 	long value;
1393ae5c961dSRajan Vaja 	int ret;
1394ae5c961dSRajan Vaja 
1395ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1396ae5c961dSRajan Vaja 		return -EINVAL;
1397ae5c961dSRajan Vaja 
1398ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1399ae5c961dSRajan Vaja 	if (ret) {
1400ae5c961dSRajan Vaja 		count = -EFAULT;
1401ae5c961dSRajan Vaja 		goto err;
1402ae5c961dSRajan Vaja 	}
1403ae5c961dSRajan Vaja 
1404ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_pggs(reg, value);
1405ae5c961dSRajan Vaja 	if (ret)
1406ae5c961dSRajan Vaja 		count = -EFAULT;
1407ae5c961dSRajan Vaja 
1408ae5c961dSRajan Vaja err:
1409ae5c961dSRajan Vaja 	return count;
1410ae5c961dSRajan Vaja }
1411ae5c961dSRajan Vaja 
1412ae5c961dSRajan Vaja #define PGGS0_SHOW(N)						\
1413ae5c961dSRajan Vaja 	ssize_t pggs##N##_show(struct device *device,		\
1414ae5c961dSRajan Vaja 			       struct device_attribute *attr,	\
1415ae5c961dSRajan Vaja 			       char *buf)			\
1416ae5c961dSRajan Vaja 	{							\
1417ae5c961dSRajan Vaja 		return pggs_show(device, attr, buf, N);		\
1418ae5c961dSRajan Vaja 	}
1419ae5c961dSRajan Vaja 
1420ae5c961dSRajan Vaja #define PGGS0_STORE(N)						\
1421ae5c961dSRajan Vaja 	ssize_t pggs##N##_store(struct device *device,		\
1422ae5c961dSRajan Vaja 				struct device_attribute *attr,	\
1423ae5c961dSRajan Vaja 				const char *buf,		\
1424ae5c961dSRajan Vaja 				size_t count)			\
1425ae5c961dSRajan Vaja 	{							\
1426ae5c961dSRajan Vaja 		return pggs_store(device, attr, buf, count, N);	\
1427ae5c961dSRajan Vaja 	}
1428ae5c961dSRajan Vaja 
1429ae5c961dSRajan Vaja /* PGGS register show functions */
1430ae5c961dSRajan Vaja static PGGS0_SHOW(0);
1431ae5c961dSRajan Vaja static PGGS0_SHOW(1);
1432ae5c961dSRajan Vaja static PGGS0_SHOW(2);
1433ae5c961dSRajan Vaja static PGGS0_SHOW(3);
1434ae5c961dSRajan Vaja 
1435ae5c961dSRajan Vaja /* PGGS register store functions */
1436ae5c961dSRajan Vaja static PGGS0_STORE(0);
1437ae5c961dSRajan Vaja static PGGS0_STORE(1);
1438ae5c961dSRajan Vaja static PGGS0_STORE(2);
1439ae5c961dSRajan Vaja static PGGS0_STORE(3);
1440ae5c961dSRajan Vaja 
1441ae5c961dSRajan Vaja /* GGS register attributes */
1442ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs0);
1443ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs1);
1444ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs2);
1445ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs3);
1446ae5c961dSRajan Vaja 
1447ae5c961dSRajan Vaja /* PGGS register attributes */
1448ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs0);
1449ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs1);
1450ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs2);
1451ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs3);
1452ae5c961dSRajan Vaja 
1453ae5c961dSRajan Vaja static struct attribute *zynqmp_firmware_attrs[] = {
1454ae5c961dSRajan Vaja 	&dev_attr_ggs0.attr,
1455ae5c961dSRajan Vaja 	&dev_attr_ggs1.attr,
1456ae5c961dSRajan Vaja 	&dev_attr_ggs2.attr,
1457ae5c961dSRajan Vaja 	&dev_attr_ggs3.attr,
1458ae5c961dSRajan Vaja 	&dev_attr_pggs0.attr,
1459ae5c961dSRajan Vaja 	&dev_attr_pggs1.attr,
1460ae5c961dSRajan Vaja 	&dev_attr_pggs2.attr,
1461ae5c961dSRajan Vaja 	&dev_attr_pggs3.attr,
1462b3ae24c4SRajan Vaja 	&dev_attr_shutdown_scope.attr,
1463a2cc220aSRajan Vaja 	&dev_attr_health_status.attr,
1464ae5c961dSRajan Vaja 	NULL,
1465ae5c961dSRajan Vaja };
1466ae5c961dSRajan Vaja 
1467ae5c961dSRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware);
1468ae5c961dSRajan Vaja 
146976582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev)
147076582671SRajan Vaja {
147176582671SRajan Vaja 	struct device *dev = &pdev->dev;
147276582671SRajan Vaja 	struct device_node *np;
147376582671SRajan Vaja 	int ret;
147476582671SRajan Vaja 
147576582671SRajan Vaja 	np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp");
1476af3f1afaSJolly Shah 	if (!np) {
1477af3f1afaSJolly Shah 		np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
147876582671SRajan Vaja 		if (!np)
147976582671SRajan Vaja 			return 0;
1480461011b1SRavi Patel 
1481461011b1SRavi Patel 		feature_check_enabled = true;
1482af3f1afaSJolly Shah 	}
148376582671SRajan Vaja 	of_node_put(np);
148476582671SRajan Vaja 
148576582671SRajan Vaja 	ret = get_set_conduit_method(dev->of_node);
148676582671SRajan Vaja 	if (ret)
148776582671SRajan Vaja 		return ret;
148876582671SRajan Vaja 
148976582671SRajan Vaja 	/* Check PM API version number */
1490168e05c1SRajan Vaja 	ret = zynqmp_pm_get_api_version(&pm_api_version);
1491168e05c1SRajan Vaja 	if (ret)
1492168e05c1SRajan Vaja 		return ret;
1493168e05c1SRajan Vaja 
149476582671SRajan Vaja 	if (pm_api_version < ZYNQMP_PM_VERSION) {
149576582671SRajan Vaja 		panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
149676582671SRajan Vaja 		      __func__,
149776582671SRajan Vaja 		      ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
149876582671SRajan Vaja 		      pm_api_version >> 16, pm_api_version & 0xFFFF);
149976582671SRajan Vaja 	}
150076582671SRajan Vaja 
150176582671SRajan Vaja 	pr_info("%s Platform Management API v%d.%d\n", __func__,
150276582671SRajan Vaja 		pm_api_version >> 16, pm_api_version & 0xFFFF);
150376582671SRajan Vaja 
150476582671SRajan Vaja 	/* Check trustzone version number */
150576582671SRajan Vaja 	ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
150676582671SRajan Vaja 	if (ret)
150776582671SRajan Vaja 		panic("Legacy trustzone found without version support\n");
150876582671SRajan Vaja 
150976582671SRajan Vaja 	if (pm_tz_version < ZYNQMP_TZ_VERSION)
151076582671SRajan Vaja 		panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
151176582671SRajan Vaja 		      __func__,
151276582671SRajan Vaja 		      ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
151376582671SRajan Vaja 		      pm_tz_version >> 16, pm_tz_version & 0xFFFF);
151476582671SRajan Vaja 
151576582671SRajan Vaja 	pr_info("%s Trustzone version v%d.%d\n", __func__,
151676582671SRajan Vaja 		pm_tz_version >> 16, pm_tz_version & 0xFFFF);
151776582671SRajan Vaja 
1518e23d9c6dSJolly Shah 	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
1519e23d9c6dSJolly Shah 			      ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
1520e23d9c6dSJolly Shah 	if (ret) {
1521e23d9c6dSJolly Shah 		dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
1522e23d9c6dSJolly Shah 		return ret;
1523e23d9c6dSJolly Shah 	}
1524e23d9c6dSJolly Shah 
152565f0539bSChristophe JAILLET 	zynqmp_pm_api_debugfs_init();
152665f0539bSChristophe JAILLET 
1527a515814eSAbhyuday Godhasara 	np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
1528a515814eSAbhyuday Godhasara 	if (np) {
1529a515814eSAbhyuday Godhasara 		em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager",
1530a515814eSAbhyuday Godhasara 						       -1, NULL, 0);
1531a515814eSAbhyuday Godhasara 		if (IS_ERR(em_dev))
1532a515814eSAbhyuday Godhasara 			dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n");
1533a515814eSAbhyuday Godhasara 	}
1534a515814eSAbhyuday Godhasara 	of_node_put(np);
1535a515814eSAbhyuday Godhasara 
153676582671SRajan Vaja 	return of_platform_populate(dev->of_node, NULL, NULL, dev);
153776582671SRajan Vaja }
153876582671SRajan Vaja 
153976582671SRajan Vaja static int zynqmp_firmware_remove(struct platform_device *pdev)
154076582671SRajan Vaja {
1541acfdd185SAmit Sunil Dhamne 	struct pm_api_feature_data *feature_data;
1542f1f21becSTejas Patel 	struct hlist_node *tmp;
1543acfdd185SAmit Sunil Dhamne 	int i;
1544acfdd185SAmit Sunil Dhamne 
1545e23d9c6dSJolly Shah 	mfd_remove_devices(&pdev->dev);
1546b3217252SRajan Vaja 	zynqmp_pm_api_debugfs_exit();
1547b3217252SRajan Vaja 
1548f1f21becSTejas Patel 	hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) {
1549acfdd185SAmit Sunil Dhamne 		hash_del(&feature_data->hentry);
1550acfdd185SAmit Sunil Dhamne 		kfree(feature_data);
1551acfdd185SAmit Sunil Dhamne 	}
1552acfdd185SAmit Sunil Dhamne 
1553a515814eSAbhyuday Godhasara 	platform_device_unregister(em_dev);
1554a515814eSAbhyuday Godhasara 
155576582671SRajan Vaja 	return 0;
155676582671SRajan Vaja }
155776582671SRajan Vaja 
155876582671SRajan Vaja static const struct of_device_id zynqmp_firmware_of_match[] = {
155976582671SRajan Vaja 	{.compatible = "xlnx,zynqmp-firmware"},
1560af3f1afaSJolly Shah 	{.compatible = "xlnx,versal-firmware"},
156176582671SRajan Vaja 	{},
156276582671SRajan Vaja };
156376582671SRajan Vaja MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
156476582671SRajan Vaja 
156576582671SRajan Vaja static struct platform_driver zynqmp_firmware_driver = {
156676582671SRajan Vaja 	.driver = {
156776582671SRajan Vaja 		.name = "zynqmp_firmware",
156876582671SRajan Vaja 		.of_match_table = zynqmp_firmware_of_match,
1569ae5c961dSRajan Vaja 		.dev_groups = zynqmp_firmware_groups,
157076582671SRajan Vaja 	},
157176582671SRajan Vaja 	.probe = zynqmp_firmware_probe,
157276582671SRajan Vaja 	.remove = zynqmp_firmware_remove,
157376582671SRajan Vaja };
157476582671SRajan Vaja module_platform_driver(zynqmp_firmware_driver);
1575