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.
692fb7133SRonak Jain * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
776582671SRajan Vaja *
8a5cb804bSMichal Simek * Michal Simek <michal.simek@amd.com>
976582671SRajan Vaja * Davorin Mista <davorin.mista@aggios.com>
1076582671SRajan Vaja * Jolly Shah <jollys@xilinx.com>
1176582671SRajan Vaja * Rajan Vaja <rajanv@xilinx.com>
1276582671SRajan Vaja */
1376582671SRajan Vaja
1476582671SRajan Vaja #include <linux/arm-smccc.h>
1576582671SRajan Vaja #include <linux/compiler.h>
1676582671SRajan Vaja #include <linux/device.h>
1776582671SRajan Vaja #include <linux/init.h>
18e23d9c6dSJolly Shah #include <linux/mfd/core.h>
1976582671SRajan Vaja #include <linux/module.h>
2076582671SRajan Vaja #include <linux/of.h>
2176582671SRajan Vaja #include <linux/of_platform.h>
225b45759cSRob Herring #include <linux/platform_device.h>
23*29ea3386SUlf Hansson #include <linux/pm_domain.h>
2476582671SRajan Vaja #include <linux/slab.h>
2576582671SRajan Vaja #include <linux/uaccess.h>
26acfdd185SAmit Sunil Dhamne #include <linux/hashtable.h>
2776582671SRajan Vaja
2876582671SRajan Vaja #include <linux/firmware/xlnx-zynqmp.h>
29a515814eSAbhyuday Godhasara #include <linux/firmware/xlnx-event-manager.h>
30b3217252SRajan Vaja #include "zynqmp-debug.h"
3176582671SRajan Vaja
32acfdd185SAmit Sunil Dhamne /* Max HashMap Order for PM API feature check (1<<7 = 128) */
33acfdd185SAmit Sunil Dhamne #define PM_API_FEATURE_CHECK_MAX_ORDER 7
34acfdd185SAmit Sunil Dhamne
3523c64d76SPiyush Mehta /* CRL registers and bitfields */
3623c64d76SPiyush Mehta #define CRL_APB_BASE 0xFF5E0000U
3723c64d76SPiyush Mehta /* BOOT_PIN_CTRL- Used to control the mode pins after boot */
3823c64d76SPiyush Mehta #define CRL_APB_BOOT_PIN_CTRL (CRL_APB_BASE + (0x250U))
3923c64d76SPiyush Mehta /* BOOT_PIN_CTRL_MASK- out_val[11:8], out_en[3:0] */
4023c64d76SPiyush Mehta #define CRL_APB_BOOTPIN_CTRL_MASK 0xF0FU
4123c64d76SPiyush Mehta
42f918cfc0SRonak Jain /* IOCTL/QUERY feature payload size */
43f918cfc0SRonak Jain #define FEATURE_PAYLOAD_SIZE 2
44f918cfc0SRonak Jain
45461011b1SRavi Patel static bool feature_check_enabled;
4669fe24d1SZou Wei static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
47f918cfc0SRonak Jain static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
48f918cfc0SRonak Jain static u32 query_features[FEATURE_PAYLOAD_SIZE];
49acfdd185SAmit Sunil Dhamne
5092fb7133SRonak Jain static u32 sip_svc_version;
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;
958c016c80SJay Buddhabhatti case XST_PM_INVALID_VERSION:
968c016c80SJay Buddhabhatti return -EOPNOTSUPP;
9776582671SRajan Vaja case XST_PM_NO_ACCESS:
9876582671SRajan Vaja return -EACCES;
9976582671SRajan Vaja case XST_PM_ABORT_SUSPEND:
10076582671SRajan Vaja return -ECANCELED;
101df2a4d94SRajan Vaja case XST_PM_MULT_USER:
102df2a4d94SRajan Vaja return -EUSERS;
10376582671SRajan Vaja case XST_PM_INTERNAL:
10476582671SRajan Vaja case XST_PM_CONFLICT:
10576582671SRajan Vaja case XST_PM_INVALID_NODE:
1065dac2a98SJay Buddhabhatti case XST_PM_INVALID_CRC:
10776582671SRajan Vaja default:
10876582671SRajan Vaja return -EINVAL;
10976582671SRajan Vaja }
11076582671SRajan Vaja }
11176582671SRajan Vaja
do_fw_call_fail(u32 * ret_payload,u32 num_args,...)112f922b16aSJay Buddhabhatti static noinline int do_fw_call_fail(u32 *ret_payload, u32 num_args, ...)
11376582671SRajan Vaja {
11476582671SRajan Vaja return -ENODEV;
11576582671SRajan Vaja }
11676582671SRajan Vaja
11776582671SRajan Vaja /*
11876582671SRajan Vaja * PM function call wrapper
11976582671SRajan Vaja * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
12076582671SRajan Vaja */
121f922b16aSJay Buddhabhatti static int (*do_fw_call)(u32 *ret_payload, u32, ...) = do_fw_call_fail;
12276582671SRajan Vaja
12376582671SRajan Vaja /**
12476582671SRajan Vaja * do_fw_call_smc() - Call system-level platform management layer (SMC)
125f922b16aSJay Buddhabhatti * @num_args: Number of variable arguments should be <= 8
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(u32 * ret_payload,u32 num_args,...)132f922b16aSJay Buddhabhatti static noinline int do_fw_call_smc(u32 *ret_payload, u32 num_args, ...)
13376582671SRajan Vaja {
13476582671SRajan Vaja struct arm_smccc_res res;
135f922b16aSJay Buddhabhatti u64 args[8] = {0};
136f922b16aSJay Buddhabhatti va_list arg_list;
137f922b16aSJay Buddhabhatti u8 i;
13876582671SRajan Vaja
139f922b16aSJay Buddhabhatti if (num_args > 8)
140f922b16aSJay Buddhabhatti return -EINVAL;
141f922b16aSJay Buddhabhatti
142f922b16aSJay Buddhabhatti va_start(arg_list, num_args);
143f922b16aSJay Buddhabhatti
144f922b16aSJay Buddhabhatti for (i = 0; i < num_args; i++)
145f922b16aSJay Buddhabhatti args[i] = va_arg(arg_list, u64);
146f922b16aSJay Buddhabhatti
147f922b16aSJay Buddhabhatti va_end(arg_list);
148f922b16aSJay Buddhabhatti
149f922b16aSJay Buddhabhatti arm_smccc_smc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
15076582671SRajan Vaja
15176582671SRajan Vaja if (ret_payload) {
15276582671SRajan Vaja ret_payload[0] = lower_32_bits(res.a0);
15376582671SRajan Vaja ret_payload[1] = upper_32_bits(res.a0);
15476582671SRajan Vaja ret_payload[2] = lower_32_bits(res.a1);
15576582671SRajan Vaja ret_payload[3] = upper_32_bits(res.a1);
15692fb7133SRonak Jain ret_payload[4] = lower_32_bits(res.a2);
15792fb7133SRonak Jain ret_payload[5] = upper_32_bits(res.a2);
15892fb7133SRonak Jain ret_payload[6] = lower_32_bits(res.a3);
15976582671SRajan Vaja }
16076582671SRajan Vaja
16176582671SRajan Vaja return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
16276582671SRajan Vaja }
16376582671SRajan Vaja
16476582671SRajan Vaja /**
16576582671SRajan Vaja * do_fw_call_hvc() - Call system-level platform management layer (HVC)
166f922b16aSJay Buddhabhatti * @num_args: Number of variable arguments should be <= 8
16776582671SRajan Vaja * @ret_payload: Returned value array
16876582671SRajan Vaja *
16976582671SRajan Vaja * Invoke platform management function via HVC
17076582671SRajan Vaja * HVC-based for communication through hypervisor
17176582671SRajan Vaja * (no direct communication with ATF).
17276582671SRajan Vaja *
17376582671SRajan Vaja * Return: Returns status, either success or error+reason
17476582671SRajan Vaja */
do_fw_call_hvc(u32 * ret_payload,u32 num_args,...)175f922b16aSJay Buddhabhatti static noinline int do_fw_call_hvc(u32 *ret_payload, u32 num_args, ...)
17676582671SRajan Vaja {
17776582671SRajan Vaja struct arm_smccc_res res;
178f922b16aSJay Buddhabhatti u64 args[8] = {0};
179f922b16aSJay Buddhabhatti va_list arg_list;
180f922b16aSJay Buddhabhatti u8 i;
18176582671SRajan Vaja
182f922b16aSJay Buddhabhatti if (num_args > 8)
183f922b16aSJay Buddhabhatti return -EINVAL;
184f922b16aSJay Buddhabhatti
185f922b16aSJay Buddhabhatti va_start(arg_list, num_args);
186f922b16aSJay Buddhabhatti
187f922b16aSJay Buddhabhatti for (i = 0; i < num_args; i++)
188f922b16aSJay Buddhabhatti args[i] = va_arg(arg_list, u64);
189f922b16aSJay Buddhabhatti
190f922b16aSJay Buddhabhatti va_end(arg_list);
191f922b16aSJay Buddhabhatti
192f922b16aSJay Buddhabhatti arm_smccc_hvc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
19376582671SRajan Vaja
19476582671SRajan Vaja if (ret_payload) {
19576582671SRajan Vaja ret_payload[0] = lower_32_bits(res.a0);
19676582671SRajan Vaja ret_payload[1] = upper_32_bits(res.a0);
19776582671SRajan Vaja ret_payload[2] = lower_32_bits(res.a1);
19876582671SRajan Vaja ret_payload[3] = upper_32_bits(res.a1);
19992fb7133SRonak Jain ret_payload[4] = lower_32_bits(res.a2);
20092fb7133SRonak Jain ret_payload[5] = upper_32_bits(res.a2);
20192fb7133SRonak Jain ret_payload[6] = lower_32_bits(res.a3);
20276582671SRajan Vaja }
20376582671SRajan Vaja
20476582671SRajan Vaja return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
20576582671SRajan Vaja }
20676582671SRajan Vaja
__do_feature_check_call(const u32 api_id,u32 * ret_payload)207218f01a8SRonak Jain static int __do_feature_check_call(const u32 api_id, u32 *ret_payload)
20894ae7f22SRonak Jain {
20994ae7f22SRonak Jain int ret;
21094ae7f22SRonak Jain u64 smc_arg[2];
211f689a0caSJay Buddhabhatti u32 module_id;
212f689a0caSJay Buddhabhatti u32 feature_check_api_id;
21394ae7f22SRonak Jain
214f689a0caSJay Buddhabhatti module_id = FIELD_GET(MODULE_ID_MASK, api_id);
215f689a0caSJay Buddhabhatti
216f689a0caSJay Buddhabhatti /*
217f689a0caSJay Buddhabhatti * Feature check of APIs belonging to PM, XSEM, and TF-A are handled by calling
218f689a0caSJay Buddhabhatti * PM_FEATURE_CHECK API. For other modules, call PM_API_FEATURES API.
219f689a0caSJay Buddhabhatti */
220f689a0caSJay Buddhabhatti if (module_id == PM_MODULE_ID || module_id == XSEM_MODULE_ID || module_id == TF_A_MODULE_ID)
221f689a0caSJay Buddhabhatti feature_check_api_id = PM_FEATURE_CHECK;
222f689a0caSJay Buddhabhatti else
223f689a0caSJay Buddhabhatti feature_check_api_id = PM_API_FEATURES;
224f689a0caSJay Buddhabhatti
225f689a0caSJay Buddhabhatti /*
226f689a0caSJay Buddhabhatti * Feature check of TF-A APIs is done in the TF-A layer and it expects for
227f689a0caSJay Buddhabhatti * MODULE_ID_MASK bits of SMC's arg[0] to be the same as PM_MODULE_ID.
228f689a0caSJay Buddhabhatti */
22955ed774dSRonak Jain if (module_id == TF_A_MODULE_ID) {
230f689a0caSJay Buddhabhatti module_id = PM_MODULE_ID;
23155ed774dSRonak Jain smc_arg[1] = api_id;
23255ed774dSRonak Jain } else {
23355ed774dSRonak Jain smc_arg[1] = (api_id & API_ID_MASK);
23455ed774dSRonak Jain }
235f689a0caSJay Buddhabhatti
236f689a0caSJay Buddhabhatti smc_arg[0] = PM_SIP_SVC | FIELD_PREP(MODULE_ID_MASK, module_id) | feature_check_api_id;
23794ae7f22SRonak Jain
238f922b16aSJay Buddhabhatti ret = do_fw_call(ret_payload, 2, smc_arg[0], smc_arg[1]);
23994ae7f22SRonak Jain if (ret)
24094ae7f22SRonak Jain ret = -EOPNOTSUPP;
24194ae7f22SRonak Jain else
24294ae7f22SRonak Jain ret = ret_payload[1];
24394ae7f22SRonak Jain
24494ae7f22SRonak Jain return ret;
24594ae7f22SRonak Jain }
24694ae7f22SRonak Jain
do_feature_check_call(const u32 api_id)247218f01a8SRonak Jain static int do_feature_check_call(const u32 api_id)
248461011b1SRavi Patel {
249461011b1SRavi Patel int ret;
250461011b1SRavi Patel u32 ret_payload[PAYLOAD_ARG_CNT];
251acfdd185SAmit Sunil Dhamne struct pm_api_feature_data *feature_data;
252461011b1SRavi Patel
253acfdd185SAmit Sunil Dhamne /* Check for existing entry in hash table for given api */
254acfdd185SAmit Sunil Dhamne hash_for_each_possible(pm_api_features_map, feature_data, hentry,
255acfdd185SAmit Sunil Dhamne api_id) {
256acfdd185SAmit Sunil Dhamne if (feature_data->pm_api_id == api_id)
257acfdd185SAmit Sunil Dhamne return feature_data->feature_status;
258acfdd185SAmit Sunil Dhamne }
259f3217d6fSArnd Bergmann
260acfdd185SAmit Sunil Dhamne /* Add new entry if not present */
26138ed310cSRoman Gushchin feature_data = kmalloc(sizeof(*feature_data), GFP_ATOMIC);
262acfdd185SAmit Sunil Dhamne if (!feature_data)
263acfdd185SAmit Sunil Dhamne return -ENOMEM;
264461011b1SRavi Patel
265acfdd185SAmit Sunil Dhamne feature_data->pm_api_id = api_id;
266218f01a8SRonak Jain ret = __do_feature_check_call(api_id, ret_payload);
267461011b1SRavi Patel
268acfdd185SAmit Sunil Dhamne feature_data->feature_status = ret;
269acfdd185SAmit Sunil Dhamne hash_add(pm_api_features_map, &feature_data->hentry, api_id);
270461011b1SRavi Patel
271f918cfc0SRonak Jain if (api_id == PM_IOCTL)
272f918cfc0SRonak Jain /* Store supported IOCTL IDs mask */
273f918cfc0SRonak Jain memcpy(ioctl_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
274f918cfc0SRonak Jain else if (api_id == PM_QUERY_DATA)
275f918cfc0SRonak Jain /* Store supported QUERY IDs mask */
276f918cfc0SRonak Jain memcpy(query_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
277f918cfc0SRonak Jain
278acfdd185SAmit Sunil Dhamne return ret;
279461011b1SRavi Patel }
280461011b1SRavi Patel
281461011b1SRavi Patel /**
282218f01a8SRonak Jain * zynqmp_pm_feature() - Check whether given feature is supported or not and
283218f01a8SRonak Jain * store supported IOCTL/QUERY ID mask
284218f01a8SRonak Jain * @api_id: API ID to check
285218f01a8SRonak Jain *
286218f01a8SRonak Jain * Return: Returns status, either success or error+reason
287218f01a8SRonak Jain */
zynqmp_pm_feature(const u32 api_id)288218f01a8SRonak Jain int zynqmp_pm_feature(const u32 api_id)
289218f01a8SRonak Jain {
290218f01a8SRonak Jain int ret;
291218f01a8SRonak Jain
292218f01a8SRonak Jain if (!feature_check_enabled)
293218f01a8SRonak Jain return 0;
294218f01a8SRonak Jain
295218f01a8SRonak Jain ret = do_feature_check_call(api_id);
296218f01a8SRonak Jain
297218f01a8SRonak Jain return ret;
298218f01a8SRonak Jain }
29979614953SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
300218f01a8SRonak Jain
301218f01a8SRonak Jain /**
302f918cfc0SRonak Jain * zynqmp_pm_is_function_supported() - Check whether given IOCTL/QUERY function
303f918cfc0SRonak Jain * is supported or not
304f918cfc0SRonak Jain * @api_id: PM_IOCTL or PM_QUERY_DATA
305f918cfc0SRonak Jain * @id: IOCTL or QUERY function IDs
306f918cfc0SRonak Jain *
307f918cfc0SRonak Jain * Return: Returns status, either success or error+reason
308f918cfc0SRonak Jain */
zynqmp_pm_is_function_supported(const u32 api_id,const u32 id)309f918cfc0SRonak Jain int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
310f918cfc0SRonak Jain {
311f918cfc0SRonak Jain int ret;
312f918cfc0SRonak Jain u32 *bit_mask;
313f918cfc0SRonak Jain
314f918cfc0SRonak Jain /* Input arguments validation */
315f918cfc0SRonak Jain if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA))
316f918cfc0SRonak Jain return -EINVAL;
317f918cfc0SRonak Jain
318f918cfc0SRonak Jain /* Check feature check API version */
319218f01a8SRonak Jain ret = do_feature_check_call(PM_FEATURE_CHECK);
320f918cfc0SRonak Jain if (ret < 0)
321f918cfc0SRonak Jain return ret;
322f918cfc0SRonak Jain
323f918cfc0SRonak Jain /* Check if feature check version 2 is supported or not */
324f918cfc0SRonak Jain if ((ret & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) {
325f918cfc0SRonak Jain /*
326f918cfc0SRonak Jain * Call feature check for IOCTL/QUERY API to get IOCTL ID or
327f918cfc0SRonak Jain * QUERY ID feature status.
328f918cfc0SRonak Jain */
329218f01a8SRonak Jain ret = do_feature_check_call(api_id);
330f918cfc0SRonak Jain if (ret < 0)
331f918cfc0SRonak Jain return ret;
332f918cfc0SRonak Jain
333f918cfc0SRonak Jain bit_mask = (api_id == PM_IOCTL) ? ioctl_features : query_features;
334f918cfc0SRonak Jain
335f918cfc0SRonak Jain if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0U)
336f918cfc0SRonak Jain return -EOPNOTSUPP;
337f918cfc0SRonak Jain } else {
338f918cfc0SRonak Jain return -ENODATA;
339f918cfc0SRonak Jain }
340f918cfc0SRonak Jain
341f918cfc0SRonak Jain return 0;
342f918cfc0SRonak Jain }
343f918cfc0SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported);
344f918cfc0SRonak Jain
345f918cfc0SRonak Jain /**
34692fb7133SRonak Jain * zynqmp_pm_invoke_fw_fn() - Invoke the system-level platform management layer
34792fb7133SRonak Jain * caller function depending on the configuration
34892fb7133SRonak Jain * @pm_api_id: Requested PM-API call
34992fb7133SRonak Jain * @ret_payload: Returned value array
35092fb7133SRonak Jain * @num_args: Number of arguments to requested PM-API call
35192fb7133SRonak Jain *
35292fb7133SRonak Jain * Invoke platform management function for SMC or HVC call, depending on
35392fb7133SRonak Jain * configuration.
35492fb7133SRonak Jain * Following SMC Calling Convention (SMCCC) for SMC64:
35592fb7133SRonak Jain * Pm Function Identifier,
35692fb7133SRonak Jain * PM_SIP_SVC + PASS_THROUGH_FW_CMD_ID =
35792fb7133SRonak Jain * ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
35892fb7133SRonak Jain * ((SMC_64) << FUNCID_CC_SHIFT)
35992fb7133SRonak Jain * ((SIP_START) << FUNCID_OEN_SHIFT)
36092fb7133SRonak Jain * (PASS_THROUGH_FW_CMD_ID))
36192fb7133SRonak Jain *
36292fb7133SRonak Jain * PM_SIP_SVC - Registered ZynqMP SIP Service Call.
36392fb7133SRonak Jain * PASS_THROUGH_FW_CMD_ID - Fixed SiP SVC call ID for FW specific calls.
36492fb7133SRonak Jain *
36592fb7133SRonak Jain * Return: Returns status, either success or error+reason
36692fb7133SRonak Jain */
zynqmp_pm_invoke_fw_fn(u32 pm_api_id,u32 * ret_payload,u32 num_args,...)36792fb7133SRonak Jain int zynqmp_pm_invoke_fw_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...)
36892fb7133SRonak Jain {
36992fb7133SRonak Jain /*
37092fb7133SRonak Jain * Added SIP service call Function Identifier
37192fb7133SRonak Jain * Make sure to stay in x0 register
37292fb7133SRonak Jain */
37392fb7133SRonak Jain u64 smc_arg[SMC_ARG_CNT_64];
37492fb7133SRonak Jain int ret, i;
37592fb7133SRonak Jain va_list arg_list;
37692fb7133SRonak Jain u32 args[SMC_ARG_CNT_32] = {0};
37792fb7133SRonak Jain u32 module_id;
37892fb7133SRonak Jain
37992fb7133SRonak Jain if (num_args > SMC_ARG_CNT_32)
38092fb7133SRonak Jain return -EINVAL;
38192fb7133SRonak Jain
38292fb7133SRonak Jain va_start(arg_list, num_args);
38392fb7133SRonak Jain
38492fb7133SRonak Jain /* Check if feature is supported or not */
38592fb7133SRonak Jain ret = zynqmp_pm_feature(pm_api_id);
38692fb7133SRonak Jain if (ret < 0)
38792fb7133SRonak Jain return ret;
38892fb7133SRonak Jain
38992fb7133SRonak Jain for (i = 0; i < num_args; i++)
39092fb7133SRonak Jain args[i] = va_arg(arg_list, u32);
39192fb7133SRonak Jain
39292fb7133SRonak Jain va_end(arg_list);
39392fb7133SRonak Jain
39492fb7133SRonak Jain module_id = FIELD_GET(PLM_MODULE_ID_MASK, pm_api_id);
39592fb7133SRonak Jain
39692fb7133SRonak Jain if (module_id == 0)
39792fb7133SRonak Jain module_id = XPM_MODULE_ID;
39892fb7133SRonak Jain
39992fb7133SRonak Jain smc_arg[0] = PM_SIP_SVC | PASS_THROUGH_FW_CMD_ID;
40092fb7133SRonak Jain smc_arg[1] = ((u64)args[0] << 32U) | FIELD_PREP(PLM_MODULE_ID_MASK, module_id) |
40192fb7133SRonak Jain (pm_api_id & API_ID_MASK);
40292fb7133SRonak Jain for (i = 1; i < (SMC_ARG_CNT_64 - 1); i++)
40392fb7133SRonak Jain smc_arg[i + 1] = ((u64)args[(i * 2)] << 32U) | args[(i * 2) - 1];
40492fb7133SRonak Jain
40592fb7133SRonak Jain return do_fw_call(ret_payload, 8, smc_arg[0], smc_arg[1], smc_arg[2], smc_arg[3],
40692fb7133SRonak Jain smc_arg[4], smc_arg[5], smc_arg[6], smc_arg[7]);
40792fb7133SRonak Jain }
40892fb7133SRonak Jain
40992fb7133SRonak Jain /**
41076582671SRajan Vaja * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
41176582671SRajan Vaja * caller function depending on the configuration
41276582671SRajan Vaja * @pm_api_id: Requested PM-API call
41376582671SRajan Vaja * @ret_payload: Returned value array
414f922b16aSJay Buddhabhatti * @num_args: Number of arguments to requested PM-API call
41576582671SRajan Vaja *
41676582671SRajan Vaja * Invoke platform management function for SMC or HVC call, depending on
41776582671SRajan Vaja * configuration.
41876582671SRajan Vaja * Following SMC Calling Convention (SMCCC) for SMC64:
41976582671SRajan Vaja * Pm Function Identifier,
42076582671SRajan Vaja * PM_SIP_SVC + PM_API_ID =
42176582671SRajan Vaja * ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
42276582671SRajan Vaja * ((SMC_64) << FUNCID_CC_SHIFT)
42376582671SRajan Vaja * ((SIP_START) << FUNCID_OEN_SHIFT)
42476582671SRajan Vaja * ((PM_API_ID) & FUNCID_NUM_MASK))
42576582671SRajan Vaja *
42676582671SRajan Vaja * PM_SIP_SVC - Registered ZynqMP SIP Service Call.
42776582671SRajan Vaja * PM_API_ID - Platform Management API ID.
42876582671SRajan Vaja *
42976582671SRajan Vaja * Return: Returns status, either success or error+reason
43076582671SRajan Vaja */
zynqmp_pm_invoke_fn(u32 pm_api_id,u32 * ret_payload,u32 num_args,...)431f922b16aSJay Buddhabhatti int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...)
43276582671SRajan Vaja {
43376582671SRajan Vaja /*
43476582671SRajan Vaja * Added SIP service call Function Identifier
43576582671SRajan Vaja * Make sure to stay in x0 register
43676582671SRajan Vaja */
437f922b16aSJay Buddhabhatti u64 smc_arg[8];
438f922b16aSJay Buddhabhatti int ret, i;
439f922b16aSJay Buddhabhatti va_list arg_list;
440f922b16aSJay Buddhabhatti u32 args[14] = {0};
441f922b16aSJay Buddhabhatti
442f922b16aSJay Buddhabhatti if (num_args > 14)
443f922b16aSJay Buddhabhatti return -EINVAL;
444f922b16aSJay Buddhabhatti
445f922b16aSJay Buddhabhatti va_start(arg_list, num_args);
44676582671SRajan Vaja
447acfdd185SAmit Sunil Dhamne /* Check if feature is supported or not */
448acfdd185SAmit Sunil Dhamne ret = zynqmp_pm_feature(pm_api_id);
449acfdd185SAmit Sunil Dhamne if (ret < 0)
450acfdd185SAmit Sunil Dhamne return ret;
451461011b1SRavi Patel
452f922b16aSJay Buddhabhatti for (i = 0; i < num_args; i++)
453f922b16aSJay Buddhabhatti args[i] = va_arg(arg_list, u32);
45476582671SRajan Vaja
455f922b16aSJay Buddhabhatti va_end(arg_list);
456f922b16aSJay Buddhabhatti
457f922b16aSJay Buddhabhatti smc_arg[0] = PM_SIP_SVC | pm_api_id;
458f922b16aSJay Buddhabhatti for (i = 0; i < 7; i++)
459f922b16aSJay Buddhabhatti smc_arg[i + 1] = ((u64)args[(i * 2) + 1] << 32) | args[i * 2];
460f922b16aSJay Buddhabhatti
461f922b16aSJay Buddhabhatti return do_fw_call(ret_payload, 8, smc_arg[0], smc_arg[1], smc_arg[2], smc_arg[3],
462f922b16aSJay Buddhabhatti smc_arg[4], smc_arg[5], smc_arg[6], smc_arg[7]);
46376582671SRajan Vaja }
46476582671SRajan Vaja
46576582671SRajan Vaja static u32 pm_api_version;
46676582671SRajan Vaja static u32 pm_tz_version;
46703ffa9afSDhaval Shah static u32 pm_family_code;
46803ffa9afSDhaval Shah static u32 pm_sub_family_code;
46976582671SRajan Vaja
zynqmp_pm_register_sgi(u32 sgi_num,u32 reset)470acd6510dSTanmay Shah int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset)
471acd6510dSTanmay Shah {
472acd6510dSTanmay Shah int ret;
473acd6510dSTanmay Shah
474f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(TF_A_PM_REGISTER_SGI, NULL, 2, sgi_num, reset);
4758c016c80SJay Buddhabhatti if (ret != -EOPNOTSUPP && !ret)
476acd6510dSTanmay Shah return ret;
477acd6510dSTanmay Shah
478acd6510dSTanmay Shah /* try old implementation as fallback strategy if above fails */
479f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, IOCTL_REGISTER_SGI, sgi_num, reset);
480acd6510dSTanmay Shah }
481acd6510dSTanmay Shah
48276582671SRajan Vaja /**
48376582671SRajan Vaja * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
48476582671SRajan Vaja * @version: Returned version value
48576582671SRajan Vaja *
48676582671SRajan Vaja * Return: Returns status, either success or error+reason
48776582671SRajan Vaja */
zynqmp_pm_get_api_version(u32 * version)488b9b3a8beSRajan Vaja int zynqmp_pm_get_api_version(u32 *version)
48976582671SRajan Vaja {
49076582671SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT];
49176582671SRajan Vaja int ret;
49276582671SRajan Vaja
49376582671SRajan Vaja if (!version)
49476582671SRajan Vaja return -EINVAL;
49576582671SRajan Vaja
49676582671SRajan Vaja /* Check is PM API version already verified */
49776582671SRajan Vaja if (pm_api_version > 0) {
49876582671SRajan Vaja *version = pm_api_version;
49976582671SRajan Vaja return 0;
50076582671SRajan Vaja }
501f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, ret_payload, 0);
50276582671SRajan Vaja *version = ret_payload[1];
50376582671SRajan Vaja
50476582671SRajan Vaja return ret;
50576582671SRajan Vaja }
506b9b3a8beSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
50776582671SRajan Vaja
50876582671SRajan Vaja /**
509fe6f42cfSNava kishore Manne * zynqmp_pm_get_chipid - Get silicon ID registers
510fe6f42cfSNava kishore Manne * @idcode: IDCODE register
511fe6f42cfSNava kishore Manne * @version: version register
512fe6f42cfSNava kishore Manne *
513fe6f42cfSNava kishore Manne * Return: Returns the status of the operation and the idcode and version
514fe6f42cfSNava kishore Manne * registers in @idcode and @version.
515fe6f42cfSNava kishore Manne */
zynqmp_pm_get_chipid(u32 * idcode,u32 * version)51621cd93baSRajan Vaja int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
517fe6f42cfSNava kishore Manne {
518fe6f42cfSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT];
519fe6f42cfSNava kishore Manne int ret;
520fe6f42cfSNava kishore Manne
521fe6f42cfSNava kishore Manne if (!idcode || !version)
522fe6f42cfSNava kishore Manne return -EINVAL;
523fe6f42cfSNava kishore Manne
524f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, ret_payload, 0);
525fe6f42cfSNava kishore Manne *idcode = ret_payload[1];
526fe6f42cfSNava kishore Manne *version = ret_payload[2];
527fe6f42cfSNava kishore Manne
528fe6f42cfSNava kishore Manne return ret;
529fe6f42cfSNava kishore Manne }
53021cd93baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
531fe6f42cfSNava kishore Manne
532fe6f42cfSNava kishore Manne /**
53303ffa9afSDhaval Shah * zynqmp_pm_get_family_info() - Get family info of platform
53403ffa9afSDhaval Shah * @family: Returned family code value
53503ffa9afSDhaval Shah * @subfamily: Returned sub-family code value
53603ffa9afSDhaval Shah *
53703ffa9afSDhaval Shah * Return: Returns status, either success or error+reason
53803ffa9afSDhaval Shah */
zynqmp_pm_get_family_info(u32 * family,u32 * subfamily)5390c4b2255SJay Buddhabhatti int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily)
54003ffa9afSDhaval Shah {
54103ffa9afSDhaval Shah u32 ret_payload[PAYLOAD_ARG_CNT];
54203ffa9afSDhaval Shah u32 idcode;
54303ffa9afSDhaval Shah int ret;
54403ffa9afSDhaval Shah
54503ffa9afSDhaval Shah /* Check is family or sub-family code already received */
54603ffa9afSDhaval Shah if (pm_family_code && pm_sub_family_code) {
54703ffa9afSDhaval Shah *family = pm_family_code;
54803ffa9afSDhaval Shah *subfamily = pm_sub_family_code;
54903ffa9afSDhaval Shah return 0;
55003ffa9afSDhaval Shah }
55103ffa9afSDhaval Shah
552f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, ret_payload, 0);
55303ffa9afSDhaval Shah if (ret < 0)
55403ffa9afSDhaval Shah return ret;
55503ffa9afSDhaval Shah
55603ffa9afSDhaval Shah idcode = ret_payload[1];
55703ffa9afSDhaval Shah pm_family_code = FIELD_GET(FAMILY_CODE_MASK, idcode);
55803ffa9afSDhaval Shah pm_sub_family_code = FIELD_GET(SUB_FAMILY_CODE_MASK, idcode);
55903ffa9afSDhaval Shah *family = pm_family_code;
56003ffa9afSDhaval Shah *subfamily = pm_sub_family_code;
56103ffa9afSDhaval Shah
56203ffa9afSDhaval Shah return 0;
56303ffa9afSDhaval Shah }
5640c4b2255SJay Buddhabhatti EXPORT_SYMBOL_GPL(zynqmp_pm_get_family_info);
56503ffa9afSDhaval Shah
56603ffa9afSDhaval Shah /**
56792fb7133SRonak Jain * zynqmp_pm_get_sip_svc_version() - Get SiP service call version
56892fb7133SRonak Jain * @version: Returned version value
56992fb7133SRonak Jain *
57092fb7133SRonak Jain * Return: Returns status, either success or error+reason
57192fb7133SRonak Jain */
zynqmp_pm_get_sip_svc_version(u32 * version)57292fb7133SRonak Jain static int zynqmp_pm_get_sip_svc_version(u32 *version)
57392fb7133SRonak Jain {
57492fb7133SRonak Jain struct arm_smccc_res res;
57592fb7133SRonak Jain u64 args[SMC_ARG_CNT_64] = {0};
57692fb7133SRonak Jain
57792fb7133SRonak Jain if (!version)
57892fb7133SRonak Jain return -EINVAL;
57992fb7133SRonak Jain
58092fb7133SRonak Jain /* Check if SiP SVC version already verified */
58192fb7133SRonak Jain if (sip_svc_version > 0) {
58292fb7133SRonak Jain *version = sip_svc_version;
58392fb7133SRonak Jain return 0;
58492fb7133SRonak Jain }
58592fb7133SRonak Jain
58692fb7133SRonak Jain args[0] = GET_SIP_SVC_VERSION;
58792fb7133SRonak Jain
58892fb7133SRonak Jain arm_smccc_smc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
58992fb7133SRonak Jain
59092fb7133SRonak Jain *version = ((lower_32_bits(res.a0) << 16U) | lower_32_bits(res.a1));
59192fb7133SRonak Jain
59292fb7133SRonak Jain return zynqmp_pm_ret_code(XST_PM_SUCCESS);
59392fb7133SRonak Jain }
59492fb7133SRonak Jain
59592fb7133SRonak Jain /**
59676582671SRajan Vaja * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
59776582671SRajan Vaja * @version: Returned version value
59876582671SRajan Vaja *
59976582671SRajan Vaja * Return: Returns status, either success or error+reason
60076582671SRajan Vaja */
zynqmp_pm_get_trustzone_version(u32 * version)60176582671SRajan Vaja static int zynqmp_pm_get_trustzone_version(u32 *version)
60276582671SRajan Vaja {
60376582671SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT];
60476582671SRajan Vaja int ret;
60576582671SRajan Vaja
60676582671SRajan Vaja if (!version)
60776582671SRajan Vaja return -EINVAL;
60876582671SRajan Vaja
60976582671SRajan Vaja /* Check is PM trustzone version already verified */
61076582671SRajan Vaja if (pm_tz_version > 0) {
61176582671SRajan Vaja *version = pm_tz_version;
61276582671SRajan Vaja return 0;
61376582671SRajan Vaja }
614f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, ret_payload, 0);
61576582671SRajan Vaja *version = ret_payload[1];
61676582671SRajan Vaja
61776582671SRajan Vaja return ret;
61876582671SRajan Vaja }
61976582671SRajan Vaja
62076582671SRajan Vaja /**
62176582671SRajan Vaja * get_set_conduit_method() - Choose SMC or HVC based communication
62276582671SRajan Vaja * @np: Pointer to the device_node structure
62376582671SRajan Vaja *
62476582671SRajan Vaja * Use SMC or HVC-based functions to communicate with EL2/EL3.
62576582671SRajan Vaja *
62676582671SRajan Vaja * Return: Returns 0 on success or error code
62776582671SRajan Vaja */
get_set_conduit_method(struct device_node * np)62876582671SRajan Vaja static int get_set_conduit_method(struct device_node *np)
62976582671SRajan Vaja {
63076582671SRajan Vaja const char *method;
63176582671SRajan Vaja
63276582671SRajan Vaja if (of_property_read_string(np, "method", &method)) {
63376582671SRajan Vaja pr_warn("%s missing \"method\" property\n", __func__);
63476582671SRajan Vaja return -ENXIO;
63576582671SRajan Vaja }
63676582671SRajan Vaja
63776582671SRajan Vaja if (!strcmp("hvc", method)) {
63876582671SRajan Vaja do_fw_call = do_fw_call_hvc;
63976582671SRajan Vaja } else if (!strcmp("smc", method)) {
64076582671SRajan Vaja do_fw_call = do_fw_call_smc;
64176582671SRajan Vaja } else {
64276582671SRajan Vaja pr_warn("%s Invalid \"method\" property: %s\n",
64376582671SRajan Vaja __func__, method);
64476582671SRajan Vaja return -EINVAL;
64576582671SRajan Vaja }
64676582671SRajan Vaja
64776582671SRajan Vaja return 0;
64876582671SRajan Vaja }
64976582671SRajan Vaja
65059ecdd77SRajan Vaja /**
65159ecdd77SRajan Vaja * zynqmp_pm_query_data() - Get query data from firmware
65259ecdd77SRajan Vaja * @qdata: Variable to the zynqmp_pm_query_data structure
65359ecdd77SRajan Vaja * @out: Returned output value
65459ecdd77SRajan Vaja *
65559ecdd77SRajan Vaja * Return: Returns status, either success or error+reason
65659ecdd77SRajan Vaja */
zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata,u32 * out)6576366c1baSRajan Vaja int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
65859ecdd77SRajan Vaja {
65992fb7133SRonak Jain int ret, i = 0;
66092fb7133SRonak Jain u32 ret_payload[PAYLOAD_ARG_CNT] = {0};
661f9627312SRajan Vaja
66292fb7133SRonak Jain if (sip_svc_version >= SIP_SVC_PASSTHROUGH_VERSION) {
66392fb7133SRonak Jain ret = zynqmp_pm_invoke_fw_fn(PM_QUERY_DATA, ret_payload, 4,
66492fb7133SRonak Jain qdata.qid, qdata.arg1,
66592fb7133SRonak Jain qdata.arg2, qdata.arg3);
66692fb7133SRonak Jain /* To support backward compatibility */
66792fb7133SRonak Jain if (!ret && !ret_payload[0]) {
66892fb7133SRonak Jain /*
66992fb7133SRonak Jain * TF-A passes return status on 0th index but
67092fb7133SRonak Jain * api to get clock name reads data from 0th
67192fb7133SRonak Jain * index so pass data at 0th index instead of
67292fb7133SRonak Jain * return status
67392fb7133SRonak Jain */
67492fb7133SRonak Jain if (qdata.qid == PM_QID_CLOCK_GET_NAME ||
67592fb7133SRonak Jain qdata.qid == PM_QID_PINCTRL_GET_FUNCTION_NAME)
67692fb7133SRonak Jain i = 1;
67792fb7133SRonak Jain
67892fb7133SRonak Jain for (; i < PAYLOAD_ARG_CNT; i++, out++)
67992fb7133SRonak Jain *out = ret_payload[i];
68092fb7133SRonak Jain
68192fb7133SRonak Jain return ret;
68292fb7133SRonak Jain }
68392fb7133SRonak Jain }
68492fb7133SRonak Jain
68592fb7133SRonak Jain ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, out, 4, qdata.qid,
68692fb7133SRonak Jain qdata.arg1, qdata.arg2, qdata.arg3);
687f9627312SRajan Vaja
688f9627312SRajan Vaja /*
689f9627312SRajan Vaja * For clock name query, all bytes in SMC response are clock name
690f9627312SRajan Vaja * characters and return code is always success. For invalid clocks,
691f9627312SRajan Vaja * clock name bytes would be zeros.
692f9627312SRajan Vaja */
693f9627312SRajan Vaja return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
694f9627312SRajan Vaja }
6956366c1baSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
696f9627312SRajan Vaja
697f9627312SRajan Vaja /**
698f9627312SRajan Vaja * zynqmp_pm_clock_enable() - Enable the clock for given id
699f9627312SRajan Vaja * @clock_id: ID of the clock to be enabled
700f9627312SRajan Vaja *
701f9627312SRajan Vaja * This function is used by master to enable the clock
702f9627312SRajan Vaja * including peripherals and PLL clocks.
703f9627312SRajan Vaja *
704f9627312SRajan Vaja * Return: Returns status, either success or error+reason
705f9627312SRajan Vaja */
zynqmp_pm_clock_enable(u32 clock_id)7063637e84cSRajan Vaja int zynqmp_pm_clock_enable(u32 clock_id)
707f9627312SRajan Vaja {
708f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, NULL, 1, clock_id);
709f9627312SRajan Vaja }
7103637e84cSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
711f9627312SRajan Vaja
712f9627312SRajan Vaja /**
713f9627312SRajan Vaja * zynqmp_pm_clock_disable() - Disable the clock for given id
714f9627312SRajan Vaja * @clock_id: ID of the clock to be disable
715f9627312SRajan Vaja *
716f9627312SRajan Vaja * This function is used by master to disable the clock
717f9627312SRajan Vaja * including peripherals and PLL clocks.
718f9627312SRajan Vaja *
719f9627312SRajan Vaja * Return: Returns status, either success or error+reason
720f9627312SRajan Vaja */
zynqmp_pm_clock_disable(u32 clock_id)721f5ccd54bSRajan Vaja int zynqmp_pm_clock_disable(u32 clock_id)
722f9627312SRajan Vaja {
723f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, NULL, 1, clock_id);
724f9627312SRajan Vaja }
725f5ccd54bSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
726f9627312SRajan Vaja
727f9627312SRajan Vaja /**
728f9627312SRajan Vaja * zynqmp_pm_clock_getstate() - Get the clock state for given id
729f9627312SRajan Vaja * @clock_id: ID of the clock to be queried
730f9627312SRajan Vaja * @state: 1/0 (Enabled/Disabled)
731f9627312SRajan Vaja *
732f9627312SRajan Vaja * This function is used by master to get the state of clock
733f9627312SRajan Vaja * including peripherals and PLL clocks.
734f9627312SRajan Vaja *
735f9627312SRajan Vaja * Return: Returns status, either success or error+reason
736f9627312SRajan Vaja */
zynqmp_pm_clock_getstate(u32 clock_id,u32 * state)7375e76731dSRajan Vaja int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
738f9627312SRajan Vaja {
739f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT];
740f9627312SRajan Vaja int ret;
741f9627312SRajan Vaja
742f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, ret_payload, 1, clock_id);
743f9627312SRajan Vaja *state = ret_payload[1];
744f9627312SRajan Vaja
745f9627312SRajan Vaja return ret;
746f9627312SRajan Vaja }
7475e76731dSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
748f9627312SRajan Vaja
749f9627312SRajan Vaja /**
750f9627312SRajan Vaja * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
751f9627312SRajan Vaja * @clock_id: ID of the clock
752f9627312SRajan Vaja * @divider: divider value
753f9627312SRajan Vaja *
754f9627312SRajan Vaja * This function is used by master to set divider for any clock
755f9627312SRajan Vaja * to achieve desired rate.
756f9627312SRajan Vaja *
757f9627312SRajan Vaja * Return: Returns status, either success or error+reason
758f9627312SRajan Vaja */
zynqmp_pm_clock_setdivider(u32 clock_id,u32 divider)759fc9fb8fbSRajan Vaja int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
760f9627312SRajan Vaja {
761f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, NULL, 2, clock_id, divider);
762f9627312SRajan Vaja }
763fc9fb8fbSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
764f9627312SRajan Vaja
765f9627312SRajan Vaja /**
766f9627312SRajan Vaja * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
767f9627312SRajan Vaja * @clock_id: ID of the clock
768f9627312SRajan Vaja * @divider: divider value
769f9627312SRajan Vaja *
770f9627312SRajan Vaja * This function is used by master to get divider values
771f9627312SRajan Vaja * for any clock.
772f9627312SRajan Vaja *
773f9627312SRajan Vaja * Return: Returns status, either success or error+reason
774f9627312SRajan Vaja */
zynqmp_pm_clock_getdivider(u32 clock_id,u32 * divider)7750667a8d1SRajan Vaja int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
776f9627312SRajan Vaja {
777f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT];
778f9627312SRajan Vaja int ret;
779f9627312SRajan Vaja
780f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, ret_payload, 1, clock_id);
781f9627312SRajan Vaja *divider = ret_payload[1];
782f9627312SRajan Vaja
783f9627312SRajan Vaja return ret;
784f9627312SRajan Vaja }
7850667a8d1SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
786f9627312SRajan Vaja
787f9627312SRajan Vaja /**
788f9627312SRajan Vaja * zynqmp_pm_clock_setparent() - Set the clock parent for given id
789f9627312SRajan Vaja * @clock_id: ID of the clock
790f9627312SRajan Vaja * @parent_id: parent id
791f9627312SRajan Vaja *
792f9627312SRajan Vaja * This function is used by master to set parent for any clock.
793f9627312SRajan Vaja *
794f9627312SRajan Vaja * Return: Returns status, either success or error+reason
795f9627312SRajan Vaja */
zynqmp_pm_clock_setparent(u32 clock_id,u32 parent_id)79670c0d364SRajan Vaja int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
797f9627312SRajan Vaja {
798f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, NULL, 2, clock_id, parent_id);
799f9627312SRajan Vaja }
80070c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
801f9627312SRajan Vaja
802f9627312SRajan Vaja /**
803f9627312SRajan Vaja * zynqmp_pm_clock_getparent() - Get the clock parent for given id
804f9627312SRajan Vaja * @clock_id: ID of the clock
805f9627312SRajan Vaja * @parent_id: parent id
806f9627312SRajan Vaja *
807f9627312SRajan Vaja * This function is used by master to get parent index
808f9627312SRajan Vaja * for any clock.
809f9627312SRajan Vaja *
810f9627312SRajan Vaja * Return: Returns status, either success or error+reason
811f9627312SRajan Vaja */
zynqmp_pm_clock_getparent(u32 clock_id,u32 * parent_id)81270c0d364SRajan Vaja int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
813f9627312SRajan Vaja {
814f9627312SRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT];
815f9627312SRajan Vaja int ret;
816f9627312SRajan Vaja
817f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, ret_payload, 1, clock_id);
818f9627312SRajan Vaja *parent_id = ret_payload[1];
819f9627312SRajan Vaja
820f9627312SRajan Vaja return ret;
82159ecdd77SRajan Vaja }
82270c0d364SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
82359ecdd77SRajan Vaja
8243b0296b8SRajan Vaja /**
825426c8d85SRajan Vaja * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
8263b0296b8SRajan Vaja *
827426c8d85SRajan Vaja * @clk_id: PLL clock ID
828426c8d85SRajan Vaja * @mode: PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
8293b0296b8SRajan Vaja *
830426c8d85SRajan Vaja * This function sets PLL mode
8313b0296b8SRajan Vaja *
8323b0296b8SRajan Vaja * Return: Returns status, either success or error+reason
8333b0296b8SRajan Vaja */
zynqmp_pm_set_pll_frac_mode(u32 clk_id,u32 mode)834426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
8353b0296b8SRajan Vaja {
836f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_PLL_FRAC_MODE, clk_id, mode);
8373b0296b8SRajan Vaja }
838426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
839426c8d85SRajan Vaja
840426c8d85SRajan Vaja /**
841426c8d85SRajan Vaja * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
842426c8d85SRajan Vaja *
843426c8d85SRajan Vaja * @clk_id: PLL clock ID
844426c8d85SRajan Vaja * @mode: PLL mode
845426c8d85SRajan Vaja *
846426c8d85SRajan Vaja * This function return current PLL mode
847426c8d85SRajan Vaja *
848426c8d85SRajan Vaja * Return: Returns status, either success or error+reason
849426c8d85SRajan Vaja */
zynqmp_pm_get_pll_frac_mode(u32 clk_id,u32 * mode)850426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
851426c8d85SRajan Vaja {
852f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, mode, 3, 0, IOCTL_GET_PLL_FRAC_MODE, clk_id);
853426c8d85SRajan Vaja }
854426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
855426c8d85SRajan Vaja
856426c8d85SRajan Vaja /**
857426c8d85SRajan Vaja * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
858426c8d85SRajan Vaja *
859426c8d85SRajan Vaja * @clk_id: PLL clock ID
860426c8d85SRajan Vaja * @data: fraction data
861426c8d85SRajan Vaja *
862426c8d85SRajan Vaja * This function sets fraction data.
863426c8d85SRajan Vaja * It is valid for fraction mode only.
864426c8d85SRajan Vaja *
865426c8d85SRajan Vaja * Return: Returns status, either success or error+reason
866426c8d85SRajan Vaja */
zynqmp_pm_set_pll_frac_data(u32 clk_id,u32 data)867426c8d85SRajan Vaja int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
868426c8d85SRajan Vaja {
869f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_PLL_FRAC_DATA, clk_id, data);
870426c8d85SRajan Vaja }
871426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
872426c8d85SRajan Vaja
873426c8d85SRajan Vaja /**
874426c8d85SRajan Vaja * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
875426c8d85SRajan Vaja *
876426c8d85SRajan Vaja * @clk_id: PLL clock ID
877426c8d85SRajan Vaja * @data: fraction data
878426c8d85SRajan Vaja *
879426c8d85SRajan Vaja * This function returns fraction data value.
880426c8d85SRajan Vaja *
881426c8d85SRajan Vaja * Return: Returns status, either success or error+reason
882426c8d85SRajan Vaja */
zynqmp_pm_get_pll_frac_data(u32 clk_id,u32 * data)883426c8d85SRajan Vaja int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
884426c8d85SRajan Vaja {
885f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, data, 3, 0, IOCTL_GET_PLL_FRAC_DATA, clk_id);
886426c8d85SRajan Vaja }
887426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
888426c8d85SRajan Vaja
889426c8d85SRajan Vaja /**
890426c8d85SRajan Vaja * zynqmp_pm_set_sd_tapdelay() - Set tap delay for the SD device
891426c8d85SRajan Vaja *
892332bee16SMichal Simek * @node_id: Node ID of the device
893332bee16SMichal Simek * @type: Type of tap delay to set (input/output)
894332bee16SMichal Simek * @value: Value to set fot the tap delay
895426c8d85SRajan Vaja *
896426c8d85SRajan Vaja * This function sets input/output tap delay for the SD device.
897426c8d85SRajan Vaja *
898332bee16SMichal Simek * Return: Returns status, either success or error+reason
899426c8d85SRajan Vaja */
zynqmp_pm_set_sd_tapdelay(u32 node_id,u32 type,u32 value)900426c8d85SRajan Vaja int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
901426c8d85SRajan Vaja {
902a4b2e606SMarek Vasut u32 reg = (type == PM_TAPDELAY_INPUT) ? SD_ITAPDLY : SD_OTAPDLYSEL;
903a4b2e606SMarek Vasut u32 mask = (node_id == NODE_SD_0) ? GENMASK(15, 0) : GENMASK(31, 16);
904a4b2e606SMarek Vasut
905a4b2e606SMarek Vasut if (value) {
906f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, node_id, IOCTL_SET_SD_TAPDELAY, type,
907f922b16aSJay Buddhabhatti value);
908426c8d85SRajan Vaja }
909a4b2e606SMarek Vasut
910a4b2e606SMarek Vasut /*
911a4b2e606SMarek Vasut * Work around completely misdesigned firmware API on Xilinx ZynqMP.
912a4b2e606SMarek Vasut * The IOCTL_SET_SD_TAPDELAY firmware call allows the caller to only
913a4b2e606SMarek Vasut * ever set IOU_SLCR SD_ITAPDLY Register SD0_ITAPDLYENA/SD1_ITAPDLYENA
914a4b2e606SMarek Vasut * bits, but there is no matching call to clear those bits. If those
915a4b2e606SMarek Vasut * bits are not cleared, SDMMC tuning may fail.
916a4b2e606SMarek Vasut *
917a4b2e606SMarek Vasut * Luckily, there are PM_MMIO_READ/PM_MMIO_WRITE calls which seem to
918a4b2e606SMarek Vasut * allow complete unrestricted access to all address space, including
919a4b2e606SMarek Vasut * IOU_SLCR SD_ITAPDLY Register and all the other registers, access
920a4b2e606SMarek Vasut * to which was supposed to be protected by the current firmware API.
921a4b2e606SMarek Vasut *
922a4b2e606SMarek Vasut * Use PM_MMIO_READ/PM_MMIO_WRITE to re-implement the missing counter
923a4b2e606SMarek Vasut * part of IOCTL_SET_SD_TAPDELAY which clears SDx_ITAPDLYENA bits.
924a4b2e606SMarek Vasut */
925f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, NULL, 2, reg, mask);
926a4b2e606SMarek Vasut }
927426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
928426c8d85SRajan Vaja
929426c8d85SRajan Vaja /**
930426c8d85SRajan Vaja * zynqmp_pm_sd_dll_reset() - Reset DLL logic
931426c8d85SRajan Vaja *
932332bee16SMichal Simek * @node_id: Node ID of the device
933332bee16SMichal Simek * @type: Reset type
934426c8d85SRajan Vaja *
935426c8d85SRajan Vaja * This function resets DLL logic for the SD device.
936426c8d85SRajan Vaja *
937332bee16SMichal Simek * Return: Returns status, either success or error+reason
938426c8d85SRajan Vaja */
zynqmp_pm_sd_dll_reset(u32 node_id,u32 type)939426c8d85SRajan Vaja int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
940426c8d85SRajan Vaja {
941f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, node_id, IOCTL_SD_DLL_RESET, type);
942426c8d85SRajan Vaja }
943426c8d85SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
9443b0296b8SRajan Vaja
945bc3843d4SNava kishore Manne /**
94674e78adcSSai Krishna Potthuri * zynqmp_pm_ospi_mux_select() - OSPI Mux selection
94774e78adcSSai Krishna Potthuri *
94874e78adcSSai Krishna Potthuri * @dev_id: Device Id of the OSPI device.
94974e78adcSSai Krishna Potthuri * @select: OSPI Mux select value.
95074e78adcSSai Krishna Potthuri *
95174e78adcSSai Krishna Potthuri * This function select the OSPI Mux.
95274e78adcSSai Krishna Potthuri *
95374e78adcSSai Krishna Potthuri * Return: Returns status, either success or error+reason
95474e78adcSSai Krishna Potthuri */
zynqmp_pm_ospi_mux_select(u32 dev_id,u32 select)95574e78adcSSai Krishna Potthuri int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
95674e78adcSSai Krishna Potthuri {
957f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, dev_id, IOCTL_OSPI_MUX_SELECT, select);
95874e78adcSSai Krishna Potthuri }
95974e78adcSSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select);
96074e78adcSSai Krishna Potthuri
96174e78adcSSai Krishna Potthuri /**
9624f680b72SRajan Vaja * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
963332bee16SMichal Simek * @index: GGS register index
964332bee16SMichal Simek * @value: Register value to be written
9654f680b72SRajan Vaja *
9664f680b72SRajan Vaja * This function writes value to GGS register.
9674f680b72SRajan Vaja *
968332bee16SMichal Simek * Return: Returns status, either success or error+reason
9694f680b72SRajan Vaja */
zynqmp_pm_write_ggs(u32 index,u32 value)9704f680b72SRajan Vaja int zynqmp_pm_write_ggs(u32 index, u32 value)
9714f680b72SRajan Vaja {
972f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_WRITE_GGS, index, value);
9734f680b72SRajan Vaja }
9744f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
9754f680b72SRajan Vaja
9764f680b72SRajan Vaja /**
9772a8faf8dSMichal Simek * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs)
978332bee16SMichal Simek * @index: GGS register index
979332bee16SMichal Simek * @value: Register value to be written
9804f680b72SRajan Vaja *
9814f680b72SRajan Vaja * This function returns GGS register value.
9824f680b72SRajan Vaja *
983332bee16SMichal Simek * Return: Returns status, either success or error+reason
9844f680b72SRajan Vaja */
zynqmp_pm_read_ggs(u32 index,u32 * value)9854f680b72SRajan Vaja int zynqmp_pm_read_ggs(u32 index, u32 *value)
9864f680b72SRajan Vaja {
987f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, value, 3, 0, IOCTL_READ_GGS, index);
9884f680b72SRajan Vaja }
9894f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
9904f680b72SRajan Vaja
9914f680b72SRajan Vaja /**
9924f680b72SRajan Vaja * zynqmp_pm_write_pggs() - PM API for writing persistent global general
9934f680b72SRajan Vaja * storage (pggs)
994332bee16SMichal Simek * @index: PGGS register index
995332bee16SMichal Simek * @value: Register value to be written
9964f680b72SRajan Vaja *
9974f680b72SRajan Vaja * This function writes value to PGGS register.
9984f680b72SRajan Vaja *
999332bee16SMichal Simek * Return: Returns status, either success or error+reason
10004f680b72SRajan Vaja */
zynqmp_pm_write_pggs(u32 index,u32 value)10014f680b72SRajan Vaja int zynqmp_pm_write_pggs(u32 index, u32 value)
10024f680b72SRajan Vaja {
1003f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_WRITE_PGGS, index, value);
10044f680b72SRajan Vaja }
10054f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
10064f680b72SRajan Vaja
10074f680b72SRajan Vaja /**
10082a8faf8dSMichal Simek * zynqmp_pm_read_pggs() - PM API for reading persistent global general
10094f680b72SRajan Vaja * storage (pggs)
1010332bee16SMichal Simek * @index: PGGS register index
1011332bee16SMichal Simek * @value: Register value to be written
10124f680b72SRajan Vaja *
10134f680b72SRajan Vaja * This function returns PGGS register value.
10144f680b72SRajan Vaja *
1015332bee16SMichal Simek * Return: Returns status, either success or error+reason
10164f680b72SRajan Vaja */
zynqmp_pm_read_pggs(u32 index,u32 * value)10174f680b72SRajan Vaja int zynqmp_pm_read_pggs(u32 index, u32 *value)
10184f680b72SRajan Vaja {
1019f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, value, 3, 0, IOCTL_READ_PGGS, index);
10204f680b72SRajan Vaja }
10214f680b72SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
10224f680b72SRajan Vaja
zynqmp_pm_set_tapdelay_bypass(u32 index,u32 value)10231e400cb9SRajan Vaja int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value)
10241e400cb9SRajan Vaja {
1025f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_TAPDELAY_BYPASS, index, value);
10261e400cb9SRajan Vaja }
10271e400cb9SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass);
10281e400cb9SRajan Vaja
10294f680b72SRajan Vaja /**
1030a2cc220aSRajan Vaja * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
1031332bee16SMichal Simek * @value: Status value to be written
1032a2cc220aSRajan Vaja *
1033a2cc220aSRajan Vaja * This function sets healthy bit value to indicate boot health status
1034a2cc220aSRajan Vaja * to firmware.
1035a2cc220aSRajan Vaja *
1036332bee16SMichal Simek * Return: Returns status, either success or error+reason
1037a2cc220aSRajan Vaja */
zynqmp_pm_set_boot_health_status(u32 value)1038a2cc220aSRajan Vaja int zynqmp_pm_set_boot_health_status(u32 value)
1039a2cc220aSRajan Vaja {
1040f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, 0, IOCTL_SET_BOOT_HEALTH_STATUS, value);
1041a2cc220aSRajan Vaja }
1042a2cc220aSRajan Vaja
1043a2cc220aSRajan Vaja /**
1044bc3843d4SNava kishore Manne * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
1045bc3843d4SNava kishore Manne * @reset: Reset to be configured
1046bc3843d4SNava kishore Manne * @assert_flag: Flag stating should reset be asserted (1) or
1047bc3843d4SNava kishore Manne * released (0)
1048bc3843d4SNava kishore Manne *
1049bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason
1050bc3843d4SNava kishore Manne */
zynqmp_pm_reset_assert(const u32 reset,const enum zynqmp_pm_reset_action assert_flag)1051f33d6099SRonak Jain int zynqmp_pm_reset_assert(const u32 reset,
1052bc3843d4SNava kishore Manne const enum zynqmp_pm_reset_action assert_flag)
1053bc3843d4SNava kishore Manne {
1054f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, NULL, 2, reset, assert_flag);
1055bc3843d4SNava kishore Manne }
1056cf23ec35SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
1057bc3843d4SNava kishore Manne
1058bc3843d4SNava kishore Manne /**
1059bc3843d4SNava kishore Manne * zynqmp_pm_reset_get_status - Get status of the reset
1060bc3843d4SNava kishore Manne * @reset: Reset whose status should be returned
1061bc3843d4SNava kishore Manne * @status: Returned status
1062bc3843d4SNava kishore Manne *
1063bc3843d4SNava kishore Manne * Return: Returns status, either success or error+reason
1064bc3843d4SNava kishore Manne */
zynqmp_pm_reset_get_status(const u32 reset,u32 * status)1065f33d6099SRonak Jain int zynqmp_pm_reset_get_status(const u32 reset, u32 *status)
1066bc3843d4SNava kishore Manne {
1067bc3843d4SNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT];
1068bc3843d4SNava kishore Manne int ret;
1069bc3843d4SNava kishore Manne
1070bc3843d4SNava kishore Manne if (!status)
1071bc3843d4SNava kishore Manne return -EINVAL;
1072bc3843d4SNava kishore Manne
1073f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, ret_payload, 1, reset);
1074bc3843d4SNava kishore Manne *status = ret_payload[1];
1075bc3843d4SNava kishore Manne
1076bc3843d4SNava kishore Manne return ret;
1077bc3843d4SNava kishore Manne }
10781b413581SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
1079bc3843d4SNava kishore Manne
1080e178df31SJolly Shah /**
1081e840deccSNava kishore Manne * zynqmp_pm_fpga_load - Perform the fpga load
1082e840deccSNava kishore Manne * @address: Address to write to
1083e840deccSNava kishore Manne * @size: pl bitstream size
1084e840deccSNava kishore Manne * @flags: Bitstream type
1085e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration
1086e840deccSNava kishore Manne * -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
1087e840deccSNava kishore Manne *
1088e840deccSNava kishore Manne * This function provides access to pmufw. To transfer
1089e840deccSNava kishore Manne * the required bitstream into PL.
1090e840deccSNava kishore Manne *
1091e840deccSNava kishore Manne * Return: Returns status, either success or error+reason
1092e840deccSNava kishore Manne */
zynqmp_pm_fpga_load(const u64 address,const u32 size,const u32 flags)10934db8180fSRajan Vaja int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
1094e840deccSNava kishore Manne {
1095e2ebc05dSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT];
1096e2ebc05dSNava kishore Manne int ret;
1097e2ebc05dSNava kishore Manne
1098f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_FPGA_LOAD, ret_payload, 4, lower_32_bits(address),
1099f922b16aSJay Buddhabhatti upper_32_bits(address), size, flags);
1100e2ebc05dSNava kishore Manne if (ret_payload[0])
1101e2ebc05dSNava kishore Manne return -ret_payload[0];
1102e2ebc05dSNava kishore Manne
1103e2ebc05dSNava kishore Manne return ret;
1104e840deccSNava kishore Manne }
110556a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
1106e840deccSNava kishore Manne
1107e840deccSNava kishore Manne /**
1108e840deccSNava kishore Manne * zynqmp_pm_fpga_get_status - Read value from PCAP status register
1109e840deccSNava kishore Manne * @value: Value to read
1110e840deccSNava kishore Manne *
1111e840deccSNava kishore Manne * This function provides access to the pmufw to get the PCAP
1112e840deccSNava kishore Manne * status
1113e840deccSNava kishore Manne *
1114e840deccSNava kishore Manne * Return: Returns status, either success or error+reason
1115e840deccSNava kishore Manne */
zynqmp_pm_fpga_get_status(u32 * value)11164db8180fSRajan Vaja int zynqmp_pm_fpga_get_status(u32 *value)
1117e840deccSNava kishore Manne {
1118e840deccSNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT];
1119e840deccSNava kishore Manne int ret;
1120e840deccSNava kishore Manne
1121e840deccSNava kishore Manne if (!value)
1122e840deccSNava kishore Manne return -EINVAL;
1123e840deccSNava kishore Manne
1124f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, ret_payload, 0);
1125e840deccSNava kishore Manne *value = ret_payload[1];
1126e840deccSNava kishore Manne
1127e840deccSNava kishore Manne return ret;
1128e840deccSNava kishore Manne }
112956a9a806SNathan Chancellor EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
1130e840deccSNava kishore Manne
1131e840deccSNava kishore Manne /**
11328f118f61SNava kishore Manne * zynqmp_pm_fpga_get_config_status - Get the FPGA configuration status.
11338f118f61SNava kishore Manne * @value: Buffer to store FPGA configuration status.
11348f118f61SNava kishore Manne *
11358f118f61SNava kishore Manne * This function provides access to the pmufw to get the FPGA configuration
11368f118f61SNava kishore Manne * status
11378f118f61SNava kishore Manne *
11388f118f61SNava kishore Manne * Return: 0 on success, a negative value on error
11398f118f61SNava kishore Manne */
zynqmp_pm_fpga_get_config_status(u32 * value)11408f118f61SNava kishore Manne int zynqmp_pm_fpga_get_config_status(u32 *value)
11418f118f61SNava kishore Manne {
11428f118f61SNava kishore Manne u32 ret_payload[PAYLOAD_ARG_CNT];
11438f118f61SNava kishore Manne int ret;
11448f118f61SNava kishore Manne
11458f118f61SNava kishore Manne if (!value)
11468f118f61SNava kishore Manne return -EINVAL;
11478f118f61SNava kishore Manne
1148f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_FPGA_READ, ret_payload, 4,
11495abc1740SSiva Durga Prasad Paladugu XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, 0, 0,
1150f922b16aSJay Buddhabhatti XILINX_ZYNQMP_PM_FPGA_READ_CONFIG_REG);
11518f118f61SNava kishore Manne
11528f118f61SNava kishore Manne *value = ret_payload[1];
11538f118f61SNava kishore Manne
11548f118f61SNava kishore Manne return ret;
11558f118f61SNava kishore Manne }
11568f118f61SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_config_status);
11578f118f61SNava kishore Manne
11588f118f61SNava kishore Manne /**
1159fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_request - Request Pin from firmware
1160fa989ae7SSai Krishna Potthuri * @pin: Pin number to request
1161fa989ae7SSai Krishna Potthuri *
1162fa989ae7SSai Krishna Potthuri * This function requests pin from firmware.
1163fa989ae7SSai Krishna Potthuri *
1164fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason.
1165fa989ae7SSai Krishna Potthuri */
zynqmp_pm_pinctrl_request(const u32 pin)1166fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_request(const u32 pin)
1167fa989ae7SSai Krishna Potthuri {
1168f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, NULL, 1, pin);
1169fa989ae7SSai Krishna Potthuri }
1170fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request);
1171fa989ae7SSai Krishna Potthuri
1172fa989ae7SSai Krishna Potthuri /**
1173fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
1174fa989ae7SSai Krishna Potthuri * @pin: Pin number to release
1175fa989ae7SSai Krishna Potthuri *
1176fa989ae7SSai Krishna Potthuri * This function release pin from firmware.
1177fa989ae7SSai Krishna Potthuri *
1178fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason.
1179fa989ae7SSai Krishna Potthuri */
zynqmp_pm_pinctrl_release(const u32 pin)1180fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_release(const u32 pin)
1181fa989ae7SSai Krishna Potthuri {
1182f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, NULL, 1, pin);
1183fa989ae7SSai Krishna Potthuri }
1184fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release);
1185fa989ae7SSai Krishna Potthuri
1186fa989ae7SSai Krishna Potthuri /**
1187fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
1188fa989ae7SSai Krishna Potthuri * @pin: Pin number
1189fa989ae7SSai Krishna Potthuri * @id: Function ID to set
1190fa989ae7SSai Krishna Potthuri *
1191fa989ae7SSai Krishna Potthuri * This function sets requested function for the given pin.
1192fa989ae7SSai Krishna Potthuri *
1193fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason.
1194fa989ae7SSai Krishna Potthuri */
zynqmp_pm_pinctrl_set_function(const u32 pin,const u32 id)1195fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
1196fa989ae7SSai Krishna Potthuri {
1197f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, NULL, 2, pin, id);
1198fa989ae7SSai Krishna Potthuri }
1199fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function);
1200fa989ae7SSai Krishna Potthuri
1201fa989ae7SSai Krishna Potthuri /**
1202fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
1203fa989ae7SSai Krishna Potthuri * @pin: Pin number
1204fa989ae7SSai Krishna Potthuri * @param: Parameter to get
1205fa989ae7SSai Krishna Potthuri * @value: Buffer to store parameter value
1206fa989ae7SSai Krishna Potthuri *
1207fa989ae7SSai Krishna Potthuri * This function gets requested configuration parameter for the given pin.
1208fa989ae7SSai Krishna Potthuri *
1209fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason.
1210fa989ae7SSai Krishna Potthuri */
zynqmp_pm_pinctrl_get_config(const u32 pin,const u32 param,u32 * value)1211fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
1212fa989ae7SSai Krishna Potthuri u32 *value)
1213fa989ae7SSai Krishna Potthuri {
1214fa989ae7SSai Krishna Potthuri u32 ret_payload[PAYLOAD_ARG_CNT];
1215fa989ae7SSai Krishna Potthuri int ret;
1216fa989ae7SSai Krishna Potthuri
1217fa989ae7SSai Krishna Potthuri if (!value)
1218fa989ae7SSai Krishna Potthuri return -EINVAL;
1219fa989ae7SSai Krishna Potthuri
1220f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, ret_payload, 2, pin, param);
1221fa989ae7SSai Krishna Potthuri *value = ret_payload[1];
1222fa989ae7SSai Krishna Potthuri
1223fa989ae7SSai Krishna Potthuri return ret;
1224fa989ae7SSai Krishna Potthuri }
1225fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config);
1226fa989ae7SSai Krishna Potthuri
1227fa989ae7SSai Krishna Potthuri /**
1228fa989ae7SSai Krishna Potthuri * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
1229fa989ae7SSai Krishna Potthuri * @pin: Pin number
1230fa989ae7SSai Krishna Potthuri * @param: Parameter to set
1231fa989ae7SSai Krishna Potthuri * @value: Parameter value to set
1232fa989ae7SSai Krishna Potthuri *
1233fa989ae7SSai Krishna Potthuri * This function sets requested configuration parameter for the given pin.
1234fa989ae7SSai Krishna Potthuri *
1235fa989ae7SSai Krishna Potthuri * Return: Returns status, either success or error+reason.
1236fa989ae7SSai Krishna Potthuri */
zynqmp_pm_pinctrl_set_config(const u32 pin,const u32 param,u32 value)1237fa989ae7SSai Krishna Potthuri int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
1238fa989ae7SSai Krishna Potthuri u32 value)
1239fa989ae7SSai Krishna Potthuri {
1240aa5ed7b3SSai Krishna Potthuri int ret;
1241aa5ed7b3SSai Krishna Potthuri
1242aa5ed7b3SSai Krishna Potthuri if (pm_family_code == ZYNQMP_FAMILY_CODE &&
1243aa5ed7b3SSai Krishna Potthuri param == PM_PINCTRL_CONFIG_TRI_STATE) {
1244aa5ed7b3SSai Krishna Potthuri ret = zynqmp_pm_feature(PM_PINCTRL_CONFIG_PARAM_SET);
1245e8415a8aSRonak Jain if (ret < PM_PINCTRL_PARAM_SET_VERSION) {
1246e8415a8aSRonak Jain pr_warn("The requested pinctrl feature is not supported in the current firmware.\n"
1247e8415a8aSRonak Jain "Expected firmware version is 2023.1 and above for this feature to work.\r\n");
1248aa5ed7b3SSai Krishna Potthuri return -EOPNOTSUPP;
1249aa5ed7b3SSai Krishna Potthuri }
1250e8415a8aSRonak Jain }
1251aa5ed7b3SSai Krishna Potthuri
1252f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, NULL, 3, pin, param, value);
1253fa989ae7SSai Krishna Potthuri }
1254fa989ae7SSai Krishna Potthuri EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config);
1255fa989ae7SSai Krishna Potthuri
1256fa989ae7SSai Krishna Potthuri /**
125723c64d76SPiyush Mehta * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status
125823c64d76SPiyush Mehta * @ps_mode: Returned output value of ps_mode
125923c64d76SPiyush Mehta *
126023c64d76SPiyush Mehta * This API function is to be used for notify the power management controller
126123c64d76SPiyush Mehta * to read bootpin status.
126223c64d76SPiyush Mehta *
126323c64d76SPiyush Mehta * Return: status, either success or error+reason
126423c64d76SPiyush Mehta */
zynqmp_pm_bootmode_read(u32 * ps_mode)126523c64d76SPiyush Mehta unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode)
126623c64d76SPiyush Mehta {
126723c64d76SPiyush Mehta unsigned int ret;
126823c64d76SPiyush Mehta u32 ret_payload[PAYLOAD_ARG_CNT];
126923c64d76SPiyush Mehta
1270f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, ret_payload, 1, CRL_APB_BOOT_PIN_CTRL);
127123c64d76SPiyush Mehta
127223c64d76SPiyush Mehta *ps_mode = ret_payload[1];
127323c64d76SPiyush Mehta
127423c64d76SPiyush Mehta return ret;
127523c64d76SPiyush Mehta }
127623c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read);
127723c64d76SPiyush Mehta
127823c64d76SPiyush Mehta /**
127923c64d76SPiyush Mehta * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin
128023c64d76SPiyush Mehta * @ps_mode: Value to be written to the bootpin ctrl register
128123c64d76SPiyush Mehta *
128223c64d76SPiyush Mehta * This API function is to be used for notify the power management controller
128323c64d76SPiyush Mehta * to configure bootpin.
128423c64d76SPiyush Mehta *
128523c64d76SPiyush Mehta * Return: Returns status, either success or error+reason
128623c64d76SPiyush Mehta */
zynqmp_pm_bootmode_write(u32 ps_mode)128723c64d76SPiyush Mehta int zynqmp_pm_bootmode_write(u32 ps_mode)
128823c64d76SPiyush Mehta {
1289f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, NULL, 3, CRL_APB_BOOT_PIN_CTRL,
1290f922b16aSJay Buddhabhatti CRL_APB_BOOTPIN_CTRL_MASK, ps_mode);
129123c64d76SPiyush Mehta }
129223c64d76SPiyush Mehta EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write);
129323c64d76SPiyush Mehta
129423c64d76SPiyush Mehta /**
1295e178df31SJolly Shah * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
1296e178df31SJolly Shah * master has initialized its own power management
1297e178df31SJolly Shah *
1298332bee16SMichal Simek * Return: Returns status, either success or error+reason
1299332bee16SMichal Simek *
1300e178df31SJolly Shah * This API function is to be used for notify the power management controller
1301e178df31SJolly Shah * about the completed power management initialization.
1302e178df31SJolly Shah */
zynqmp_pm_init_finalize(void)130310086a4fSUlf Hansson static int zynqmp_pm_init_finalize(void)
1304e178df31SJolly Shah {
1305f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, NULL, 0);
1306e178df31SJolly Shah }
1307e178df31SJolly Shah
1308e178df31SJolly Shah /**
1309e178df31SJolly Shah * zynqmp_pm_set_suspend_mode() - Set system suspend mode
1310e178df31SJolly Shah * @mode: Mode to set for system suspend
1311e178df31SJolly Shah *
1312e178df31SJolly Shah * This API function is used to set mode of system suspend.
1313e178df31SJolly Shah *
1314e178df31SJolly Shah * Return: Returns status, either success or error+reason
1315e178df31SJolly Shah */
zynqmp_pm_set_suspend_mode(u32 mode)1316951d0a97SRajan Vaja int zynqmp_pm_set_suspend_mode(u32 mode)
1317e178df31SJolly Shah {
1318f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, NULL, 1, mode);
1319e178df31SJolly Shah }
1320951d0a97SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
1321e178df31SJolly Shah
1322c1986ac3SRajan Vaja /**
1323c1986ac3SRajan Vaja * zynqmp_pm_request_node() - Request a node with specific capabilities
1324c1986ac3SRajan Vaja * @node: Node ID of the slave
1325c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave
1326c1986ac3SRajan Vaja * @qos: Quality of service (not supported)
1327c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested
1328c1986ac3SRajan Vaja *
1329c1986ac3SRajan Vaja * This function is used by master to request particular node from firmware.
1330c1986ac3SRajan Vaja * Every master must request node before using it.
1331c1986ac3SRajan Vaja *
1332c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason
1333c1986ac3SRajan Vaja */
zynqmp_pm_request_node(const u32 node,const u32 capabilities,const u32 qos,const enum zynqmp_pm_request_ack ack)1334bf8b27edSRajan Vaja int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
1335bf8b27edSRajan Vaja const u32 qos, const enum zynqmp_pm_request_ack ack)
1336c1986ac3SRajan Vaja {
1337f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, NULL, 4, node, capabilities, qos, ack);
1338c1986ac3SRajan Vaja }
1339bf8b27edSRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
1340c1986ac3SRajan Vaja
1341c1986ac3SRajan Vaja /**
1342c1986ac3SRajan Vaja * zynqmp_pm_release_node() - Release a node
1343c1986ac3SRajan Vaja * @node: Node ID of the slave
1344c1986ac3SRajan Vaja *
1345c1986ac3SRajan Vaja * This function is used by master to inform firmware that master
1346c1986ac3SRajan Vaja * has released node. Once released, master must not use that node
1347c1986ac3SRajan Vaja * without re-request.
1348c1986ac3SRajan Vaja *
1349c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason
1350c1986ac3SRajan Vaja */
zynqmp_pm_release_node(const u32 node)135107fb1a46SRajan Vaja int zynqmp_pm_release_node(const u32 node)
1352c1986ac3SRajan Vaja {
1353f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, NULL, 1, node);
1354c1986ac3SRajan Vaja }
135507fb1a46SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
1356c1986ac3SRajan Vaja
1357c1986ac3SRajan Vaja /**
1358a5e56980SBen Levinsky * zynqmp_pm_get_rpu_mode() - Get RPU mode
1359a5e56980SBen Levinsky * @node_id: Node ID of the device
1360a5e56980SBen Levinsky * @rpu_mode: return by reference value
1361a5e56980SBen Levinsky * either split or lockstep
1362a5e56980SBen Levinsky *
1363a5e56980SBen Levinsky * Return: return 0 on success or error+reason.
1364a5e56980SBen Levinsky * if success, then rpu_mode will be set
1365a5e56980SBen Levinsky * to current rpu mode.
1366a5e56980SBen Levinsky */
zynqmp_pm_get_rpu_mode(u32 node_id,enum rpu_oper_mode * rpu_mode)1367a5e56980SBen Levinsky int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mode)
1368a5e56980SBen Levinsky {
1369a5e56980SBen Levinsky u32 ret_payload[PAYLOAD_ARG_CNT];
1370a5e56980SBen Levinsky int ret;
1371a5e56980SBen Levinsky
1372f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_IOCTL, ret_payload, 2, node_id, IOCTL_GET_RPU_OPER_MODE);
1373a5e56980SBen Levinsky
1374a5e56980SBen Levinsky /* only set rpu_mode if no error */
1375a5e56980SBen Levinsky if (ret == XST_PM_SUCCESS)
1376a5e56980SBen Levinsky *rpu_mode = ret_payload[0];
1377a5e56980SBen Levinsky
1378a5e56980SBen Levinsky return ret;
1379a5e56980SBen Levinsky }
1380a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_get_rpu_mode);
1381a5e56980SBen Levinsky
1382a5e56980SBen Levinsky /**
1383a5e56980SBen Levinsky * zynqmp_pm_set_rpu_mode() - Set RPU mode
1384a5e56980SBen Levinsky * @node_id: Node ID of the device
1385a5e56980SBen Levinsky * @rpu_mode: Argument 1 to requested IOCTL call. either split or lockstep
1386a5e56980SBen Levinsky *
1387a5e56980SBen Levinsky * This function is used to set RPU mode to split or
1388a5e56980SBen Levinsky * lockstep
1389a5e56980SBen Levinsky *
1390a5e56980SBen Levinsky * Return: Returns status, either success or error+reason
1391a5e56980SBen Levinsky */
zynqmp_pm_set_rpu_mode(u32 node_id,enum rpu_oper_mode rpu_mode)1392a5e56980SBen Levinsky int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode)
1393a5e56980SBen Levinsky {
1394f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, node_id, IOCTL_SET_RPU_OPER_MODE,
1395f922b16aSJay Buddhabhatti (u32)rpu_mode);
1396a5e56980SBen Levinsky }
1397a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_set_rpu_mode);
1398a5e56980SBen Levinsky
1399a5e56980SBen Levinsky /**
1400a5e56980SBen Levinsky * zynqmp_pm_set_tcm_config - configure TCM
1401a5e56980SBen Levinsky * @node_id: Firmware specific TCM subsystem ID
1402a5e56980SBen Levinsky * @tcm_mode: Argument 1 to requested IOCTL call
1403a5e56980SBen Levinsky * either PM_RPU_TCM_COMB or PM_RPU_TCM_SPLIT
1404a5e56980SBen Levinsky *
1405a5e56980SBen Levinsky * This function is used to set RPU mode to split or combined
1406a5e56980SBen Levinsky *
1407a5e56980SBen Levinsky * Return: status: 0 for success, else failure
1408a5e56980SBen Levinsky */
zynqmp_pm_set_tcm_config(u32 node_id,enum rpu_tcm_comb tcm_mode)1409a5e56980SBen Levinsky int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode)
1410a5e56980SBen Levinsky {
1411f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, node_id, IOCTL_TCM_COMB_CONFIG,
1412f922b16aSJay Buddhabhatti (u32)tcm_mode);
1413a5e56980SBen Levinsky }
1414a5e56980SBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_set_tcm_config);
1415a5e56980SBen Levinsky
1416a5e56980SBen Levinsky /**
1417da22a04fSBen Levinsky * zynqmp_pm_force_pwrdwn - PM call to request for another PU or subsystem to
1418da22a04fSBen Levinsky * be powered down forcefully
1419da22a04fSBen Levinsky * @node: Node ID of the targeted PU or subsystem
1420da22a04fSBen Levinsky * @ack: Flag to specify whether acknowledge is requested
1421da22a04fSBen Levinsky *
1422da22a04fSBen Levinsky * Return: status, either success or error+reason
1423da22a04fSBen Levinsky */
zynqmp_pm_force_pwrdwn(const u32 node,const enum zynqmp_pm_request_ack ack)1424da22a04fSBen Levinsky int zynqmp_pm_force_pwrdwn(const u32 node,
1425da22a04fSBen Levinsky const enum zynqmp_pm_request_ack ack)
1426da22a04fSBen Levinsky {
1427f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, NULL, 2, node, ack);
1428da22a04fSBen Levinsky }
1429da22a04fSBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_force_pwrdwn);
1430da22a04fSBen Levinsky
1431da22a04fSBen Levinsky /**
1432da22a04fSBen Levinsky * zynqmp_pm_request_wake - PM call to wake up selected master or subsystem
1433da22a04fSBen Levinsky * @node: Node ID of the master or subsystem
1434da22a04fSBen Levinsky * @set_addr: Specifies whether the address argument is relevant
1435da22a04fSBen Levinsky * @address: Address from which to resume when woken up
1436da22a04fSBen Levinsky * @ack: Flag to specify whether acknowledge requested
1437da22a04fSBen Levinsky *
1438da22a04fSBen Levinsky * Return: status, either success or error+reason
1439da22a04fSBen Levinsky */
zynqmp_pm_request_wake(const u32 node,const bool set_addr,const u64 address,const enum zynqmp_pm_request_ack ack)1440da22a04fSBen Levinsky int zynqmp_pm_request_wake(const u32 node,
1441da22a04fSBen Levinsky const bool set_addr,
1442da22a04fSBen Levinsky const u64 address,
1443da22a04fSBen Levinsky const enum zynqmp_pm_request_ack ack)
1444da22a04fSBen Levinsky {
1445da22a04fSBen Levinsky /* set_addr flag is encoded into 1st bit of address */
1446f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_REQUEST_WAKEUP, NULL, 4, node, address | set_addr,
1447f922b16aSJay Buddhabhatti address >> 32, ack);
1448da22a04fSBen Levinsky }
1449da22a04fSBen Levinsky EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake);
1450da22a04fSBen Levinsky
1451da22a04fSBen Levinsky /**
1452c1986ac3SRajan Vaja * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
1453c1986ac3SRajan Vaja * @node: Node ID of the slave
1454c1986ac3SRajan Vaja * @capabilities: Requested capabilities of the slave
1455c1986ac3SRajan Vaja * @qos: Quality of service (not supported)
1456c1986ac3SRajan Vaja * @ack: Flag to specify whether acknowledge is requested
1457c1986ac3SRajan Vaja *
1458c1986ac3SRajan Vaja * This API function is to be used for slaves a PU already has requested
1459c1986ac3SRajan Vaja * to change its capabilities.
1460c1986ac3SRajan Vaja *
1461c1986ac3SRajan Vaja * Return: Returns status, either success or error+reason
1462c1986ac3SRajan Vaja */
zynqmp_pm_set_requirement(const u32 node,const u32 capabilities,const u32 qos,const enum zynqmp_pm_request_ack ack)1463cbbbda71SRajan Vaja int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
1464c1986ac3SRajan Vaja const u32 qos,
1465c1986ac3SRajan Vaja const enum zynqmp_pm_request_ack ack)
1466c1986ac3SRajan Vaja {
1467f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, NULL, 4, node, capabilities, qos, ack);
1468c1986ac3SRajan Vaja }
1469cbbbda71SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
1470c1986ac3SRajan Vaja
1471057a0fb6SKalyani Akula /**
14722b9fc773SNava kishore Manne * zynqmp_pm_load_pdi - Load and process PDI
14732b9fc773SNava kishore Manne * @src: Source device where PDI is located
14742b9fc773SNava kishore Manne * @address: PDI src address
14752b9fc773SNava kishore Manne *
14762b9fc773SNava kishore Manne * This function provides support to load PDI from linux
14772b9fc773SNava kishore Manne *
14782b9fc773SNava kishore Manne * Return: Returns status, either success or error+reason
14792b9fc773SNava kishore Manne */
zynqmp_pm_load_pdi(const u32 src,const u64 address)14802b9fc773SNava kishore Manne int zynqmp_pm_load_pdi(const u32 src, const u64 address)
14812b9fc773SNava kishore Manne {
1482f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_LOAD_PDI, NULL, 3, src, lower_32_bits(address),
1483f922b16aSJay Buddhabhatti upper_32_bits(address));
14842b9fc773SNava kishore Manne }
14852b9fc773SNava kishore Manne EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi);
14862b9fc773SNava kishore Manne
14872b9fc773SNava kishore Manne /**
14882a8faf8dSMichal Simek * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
1489057a0fb6SKalyani Akula * AES-GCM core.
1490057a0fb6SKalyani Akula * @address: Address of the AesParams structure.
1491057a0fb6SKalyani Akula * @out: Returned output value
1492057a0fb6SKalyani Akula *
1493057a0fb6SKalyani Akula * Return: Returns status, either success or error code.
1494057a0fb6SKalyani Akula */
zynqmp_pm_aes_engine(const u64 address,u32 * out)1495bc86f9c5SRajan Vaja int zynqmp_pm_aes_engine(const u64 address, u32 *out)
1496057a0fb6SKalyani Akula {
1497057a0fb6SKalyani Akula u32 ret_payload[PAYLOAD_ARG_CNT];
1498057a0fb6SKalyani Akula int ret;
1499057a0fb6SKalyani Akula
1500057a0fb6SKalyani Akula if (!out)
1501057a0fb6SKalyani Akula return -EINVAL;
1502057a0fb6SKalyani Akula
1503f922b16aSJay Buddhabhatti ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, ret_payload, 2, upper_32_bits(address),
1504f922b16aSJay Buddhabhatti lower_32_bits(address));
1505057a0fb6SKalyani Akula *out = ret_payload[1];
1506057a0fb6SKalyani Akula
1507057a0fb6SKalyani Akula return ret;
1508057a0fb6SKalyani Akula }
1509bc86f9c5SRajan Vaja EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
1510057a0fb6SKalyani Akula
1511fdd2ed88SRajan Vaja /**
1512e34b9430SPraveen Teja Kundanala * zynqmp_pm_efuse_access - Provides access to efuse memory.
1513e34b9430SPraveen Teja Kundanala * @address: Address of the efuse params structure
1514e34b9430SPraveen Teja Kundanala * @out: Returned output value
1515e34b9430SPraveen Teja Kundanala *
1516e34b9430SPraveen Teja Kundanala * Return: Returns status, either success or error code.
1517e34b9430SPraveen Teja Kundanala */
zynqmp_pm_efuse_access(const u64 address,u32 * out)1518e34b9430SPraveen Teja Kundanala int zynqmp_pm_efuse_access(const u64 address, u32 *out)
1519e34b9430SPraveen Teja Kundanala {
1520e34b9430SPraveen Teja Kundanala u32 ret_payload[PAYLOAD_ARG_CNT];
1521e34b9430SPraveen Teja Kundanala int ret;
1522e34b9430SPraveen Teja Kundanala
1523e34b9430SPraveen Teja Kundanala if (!out)
1524e34b9430SPraveen Teja Kundanala return -EINVAL;
1525e34b9430SPraveen Teja Kundanala
1526e34b9430SPraveen Teja Kundanala ret = zynqmp_pm_invoke_fn(PM_EFUSE_ACCESS, ret_payload, 2,
1527e34b9430SPraveen Teja Kundanala upper_32_bits(address),
1528e34b9430SPraveen Teja Kundanala lower_32_bits(address));
1529e34b9430SPraveen Teja Kundanala *out = ret_payload[1];
1530e34b9430SPraveen Teja Kundanala
1531e34b9430SPraveen Teja Kundanala return ret;
1532e34b9430SPraveen Teja Kundanala }
1533e34b9430SPraveen Teja Kundanala EXPORT_SYMBOL_GPL(zynqmp_pm_efuse_access);
1534e34b9430SPraveen Teja Kundanala
1535e34b9430SPraveen Teja Kundanala /**
153680f940efSHarsha * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
153780f940efSHarsha * @address: Address of the data/ Address of output buffer where
153880f940efSHarsha * hash should be stored.
153980f940efSHarsha * @size: Size of the data.
154080f940efSHarsha * @flags:
154180f940efSHarsha * BIT(0) - for initializing csudma driver and SHA3(Here address
154280f940efSHarsha * and size inputs can be NULL).
154380f940efSHarsha * BIT(1) - to call Sha3_Update API which can be called multiple
154480f940efSHarsha * times when data is not contiguous.
154580f940efSHarsha * BIT(2) - to get final hash of the whole updated data.
154680f940efSHarsha * Hash will be overwritten at provided address with
154780f940efSHarsha * 48 bytes.
154880f940efSHarsha *
154980f940efSHarsha * Return: Returns status, either success or error code.
155080f940efSHarsha */
zynqmp_pm_sha_hash(const u64 address,const u32 size,const u32 flags)155180f940efSHarsha int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags)
155280f940efSHarsha {
155380f940efSHarsha u32 lower_addr = lower_32_bits(address);
155480f940efSHarsha u32 upper_addr = upper_32_bits(address);
155580f940efSHarsha
1556f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_SECURE_SHA, NULL, 4, upper_addr, lower_addr, size, flags);
155780f940efSHarsha }
155880f940efSHarsha EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash);
155980f940efSHarsha
156080f940efSHarsha /**
15611881eadbSAbhyuday Godhasara * zynqmp_pm_register_notifier() - PM API for register a subsystem
15621881eadbSAbhyuday Godhasara * to be notified about specific
15631881eadbSAbhyuday Godhasara * event/error.
15641881eadbSAbhyuday Godhasara * @node: Node ID to which the event is related.
15651881eadbSAbhyuday Godhasara * @event: Event Mask of Error events for which wants to get notified.
15661881eadbSAbhyuday Godhasara * @wake: Wake subsystem upon capturing the event if value 1
15671881eadbSAbhyuday Godhasara * @enable: Enable the registration for value 1, disable for value 0
15681881eadbSAbhyuday Godhasara *
15691881eadbSAbhyuday Godhasara * This function is used to register/un-register for particular node-event
15701881eadbSAbhyuday Godhasara * combination in firmware.
15711881eadbSAbhyuday Godhasara *
15721881eadbSAbhyuday Godhasara * Return: Returns status, either success or error+reason
15731881eadbSAbhyuday Godhasara */
15741881eadbSAbhyuday Godhasara
zynqmp_pm_register_notifier(const u32 node,const u32 event,const u32 wake,const u32 enable)15751881eadbSAbhyuday Godhasara int zynqmp_pm_register_notifier(const u32 node, const u32 event,
15761881eadbSAbhyuday Godhasara const u32 wake, const u32 enable)
15771881eadbSAbhyuday Godhasara {
1578f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, NULL, 4, node, event, wake, enable);
15791881eadbSAbhyuday Godhasara }
15801881eadbSAbhyuday Godhasara EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier);
15811881eadbSAbhyuday Godhasara
15821881eadbSAbhyuday Godhasara /**
1583fdd2ed88SRajan Vaja * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
1584fdd2ed88SRajan Vaja * @type: Shutdown or restart? 0 for shutdown, 1 for restart
1585fdd2ed88SRajan Vaja * @subtype: Specifies which system should be restarted or shut down
1586fdd2ed88SRajan Vaja *
1587fdd2ed88SRajan Vaja * Return: Returns status, either success or error+reason
1588fdd2ed88SRajan Vaja */
zynqmp_pm_system_shutdown(const u32 type,const u32 subtype)1589fdd2ed88SRajan Vaja int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
1590fdd2ed88SRajan Vaja {
1591f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, NULL, 2, type, subtype);
1592fdd2ed88SRajan Vaja }
1593fdd2ed88SRajan Vaja
1594b3ae24c4SRajan Vaja /**
1595f1d0821bSRonak Jain * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config
1596f1d0821bSRonak Jain * @id: The config ID of the feature to be configured
1597f1d0821bSRonak Jain * @value: The config value of the feature to be configured
1598f1d0821bSRonak Jain *
1599f1d0821bSRonak Jain * Return: Returns 0 on success or error value on failure.
1600f1d0821bSRonak Jain */
zynqmp_pm_set_feature_config(enum pm_feature_config_id id,u32 value)1601f1d0821bSRonak Jain int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value)
1602f1d0821bSRonak Jain {
1603f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_FEATURE_CONFIG, id, value);
1604f1d0821bSRonak Jain }
1605f1d0821bSRonak Jain
1606f1d0821bSRonak Jain /**
1607f1d0821bSRonak Jain * zynqmp_pm_get_feature_config - PM call to get value of configured feature
1608f1d0821bSRonak Jain * @id: The config id of the feature to be queried
1609f1d0821bSRonak Jain * @payload: Returned value array
1610f1d0821bSRonak Jain *
1611f1d0821bSRonak Jain * Return: Returns 0 on success or error value on failure.
1612f1d0821bSRonak Jain */
zynqmp_pm_get_feature_config(enum pm_feature_config_id id,u32 * payload)1613f1d0821bSRonak Jain int zynqmp_pm_get_feature_config(enum pm_feature_config_id id,
1614f1d0821bSRonak Jain u32 *payload)
1615f1d0821bSRonak Jain {
1616f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, payload, 3, 0, IOCTL_GET_FEATURE_CONFIG, id);
1617f1d0821bSRonak Jain }
1618f1d0821bSRonak Jain
1619f1d0821bSRonak Jain /**
1620256dea91SRonak Jain * zynqmp_pm_set_sd_config - PM call to set value of SD config registers
1621256dea91SRonak Jain * @node: SD node ID
1622256dea91SRonak Jain * @config: The config type of SD registers
1623256dea91SRonak Jain * @value: Value to be set
1624256dea91SRonak Jain *
1625256dea91SRonak Jain * Return: Returns 0 on success or error value on failure.
1626256dea91SRonak Jain */
zynqmp_pm_set_sd_config(u32 node,enum pm_sd_config_type config,u32 value)1627256dea91SRonak Jain int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value)
1628256dea91SRonak Jain {
1629f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, node, IOCTL_SET_SD_CONFIG, config, value);
1630256dea91SRonak Jain }
1631256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_config);
1632256dea91SRonak Jain
1633256dea91SRonak Jain /**
1634256dea91SRonak Jain * zynqmp_pm_set_gem_config - PM call to set value of GEM config registers
1635256dea91SRonak Jain * @node: GEM node ID
1636256dea91SRonak Jain * @config: The config type of GEM registers
1637256dea91SRonak Jain * @value: Value to be set
1638256dea91SRonak Jain *
1639256dea91SRonak Jain * Return: Returns 0 on success or error value on failure.
1640256dea91SRonak Jain */
zynqmp_pm_set_gem_config(u32 node,enum pm_gem_config_type config,u32 value)1641256dea91SRonak Jain int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
1642256dea91SRonak Jain u32 value)
1643256dea91SRonak Jain {
1644f922b16aSJay Buddhabhatti return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, node, IOCTL_SET_GEM_CONFIG, config, value);
1645256dea91SRonak Jain }
1646256dea91SRonak Jain EXPORT_SYMBOL_GPL(zynqmp_pm_set_gem_config);
1647256dea91SRonak Jain
1648256dea91SRonak Jain /**
1649b3ae24c4SRajan Vaja * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
1650b3ae24c4SRajan Vaja * @subtype: Shutdown subtype
1651b3ae24c4SRajan Vaja * @name: Matching string for scope argument
1652b3ae24c4SRajan Vaja *
1653b3ae24c4SRajan Vaja * This struct encapsulates mapping between shutdown scope ID and string.
1654b3ae24c4SRajan Vaja */
1655b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope {
1656b3ae24c4SRajan Vaja const enum zynqmp_pm_shutdown_subtype subtype;
1657b3ae24c4SRajan Vaja const char *name;
1658b3ae24c4SRajan Vaja };
1659b3ae24c4SRajan Vaja
1660b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
1661b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
1662b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
1663b3ae24c4SRajan Vaja .name = "subsystem",
1664b3ae24c4SRajan Vaja },
1665b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
1666b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
1667b3ae24c4SRajan Vaja .name = "ps_only",
1668b3ae24c4SRajan Vaja },
1669b3ae24c4SRajan Vaja [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
1670b3ae24c4SRajan Vaja .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
1671b3ae24c4SRajan Vaja .name = "system",
1672b3ae24c4SRajan Vaja },
1673b3ae24c4SRajan Vaja };
1674b3ae24c4SRajan Vaja
1675b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope *selected_scope =
1676b3ae24c4SRajan Vaja &shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
1677b3ae24c4SRajan Vaja
1678b3ae24c4SRajan Vaja /**
1679b3ae24c4SRajan Vaja * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
1680b3ae24c4SRajan Vaja * @scope_string: Shutdown scope string
1681b3ae24c4SRajan Vaja *
1682b3ae24c4SRajan Vaja * Return: Return pointer to matching shutdown scope struct from
1683b3ae24c4SRajan Vaja * array of available options in system if string is valid,
1684b3ae24c4SRajan Vaja * otherwise returns NULL.
1685b3ae24c4SRajan Vaja */
1686b3ae24c4SRajan Vaja static struct zynqmp_pm_shutdown_scope*
zynqmp_pm_is_shutdown_scope_valid(const char * scope_string)1687b3ae24c4SRajan Vaja zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
1688b3ae24c4SRajan Vaja {
1689b3ae24c4SRajan Vaja int count;
1690b3ae24c4SRajan Vaja
1691b3ae24c4SRajan Vaja for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
1692b3ae24c4SRajan Vaja if (sysfs_streq(scope_string, shutdown_scopes[count].name))
1693b3ae24c4SRajan Vaja return &shutdown_scopes[count];
1694b3ae24c4SRajan Vaja
1695b3ae24c4SRajan Vaja return NULL;
1696b3ae24c4SRajan Vaja }
1697b3ae24c4SRajan Vaja
shutdown_scope_show(struct device * device,struct device_attribute * attr,char * buf)1698b3ae24c4SRajan Vaja static ssize_t shutdown_scope_show(struct device *device,
1699b3ae24c4SRajan Vaja struct device_attribute *attr,
1700b3ae24c4SRajan Vaja char *buf)
1701b3ae24c4SRajan Vaja {
1702b3ae24c4SRajan Vaja int i;
1703b3ae24c4SRajan Vaja
1704b3ae24c4SRajan Vaja for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
1705b3ae24c4SRajan Vaja if (&shutdown_scopes[i] == selected_scope) {
1706b3ae24c4SRajan Vaja strcat(buf, "[");
1707b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name);
1708b3ae24c4SRajan Vaja strcat(buf, "]");
1709b3ae24c4SRajan Vaja } else {
1710b3ae24c4SRajan Vaja strcat(buf, shutdown_scopes[i].name);
1711b3ae24c4SRajan Vaja }
1712b3ae24c4SRajan Vaja strcat(buf, " ");
1713b3ae24c4SRajan Vaja }
1714b3ae24c4SRajan Vaja strcat(buf, "\n");
1715b3ae24c4SRajan Vaja
1716b3ae24c4SRajan Vaja return strlen(buf);
1717b3ae24c4SRajan Vaja }
1718b3ae24c4SRajan Vaja
shutdown_scope_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)1719b3ae24c4SRajan Vaja static ssize_t shutdown_scope_store(struct device *device,
1720b3ae24c4SRajan Vaja struct device_attribute *attr,
1721b3ae24c4SRajan Vaja const char *buf, size_t count)
1722b3ae24c4SRajan Vaja {
1723b3ae24c4SRajan Vaja int ret;
1724b3ae24c4SRajan Vaja struct zynqmp_pm_shutdown_scope *scope;
1725b3ae24c4SRajan Vaja
1726b3ae24c4SRajan Vaja scope = zynqmp_pm_is_shutdown_scope_valid(buf);
1727b3ae24c4SRajan Vaja if (!scope)
1728b3ae24c4SRajan Vaja return -EINVAL;
1729b3ae24c4SRajan Vaja
1730b3ae24c4SRajan Vaja ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
1731b3ae24c4SRajan Vaja scope->subtype);
1732b3ae24c4SRajan Vaja if (ret) {
1733b3ae24c4SRajan Vaja pr_err("unable to set shutdown scope %s\n", buf);
1734b3ae24c4SRajan Vaja return ret;
1735b3ae24c4SRajan Vaja }
1736b3ae24c4SRajan Vaja
1737b3ae24c4SRajan Vaja selected_scope = scope;
1738b3ae24c4SRajan Vaja
1739b3ae24c4SRajan Vaja return count;
1740b3ae24c4SRajan Vaja }
1741b3ae24c4SRajan Vaja
1742b3ae24c4SRajan Vaja static DEVICE_ATTR_RW(shutdown_scope);
1743b3ae24c4SRajan Vaja
health_status_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)1744a2cc220aSRajan Vaja static ssize_t health_status_store(struct device *device,
1745a2cc220aSRajan Vaja struct device_attribute *attr,
1746a2cc220aSRajan Vaja const char *buf, size_t count)
1747a2cc220aSRajan Vaja {
1748a2cc220aSRajan Vaja int ret;
1749a2cc220aSRajan Vaja unsigned int value;
1750a2cc220aSRajan Vaja
1751a2cc220aSRajan Vaja ret = kstrtouint(buf, 10, &value);
1752a2cc220aSRajan Vaja if (ret)
1753a2cc220aSRajan Vaja return ret;
1754a2cc220aSRajan Vaja
1755a2cc220aSRajan Vaja ret = zynqmp_pm_set_boot_health_status(value);
1756a2cc220aSRajan Vaja if (ret) {
1757a2cc220aSRajan Vaja dev_err(device, "unable to set healthy bit value to %u\n",
1758a2cc220aSRajan Vaja value);
1759a2cc220aSRajan Vaja return ret;
1760a2cc220aSRajan Vaja }
1761a2cc220aSRajan Vaja
1762a2cc220aSRajan Vaja return count;
1763a2cc220aSRajan Vaja }
1764a2cc220aSRajan Vaja
1765a2cc220aSRajan Vaja static DEVICE_ATTR_WO(health_status);
1766a2cc220aSRajan Vaja
ggs_show(struct device * device,struct device_attribute * attr,char * buf,u32 reg)1767ae5c961dSRajan Vaja static ssize_t ggs_show(struct device *device,
1768ae5c961dSRajan Vaja struct device_attribute *attr,
1769ae5c961dSRajan Vaja char *buf,
1770ae5c961dSRajan Vaja u32 reg)
1771ae5c961dSRajan Vaja {
1772ae5c961dSRajan Vaja int ret;
1773ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT];
1774ae5c961dSRajan Vaja
1775ae5c961dSRajan Vaja ret = zynqmp_pm_read_ggs(reg, ret_payload);
1776ae5c961dSRajan Vaja if (ret)
1777ae5c961dSRajan Vaja return ret;
1778ae5c961dSRajan Vaja
1779ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]);
1780ae5c961dSRajan Vaja }
1781ae5c961dSRajan Vaja
ggs_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count,u32 reg)1782ae5c961dSRajan Vaja static ssize_t ggs_store(struct device *device,
1783ae5c961dSRajan Vaja struct device_attribute *attr,
1784ae5c961dSRajan Vaja const char *buf, size_t count,
1785ae5c961dSRajan Vaja u32 reg)
1786ae5c961dSRajan Vaja {
1787ae5c961dSRajan Vaja long value;
1788ae5c961dSRajan Vaja int ret;
1789ae5c961dSRajan Vaja
1790ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS)
1791ae5c961dSRajan Vaja return -EINVAL;
1792ae5c961dSRajan Vaja
1793ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value);
1794ae5c961dSRajan Vaja if (ret) {
1795ae5c961dSRajan Vaja count = -EFAULT;
1796ae5c961dSRajan Vaja goto err;
1797ae5c961dSRajan Vaja }
1798ae5c961dSRajan Vaja
1799ae5c961dSRajan Vaja ret = zynqmp_pm_write_ggs(reg, value);
1800ae5c961dSRajan Vaja if (ret)
1801ae5c961dSRajan Vaja count = -EFAULT;
1802ae5c961dSRajan Vaja err:
1803ae5c961dSRajan Vaja return count;
1804ae5c961dSRajan Vaja }
1805ae5c961dSRajan Vaja
1806ae5c961dSRajan Vaja /* GGS register show functions */
1807ae5c961dSRajan Vaja #define GGS0_SHOW(N) \
1808ae5c961dSRajan Vaja ssize_t ggs##N##_show(struct device *device, \
1809ae5c961dSRajan Vaja struct device_attribute *attr, \
1810ae5c961dSRajan Vaja char *buf) \
1811ae5c961dSRajan Vaja { \
1812ae5c961dSRajan Vaja return ggs_show(device, attr, buf, N); \
1813ae5c961dSRajan Vaja }
1814ae5c961dSRajan Vaja
1815ae5c961dSRajan Vaja static GGS0_SHOW(0);
1816ae5c961dSRajan Vaja static GGS0_SHOW(1);
1817ae5c961dSRajan Vaja static GGS0_SHOW(2);
1818ae5c961dSRajan Vaja static GGS0_SHOW(3);
1819ae5c961dSRajan Vaja
1820ae5c961dSRajan Vaja /* GGS register store function */
1821ae5c961dSRajan Vaja #define GGS0_STORE(N) \
1822ae5c961dSRajan Vaja ssize_t ggs##N##_store(struct device *device, \
1823ae5c961dSRajan Vaja struct device_attribute *attr, \
1824ae5c961dSRajan Vaja const char *buf, \
1825ae5c961dSRajan Vaja size_t count) \
1826ae5c961dSRajan Vaja { \
1827ae5c961dSRajan Vaja return ggs_store(device, attr, buf, count, N); \
1828ae5c961dSRajan Vaja }
1829ae5c961dSRajan Vaja
1830ae5c961dSRajan Vaja static GGS0_STORE(0);
1831ae5c961dSRajan Vaja static GGS0_STORE(1);
1832ae5c961dSRajan Vaja static GGS0_STORE(2);
1833ae5c961dSRajan Vaja static GGS0_STORE(3);
1834ae5c961dSRajan Vaja
pggs_show(struct device * device,struct device_attribute * attr,char * buf,u32 reg)1835ae5c961dSRajan Vaja static ssize_t pggs_show(struct device *device,
1836ae5c961dSRajan Vaja struct device_attribute *attr,
1837ae5c961dSRajan Vaja char *buf,
1838ae5c961dSRajan Vaja u32 reg)
1839ae5c961dSRajan Vaja {
1840ae5c961dSRajan Vaja int ret;
1841ae5c961dSRajan Vaja u32 ret_payload[PAYLOAD_ARG_CNT];
1842ae5c961dSRajan Vaja
1843ae5c961dSRajan Vaja ret = zynqmp_pm_read_pggs(reg, ret_payload);
1844ae5c961dSRajan Vaja if (ret)
1845ae5c961dSRajan Vaja return ret;
1846ae5c961dSRajan Vaja
1847ae5c961dSRajan Vaja return sprintf(buf, "0x%x\n", ret_payload[1]);
1848ae5c961dSRajan Vaja }
1849ae5c961dSRajan Vaja
pggs_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count,u32 reg)1850ae5c961dSRajan Vaja static ssize_t pggs_store(struct device *device,
1851ae5c961dSRajan Vaja struct device_attribute *attr,
1852ae5c961dSRajan Vaja const char *buf, size_t count,
1853ae5c961dSRajan Vaja u32 reg)
1854ae5c961dSRajan Vaja {
1855ae5c961dSRajan Vaja long value;
1856ae5c961dSRajan Vaja int ret;
1857ae5c961dSRajan Vaja
1858ae5c961dSRajan Vaja if (reg >= GSS_NUM_REGS)
1859ae5c961dSRajan Vaja return -EINVAL;
1860ae5c961dSRajan Vaja
1861ae5c961dSRajan Vaja ret = kstrtol(buf, 16, &value);
1862ae5c961dSRajan Vaja if (ret) {
1863ae5c961dSRajan Vaja count = -EFAULT;
1864ae5c961dSRajan Vaja goto err;
1865ae5c961dSRajan Vaja }
1866ae5c961dSRajan Vaja
1867ae5c961dSRajan Vaja ret = zynqmp_pm_write_pggs(reg, value);
1868ae5c961dSRajan Vaja if (ret)
1869ae5c961dSRajan Vaja count = -EFAULT;
1870ae5c961dSRajan Vaja
1871ae5c961dSRajan Vaja err:
1872ae5c961dSRajan Vaja return count;
1873ae5c961dSRajan Vaja }
1874ae5c961dSRajan Vaja
1875ae5c961dSRajan Vaja #define PGGS0_SHOW(N) \
1876ae5c961dSRajan Vaja ssize_t pggs##N##_show(struct device *device, \
1877ae5c961dSRajan Vaja struct device_attribute *attr, \
1878ae5c961dSRajan Vaja char *buf) \
1879ae5c961dSRajan Vaja { \
1880ae5c961dSRajan Vaja return pggs_show(device, attr, buf, N); \
1881ae5c961dSRajan Vaja }
1882ae5c961dSRajan Vaja
1883ae5c961dSRajan Vaja #define PGGS0_STORE(N) \
1884ae5c961dSRajan Vaja ssize_t pggs##N##_store(struct device *device, \
1885ae5c961dSRajan Vaja struct device_attribute *attr, \
1886ae5c961dSRajan Vaja const char *buf, \
1887ae5c961dSRajan Vaja size_t count) \
1888ae5c961dSRajan Vaja { \
1889ae5c961dSRajan Vaja return pggs_store(device, attr, buf, count, N); \
1890ae5c961dSRajan Vaja }
1891ae5c961dSRajan Vaja
1892ae5c961dSRajan Vaja /* PGGS register show functions */
1893ae5c961dSRajan Vaja static PGGS0_SHOW(0);
1894ae5c961dSRajan Vaja static PGGS0_SHOW(1);
1895ae5c961dSRajan Vaja static PGGS0_SHOW(2);
1896ae5c961dSRajan Vaja static PGGS0_SHOW(3);
1897ae5c961dSRajan Vaja
1898ae5c961dSRajan Vaja /* PGGS register store functions */
1899ae5c961dSRajan Vaja static PGGS0_STORE(0);
1900ae5c961dSRajan Vaja static PGGS0_STORE(1);
1901ae5c961dSRajan Vaja static PGGS0_STORE(2);
1902ae5c961dSRajan Vaja static PGGS0_STORE(3);
1903ae5c961dSRajan Vaja
1904ae5c961dSRajan Vaja /* GGS register attributes */
1905ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs0);
1906ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs1);
1907ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs2);
1908ae5c961dSRajan Vaja static DEVICE_ATTR_RW(ggs3);
1909ae5c961dSRajan Vaja
1910ae5c961dSRajan Vaja /* PGGS register attributes */
1911ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs0);
1912ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs1);
1913ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs2);
1914ae5c961dSRajan Vaja static DEVICE_ATTR_RW(pggs3);
1915ae5c961dSRajan Vaja
feature_config_id_show(struct device * device,struct device_attribute * attr,char * buf)19162c5d8f7cSRonak Jain static ssize_t feature_config_id_show(struct device *device,
19172c5d8f7cSRonak Jain struct device_attribute *attr,
19182c5d8f7cSRonak Jain char *buf)
19192c5d8f7cSRonak Jain {
19202c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
19212c5d8f7cSRonak Jain
19222c5d8f7cSRonak Jain return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id);
19232c5d8f7cSRonak Jain }
19242c5d8f7cSRonak Jain
feature_config_id_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)19252c5d8f7cSRonak Jain static ssize_t feature_config_id_store(struct device *device,
19262c5d8f7cSRonak Jain struct device_attribute *attr,
19272c5d8f7cSRonak Jain const char *buf, size_t count)
19282c5d8f7cSRonak Jain {
19292c5d8f7cSRonak Jain u32 config_id;
19302c5d8f7cSRonak Jain int ret;
19312c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
19322c5d8f7cSRonak Jain
19332c5d8f7cSRonak Jain if (!buf)
19342c5d8f7cSRonak Jain return -EINVAL;
19352c5d8f7cSRonak Jain
19362c5d8f7cSRonak Jain ret = kstrtou32(buf, 10, &config_id);
19372c5d8f7cSRonak Jain if (ret)
19382c5d8f7cSRonak Jain return ret;
19392c5d8f7cSRonak Jain
19402c5d8f7cSRonak Jain devinfo->feature_conf_id = config_id;
19412c5d8f7cSRonak Jain
19422c5d8f7cSRonak Jain return count;
19432c5d8f7cSRonak Jain }
19442c5d8f7cSRonak Jain
19452c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_id);
19462c5d8f7cSRonak Jain
feature_config_value_show(struct device * device,struct device_attribute * attr,char * buf)19472c5d8f7cSRonak Jain static ssize_t feature_config_value_show(struct device *device,
19482c5d8f7cSRonak Jain struct device_attribute *attr,
19492c5d8f7cSRonak Jain char *buf)
19502c5d8f7cSRonak Jain {
19512c5d8f7cSRonak Jain int ret;
19522c5d8f7cSRonak Jain u32 ret_payload[PAYLOAD_ARG_CNT];
19532c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
19542c5d8f7cSRonak Jain
19552c5d8f7cSRonak Jain ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id,
19562c5d8f7cSRonak Jain ret_payload);
19572c5d8f7cSRonak Jain if (ret)
19582c5d8f7cSRonak Jain return ret;
19592c5d8f7cSRonak Jain
19602c5d8f7cSRonak Jain return sysfs_emit(buf, "%d\n", ret_payload[1]);
19612c5d8f7cSRonak Jain }
19622c5d8f7cSRonak Jain
feature_config_value_store(struct device * device,struct device_attribute * attr,const char * buf,size_t count)19632c5d8f7cSRonak Jain static ssize_t feature_config_value_store(struct device *device,
19642c5d8f7cSRonak Jain struct device_attribute *attr,
19652c5d8f7cSRonak Jain const char *buf, size_t count)
19662c5d8f7cSRonak Jain {
19672c5d8f7cSRonak Jain u32 value;
19682c5d8f7cSRonak Jain int ret;
19692c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
19702c5d8f7cSRonak Jain
19712c5d8f7cSRonak Jain if (!buf)
19722c5d8f7cSRonak Jain return -EINVAL;
19732c5d8f7cSRonak Jain
19742c5d8f7cSRonak Jain ret = kstrtou32(buf, 10, &value);
19752c5d8f7cSRonak Jain if (ret)
19762c5d8f7cSRonak Jain return ret;
19772c5d8f7cSRonak Jain
19782c5d8f7cSRonak Jain ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id,
19792c5d8f7cSRonak Jain value);
19802c5d8f7cSRonak Jain if (ret)
19812c5d8f7cSRonak Jain return ret;
19822c5d8f7cSRonak Jain
19832c5d8f7cSRonak Jain return count;
19842c5d8f7cSRonak Jain }
19852c5d8f7cSRonak Jain
19862c5d8f7cSRonak Jain static DEVICE_ATTR_RW(feature_config_value);
19872c5d8f7cSRonak Jain
1988ae5c961dSRajan Vaja static struct attribute *zynqmp_firmware_attrs[] = {
1989ae5c961dSRajan Vaja &dev_attr_ggs0.attr,
1990ae5c961dSRajan Vaja &dev_attr_ggs1.attr,
1991ae5c961dSRajan Vaja &dev_attr_ggs2.attr,
1992ae5c961dSRajan Vaja &dev_attr_ggs3.attr,
1993ae5c961dSRajan Vaja &dev_attr_pggs0.attr,
1994ae5c961dSRajan Vaja &dev_attr_pggs1.attr,
1995ae5c961dSRajan Vaja &dev_attr_pggs2.attr,
1996ae5c961dSRajan Vaja &dev_attr_pggs3.attr,
1997b3ae24c4SRajan Vaja &dev_attr_shutdown_scope.attr,
1998a2cc220aSRajan Vaja &dev_attr_health_status.attr,
19992c5d8f7cSRonak Jain &dev_attr_feature_config_id.attr,
20002c5d8f7cSRonak Jain &dev_attr_feature_config_value.attr,
2001ae5c961dSRajan Vaja NULL,
2002ae5c961dSRajan Vaja };
2003ae5c961dSRajan Vaja
2004ae5c961dSRajan Vaja ATTRIBUTE_GROUPS(zynqmp_firmware);
2005ae5c961dSRajan Vaja
zynqmp_firmware_probe(struct platform_device * pdev)200676582671SRajan Vaja static int zynqmp_firmware_probe(struct platform_device *pdev)
200776582671SRajan Vaja {
200876582671SRajan Vaja struct device *dev = &pdev->dev;
20092c5d8f7cSRonak Jain struct zynqmp_devinfo *devinfo;
201076582671SRajan Vaja int ret;
201176582671SRajan Vaja
2012e5052becSRonak Jain ret = get_set_conduit_method(dev->of_node);
2013e5052becSRonak Jain if (ret)
2014e5052becSRonak Jain return ret;
2015e5052becSRonak Jain
201692fb7133SRonak Jain /* Get SiP SVC version number */
201792fb7133SRonak Jain ret = zynqmp_pm_get_sip_svc_version(&sip_svc_version);
201892fb7133SRonak Jain if (ret)
201992fb7133SRonak Jain return ret;
202092fb7133SRonak Jain
2021e5052becSRonak Jain ret = do_feature_check_call(PM_FEATURE_CHECK);
2022f689a0caSJay Buddhabhatti if (ret >= 0 && ((ret & FIRMWARE_VERSION_MASK) >= PM_API_VERSION_1))
2023e5052becSRonak Jain feature_check_enabled = true;
202476582671SRajan Vaja
20252c5d8f7cSRonak Jain devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL);
20262c5d8f7cSRonak Jain if (!devinfo)
20272c5d8f7cSRonak Jain return -ENOMEM;
20282c5d8f7cSRonak Jain
20292c5d8f7cSRonak Jain devinfo->dev = dev;
20302c5d8f7cSRonak Jain
20312c5d8f7cSRonak Jain platform_set_drvdata(pdev, devinfo);
20322c5d8f7cSRonak Jain
203376582671SRajan Vaja /* Check PM API version number */
2034168e05c1SRajan Vaja ret = zynqmp_pm_get_api_version(&pm_api_version);
2035168e05c1SRajan Vaja if (ret)
2036168e05c1SRajan Vaja return ret;
2037168e05c1SRajan Vaja
203876582671SRajan Vaja if (pm_api_version < ZYNQMP_PM_VERSION) {
203976582671SRajan Vaja panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
204076582671SRajan Vaja __func__,
204176582671SRajan Vaja ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
204276582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF);
204376582671SRajan Vaja }
204476582671SRajan Vaja
204576582671SRajan Vaja pr_info("%s Platform Management API v%d.%d\n", __func__,
204676582671SRajan Vaja pm_api_version >> 16, pm_api_version & 0xFFFF);
204776582671SRajan Vaja
204803ffa9afSDhaval Shah /* Get the Family code and sub family code of platform */
204903ffa9afSDhaval Shah ret = zynqmp_pm_get_family_info(&pm_family_code, &pm_sub_family_code);
205003ffa9afSDhaval Shah if (ret < 0)
205103ffa9afSDhaval Shah return ret;
205203ffa9afSDhaval Shah
205376582671SRajan Vaja /* Check trustzone version number */
205476582671SRajan Vaja ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
205576582671SRajan Vaja if (ret)
205676582671SRajan Vaja panic("Legacy trustzone found without version support\n");
205776582671SRajan Vaja
205876582671SRajan Vaja if (pm_tz_version < ZYNQMP_TZ_VERSION)
205976582671SRajan Vaja panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
206076582671SRajan Vaja __func__,
206176582671SRajan Vaja ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
206276582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF);
206376582671SRajan Vaja
206476582671SRajan Vaja pr_info("%s Trustzone version v%d.%d\n", __func__,
206576582671SRajan Vaja pm_tz_version >> 16, pm_tz_version & 0xFFFF);
206676582671SRajan Vaja
2067e23d9c6dSJolly Shah ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
2068e23d9c6dSJolly Shah ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
2069e23d9c6dSJolly Shah if (ret) {
2070e23d9c6dSJolly Shah dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
2071e23d9c6dSJolly Shah return ret;
2072e23d9c6dSJolly Shah }
2073e23d9c6dSJolly Shah
207465f0539bSChristophe JAILLET zynqmp_pm_api_debugfs_init();
207565f0539bSChristophe JAILLET
2076a9d06184SJay Buddhabhatti if (pm_family_code == VERSAL_FAMILY_CODE) {
2077a515814eSAbhyuday Godhasara em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager",
2078a515814eSAbhyuday Godhasara -1, NULL, 0);
2079a515814eSAbhyuday Godhasara if (IS_ERR(em_dev))
2080a515814eSAbhyuday Godhasara dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n");
2081a515814eSAbhyuday Godhasara }
2082a515814eSAbhyuday Godhasara
208376582671SRajan Vaja return of_platform_populate(dev->of_node, NULL, NULL, dev);
208476582671SRajan Vaja }
208576582671SRajan Vaja
zynqmp_firmware_remove(struct platform_device * pdev)2086408201ebSUwe Kleine-König static void zynqmp_firmware_remove(struct platform_device *pdev)
208776582671SRajan Vaja {
2088acfdd185SAmit Sunil Dhamne struct pm_api_feature_data *feature_data;
2089f1f21becSTejas Patel struct hlist_node *tmp;
2090acfdd185SAmit Sunil Dhamne int i;
2091acfdd185SAmit Sunil Dhamne
2092e23d9c6dSJolly Shah mfd_remove_devices(&pdev->dev);
2093b3217252SRajan Vaja zynqmp_pm_api_debugfs_exit();
2094b3217252SRajan Vaja
2095f1f21becSTejas Patel hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) {
2096acfdd185SAmit Sunil Dhamne hash_del(&feature_data->hentry);
2097acfdd185SAmit Sunil Dhamne kfree(feature_data);
2098acfdd185SAmit Sunil Dhamne }
2099acfdd185SAmit Sunil Dhamne
2100a515814eSAbhyuday Godhasara platform_device_unregister(em_dev);
210176582671SRajan Vaja }
210276582671SRajan Vaja
zynqmp_firmware_sync_state(struct device * dev)21033da405eaSUlf Hansson static void zynqmp_firmware_sync_state(struct device *dev)
21043da405eaSUlf Hansson {
2105*29ea3386SUlf Hansson struct device_node *np = dev->of_node;
2106*29ea3386SUlf Hansson
2107*29ea3386SUlf Hansson if (!of_device_is_compatible(np, "xlnx,zynqmp-firmware"))
21083da405eaSUlf Hansson return;
21093da405eaSUlf Hansson
2110*29ea3386SUlf Hansson of_genpd_sync_state(np);
2111*29ea3386SUlf Hansson
21123da405eaSUlf Hansson if (zynqmp_pm_init_finalize())
21133da405eaSUlf Hansson dev_warn(dev, "failed to release power management to firmware\n");
21143da405eaSUlf Hansson }
21153da405eaSUlf Hansson
211676582671SRajan Vaja static const struct of_device_id zynqmp_firmware_of_match[] = {
211776582671SRajan Vaja {.compatible = "xlnx,zynqmp-firmware"},
2118af3f1afaSJolly Shah {.compatible = "xlnx,versal-firmware"},
211976582671SRajan Vaja {},
212076582671SRajan Vaja };
212176582671SRajan Vaja MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
212276582671SRajan Vaja
212376582671SRajan Vaja static struct platform_driver zynqmp_firmware_driver = {
212476582671SRajan Vaja .driver = {
212576582671SRajan Vaja .name = "zynqmp_firmware",
212676582671SRajan Vaja .of_match_table = zynqmp_firmware_of_match,
2127ae5c961dSRajan Vaja .dev_groups = zynqmp_firmware_groups,
21283da405eaSUlf Hansson .sync_state = zynqmp_firmware_sync_state,
212976582671SRajan Vaja },
213076582671SRajan Vaja .probe = zynqmp_firmware_probe,
21315770e9f2SUwe Kleine-König .remove = zynqmp_firmware_remove,
213276582671SRajan Vaja };
213376582671SRajan Vaja module_platform_driver(zynqmp_firmware_driver);
2134