xref: /openbmc/linux/drivers/firmware/xilinx/zynqmp.c (revision f4426311)
176582671SRajan Vaja // SPDX-License-Identifier: GPL-2.0
276582671SRajan Vaja /*
376582671SRajan Vaja  * Xilinx Zynq MPSoC Firmware layer
476582671SRajan Vaja  *
5ae5c961dSRajan Vaja  *  Copyright (C) 2014-2020 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>
2376582671SRajan Vaja 
2476582671SRajan Vaja #include <linux/firmware/xlnx-zynqmp.h>
25b3217252SRajan Vaja #include "zynqmp-debug.h"
2676582671SRajan Vaja 
27461011b1SRavi Patel static bool feature_check_enabled;
28461011b1SRavi Patel static u32 zynqmp_pm_features[PM_API_MAX];
29461011b1SRavi Patel 
30e23d9c6dSJolly Shah static const struct mfd_cell firmware_devs[] = {
31e23d9c6dSJolly Shah 	{
32e23d9c6dSJolly Shah 		.name = "zynqmp_power_controller",
33e23d9c6dSJolly Shah 	},
34e23d9c6dSJolly Shah };
35e23d9c6dSJolly Shah 
3676582671SRajan Vaja /**
3776582671SRajan Vaja  * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
3876582671SRajan Vaja  * @ret_status:		PMUFW return code
3976582671SRajan Vaja  *
4076582671SRajan Vaja  * Return: corresponding Linux error code
4176582671SRajan Vaja  */
4276582671SRajan Vaja static int zynqmp_pm_ret_code(u32 ret_status)
4376582671SRajan Vaja {
4476582671SRajan Vaja 	switch (ret_status) {
4576582671SRajan Vaja 	case XST_PM_SUCCESS:
4676582671SRajan Vaja 	case XST_PM_DOUBLE_REQ:
4776582671SRajan Vaja 		return 0;
48461011b1SRavi Patel 	case XST_PM_NO_FEATURE:
49461011b1SRavi Patel 		return -ENOTSUPP;
5076582671SRajan Vaja 	case XST_PM_NO_ACCESS:
5176582671SRajan Vaja 		return -EACCES;
5276582671SRajan Vaja 	case XST_PM_ABORT_SUSPEND:
5376582671SRajan Vaja 		return -ECANCELED;
54df2a4d94SRajan Vaja 	case XST_PM_MULT_USER:
55df2a4d94SRajan Vaja 		return -EUSERS;
5676582671SRajan Vaja 	case XST_PM_INTERNAL:
5776582671SRajan Vaja 	case XST_PM_CONFLICT:
5876582671SRajan Vaja 	case XST_PM_INVALID_NODE:
5976582671SRajan Vaja 	default:
6076582671SRajan Vaja 		return -EINVAL;
6176582671SRajan Vaja 	}
6276582671SRajan Vaja }
6376582671SRajan Vaja 
6476582671SRajan Vaja static noinline int do_fw_call_fail(u64 arg0, u64 arg1, u64 arg2,
6576582671SRajan Vaja 				    u32 *ret_payload)
6676582671SRajan Vaja {
6776582671SRajan Vaja 	return -ENODEV;
6876582671SRajan Vaja }
6976582671SRajan Vaja 
7076582671SRajan Vaja /*
7176582671SRajan Vaja  * PM function call wrapper
7276582671SRajan Vaja  * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
7376582671SRajan Vaja  */
7476582671SRajan Vaja static int (*do_fw_call)(u64, u64, u64, u32 *ret_payload) = do_fw_call_fail;
7576582671SRajan Vaja 
7676582671SRajan Vaja /**
7776582671SRajan Vaja  * do_fw_call_smc() - Call system-level platform management layer (SMC)
7876582671SRajan Vaja  * @arg0:		Argument 0 to SMC call
7976582671SRajan Vaja  * @arg1:		Argument 1 to SMC call
8076582671SRajan Vaja  * @arg2:		Argument 2 to SMC call
8176582671SRajan Vaja  * @ret_payload:	Returned value array
8276582671SRajan Vaja  *
8376582671SRajan Vaja  * Invoke platform management function via SMC call (no hypervisor present).
8476582671SRajan Vaja  *
8576582671SRajan Vaja  * Return: Returns status, either success or error+reason
8676582671SRajan Vaja  */
8776582671SRajan Vaja static noinline int do_fw_call_smc(u64 arg0, u64 arg1, u64 arg2,
8876582671SRajan Vaja 				   u32 *ret_payload)
8976582671SRajan Vaja {
9076582671SRajan Vaja 	struct arm_smccc_res res;
9176582671SRajan Vaja 
9276582671SRajan Vaja 	arm_smccc_smc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
9376582671SRajan Vaja 
9476582671SRajan Vaja 	if (ret_payload) {
9576582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
9676582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
9776582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
9876582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
9976582671SRajan Vaja 	}
10076582671SRajan Vaja 
10176582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
10276582671SRajan Vaja }
10376582671SRajan Vaja 
10476582671SRajan Vaja /**
10576582671SRajan Vaja  * do_fw_call_hvc() - Call system-level platform management layer (HVC)
10676582671SRajan Vaja  * @arg0:		Argument 0 to HVC call
10776582671SRajan Vaja  * @arg1:		Argument 1 to HVC call
10876582671SRajan Vaja  * @arg2:		Argument 2 to HVC call
10976582671SRajan Vaja  * @ret_payload:	Returned value array
11076582671SRajan Vaja  *
11176582671SRajan Vaja  * Invoke platform management function via HVC
11276582671SRajan Vaja  * HVC-based for communication through hypervisor
11376582671SRajan Vaja  * (no direct communication with ATF).
11476582671SRajan Vaja  *
11576582671SRajan Vaja  * Return: Returns status, either success or error+reason
11676582671SRajan Vaja  */
11776582671SRajan Vaja static noinline int do_fw_call_hvc(u64 arg0, u64 arg1, u64 arg2,
11876582671SRajan Vaja 				   u32 *ret_payload)
11976582671SRajan Vaja {
12076582671SRajan Vaja 	struct arm_smccc_res res;
12176582671SRajan Vaja 
12276582671SRajan Vaja 	arm_smccc_hvc(arg0, arg1, arg2, 0, 0, 0, 0, 0, &res);
12376582671SRajan Vaja 
12476582671SRajan Vaja 	if (ret_payload) {
12576582671SRajan Vaja 		ret_payload[0] = lower_32_bits(res.a0);
12676582671SRajan Vaja 		ret_payload[1] = upper_32_bits(res.a0);
12776582671SRajan Vaja 		ret_payload[2] = lower_32_bits(res.a1);
12876582671SRajan Vaja 		ret_payload[3] = upper_32_bits(res.a1);
12976582671SRajan Vaja 	}
13076582671SRajan Vaja 
13176582671SRajan Vaja 	return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
13276582671SRajan Vaja }
13376582671SRajan Vaja 
13476582671SRajan Vaja /**
135461011b1SRavi Patel  * zynqmp_pm_feature() - Check weather given feature is supported or not
136461011b1SRavi Patel  * @api_id:		API ID to check
137461011b1SRavi Patel  *
138461011b1SRavi Patel  * Return: Returns status, either success or error+reason
139461011b1SRavi Patel  */
140461011b1SRavi Patel static int zynqmp_pm_feature(u32 api_id)
141461011b1SRavi Patel {
142461011b1SRavi Patel 	int ret;
143461011b1SRavi Patel 	u32 ret_payload[PAYLOAD_ARG_CNT];
144461011b1SRavi Patel 	u64 smc_arg[2];
145461011b1SRavi Patel 
146461011b1SRavi Patel 	if (!feature_check_enabled)
147461011b1SRavi Patel 		return 0;
148461011b1SRavi Patel 
149461011b1SRavi Patel 	/* Return value if feature is already checked */
150f3217d6fSArnd Bergmann 	if (api_id > ARRAY_SIZE(zynqmp_pm_features))
151f3217d6fSArnd Bergmann 		return PM_FEATURE_INVALID;
152f3217d6fSArnd Bergmann 
153461011b1SRavi Patel 	if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
154461011b1SRavi Patel 		return zynqmp_pm_features[api_id];
155461011b1SRavi Patel 
156461011b1SRavi Patel 	smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK;
157461011b1SRavi Patel 	smc_arg[1] = api_id;
158461011b1SRavi Patel 
159461011b1SRavi Patel 	ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload);
160461011b1SRavi Patel 	if (ret) {
161461011b1SRavi Patel 		zynqmp_pm_features[api_id] = PM_FEATURE_INVALID;
162461011b1SRavi Patel 		return PM_FEATURE_INVALID;
163461011b1SRavi Patel 	}
164461011b1SRavi Patel 
165461011b1SRavi Patel 	zynqmp_pm_features[api_id] = ret_payload[1];
166461011b1SRavi Patel 
167461011b1SRavi Patel 	return zynqmp_pm_features[api_id];
168461011b1SRavi Patel }
169461011b1SRavi Patel 
170461011b1SRavi Patel /**
17176582671SRajan Vaja  * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
17276582671SRajan Vaja  *			   caller function depending on the configuration
17376582671SRajan Vaja  * @pm_api_id:		Requested PM-API call
17476582671SRajan Vaja  * @arg0:		Argument 0 to requested PM-API call
17576582671SRajan Vaja  * @arg1:		Argument 1 to requested PM-API call
17676582671SRajan Vaja  * @arg2:		Argument 2 to requested PM-API call
17776582671SRajan Vaja  * @arg3:		Argument 3 to requested PM-API call
17876582671SRajan Vaja  * @ret_payload:	Returned value array
17976582671SRajan Vaja  *
18076582671SRajan Vaja  * Invoke platform management function for SMC or HVC call, depending on
18176582671SRajan Vaja  * configuration.
18276582671SRajan Vaja  * Following SMC Calling Convention (SMCCC) for SMC64:
18376582671SRajan Vaja  * Pm Function Identifier,
18476582671SRajan Vaja  * PM_SIP_SVC + PM_API_ID =
18576582671SRajan Vaja  *	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
18676582671SRajan Vaja  *	((SMC_64) << FUNCID_CC_SHIFT)
18776582671SRajan Vaja  *	((SIP_START) << FUNCID_OEN_SHIFT)
18876582671SRajan Vaja  *	((PM_API_ID) & FUNCID_NUM_MASK))
18976582671SRajan Vaja  *
19076582671SRajan Vaja  * PM_SIP_SVC	- Registered ZynqMP SIP Service Call.
19176582671SRajan Vaja  * PM_API_ID	- Platform Management API ID.
19276582671SRajan Vaja  *
19376582671SRajan Vaja  * Return: Returns status, either success or error+reason
19476582671SRajan Vaja  */
19576582671SRajan Vaja int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 arg0, u32 arg1,
19676582671SRajan Vaja 			u32 arg2, u32 arg3, u32 *ret_payload)
19776582671SRajan Vaja {
19876582671SRajan Vaja 	/*
19976582671SRajan Vaja 	 * Added SIP service call Function Identifier
20076582671SRajan Vaja 	 * Make sure to stay in x0 register
20176582671SRajan Vaja 	 */
20276582671SRajan Vaja 	u64 smc_arg[4];
20376582671SRajan Vaja 
204461011b1SRavi Patel 	if (zynqmp_pm_feature(pm_api_id) == PM_FEATURE_INVALID)
205461011b1SRavi Patel 		return -ENOTSUPP;
206461011b1SRavi Patel 
20776582671SRajan Vaja 	smc_arg[0] = PM_SIP_SVC | pm_api_id;
20876582671SRajan Vaja 	smc_arg[1] = ((u64)arg1 << 32) | arg0;
20976582671SRajan Vaja 	smc_arg[2] = ((u64)arg3 << 32) | arg2;
21076582671SRajan Vaja 
21176582671SRajan Vaja 	return do_fw_call(smc_arg[0], smc_arg[1], smc_arg[2], ret_payload);
21276582671SRajan Vaja }
21376582671SRajan Vaja 
21476582671SRajan Vaja static u32 pm_api_version;
21576582671SRajan Vaja static u32 pm_tz_version;
21676582671SRajan Vaja 
21776582671SRajan Vaja /**
21876582671SRajan Vaja  * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
21976582671SRajan Vaja  * @version:	Returned version value
22076582671SRajan Vaja  *
22176582671SRajan Vaja  * Return: Returns status, either success or error+reason
22276582671SRajan Vaja  */
223b9b3a8beSRajan Vaja int zynqmp_pm_get_api_version(u32 *version)
22476582671SRajan Vaja {
22576582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
22676582671SRajan Vaja 	int ret;
22776582671SRajan Vaja 
22876582671SRajan Vaja 	if (!version)
22976582671SRajan Vaja 		return -EINVAL;
23076582671SRajan Vaja 
23176582671SRajan Vaja 	/* Check is PM API version already verified */
23276582671SRajan Vaja 	if (pm_api_version > 0) {
23376582671SRajan Vaja 		*version = pm_api_version;
23476582671SRajan Vaja 		return 0;
23576582671SRajan Vaja 	}
23676582671SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, 0, 0, 0, 0, ret_payload);
23776582671SRajan Vaja 	*version = ret_payload[1];
23876582671SRajan Vaja 
23976582671SRajan Vaja 	return ret;
24076582671SRajan Vaja }
241b9b3a8beSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
24276582671SRajan Vaja 
24376582671SRajan Vaja /**
244fe6f42cfSNava kishore Manne  * zynqmp_pm_get_chipid - Get silicon ID registers
245fe6f42cfSNava kishore Manne  * @idcode:     IDCODE register
246fe6f42cfSNava kishore Manne  * @version:    version register
247fe6f42cfSNava kishore Manne  *
248fe6f42cfSNava kishore Manne  * Return:      Returns the status of the operation and the idcode and version
249fe6f42cfSNava kishore Manne  *              registers in @idcode and @version.
250fe6f42cfSNava kishore Manne  */
25121cd93baSRajan Vaja int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
252fe6f42cfSNava kishore Manne {
253fe6f42cfSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
254fe6f42cfSNava kishore Manne 	int ret;
255fe6f42cfSNava kishore Manne 
256fe6f42cfSNava kishore Manne 	if (!idcode || !version)
257fe6f42cfSNava kishore Manne 		return -EINVAL;
258fe6f42cfSNava kishore Manne 
259fe6f42cfSNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
260fe6f42cfSNava kishore Manne 	*idcode = ret_payload[1];
261fe6f42cfSNava kishore Manne 	*version = ret_payload[2];
262fe6f42cfSNava kishore Manne 
263fe6f42cfSNava kishore Manne 	return ret;
264fe6f42cfSNava kishore Manne }
26521cd93baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
266fe6f42cfSNava kishore Manne 
267fe6f42cfSNava kishore Manne /**
26876582671SRajan Vaja  * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
26976582671SRajan Vaja  * @version:	Returned version value
27076582671SRajan Vaja  *
27176582671SRajan Vaja  * Return: Returns status, either success or error+reason
27276582671SRajan Vaja  */
27376582671SRajan Vaja static int zynqmp_pm_get_trustzone_version(u32 *version)
27476582671SRajan Vaja {
27576582671SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
27676582671SRajan Vaja 	int ret;
27776582671SRajan Vaja 
27876582671SRajan Vaja 	if (!version)
27976582671SRajan Vaja 		return -EINVAL;
28076582671SRajan Vaja 
28176582671SRajan Vaja 	/* Check is PM trustzone version already verified */
28276582671SRajan Vaja 	if (pm_tz_version > 0) {
28376582671SRajan Vaja 		*version = pm_tz_version;
28476582671SRajan Vaja 		return 0;
28576582671SRajan Vaja 	}
28676582671SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, 0, 0,
28776582671SRajan Vaja 				  0, 0, ret_payload);
28876582671SRajan Vaja 	*version = ret_payload[1];
28976582671SRajan Vaja 
29076582671SRajan Vaja 	return ret;
29176582671SRajan Vaja }
29276582671SRajan Vaja 
29376582671SRajan Vaja /**
29476582671SRajan Vaja  * get_set_conduit_method() - Choose SMC or HVC based communication
29576582671SRajan Vaja  * @np:		Pointer to the device_node structure
29676582671SRajan Vaja  *
29776582671SRajan Vaja  * Use SMC or HVC-based functions to communicate with EL2/EL3.
29876582671SRajan Vaja  *
29976582671SRajan Vaja  * Return: Returns 0 on success or error code
30076582671SRajan Vaja  */
30176582671SRajan Vaja static int get_set_conduit_method(struct device_node *np)
30276582671SRajan Vaja {
30376582671SRajan Vaja 	const char *method;
30476582671SRajan Vaja 
30576582671SRajan Vaja 	if (of_property_read_string(np, "method", &method)) {
30676582671SRajan Vaja 		pr_warn("%s missing \"method\" property\n", __func__);
30776582671SRajan Vaja 		return -ENXIO;
30876582671SRajan Vaja 	}
30976582671SRajan Vaja 
31076582671SRajan Vaja 	if (!strcmp("hvc", method)) {
31176582671SRajan Vaja 		do_fw_call = do_fw_call_hvc;
31276582671SRajan Vaja 	} else if (!strcmp("smc", method)) {
31376582671SRajan Vaja 		do_fw_call = do_fw_call_smc;
31476582671SRajan Vaja 	} else {
31576582671SRajan Vaja 		pr_warn("%s Invalid \"method\" property: %s\n",
31676582671SRajan Vaja 			__func__, method);
31776582671SRajan Vaja 		return -EINVAL;
31876582671SRajan Vaja 	}
31976582671SRajan Vaja 
32076582671SRajan Vaja 	return 0;
32176582671SRajan Vaja }
32276582671SRajan Vaja 
32359ecdd77SRajan Vaja /**
32459ecdd77SRajan Vaja  * zynqmp_pm_query_data() - Get query data from firmware
32559ecdd77SRajan Vaja  * @qdata:	Variable to the zynqmp_pm_query_data structure
32659ecdd77SRajan Vaja  * @out:	Returned output value
32759ecdd77SRajan Vaja  *
32859ecdd77SRajan Vaja  * Return: Returns status, either success or error+reason
32959ecdd77SRajan Vaja  */
3306366c1baSRajan Vaja int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
33159ecdd77SRajan Vaja {
332f9627312SRajan Vaja 	int ret;
333f9627312SRajan Vaja 
334f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1,
33559ecdd77SRajan Vaja 				  qdata.arg2, qdata.arg3, out);
336f9627312SRajan Vaja 
337f9627312SRajan Vaja 	/*
338f9627312SRajan Vaja 	 * For clock name query, all bytes in SMC response are clock name
339f9627312SRajan Vaja 	 * characters and return code is always success. For invalid clocks,
340f9627312SRajan Vaja 	 * clock name bytes would be zeros.
341f9627312SRajan Vaja 	 */
342f9627312SRajan Vaja 	return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
343f9627312SRajan Vaja }
3446366c1baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
345f9627312SRajan Vaja 
346f9627312SRajan Vaja /**
347f9627312SRajan Vaja  * zynqmp_pm_clock_enable() - Enable the clock for given id
348f9627312SRajan Vaja  * @clock_id:	ID of the clock to be enabled
349f9627312SRajan Vaja  *
350f9627312SRajan Vaja  * This function is used by master to enable the clock
351f9627312SRajan Vaja  * including peripherals and PLL clocks.
352f9627312SRajan Vaja  *
353f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
354f9627312SRajan Vaja  */
3553637e84cSRajan Vaja int zynqmp_pm_clock_enable(u32 clock_id)
356f9627312SRajan Vaja {
357f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
358f9627312SRajan Vaja }
3593637e84cSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
360f9627312SRajan Vaja 
361f9627312SRajan Vaja /**
362f9627312SRajan Vaja  * zynqmp_pm_clock_disable() - Disable the clock for given id
363f9627312SRajan Vaja  * @clock_id:	ID of the clock to be disable
364f9627312SRajan Vaja  *
365f9627312SRajan Vaja  * This function is used by master to disable the clock
366f9627312SRajan Vaja  * including peripherals and PLL clocks.
367f9627312SRajan Vaja  *
368f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
369f9627312SRajan Vaja  */
370f5ccd54bSRajan Vaja int zynqmp_pm_clock_disable(u32 clock_id)
371f9627312SRajan Vaja {
372f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
373f9627312SRajan Vaja }
374f5ccd54bSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
375f9627312SRajan Vaja 
376f9627312SRajan Vaja /**
377f9627312SRajan Vaja  * zynqmp_pm_clock_getstate() - Get the clock state for given id
378f9627312SRajan Vaja  * @clock_id:	ID of the clock to be queried
379f9627312SRajan Vaja  * @state:	1/0 (Enabled/Disabled)
380f9627312SRajan Vaja  *
381f9627312SRajan Vaja  * This function is used by master to get the state of clock
382f9627312SRajan Vaja  * including peripherals and PLL clocks.
383f9627312SRajan Vaja  *
384f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
385f9627312SRajan Vaja  */
3865e76731dSRajan Vaja int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
387f9627312SRajan Vaja {
388f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
389f9627312SRajan Vaja 	int ret;
390f9627312SRajan Vaja 
391f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0,
392f9627312SRajan Vaja 				  0, 0, ret_payload);
393f9627312SRajan Vaja 	*state = ret_payload[1];
394f9627312SRajan Vaja 
395f9627312SRajan Vaja 	return ret;
396f9627312SRajan Vaja }
3975e76731dSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
398f9627312SRajan Vaja 
399f9627312SRajan Vaja /**
400f9627312SRajan Vaja  * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
401f9627312SRajan Vaja  * @clock_id:	ID of the clock
402f9627312SRajan Vaja  * @divider:	divider value
403f9627312SRajan Vaja  *
404f9627312SRajan Vaja  * This function is used by master to set divider for any clock
405f9627312SRajan Vaja  * to achieve desired rate.
406f9627312SRajan Vaja  *
407f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
408f9627312SRajan Vaja  */
409fc9fb8fbSRajan Vaja int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
410f9627312SRajan Vaja {
411f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
412f9627312SRajan Vaja 				   0, 0, NULL);
413f9627312SRajan Vaja }
414fc9fb8fbSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
415f9627312SRajan Vaja 
416f9627312SRajan Vaja /**
417f9627312SRajan Vaja  * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
418f9627312SRajan Vaja  * @clock_id:	ID of the clock
419f9627312SRajan Vaja  * @divider:	divider value
420f9627312SRajan Vaja  *
421f9627312SRajan Vaja  * This function is used by master to get divider values
422f9627312SRajan Vaja  * for any clock.
423f9627312SRajan Vaja  *
424f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
425f9627312SRajan Vaja  */
4260667a8d1SRajan Vaja int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
427f9627312SRajan Vaja {
428f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
429f9627312SRajan Vaja 	int ret;
430f9627312SRajan Vaja 
431f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0,
432f9627312SRajan Vaja 				  0, 0, ret_payload);
433f9627312SRajan Vaja 	*divider = ret_payload[1];
434f9627312SRajan Vaja 
435f9627312SRajan Vaja 	return ret;
436f9627312SRajan Vaja }
4370667a8d1SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
438f9627312SRajan Vaja 
439f9627312SRajan Vaja /**
440f9627312SRajan Vaja  * zynqmp_pm_clock_setrate() - Set the clock rate for given id
441f9627312SRajan Vaja  * @clock_id:	ID of the clock
442f9627312SRajan Vaja  * @rate:	rate value in hz
443f9627312SRajan Vaja  *
444f9627312SRajan Vaja  * This function is used by master to set rate for any clock.
445f9627312SRajan Vaja  *
446f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
447f9627312SRajan Vaja  */
4487a1e1062SRajan Vaja int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
449f9627312SRajan Vaja {
450f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
451f9627312SRajan Vaja 				   lower_32_bits(rate),
452f9627312SRajan Vaja 				   upper_32_bits(rate),
453f9627312SRajan Vaja 				   0, NULL);
454f9627312SRajan Vaja }
4557a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate);
456f9627312SRajan Vaja 
457f9627312SRajan Vaja /**
458f9627312SRajan Vaja  * zynqmp_pm_clock_getrate() - Get the clock rate for given id
459f9627312SRajan Vaja  * @clock_id:	ID of the clock
460f9627312SRajan Vaja  * @rate:	rate value in hz
461f9627312SRajan Vaja  *
462f9627312SRajan Vaja  * This function is used by master to get rate
463f9627312SRajan Vaja  * for any clock.
464f9627312SRajan Vaja  *
465f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
466f9627312SRajan Vaja  */
4677a1e1062SRajan Vaja int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
468f9627312SRajan Vaja {
469f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
470f9627312SRajan Vaja 	int ret;
471f9627312SRajan Vaja 
472f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0,
473f9627312SRajan Vaja 				  0, 0, ret_payload);
474f9627312SRajan Vaja 	*rate = ((u64)ret_payload[2] << 32) | ret_payload[1];
475f9627312SRajan Vaja 
476f9627312SRajan Vaja 	return ret;
477f9627312SRajan Vaja }
4787a1e1062SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate);
479f9627312SRajan Vaja 
480f9627312SRajan Vaja /**
481f9627312SRajan Vaja  * zynqmp_pm_clock_setparent() - Set the clock parent for given id
482f9627312SRajan Vaja  * @clock_id:	ID of the clock
483f9627312SRajan Vaja  * @parent_id:	parent id
484f9627312SRajan Vaja  *
485f9627312SRajan Vaja  * This function is used by master to set parent for any clock.
486f9627312SRajan Vaja  *
487f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
488f9627312SRajan Vaja  */
48970c0d364SRajan Vaja int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
490f9627312SRajan Vaja {
491f9627312SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
492f9627312SRajan Vaja 				   parent_id, 0, 0, NULL);
493f9627312SRajan Vaja }
49470c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
495f9627312SRajan Vaja 
496f9627312SRajan Vaja /**
497f9627312SRajan Vaja  * zynqmp_pm_clock_getparent() - Get the clock parent for given id
498f9627312SRajan Vaja  * @clock_id:	ID of the clock
499f9627312SRajan Vaja  * @parent_id:	parent id
500f9627312SRajan Vaja  *
501f9627312SRajan Vaja  * This function is used by master to get parent index
502f9627312SRajan Vaja  * for any clock.
503f9627312SRajan Vaja  *
504f9627312SRajan Vaja  * Return: Returns status, either success or error+reason
505f9627312SRajan Vaja  */
50670c0d364SRajan Vaja int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
507f9627312SRajan Vaja {
508f9627312SRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
509f9627312SRajan Vaja 	int ret;
510f9627312SRajan Vaja 
511f9627312SRajan Vaja 	ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0,
512f9627312SRajan Vaja 				  0, 0, ret_payload);
513f9627312SRajan Vaja 	*parent_id = ret_payload[1];
514f9627312SRajan Vaja 
515f9627312SRajan Vaja 	return ret;
51659ecdd77SRajan Vaja }
51770c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
51859ecdd77SRajan Vaja 
5193b0296b8SRajan Vaja /**
520426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
5213b0296b8SRajan Vaja  *
522426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
523426c8d85SRajan Vaja  * @mode:	PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
5243b0296b8SRajan Vaja  *
525426c8d85SRajan Vaja  * This function sets PLL mode
5263b0296b8SRajan Vaja  *
5273b0296b8SRajan Vaja  * Return: Returns status, either success or error+reason
5283b0296b8SRajan Vaja  */
529426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
5303b0296b8SRajan Vaja {
531426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE,
532426c8d85SRajan Vaja 				   clk_id, mode, NULL);
5333b0296b8SRajan Vaja }
534426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
535426c8d85SRajan Vaja 
536426c8d85SRajan Vaja /**
537426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
538426c8d85SRajan Vaja  *
539426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
540426c8d85SRajan Vaja  * @mode:	PLL mode
541426c8d85SRajan Vaja  *
542426c8d85SRajan Vaja  * This function return current PLL mode
543426c8d85SRajan Vaja  *
544426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
545426c8d85SRajan Vaja  */
546426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
547426c8d85SRajan Vaja {
548426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE,
549426c8d85SRajan Vaja 				   clk_id, 0, mode);
550426c8d85SRajan Vaja }
551426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
552426c8d85SRajan Vaja 
553426c8d85SRajan Vaja /**
554426c8d85SRajan Vaja  * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
555426c8d85SRajan Vaja  *
556426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
557426c8d85SRajan Vaja  * @data:	fraction data
558426c8d85SRajan Vaja  *
559426c8d85SRajan Vaja  * This function sets fraction data.
560426c8d85SRajan Vaja  * It is valid for fraction mode only.
561426c8d85SRajan Vaja  *
562426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
563426c8d85SRajan Vaja  */
564426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
565426c8d85SRajan Vaja {
566426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA,
567426c8d85SRajan Vaja 				   clk_id, data, NULL);
568426c8d85SRajan Vaja }
569426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
570426c8d85SRajan Vaja 
571426c8d85SRajan Vaja /**
572426c8d85SRajan Vaja  * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
573426c8d85SRajan Vaja  *
574426c8d85SRajan Vaja  * @clk_id:	PLL clock ID
575426c8d85SRajan Vaja  * @data:	fraction data
576426c8d85SRajan Vaja  *
577426c8d85SRajan Vaja  * This function returns fraction data value.
578426c8d85SRajan Vaja  *
579426c8d85SRajan Vaja  * Return: Returns status, either success or error+reason
580426c8d85SRajan Vaja  */
581426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
582426c8d85SRajan Vaja {
583426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA,
584426c8d85SRajan Vaja 				   clk_id, 0, data);
585426c8d85SRajan Vaja }
586426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
587426c8d85SRajan Vaja 
588426c8d85SRajan Vaja /**
589426c8d85SRajan Vaja  * zynqmp_pm_set_sd_tapdelay() -  Set tap delay for the SD device
590426c8d85SRajan Vaja  *
591426c8d85SRajan Vaja  * @node_id	Node ID of the device
592426c8d85SRajan Vaja  * @type	Type of tap delay to set (input/output)
593426c8d85SRajan Vaja  * @value	Value to set fot the tap delay
594426c8d85SRajan Vaja  *
595426c8d85SRajan Vaja  * This function sets input/output tap delay for the SD device.
596426c8d85SRajan Vaja  *
597426c8d85SRajan Vaja  * @return	Returns status, either success or error+reason
598426c8d85SRajan Vaja  */
599426c8d85SRajan Vaja int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
600426c8d85SRajan Vaja {
601426c8d85SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
602426c8d85SRajan Vaja 				   type, value, NULL);
603426c8d85SRajan Vaja }
604426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
605426c8d85SRajan Vaja 
606426c8d85SRajan Vaja /**
607426c8d85SRajan Vaja  * zynqmp_pm_sd_dll_reset() - Reset DLL logic
608426c8d85SRajan Vaja  *
609426c8d85SRajan Vaja  * @node_id	Node ID of the device
610426c8d85SRajan Vaja  * @type	Reset type
611426c8d85SRajan Vaja  *
612426c8d85SRajan Vaja  * This function resets DLL logic for the SD device.
613426c8d85SRajan Vaja  *
614426c8d85SRajan Vaja  * @return	Returns status, either success or error+reason
615426c8d85SRajan Vaja  */
616426c8d85SRajan Vaja int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
617426c8d85SRajan Vaja {
618f4426311SManish Narani 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SD_DLL_RESET,
619426c8d85SRajan Vaja 				   type, 0, NULL);
620426c8d85SRajan Vaja }
621426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
6223b0296b8SRajan Vaja 
623bc3843d4SNava kishore Manne /**
6244f680b72SRajan Vaja  * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
6254f680b72SRajan Vaja  * @index	GGS register index
6264f680b72SRajan Vaja  * @value	Register value to be written
6274f680b72SRajan Vaja  *
6284f680b72SRajan Vaja  * This function writes value to GGS register.
6294f680b72SRajan Vaja  *
6304f680b72SRajan Vaja  * @return      Returns status, either success or error+reason
6314f680b72SRajan Vaja  */
6324f680b72SRajan Vaja int zynqmp_pm_write_ggs(u32 index, u32 value)
6334f680b72SRajan Vaja {
6344f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS,
6354f680b72SRajan Vaja 				   index, value, NULL);
6364f680b72SRajan Vaja }
6374f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
6384f680b72SRajan Vaja 
6394f680b72SRajan Vaja /**
6404f680b72SRajan Vaja  * zynqmp_pm_write_ggs() - PM API for reading global general storage (ggs)
6414f680b72SRajan Vaja  * @index	GGS register index
6424f680b72SRajan Vaja  * @value	Register value to be written
6434f680b72SRajan Vaja  *
6444f680b72SRajan Vaja  * This function returns GGS register value.
6454f680b72SRajan Vaja  *
6464f680b72SRajan Vaja  * @return      Returns status, either success or error+reason
6474f680b72SRajan Vaja  */
6484f680b72SRajan Vaja int zynqmp_pm_read_ggs(u32 index, u32 *value)
6494f680b72SRajan Vaja {
6504f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS,
6514f680b72SRajan Vaja 				   index, 0, value);
6524f680b72SRajan Vaja }
6534f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
6544f680b72SRajan Vaja 
6554f680b72SRajan Vaja /**
6564f680b72SRajan Vaja  * zynqmp_pm_write_pggs() - PM API for writing persistent global general
6574f680b72SRajan Vaja  *			     storage (pggs)
6584f680b72SRajan Vaja  * @index	PGGS register index
6594f680b72SRajan Vaja  * @value	Register value to be written
6604f680b72SRajan Vaja  *
6614f680b72SRajan Vaja  * This function writes value to PGGS register.
6624f680b72SRajan Vaja  *
6634f680b72SRajan Vaja  * @return      Returns status, either success or error+reason
6644f680b72SRajan Vaja  */
6654f680b72SRajan Vaja int zynqmp_pm_write_pggs(u32 index, u32 value)
6664f680b72SRajan Vaja {
6674f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value,
6684f680b72SRajan Vaja 				   NULL);
6694f680b72SRajan Vaja }
6704f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
6714f680b72SRajan Vaja 
6724f680b72SRajan Vaja /**
6734f680b72SRajan Vaja  * zynqmp_pm_write_pggs() - PM API for reading persistent global general
6744f680b72SRajan Vaja  *			     storage (pggs)
6754f680b72SRajan Vaja  * @index	PGGS register index
6764f680b72SRajan Vaja  * @value	Register value to be written
6774f680b72SRajan Vaja  *
6784f680b72SRajan Vaja  * This function returns PGGS register value.
6794f680b72SRajan Vaja  *
6804f680b72SRajan Vaja  * @return      Returns status, either success or error+reason
6814f680b72SRajan Vaja  */
6824f680b72SRajan Vaja int zynqmp_pm_read_pggs(u32 index, u32 *value)
6834f680b72SRajan Vaja {
6844f680b72SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0,
6854f680b72SRajan Vaja 				   value);
6864f680b72SRajan Vaja }
6874f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
6884f680b72SRajan Vaja 
6894f680b72SRajan Vaja /**
690a2cc220aSRajan Vaja  * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
691a2cc220aSRajan Vaja  * @value	Status value to be written
692a2cc220aSRajan Vaja  *
693a2cc220aSRajan Vaja  * This function sets healthy bit value to indicate boot health status
694a2cc220aSRajan Vaja  * to firmware.
695a2cc220aSRajan Vaja  *
696a2cc220aSRajan Vaja  * @return      Returns status, either success or error+reason
697a2cc220aSRajan Vaja  */
698a2cc220aSRajan Vaja int zynqmp_pm_set_boot_health_status(u32 value)
699a2cc220aSRajan Vaja {
700a2cc220aSRajan Vaja 	return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS,
701a2cc220aSRajan Vaja 				   value, 0, NULL);
702a2cc220aSRajan Vaja }
703a2cc220aSRajan Vaja 
704a2cc220aSRajan Vaja /**
705bc3843d4SNava kishore Manne  * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
706bc3843d4SNava kishore Manne  * @reset:		Reset to be configured
707bc3843d4SNava kishore Manne  * @assert_flag:	Flag stating should reset be asserted (1) or
708bc3843d4SNava kishore Manne  *			released (0)
709bc3843d4SNava kishore Manne  *
710bc3843d4SNava kishore Manne  * Return: Returns status, either success or error+reason
711bc3843d4SNava kishore Manne  */
712cf23ec35SRajan Vaja int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
713bc3843d4SNava kishore Manne 			   const enum zynqmp_pm_reset_action assert_flag)
714bc3843d4SNava kishore Manne {
715bc3843d4SNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
716bc3843d4SNava kishore Manne 				   0, 0, NULL);
717bc3843d4SNava kishore Manne }
718cf23ec35SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
719bc3843d4SNava kishore Manne 
720bc3843d4SNava kishore Manne /**
721bc3843d4SNava kishore Manne  * zynqmp_pm_reset_get_status - Get status of the reset
722bc3843d4SNava kishore Manne  * @reset:      Reset whose status should be returned
723bc3843d4SNava kishore Manne  * @status:     Returned status
724bc3843d4SNava kishore Manne  *
725bc3843d4SNava kishore Manne  * Return: Returns status, either success or error+reason
726bc3843d4SNava kishore Manne  */
7271b413581SRajan Vaja int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
728bc3843d4SNava kishore Manne {
729bc3843d4SNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
730bc3843d4SNava kishore Manne 	int ret;
731bc3843d4SNava kishore Manne 
732bc3843d4SNava kishore Manne 	if (!status)
733bc3843d4SNava kishore Manne 		return -EINVAL;
734bc3843d4SNava kishore Manne 
735bc3843d4SNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, reset, 0,
736bc3843d4SNava kishore Manne 				  0, 0, ret_payload);
737bc3843d4SNava kishore Manne 	*status = ret_payload[1];
738bc3843d4SNava kishore Manne 
739bc3843d4SNava kishore Manne 	return ret;
740bc3843d4SNava kishore Manne }
7411b413581SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
742bc3843d4SNava kishore Manne 
743e178df31SJolly Shah /**
744e840deccSNava kishore Manne  * zynqmp_pm_fpga_load - Perform the fpga load
745e840deccSNava kishore Manne  * @address:	Address to write to
746e840deccSNava kishore Manne  * @size:	pl bitstream size
747e840deccSNava kishore Manne  * @flags:	Bitstream type
748e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
749e840deccSNava kishore Manne  *	-XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
750e840deccSNava kishore Manne  *
751e840deccSNava kishore Manne  * This function provides access to pmufw. To transfer
752e840deccSNava kishore Manne  * the required bitstream into PL.
753e840deccSNava kishore Manne  *
754e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
755e840deccSNava kishore Manne  */
7564db8180fSRajan Vaja int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
757e840deccSNava kishore Manne {
758e840deccSNava kishore Manne 	return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
759e840deccSNava kishore Manne 				   upper_32_bits(address), size, flags, NULL);
760e840deccSNava kishore Manne }
76156a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
762e840deccSNava kishore Manne 
763e840deccSNava kishore Manne /**
764e840deccSNava kishore Manne  * zynqmp_pm_fpga_get_status - Read value from PCAP status register
765e840deccSNava kishore Manne  * @value: Value to read
766e840deccSNava kishore Manne  *
767e840deccSNava kishore Manne  * This function provides access to the pmufw to get the PCAP
768e840deccSNava kishore Manne  * status
769e840deccSNava kishore Manne  *
770e840deccSNava kishore Manne  * Return: Returns status, either success or error+reason
771e840deccSNava kishore Manne  */
7724db8180fSRajan Vaja int zynqmp_pm_fpga_get_status(u32 *value)
773e840deccSNava kishore Manne {
774e840deccSNava kishore Manne 	u32 ret_payload[PAYLOAD_ARG_CNT];
775e840deccSNava kishore Manne 	int ret;
776e840deccSNava kishore Manne 
777e840deccSNava kishore Manne 	if (!value)
778e840deccSNava kishore Manne 		return -EINVAL;
779e840deccSNava kishore Manne 
780e840deccSNava kishore Manne 	ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
781e840deccSNava kishore Manne 	*value = ret_payload[1];
782e840deccSNava kishore Manne 
783e840deccSNava kishore Manne 	return ret;
784e840deccSNava kishore Manne }
78556a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
786e840deccSNava kishore Manne 
787e840deccSNava kishore Manne /**
788e178df31SJolly Shah  * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
789e178df31SJolly Shah  *			       master has initialized its own power management
790e178df31SJolly Shah  *
791e178df31SJolly Shah  * This API function is to be used for notify the power management controller
792e178df31SJolly Shah  * about the completed power management initialization.
793e178df31SJolly Shah  *
794e178df31SJolly Shah  * Return: Returns status, either success or error+reason
795e178df31SJolly Shah  */
7969474da95SRajan Vaja int zynqmp_pm_init_finalize(void)
797e178df31SJolly Shah {
798e178df31SJolly Shah 	return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
799e178df31SJolly Shah }
8009474da95SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize);
801e178df31SJolly Shah 
802e178df31SJolly Shah /**
803e178df31SJolly Shah  * zynqmp_pm_set_suspend_mode()	- Set system suspend mode
804e178df31SJolly Shah  * @mode:	Mode to set for system suspend
805e178df31SJolly Shah  *
806e178df31SJolly Shah  * This API function is used to set mode of system suspend.
807e178df31SJolly Shah  *
808e178df31SJolly Shah  * Return: Returns status, either success or error+reason
809e178df31SJolly Shah  */
810951d0a97SRajan Vaja int zynqmp_pm_set_suspend_mode(u32 mode)
811e178df31SJolly Shah {
812e178df31SJolly Shah 	return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
813e178df31SJolly Shah }
814951d0a97SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
815e178df31SJolly Shah 
816c1986ac3SRajan Vaja /**
817c1986ac3SRajan Vaja  * zynqmp_pm_request_node() - Request a node with specific capabilities
818c1986ac3SRajan Vaja  * @node:		Node ID of the slave
819c1986ac3SRajan Vaja  * @capabilities:	Requested capabilities of the slave
820c1986ac3SRajan Vaja  * @qos:		Quality of service (not supported)
821c1986ac3SRajan Vaja  * @ack:		Flag to specify whether acknowledge is requested
822c1986ac3SRajan Vaja  *
823c1986ac3SRajan Vaja  * This function is used by master to request particular node from firmware.
824c1986ac3SRajan Vaja  * Every master must request node before using it.
825c1986ac3SRajan Vaja  *
826c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
827c1986ac3SRajan Vaja  */
828bf8b27edSRajan Vaja int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
829bf8b27edSRajan Vaja 			   const u32 qos, const enum zynqmp_pm_request_ack ack)
830c1986ac3SRajan Vaja {
831c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
832c1986ac3SRajan Vaja 				   qos, ack, NULL);
833c1986ac3SRajan Vaja }
834bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
835c1986ac3SRajan Vaja 
836c1986ac3SRajan Vaja /**
837c1986ac3SRajan Vaja  * zynqmp_pm_release_node() - Release a node
838c1986ac3SRajan Vaja  * @node:	Node ID of the slave
839c1986ac3SRajan Vaja  *
840c1986ac3SRajan Vaja  * This function is used by master to inform firmware that master
841c1986ac3SRajan Vaja  * has released node. Once released, master must not use that node
842c1986ac3SRajan Vaja  * without re-request.
843c1986ac3SRajan Vaja  *
844c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
845c1986ac3SRajan Vaja  */
84607fb1a46SRajan Vaja int zynqmp_pm_release_node(const u32 node)
847c1986ac3SRajan Vaja {
848c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
849c1986ac3SRajan Vaja }
85007fb1a46SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
851c1986ac3SRajan Vaja 
852c1986ac3SRajan Vaja /**
853c1986ac3SRajan Vaja  * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
854c1986ac3SRajan Vaja  * @node:		Node ID of the slave
855c1986ac3SRajan Vaja  * @capabilities:	Requested capabilities of the slave
856c1986ac3SRajan Vaja  * @qos:		Quality of service (not supported)
857c1986ac3SRajan Vaja  * @ack:		Flag to specify whether acknowledge is requested
858c1986ac3SRajan Vaja  *
859c1986ac3SRajan Vaja  * This API function is to be used for slaves a PU already has requested
860c1986ac3SRajan Vaja  * to change its capabilities.
861c1986ac3SRajan Vaja  *
862c1986ac3SRajan Vaja  * Return: Returns status, either success or error+reason
863c1986ac3SRajan Vaja  */
864cbbbda71SRajan Vaja int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
865c1986ac3SRajan Vaja 			      const u32 qos,
866c1986ac3SRajan Vaja 			      const enum zynqmp_pm_request_ack ack)
867c1986ac3SRajan Vaja {
868c1986ac3SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
869c1986ac3SRajan Vaja 				   qos, ack, NULL);
870c1986ac3SRajan Vaja }
871cbbbda71SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
872c1986ac3SRajan Vaja 
873057a0fb6SKalyani Akula /**
874057a0fb6SKalyani Akula  * zynqmp_pm_aes - Access AES hardware to encrypt/decrypt the data using
875057a0fb6SKalyani Akula  * AES-GCM core.
876057a0fb6SKalyani Akula  * @address:	Address of the AesParams structure.
877057a0fb6SKalyani Akula  * @out:	Returned output value
878057a0fb6SKalyani Akula  *
879057a0fb6SKalyani Akula  * Return:	Returns status, either success or error code.
880057a0fb6SKalyani Akula  */
881bc86f9c5SRajan Vaja int zynqmp_pm_aes_engine(const u64 address, u32 *out)
882057a0fb6SKalyani Akula {
883057a0fb6SKalyani Akula 	u32 ret_payload[PAYLOAD_ARG_CNT];
884057a0fb6SKalyani Akula 	int ret;
885057a0fb6SKalyani Akula 
886057a0fb6SKalyani Akula 	if (!out)
887057a0fb6SKalyani Akula 		return -EINVAL;
888057a0fb6SKalyani Akula 
889057a0fb6SKalyani Akula 	ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address),
890057a0fb6SKalyani Akula 				  lower_32_bits(address),
891057a0fb6SKalyani Akula 				  0, 0, ret_payload);
892057a0fb6SKalyani Akula 	*out = ret_payload[1];
893057a0fb6SKalyani Akula 
894057a0fb6SKalyani Akula 	return ret;
895057a0fb6SKalyani Akula }
896bc86f9c5SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
897057a0fb6SKalyani Akula 
898fdd2ed88SRajan Vaja /**
899fdd2ed88SRajan Vaja  * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
900fdd2ed88SRajan Vaja  * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
901fdd2ed88SRajan Vaja  * @subtype:	Specifies which system should be restarted or shut down
902fdd2ed88SRajan Vaja  *
903fdd2ed88SRajan Vaja  * Return:	Returns status, either success or error+reason
904fdd2ed88SRajan Vaja  */
905fdd2ed88SRajan Vaja int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
906fdd2ed88SRajan Vaja {
907fdd2ed88SRajan Vaja 	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
908fdd2ed88SRajan Vaja 				   0, 0, NULL);
909fdd2ed88SRajan Vaja }
910fdd2ed88SRajan Vaja 
911b3ae24c4SRajan Vaja /**
912b3ae24c4SRajan Vaja  * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
913b3ae24c4SRajan Vaja  * @subtype:	Shutdown subtype
914b3ae24c4SRajan Vaja  * @name:	Matching string for scope argument
915b3ae24c4SRajan Vaja  *
916b3ae24c4SRajan Vaja  * This struct encapsulates mapping between shutdown scope ID and string.
917b3ae24c4SRajan Vaja  */
918b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope {
919b3ae24c4SRajan Vaja 	const enum zynqmp_pm_shutdown_subtype subtype;
920b3ae24c4SRajan Vaja 	const char *name;
921b3ae24c4SRajan Vaja };
922b3ae24c4SRajan Vaja 
923b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
924b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
925b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
926b3ae24c4SRajan Vaja 		.name = "subsystem",
927b3ae24c4SRajan Vaja 	},
928b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
929b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
930b3ae24c4SRajan Vaja 		.name = "ps_only",
931b3ae24c4SRajan Vaja 	},
932b3ae24c4SRajan Vaja 	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
933b3ae24c4SRajan Vaja 		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
934b3ae24c4SRajan Vaja 		.name = "system",
935b3ae24c4SRajan Vaja 	},
936b3ae24c4SRajan Vaja };
937b3ae24c4SRajan Vaja 
938b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope =
939b3ae24c4SRajan Vaja 		&shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
940b3ae24c4SRajan Vaja 
941b3ae24c4SRajan Vaja /**
942b3ae24c4SRajan Vaja  * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
943b3ae24c4SRajan Vaja  * @scope_string:	Shutdown scope string
944b3ae24c4SRajan Vaja  *
945b3ae24c4SRajan Vaja  * Return:		Return pointer to matching shutdown scope struct from
946b3ae24c4SRajan Vaja  *			array of available options in system if string is valid,
947b3ae24c4SRajan Vaja  *			otherwise returns NULL.
948b3ae24c4SRajan Vaja  */
949b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope*
950b3ae24c4SRajan Vaja 		zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
951b3ae24c4SRajan Vaja {
952b3ae24c4SRajan Vaja 	int count;
953b3ae24c4SRajan Vaja 
954b3ae24c4SRajan Vaja 	for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
955b3ae24c4SRajan Vaja 		if (sysfs_streq(scope_string, shutdown_scopes[count].name))
956b3ae24c4SRajan Vaja 			return &shutdown_scopes[count];
957b3ae24c4SRajan Vaja 
958b3ae24c4SRajan Vaja 	return NULL;
959b3ae24c4SRajan Vaja }
960b3ae24c4SRajan Vaja 
961b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device,
962b3ae24c4SRajan Vaja 				   struct device_attribute *attr,
963b3ae24c4SRajan Vaja 				   char *buf)
964b3ae24c4SRajan Vaja {
965b3ae24c4SRajan Vaja 	int i;
966b3ae24c4SRajan Vaja 
967b3ae24c4SRajan Vaja 	for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
968b3ae24c4SRajan Vaja 		if (&shutdown_scopes[i] == selected_scope) {
969b3ae24c4SRajan Vaja 			strcat(buf, "[");
970b3ae24c4SRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
971b3ae24c4SRajan Vaja 			strcat(buf, "]");
972b3ae24c4SRajan Vaja 		} else {
973b3ae24c4SRajan Vaja 			strcat(buf, shutdown_scopes[i].name);
974b3ae24c4SRajan Vaja 		}
975b3ae24c4SRajan Vaja 		strcat(buf, " ");
976b3ae24c4SRajan Vaja 	}
977b3ae24c4SRajan Vaja 	strcat(buf, "\n");
978b3ae24c4SRajan Vaja 
979b3ae24c4SRajan Vaja 	return strlen(buf);
980b3ae24c4SRajan Vaja }
981b3ae24c4SRajan Vaja 
982b3ae24c4SRajan Vaja static ssize_t shutdown_scope_store(struct device *device,
983b3ae24c4SRajan Vaja 				    struct device_attribute *attr,
984b3ae24c4SRajan Vaja 				    const char *buf, size_t count)
985b3ae24c4SRajan Vaja {
986b3ae24c4SRajan Vaja 	int ret;
987b3ae24c4SRajan Vaja 	struct zynqmp_pm_shutdown_scope *scope;
988b3ae24c4SRajan Vaja 
989b3ae24c4SRajan Vaja 	scope = zynqmp_pm_is_shutdown_scope_valid(buf);
990b3ae24c4SRajan Vaja 	if (!scope)
991b3ae24c4SRajan Vaja 		return -EINVAL;
992b3ae24c4SRajan Vaja 
993b3ae24c4SRajan Vaja 	ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
994b3ae24c4SRajan Vaja 					scope->subtype);
995b3ae24c4SRajan Vaja 	if (ret) {
996b3ae24c4SRajan Vaja 		pr_err("unable to set shutdown scope %s\n", buf);
997b3ae24c4SRajan Vaja 		return ret;
998b3ae24c4SRajan Vaja 	}
999b3ae24c4SRajan Vaja 
1000b3ae24c4SRajan Vaja 	selected_scope = scope;
1001b3ae24c4SRajan Vaja 
1002b3ae24c4SRajan Vaja 	return count;
1003b3ae24c4SRajan Vaja }
1004b3ae24c4SRajan Vaja 
1005b3ae24c4SRajan Vaja static DEVICE_ATTR_RW(shutdown_scope);
1006b3ae24c4SRajan Vaja 
1007a2cc220aSRajan Vaja static ssize_t health_status_store(struct device *device,
1008a2cc220aSRajan Vaja 				   struct device_attribute *attr,
1009a2cc220aSRajan Vaja 				   const char *buf, size_t count)
1010a2cc220aSRajan Vaja {
1011a2cc220aSRajan Vaja 	int ret;
1012a2cc220aSRajan Vaja 	unsigned int value;
1013a2cc220aSRajan Vaja 
1014a2cc220aSRajan Vaja 	ret = kstrtouint(buf, 10, &value);
1015a2cc220aSRajan Vaja 	if (ret)
1016a2cc220aSRajan Vaja 		return ret;
1017a2cc220aSRajan Vaja 
1018a2cc220aSRajan Vaja 	ret = zynqmp_pm_set_boot_health_status(value);
1019a2cc220aSRajan Vaja 	if (ret) {
1020a2cc220aSRajan Vaja 		dev_err(device, "unable to set healthy bit value to %u\n",
1021a2cc220aSRajan Vaja 			value);
1022a2cc220aSRajan Vaja 		return ret;
1023a2cc220aSRajan Vaja 	}
1024a2cc220aSRajan Vaja 
1025a2cc220aSRajan Vaja 	return count;
1026a2cc220aSRajan Vaja }
1027a2cc220aSRajan Vaja 
1028a2cc220aSRajan Vaja static DEVICE_ATTR_WO(health_status);
1029a2cc220aSRajan Vaja 
1030ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device,
1031ae5c961dSRajan Vaja 			struct device_attribute *attr,
1032ae5c961dSRajan Vaja 			char *buf,
1033ae5c961dSRajan Vaja 			u32 reg)
1034ae5c961dSRajan Vaja {
1035ae5c961dSRajan Vaja 	int ret;
1036ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1037ae5c961dSRajan Vaja 
1038ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_ggs(reg, ret_payload);
1039ae5c961dSRajan Vaja 	if (ret)
1040ae5c961dSRajan Vaja 		return ret;
1041ae5c961dSRajan Vaja 
1042ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1043ae5c961dSRajan Vaja }
1044ae5c961dSRajan Vaja 
1045ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device,
1046ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1047ae5c961dSRajan Vaja 			 const char *buf, size_t count,
1048ae5c961dSRajan Vaja 			 u32 reg)
1049ae5c961dSRajan Vaja {
1050ae5c961dSRajan Vaja 	long value;
1051ae5c961dSRajan Vaja 	int ret;
1052ae5c961dSRajan Vaja 
1053ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1054ae5c961dSRajan Vaja 		return -EINVAL;
1055ae5c961dSRajan Vaja 
1056ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1057ae5c961dSRajan Vaja 	if (ret) {
1058ae5c961dSRajan Vaja 		count = -EFAULT;
1059ae5c961dSRajan Vaja 		goto err;
1060ae5c961dSRajan Vaja 	}
1061ae5c961dSRajan Vaja 
1062ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_ggs(reg, value);
1063ae5c961dSRajan Vaja 	if (ret)
1064ae5c961dSRajan Vaja 		count = -EFAULT;
1065ae5c961dSRajan Vaja err:
1066ae5c961dSRajan Vaja 	return count;
1067ae5c961dSRajan Vaja }
1068ae5c961dSRajan Vaja 
1069ae5c961dSRajan Vaja /* GGS register show functions */
1070ae5c961dSRajan Vaja #define GGS0_SHOW(N)						\
1071ae5c961dSRajan Vaja 	ssize_t ggs##N##_show(struct device *device,		\
1072ae5c961dSRajan Vaja 			      struct device_attribute *attr,	\
1073ae5c961dSRajan Vaja 			      char *buf)			\
1074ae5c961dSRajan Vaja 	{							\
1075ae5c961dSRajan Vaja 		return ggs_show(device, attr, buf, N);		\
1076ae5c961dSRajan Vaja 	}
1077ae5c961dSRajan Vaja 
1078ae5c961dSRajan Vaja static GGS0_SHOW(0);
1079ae5c961dSRajan Vaja static GGS0_SHOW(1);
1080ae5c961dSRajan Vaja static GGS0_SHOW(2);
1081ae5c961dSRajan Vaja static GGS0_SHOW(3);
1082ae5c961dSRajan Vaja 
1083ae5c961dSRajan Vaja /* GGS register store function */
1084ae5c961dSRajan Vaja #define GGS0_STORE(N)						\
1085ae5c961dSRajan Vaja 	ssize_t ggs##N##_store(struct device *device,		\
1086ae5c961dSRajan Vaja 			       struct device_attribute *attr,	\
1087ae5c961dSRajan Vaja 			       const char *buf,			\
1088ae5c961dSRajan Vaja 			       size_t count)			\
1089ae5c961dSRajan Vaja 	{							\
1090ae5c961dSRajan Vaja 		return ggs_store(device, attr, buf, count, N);	\
1091ae5c961dSRajan Vaja 	}
1092ae5c961dSRajan Vaja 
1093ae5c961dSRajan Vaja static GGS0_STORE(0);
1094ae5c961dSRajan Vaja static GGS0_STORE(1);
1095ae5c961dSRajan Vaja static GGS0_STORE(2);
1096ae5c961dSRajan Vaja static GGS0_STORE(3);
1097ae5c961dSRajan Vaja 
1098ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device,
1099ae5c961dSRajan Vaja 			 struct device_attribute *attr,
1100ae5c961dSRajan Vaja 			 char *buf,
1101ae5c961dSRajan Vaja 			 u32 reg)
1102ae5c961dSRajan Vaja {
1103ae5c961dSRajan Vaja 	int ret;
1104ae5c961dSRajan Vaja 	u32 ret_payload[PAYLOAD_ARG_CNT];
1105ae5c961dSRajan Vaja 
1106ae5c961dSRajan Vaja 	ret = zynqmp_pm_read_pggs(reg, ret_payload);
1107ae5c961dSRajan Vaja 	if (ret)
1108ae5c961dSRajan Vaja 		return ret;
1109ae5c961dSRajan Vaja 
1110ae5c961dSRajan Vaja 	return sprintf(buf, "0x%x\n", ret_payload[1]);
1111ae5c961dSRajan Vaja }
1112ae5c961dSRajan Vaja 
1113ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device,
1114ae5c961dSRajan Vaja 			  struct device_attribute *attr,
1115ae5c961dSRajan Vaja 			  const char *buf, size_t count,
1116ae5c961dSRajan Vaja 			  u32 reg)
1117ae5c961dSRajan Vaja {
1118ae5c961dSRajan Vaja 	long value;
1119ae5c961dSRajan Vaja 	int ret;
1120ae5c961dSRajan Vaja 
1121ae5c961dSRajan Vaja 	if (reg >= GSS_NUM_REGS)
1122ae5c961dSRajan Vaja 		return -EINVAL;
1123ae5c961dSRajan Vaja 
1124ae5c961dSRajan Vaja 	ret = kstrtol(buf, 16, &value);
1125ae5c961dSRajan Vaja 	if (ret) {
1126ae5c961dSRajan Vaja 		count = -EFAULT;
1127ae5c961dSRajan Vaja 		goto err;
1128ae5c961dSRajan Vaja 	}
1129ae5c961dSRajan Vaja 
1130ae5c961dSRajan Vaja 	ret = zynqmp_pm_write_pggs(reg, value);
1131ae5c961dSRajan Vaja 	if (ret)
1132ae5c961dSRajan Vaja 		count = -EFAULT;
1133ae5c961dSRajan Vaja 
1134ae5c961dSRajan Vaja err:
1135ae5c961dSRajan Vaja 	return count;
1136ae5c961dSRajan Vaja }
1137ae5c961dSRajan Vaja 
1138ae5c961dSRajan Vaja #define PGGS0_SHOW(N)						\
1139ae5c961dSRajan Vaja 	ssize_t pggs##N##_show(struct device *device,		\
1140ae5c961dSRajan Vaja 			       struct device_attribute *attr,	\
1141ae5c961dSRajan Vaja 			       char *buf)			\
1142ae5c961dSRajan Vaja 	{							\
1143ae5c961dSRajan Vaja 		return pggs_show(device, attr, buf, N);		\
1144ae5c961dSRajan Vaja 	}
1145ae5c961dSRajan Vaja 
1146ae5c961dSRajan Vaja #define PGGS0_STORE(N)						\
1147ae5c961dSRajan Vaja 	ssize_t pggs##N##_store(struct device *device,		\
1148ae5c961dSRajan Vaja 				struct device_attribute *attr,	\
1149ae5c961dSRajan Vaja 				const char *buf,		\
1150ae5c961dSRajan Vaja 				size_t count)			\
1151ae5c961dSRajan Vaja 	{							\
1152ae5c961dSRajan Vaja 		return pggs_store(device, attr, buf, count, N);	\
1153ae5c961dSRajan Vaja 	}
1154ae5c961dSRajan Vaja 
1155ae5c961dSRajan Vaja /* PGGS register show functions */
1156ae5c961dSRajan Vaja static PGGS0_SHOW(0);
1157ae5c961dSRajan Vaja static PGGS0_SHOW(1);
1158ae5c961dSRajan Vaja static PGGS0_SHOW(2);
1159ae5c961dSRajan Vaja static PGGS0_SHOW(3);
1160ae5c961dSRajan Vaja 
1161ae5c961dSRajan Vaja /* PGGS register store functions */
1162ae5c961dSRajan Vaja static PGGS0_STORE(0);
1163ae5c961dSRajan Vaja static PGGS0_STORE(1);
1164ae5c961dSRajan Vaja static PGGS0_STORE(2);
1165ae5c961dSRajan Vaja static PGGS0_STORE(3);
1166ae5c961dSRajan Vaja 
1167ae5c961dSRajan Vaja /* GGS register attributes */
1168ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs0);
1169ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs1);
1170ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs2);
1171ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs3);
1172ae5c961dSRajan Vaja 
1173ae5c961dSRajan Vaja /* PGGS register attributes */
1174ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs0);
1175ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs1);
1176ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs2);
1177ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs3);
1178ae5c961dSRajan Vaja 
1179ae5c961dSRajan Vaja static struct attribute *zynqmp_firmware_attrs[] = {
1180ae5c961dSRajan Vaja 	&dev_attr_ggs0.attr,
1181ae5c961dSRajan Vaja 	&dev_attr_ggs1.attr,
1182ae5c961dSRajan Vaja 	&dev_attr_ggs2.attr,
1183ae5c961dSRajan Vaja 	&dev_attr_ggs3.attr,
1184ae5c961dSRajan Vaja 	&dev_attr_pggs0.attr,
1185ae5c961dSRajan Vaja 	&dev_attr_pggs1.attr,
1186ae5c961dSRajan Vaja 	&dev_attr_pggs2.attr,
1187ae5c961dSRajan Vaja 	&dev_attr_pggs3.attr,
1188b3ae24c4SRajan Vaja 	&dev_attr_shutdown_scope.attr,
1189a2cc220aSRajan Vaja 	&dev_attr_health_status.attr,
1190ae5c961dSRajan Vaja 	NULL,
1191ae5c961dSRajan Vaja };
1192ae5c961dSRajan Vaja 
1193ae5c961dSRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware);
1194ae5c961dSRajan Vaja 
119576582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev)
119676582671SRajan Vaja {
119776582671SRajan Vaja 	struct device *dev = &pdev->dev;
119876582671SRajan Vaja 	struct device_node *np;
119976582671SRajan Vaja 	int ret;
120076582671SRajan Vaja 
120176582671SRajan Vaja 	np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp");
1202af3f1afaSJolly Shah 	if (!np) {
1203af3f1afaSJolly Shah 		np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
120476582671SRajan Vaja 		if (!np)
120576582671SRajan Vaja 			return 0;
1206461011b1SRavi Patel 
1207461011b1SRavi Patel 		feature_check_enabled = true;
1208af3f1afaSJolly Shah 	}
120976582671SRajan Vaja 	of_node_put(np);
121076582671SRajan Vaja 
121176582671SRajan Vaja 	ret = get_set_conduit_method(dev->of_node);
121276582671SRajan Vaja 	if (ret)
121376582671SRajan Vaja 		return ret;
121476582671SRajan Vaja 
121576582671SRajan Vaja 	/* Check PM API version number */
121676582671SRajan Vaja 	zynqmp_pm_get_api_version(&pm_api_version);
121776582671SRajan Vaja 	if (pm_api_version < ZYNQMP_PM_VERSION) {
121876582671SRajan Vaja 		panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
121976582671SRajan Vaja 		      __func__,
122076582671SRajan Vaja 		      ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
122176582671SRajan Vaja 		      pm_api_version >> 16, pm_api_version & 0xFFFF);
122276582671SRajan Vaja 	}
122376582671SRajan Vaja 
122476582671SRajan Vaja 	pr_info("%s Platform Management API v%d.%d\n", __func__,
122576582671SRajan Vaja 		pm_api_version >> 16, pm_api_version & 0xFFFF);
122676582671SRajan Vaja 
122776582671SRajan Vaja 	/* Check trustzone version number */
122876582671SRajan Vaja 	ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
122976582671SRajan Vaja 	if (ret)
123076582671SRajan Vaja 		panic("Legacy trustzone found without version support\n");
123176582671SRajan Vaja 
123276582671SRajan Vaja 	if (pm_tz_version < ZYNQMP_TZ_VERSION)
123376582671SRajan Vaja 		panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
123476582671SRajan Vaja 		      __func__,
123576582671SRajan Vaja 		      ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
123676582671SRajan Vaja 		      pm_tz_version >> 16, pm_tz_version & 0xFFFF);
123776582671SRajan Vaja 
123876582671SRajan Vaja 	pr_info("%s Trustzone version v%d.%d\n", __func__,
123976582671SRajan Vaja 		pm_tz_version >> 16, pm_tz_version & 0xFFFF);
124076582671SRajan Vaja 
1241e23d9c6dSJolly Shah 	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
1242e23d9c6dSJolly Shah 			      ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
1243e23d9c6dSJolly Shah 	if (ret) {
1244e23d9c6dSJolly Shah 		dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
1245e23d9c6dSJolly Shah 		return ret;
1246e23d9c6dSJolly Shah 	}
1247e23d9c6dSJolly Shah 
124865f0539bSChristophe JAILLET 	zynqmp_pm_api_debugfs_init();
124965f0539bSChristophe JAILLET 
125076582671SRajan Vaja 	return of_platform_populate(dev->of_node, NULL, NULL, dev);
125176582671SRajan Vaja }
125276582671SRajan Vaja 
125376582671SRajan Vaja static int zynqmp_firmware_remove(struct platform_device *pdev)
125476582671SRajan Vaja {
1255e23d9c6dSJolly Shah 	mfd_remove_devices(&pdev->dev);
1256b3217252SRajan Vaja 	zynqmp_pm_api_debugfs_exit();
1257b3217252SRajan Vaja 
125876582671SRajan Vaja 	return 0;
125976582671SRajan Vaja }
126076582671SRajan Vaja 
126176582671SRajan Vaja static const struct of_device_id zynqmp_firmware_of_match[] = {
126276582671SRajan Vaja 	{.compatible = "xlnx,zynqmp-firmware"},
1263af3f1afaSJolly Shah 	{.compatible = "xlnx,versal-firmware"},
126476582671SRajan Vaja 	{},
126576582671SRajan Vaja };
126676582671SRajan Vaja MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
126776582671SRajan Vaja 
126876582671SRajan Vaja static struct platform_driver zynqmp_firmware_driver = {
126976582671SRajan Vaja 	.driver = {
127076582671SRajan Vaja 		.name = "zynqmp_firmware",
127176582671SRajan Vaja 		.of_match_table = zynqmp_firmware_of_match,
1272ae5c961dSRajan Vaja 		.dev_groups = zynqmp_firmware_groups,
127376582671SRajan Vaja 	},
127476582671SRajan Vaja 	.probe = zynqmp_firmware_probe,
127576582671SRajan Vaja 	.remove = zynqmp_firmware_remove,
127676582671SRajan Vaja };
127776582671SRajan Vaja module_platform_driver(zynqmp_firmware_driver);
1278