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