firmware: xilinx: Remove zynqmp_pm_pinctrl_get_function()
[linux-2.6-block.git] / drivers / firmware / xilinx / zynqmp.c
CommitLineData
76582671
RV
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Xilinx Zynq MPSoC Firmware layer
4 *
acd6510d 5 * Copyright (C) 2014-2022 Xilinx, Inc.
76582671 6 *
a5cb804b 7 * Michal Simek <michal.simek@amd.com>
76582671
RV
8 * Davorin Mista <davorin.mista@aggios.com>
9 * Jolly Shah <jollys@xilinx.com>
10 * Rajan Vaja <rajanv@xilinx.com>
11 */
12
13#include <linux/arm-smccc.h>
14#include <linux/compiler.h>
15#include <linux/device.h>
16#include <linux/init.h>
e23d9c6d 17#include <linux/mfd/core.h>
76582671
RV
18#include <linux/module.h>
19#include <linux/of.h>
20#include <linux/of_platform.h>
5b45759c 21#include <linux/platform_device.h>
76582671
RV
22#include <linux/slab.h>
23#include <linux/uaccess.h>
acfdd185 24#include <linux/hashtable.h>
76582671
RV
25
26#include <linux/firmware/xlnx-zynqmp.h>
a515814e 27#include <linux/firmware/xlnx-event-manager.h>
b3217252 28#include "zynqmp-debug.h"
76582671 29
acfdd185
ASD
30/* Max HashMap Order for PM API feature check (1<<7 = 128) */
31#define PM_API_FEATURE_CHECK_MAX_ORDER 7
32
23c64d76
PM
33/* CRL registers and bitfields */
34#define CRL_APB_BASE 0xFF5E0000U
35/* BOOT_PIN_CTRL- Used to control the mode pins after boot */
36#define CRL_APB_BOOT_PIN_CTRL (CRL_APB_BASE + (0x250U))
37/* BOOT_PIN_CTRL_MASK- out_val[11:8], out_en[3:0] */
38#define CRL_APB_BOOTPIN_CTRL_MASK 0xF0FU
39
f918cfc0
RJ
40/* IOCTL/QUERY feature payload size */
41#define FEATURE_PAYLOAD_SIZE 2
42
43/* Firmware feature check version mask */
44#define FIRMWARE_VERSION_MASK GENMASK(15, 0)
45
461011b1 46static bool feature_check_enabled;
69fe24d1 47static DEFINE_HASHTABLE(pm_api_features_map, PM_API_FEATURE_CHECK_MAX_ORDER);
f918cfc0
RJ
48static u32 ioctl_features[FEATURE_PAYLOAD_SIZE];
49static u32 query_features[FEATURE_PAYLOAD_SIZE];
acfdd185 50
a515814e
AG
51static struct platform_device *em_dev;
52
2c5d8f7c
RJ
53/**
54 * struct zynqmp_devinfo - Structure for Zynqmp device instance
55 * @dev: Device Pointer
56 * @feature_conf_id: Feature conf id
57 */
58struct zynqmp_devinfo {
59 struct device *dev;
60 u32 feature_conf_id;
61};
62
acfdd185
ASD
63/**
64 * struct pm_api_feature_data - PM API Feature data
65 * @pm_api_id: PM API Id, used as key to index into hashmap
66 * @feature_status: status of PM API feature: valid, invalid
67 * @hentry: hlist_node that hooks this entry into hashtable
68 */
69struct pm_api_feature_data {
70 u32 pm_api_id;
71 int feature_status;
72 struct hlist_node hentry;
73};
461011b1 74
e23d9c6d
JS
75static const struct mfd_cell firmware_devs[] = {
76 {
77 .name = "zynqmp_power_controller",
78 },
79};
80
76582671
RV
81/**
82 * zynqmp_pm_ret_code() - Convert PMU-FW error codes to Linux error codes
83 * @ret_status: PMUFW return code
84 *
85 * Return: corresponding Linux error code
86 */
87static int zynqmp_pm_ret_code(u32 ret_status)
88{
89 switch (ret_status) {
90 case XST_PM_SUCCESS:
91 case XST_PM_DOUBLE_REQ:
92 return 0;
461011b1
RP
93 case XST_PM_NO_FEATURE:
94 return -ENOTSUPP;
8c016c80
JB
95 case XST_PM_INVALID_VERSION:
96 return -EOPNOTSUPP;
76582671
RV
97 case XST_PM_NO_ACCESS:
98 return -EACCES;
99 case XST_PM_ABORT_SUSPEND:
100 return -ECANCELED;
df2a4d94
RV
101 case XST_PM_MULT_USER:
102 return -EUSERS;
76582671
RV
103 case XST_PM_INTERNAL:
104 case XST_PM_CONFLICT:
105 case XST_PM_INVALID_NODE:
5dac2a98 106 case XST_PM_INVALID_CRC:
76582671
RV
107 default:
108 return -EINVAL;
109 }
110}
111
f922b16a 112static noinline int do_fw_call_fail(u32 *ret_payload, u32 num_args, ...)
76582671
RV
113{
114 return -ENODEV;
115}
116
117/*
118 * PM function call wrapper
119 * Invoke do_fw_call_smc or do_fw_call_hvc, depending on the configuration
120 */
f922b16a 121static int (*do_fw_call)(u32 *ret_payload, u32, ...) = do_fw_call_fail;
76582671
RV
122
123/**
124 * do_fw_call_smc() - Call system-level platform management layer (SMC)
f922b16a 125 * @num_args: Number of variable arguments should be <= 8
76582671
RV
126 * @ret_payload: Returned value array
127 *
128 * Invoke platform management function via SMC call (no hypervisor present).
129 *
130 * Return: Returns status, either success or error+reason
131 */
f922b16a 132static noinline int do_fw_call_smc(u32 *ret_payload, u32 num_args, ...)
76582671
RV
133{
134 struct arm_smccc_res res;
f922b16a
JB
135 u64 args[8] = {0};
136 va_list arg_list;
137 u8 i;
76582671 138
f922b16a
JB
139 if (num_args > 8)
140 return -EINVAL;
141
142 va_start(arg_list, num_args);
143
144 for (i = 0; i < num_args; i++)
145 args[i] = va_arg(arg_list, u64);
146
147 va_end(arg_list);
148
149 arm_smccc_smc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
76582671
RV
150
151 if (ret_payload) {
152 ret_payload[0] = lower_32_bits(res.a0);
153 ret_payload[1] = upper_32_bits(res.a0);
154 ret_payload[2] = lower_32_bits(res.a1);
155 ret_payload[3] = upper_32_bits(res.a1);
156 }
157
158 return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
159}
160
161/**
162 * do_fw_call_hvc() - Call system-level platform management layer (HVC)
f922b16a 163 * @num_args: Number of variable arguments should be <= 8
76582671
RV
164 * @ret_payload: Returned value array
165 *
166 * Invoke platform management function via HVC
167 * HVC-based for communication through hypervisor
168 * (no direct communication with ATF).
169 *
170 * Return: Returns status, either success or error+reason
171 */
f922b16a 172static noinline int do_fw_call_hvc(u32 *ret_payload, u32 num_args, ...)
76582671
RV
173{
174 struct arm_smccc_res res;
f922b16a
JB
175 u64 args[8] = {0};
176 va_list arg_list;
177 u8 i;
178
179 if (num_args > 8)
180 return -EINVAL;
181
182 va_start(arg_list, num_args);
76582671 183
f922b16a
JB
184 for (i = 0; i < num_args; i++)
185 args[i] = va_arg(arg_list, u64);
186
187 va_end(arg_list);
188
189 arm_smccc_hvc(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], &res);
76582671
RV
190
191 if (ret_payload) {
192 ret_payload[0] = lower_32_bits(res.a0);
193 ret_payload[1] = upper_32_bits(res.a0);
194 ret_payload[2] = lower_32_bits(res.a1);
195 ret_payload[3] = upper_32_bits(res.a1);
196 }
197
198 return zynqmp_pm_ret_code((enum pm_ret_status)res.a0);
199}
200
218f01a8 201static int __do_feature_check_call(const u32 api_id, u32 *ret_payload)
94ae7f22
RJ
202{
203 int ret;
204 u64 smc_arg[2];
f689a0ca
JB
205 u32 module_id;
206 u32 feature_check_api_id;
94ae7f22 207
f689a0ca
JB
208 module_id = FIELD_GET(MODULE_ID_MASK, api_id);
209
210 /*
211 * Feature check of APIs belonging to PM, XSEM, and TF-A are handled by calling
212 * PM_FEATURE_CHECK API. For other modules, call PM_API_FEATURES API.
213 */
214 if (module_id == PM_MODULE_ID || module_id == XSEM_MODULE_ID || module_id == TF_A_MODULE_ID)
215 feature_check_api_id = PM_FEATURE_CHECK;
216 else
217 feature_check_api_id = PM_API_FEATURES;
218
219 /*
220 * Feature check of TF-A APIs is done in the TF-A layer and it expects for
221 * MODULE_ID_MASK bits of SMC's arg[0] to be the same as PM_MODULE_ID.
222 */
223 if (module_id == TF_A_MODULE_ID)
224 module_id = PM_MODULE_ID;
225
226 smc_arg[0] = PM_SIP_SVC | FIELD_PREP(MODULE_ID_MASK, module_id) | feature_check_api_id;
227 smc_arg[1] = (api_id & API_ID_MASK);
94ae7f22 228
f922b16a 229 ret = do_fw_call(ret_payload, 2, smc_arg[0], smc_arg[1]);
94ae7f22
RJ
230 if (ret)
231 ret = -EOPNOTSUPP;
232 else
233 ret = ret_payload[1];
234
235 return ret;
236}
237
218f01a8 238static int do_feature_check_call(const u32 api_id)
461011b1
RP
239{
240 int ret;
241 u32 ret_payload[PAYLOAD_ARG_CNT];
acfdd185 242 struct pm_api_feature_data *feature_data;
461011b1 243
acfdd185
ASD
244 /* Check for existing entry in hash table for given api */
245 hash_for_each_possible(pm_api_features_map, feature_data, hentry,
246 api_id) {
247 if (feature_data->pm_api_id == api_id)
248 return feature_data->feature_status;
249 }
f3217d6f 250
acfdd185 251 /* Add new entry if not present */
38ed310c 252 feature_data = kmalloc(sizeof(*feature_data), GFP_ATOMIC);
acfdd185
ASD
253 if (!feature_data)
254 return -ENOMEM;
461011b1 255
acfdd185 256 feature_data->pm_api_id = api_id;
218f01a8 257 ret = __do_feature_check_call(api_id, ret_payload);
461011b1 258
acfdd185
ASD
259 feature_data->feature_status = ret;
260 hash_add(pm_api_features_map, &feature_data->hentry, api_id);
461011b1 261
f918cfc0
RJ
262 if (api_id == PM_IOCTL)
263 /* Store supported IOCTL IDs mask */
264 memcpy(ioctl_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
265 else if (api_id == PM_QUERY_DATA)
266 /* Store supported QUERY IDs mask */
267 memcpy(query_features, &ret_payload[2], FEATURE_PAYLOAD_SIZE * 4);
268
acfdd185 269 return ret;
461011b1
RP
270}
271
218f01a8
RJ
272/**
273 * zynqmp_pm_feature() - Check whether given feature is supported or not and
274 * store supported IOCTL/QUERY ID mask
275 * @api_id: API ID to check
276 *
277 * Return: Returns status, either success or error+reason
278 */
279int zynqmp_pm_feature(const u32 api_id)
280{
281 int ret;
282
283 if (!feature_check_enabled)
284 return 0;
285
286 ret = do_feature_check_call(api_id);
287
288 return ret;
289}
79614953 290EXPORT_SYMBOL_GPL(zynqmp_pm_feature);
218f01a8 291
f918cfc0
RJ
292/**
293 * zynqmp_pm_is_function_supported() - Check whether given IOCTL/QUERY function
294 * is supported or not
295 * @api_id: PM_IOCTL or PM_QUERY_DATA
296 * @id: IOCTL or QUERY function IDs
297 *
298 * Return: Returns status, either success or error+reason
299 */
300int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
301{
302 int ret;
303 u32 *bit_mask;
304
305 /* Input arguments validation */
306 if (id >= 64 || (api_id != PM_IOCTL && api_id != PM_QUERY_DATA))
307 return -EINVAL;
308
309 /* Check feature check API version */
218f01a8 310 ret = do_feature_check_call(PM_FEATURE_CHECK);
f918cfc0
RJ
311 if (ret < 0)
312 return ret;
313
314 /* Check if feature check version 2 is supported or not */
315 if ((ret & FIRMWARE_VERSION_MASK) == PM_API_VERSION_2) {
316 /*
317 * Call feature check for IOCTL/QUERY API to get IOCTL ID or
318 * QUERY ID feature status.
319 */
218f01a8 320 ret = do_feature_check_call(api_id);
f918cfc0
RJ
321 if (ret < 0)
322 return ret;
323
324 bit_mask = (api_id == PM_IOCTL) ? ioctl_features : query_features;
325
326 if ((bit_mask[(id / 32)] & BIT((id % 32))) == 0U)
327 return -EOPNOTSUPP;
328 } else {
329 return -ENODATA;
330 }
331
332 return 0;
333}
334EXPORT_SYMBOL_GPL(zynqmp_pm_is_function_supported);
335
76582671
RV
336/**
337 * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
338 * caller function depending on the configuration
339 * @pm_api_id: Requested PM-API call
76582671 340 * @ret_payload: Returned value array
f922b16a 341 * @num_args: Number of arguments to requested PM-API call
76582671
RV
342 *
343 * Invoke platform management function for SMC or HVC call, depending on
344 * configuration.
345 * Following SMC Calling Convention (SMCCC) for SMC64:
346 * Pm Function Identifier,
347 * PM_SIP_SVC + PM_API_ID =
348 * ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)
349 * ((SMC_64) << FUNCID_CC_SHIFT)
350 * ((SIP_START) << FUNCID_OEN_SHIFT)
351 * ((PM_API_ID) & FUNCID_NUM_MASK))
352 *
353 * PM_SIP_SVC - Registered ZynqMP SIP Service Call.
354 * PM_API_ID - Platform Management API ID.
355 *
356 * Return: Returns status, either success or error+reason
357 */
f922b16a 358int zynqmp_pm_invoke_fn(u32 pm_api_id, u32 *ret_payload, u32 num_args, ...)
76582671
RV
359{
360 /*
361 * Added SIP service call Function Identifier
362 * Make sure to stay in x0 register
363 */
f922b16a
JB
364 u64 smc_arg[8];
365 int ret, i;
366 va_list arg_list;
367 u32 args[14] = {0};
368
369 if (num_args > 14)
370 return -EINVAL;
371
372 va_start(arg_list, num_args);
76582671 373
acfdd185
ASD
374 /* Check if feature is supported or not */
375 ret = zynqmp_pm_feature(pm_api_id);
376 if (ret < 0)
377 return ret;
461011b1 378
f922b16a
JB
379 for (i = 0; i < num_args; i++)
380 args[i] = va_arg(arg_list, u32);
381
382 va_end(arg_list);
383
76582671 384 smc_arg[0] = PM_SIP_SVC | pm_api_id;
f922b16a
JB
385 for (i = 0; i < 7; i++)
386 smc_arg[i + 1] = ((u64)args[(i * 2) + 1] << 32) | args[i * 2];
76582671 387
f922b16a
JB
388 return do_fw_call(ret_payload, 8, smc_arg[0], smc_arg[1], smc_arg[2], smc_arg[3],
389 smc_arg[4], smc_arg[5], smc_arg[6], smc_arg[7]);
76582671
RV
390}
391
392static u32 pm_api_version;
393static u32 pm_tz_version;
03ffa9af
DS
394static u32 pm_family_code;
395static u32 pm_sub_family_code;
76582671 396
acd6510d
TS
397int zynqmp_pm_register_sgi(u32 sgi_num, u32 reset)
398{
399 int ret;
400
f922b16a 401 ret = zynqmp_pm_invoke_fn(TF_A_PM_REGISTER_SGI, NULL, 2, sgi_num, reset);
8c016c80 402 if (ret != -EOPNOTSUPP && !ret)
acd6510d
TS
403 return ret;
404
405 /* try old implementation as fallback strategy if above fails */
f922b16a 406 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, IOCTL_REGISTER_SGI, sgi_num, reset);
acd6510d
TS
407}
408
76582671
RV
409/**
410 * zynqmp_pm_get_api_version() - Get version number of PMU PM firmware
411 * @version: Returned version value
412 *
413 * Return: Returns status, either success or error+reason
414 */
b9b3a8be 415int zynqmp_pm_get_api_version(u32 *version)
76582671
RV
416{
417 u32 ret_payload[PAYLOAD_ARG_CNT];
418 int ret;
419
420 if (!version)
421 return -EINVAL;
422
423 /* Check is PM API version already verified */
424 if (pm_api_version > 0) {
425 *version = pm_api_version;
426 return 0;
427 }
f922b16a 428 ret = zynqmp_pm_invoke_fn(PM_GET_API_VERSION, ret_payload, 0);
76582671
RV
429 *version = ret_payload[1];
430
431 return ret;
432}
b9b3a8be 433EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
76582671 434
fe6f42cf
NM
435/**
436 * zynqmp_pm_get_chipid - Get silicon ID registers
437 * @idcode: IDCODE register
438 * @version: version register
439 *
440 * Return: Returns the status of the operation and the idcode and version
441 * registers in @idcode and @version.
442 */
21cd93ba 443int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
fe6f42cf
NM
444{
445 u32 ret_payload[PAYLOAD_ARG_CNT];
446 int ret;
447
448 if (!idcode || !version)
449 return -EINVAL;
450
f922b16a 451 ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, ret_payload, 0);
fe6f42cf
NM
452 *idcode = ret_payload[1];
453 *version = ret_payload[2];
454
455 return ret;
456}
21cd93ba 457EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
fe6f42cf 458
03ffa9af
DS
459/**
460 * zynqmp_pm_get_family_info() - Get family info of platform
461 * @family: Returned family code value
462 * @subfamily: Returned sub-family code value
463 *
464 * Return: Returns status, either success or error+reason
465 */
466static int zynqmp_pm_get_family_info(u32 *family, u32 *subfamily)
467{
468 u32 ret_payload[PAYLOAD_ARG_CNT];
469 u32 idcode;
470 int ret;
471
472 /* Check is family or sub-family code already received */
473 if (pm_family_code && pm_sub_family_code) {
474 *family = pm_family_code;
475 *subfamily = pm_sub_family_code;
476 return 0;
477 }
478
f922b16a 479 ret = zynqmp_pm_invoke_fn(PM_GET_CHIPID, ret_payload, 0);
03ffa9af
DS
480 if (ret < 0)
481 return ret;
482
483 idcode = ret_payload[1];
484 pm_family_code = FIELD_GET(FAMILY_CODE_MASK, idcode);
485 pm_sub_family_code = FIELD_GET(SUB_FAMILY_CODE_MASK, idcode);
486 *family = pm_family_code;
487 *subfamily = pm_sub_family_code;
488
489 return 0;
490}
491
76582671
RV
492/**
493 * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
494 * @version: Returned version value
495 *
496 * Return: Returns status, either success or error+reason
497 */
498static int zynqmp_pm_get_trustzone_version(u32 *version)
499{
500 u32 ret_payload[PAYLOAD_ARG_CNT];
501 int ret;
502
503 if (!version)
504 return -EINVAL;
505
506 /* Check is PM trustzone version already verified */
507 if (pm_tz_version > 0) {
508 *version = pm_tz_version;
509 return 0;
510 }
f922b16a 511 ret = zynqmp_pm_invoke_fn(PM_GET_TRUSTZONE_VERSION, ret_payload, 0);
76582671
RV
512 *version = ret_payload[1];
513
514 return ret;
515}
516
517/**
518 * get_set_conduit_method() - Choose SMC or HVC based communication
519 * @np: Pointer to the device_node structure
520 *
521 * Use SMC or HVC-based functions to communicate with EL2/EL3.
522 *
523 * Return: Returns 0 on success or error code
524 */
525static int get_set_conduit_method(struct device_node *np)
526{
527 const char *method;
528
529 if (of_property_read_string(np, "method", &method)) {
530 pr_warn("%s missing \"method\" property\n", __func__);
531 return -ENXIO;
532 }
533
534 if (!strcmp("hvc", method)) {
535 do_fw_call = do_fw_call_hvc;
536 } else if (!strcmp("smc", method)) {
537 do_fw_call = do_fw_call_smc;
538 } else {
539 pr_warn("%s Invalid \"method\" property: %s\n",
540 __func__, method);
541 return -EINVAL;
542 }
543
544 return 0;
545}
546
59ecdd77
RV
547/**
548 * zynqmp_pm_query_data() - Get query data from firmware
549 * @qdata: Variable to the zynqmp_pm_query_data structure
550 * @out: Returned output value
551 *
552 * Return: Returns status, either success or error+reason
553 */
6366c1ba 554int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
59ecdd77 555{
f9627312
RV
556 int ret;
557
f922b16a
JB
558 ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, out, 4, qdata.qid, qdata.arg1, qdata.arg2,
559 qdata.arg3);
f9627312
RV
560
561 /*
562 * For clock name query, all bytes in SMC response are clock name
563 * characters and return code is always success. For invalid clocks,
564 * clock name bytes would be zeros.
565 */
566 return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
567}
6366c1ba 568EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
f9627312
RV
569
570/**
571 * zynqmp_pm_clock_enable() - Enable the clock for given id
572 * @clock_id: ID of the clock to be enabled
573 *
574 * This function is used by master to enable the clock
575 * including peripherals and PLL clocks.
576 *
577 * Return: Returns status, either success or error+reason
578 */
3637e84c 579int zynqmp_pm_clock_enable(u32 clock_id)
f9627312 580{
f922b16a 581 return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, NULL, 1, clock_id);
f9627312 582}
3637e84c 583EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
f9627312
RV
584
585/**
586 * zynqmp_pm_clock_disable() - Disable the clock for given id
587 * @clock_id: ID of the clock to be disable
588 *
589 * This function is used by master to disable the clock
590 * including peripherals and PLL clocks.
591 *
592 * Return: Returns status, either success or error+reason
593 */
f5ccd54b 594int zynqmp_pm_clock_disable(u32 clock_id)
f9627312 595{
f922b16a 596 return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, NULL, 1, clock_id);
f9627312 597}
f5ccd54b 598EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
f9627312
RV
599
600/**
601 * zynqmp_pm_clock_getstate() - Get the clock state for given id
602 * @clock_id: ID of the clock to be queried
603 * @state: 1/0 (Enabled/Disabled)
604 *
605 * This function is used by master to get the state of clock
606 * including peripherals and PLL clocks.
607 *
608 * Return: Returns status, either success or error+reason
609 */
5e76731d 610int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
f9627312
RV
611{
612 u32 ret_payload[PAYLOAD_ARG_CNT];
613 int ret;
614
f922b16a 615 ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, ret_payload, 1, clock_id);
f9627312
RV
616 *state = ret_payload[1];
617
618 return ret;
619}
5e76731d 620EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
f9627312
RV
621
622/**
623 * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
624 * @clock_id: ID of the clock
625 * @divider: divider value
626 *
627 * This function is used by master to set divider for any clock
628 * to achieve desired rate.
629 *
630 * Return: Returns status, either success or error+reason
631 */
fc9fb8fb 632int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
f9627312 633{
f922b16a 634 return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, NULL, 2, clock_id, divider);
f9627312 635}
fc9fb8fb 636EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
f9627312
RV
637
638/**
639 * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
640 * @clock_id: ID of the clock
641 * @divider: divider value
642 *
643 * This function is used by master to get divider values
644 * for any clock.
645 *
646 * Return: Returns status, either success or error+reason
647 */
0667a8d1 648int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
f9627312
RV
649{
650 u32 ret_payload[PAYLOAD_ARG_CNT];
651 int ret;
652
f922b16a 653 ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, ret_payload, 1, clock_id);
f9627312
RV
654 *divider = ret_payload[1];
655
656 return ret;
657}
0667a8d1 658EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
f9627312 659
f9627312
RV
660/**
661 * zynqmp_pm_clock_setparent() - Set the clock parent for given id
662 * @clock_id: ID of the clock
663 * @parent_id: parent id
664 *
665 * This function is used by master to set parent for any clock.
666 *
667 * Return: Returns status, either success or error+reason
668 */
70c0d364 669int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
f9627312 670{
f922b16a 671 return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, NULL, 2, clock_id, parent_id);
f9627312 672}
70c0d364 673EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
f9627312
RV
674
675/**
676 * zynqmp_pm_clock_getparent() - Get the clock parent for given id
677 * @clock_id: ID of the clock
678 * @parent_id: parent id
679 *
680 * This function is used by master to get parent index
681 * for any clock.
682 *
683 * Return: Returns status, either success or error+reason
684 */
70c0d364 685int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
f9627312
RV
686{
687 u32 ret_payload[PAYLOAD_ARG_CNT];
688 int ret;
689
f922b16a 690 ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, ret_payload, 1, clock_id);
f9627312
RV
691 *parent_id = ret_payload[1];
692
693 return ret;
59ecdd77 694}
70c0d364 695EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
59ecdd77 696
3b0296b8 697/**
426c8d85 698 * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
3b0296b8 699 *
426c8d85
RV
700 * @clk_id: PLL clock ID
701 * @mode: PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
702 *
703 * This function sets PLL mode
704 *
705 * Return: Returns status, either success or error+reason
3b0296b8 706 */
426c8d85 707int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
3b0296b8 708{
f922b16a 709 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_PLL_FRAC_MODE, clk_id, mode);
3b0296b8 710}
426c8d85 711EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
3b0296b8
RV
712
713/**
426c8d85
RV
714 * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
715 *
716 * @clk_id: PLL clock ID
717 * @mode: PLL mode
3b0296b8 718 *
426c8d85 719 * This function return current PLL mode
3b0296b8
RV
720 *
721 * Return: Returns status, either success or error+reason
722 */
426c8d85 723int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
3b0296b8 724{
f922b16a 725 return zynqmp_pm_invoke_fn(PM_IOCTL, mode, 3, 0, IOCTL_GET_PLL_FRAC_MODE, clk_id);
426c8d85
RV
726}
727EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
728
729/**
730 * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
731 *
732 * @clk_id: PLL clock ID
733 * @data: fraction data
734 *
735 * This function sets fraction data.
736 * It is valid for fraction mode only.
737 *
738 * Return: Returns status, either success or error+reason
739 */
740int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
741{
f922b16a 742 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_PLL_FRAC_DATA, clk_id, data);
426c8d85
RV
743}
744EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
745
746/**
747 * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
748 *
749 * @clk_id: PLL clock ID
750 * @data: fraction data
751 *
752 * This function returns fraction data value.
753 *
754 * Return: Returns status, either success or error+reason
755 */
756int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
757{
f922b16a 758 return zynqmp_pm_invoke_fn(PM_IOCTL, data, 3, 0, IOCTL_GET_PLL_FRAC_DATA, clk_id);
426c8d85
RV
759}
760EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
3b0296b8 761
426c8d85
RV
762/**
763 * zynqmp_pm_set_sd_tapdelay() - Set tap delay for the SD device
764 *
332bee16
MS
765 * @node_id: Node ID of the device
766 * @type: Type of tap delay to set (input/output)
767 * @value: Value to set fot the tap delay
426c8d85
RV
768 *
769 * This function sets input/output tap delay for the SD device.
770 *
332bee16 771 * Return: Returns status, either success or error+reason
426c8d85
RV
772 */
773int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
774{
a4b2e606
MV
775 u32 reg = (type == PM_TAPDELAY_INPUT) ? SD_ITAPDLY : SD_OTAPDLYSEL;
776 u32 mask = (node_id == NODE_SD_0) ? GENMASK(15, 0) : GENMASK(31, 16);
777
778 if (value) {
f922b16a
JB
779 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, node_id, IOCTL_SET_SD_TAPDELAY, type,
780 value);
a4b2e606
MV
781 }
782
783 /*
784 * Work around completely misdesigned firmware API on Xilinx ZynqMP.
785 * The IOCTL_SET_SD_TAPDELAY firmware call allows the caller to only
786 * ever set IOU_SLCR SD_ITAPDLY Register SD0_ITAPDLYENA/SD1_ITAPDLYENA
787 * bits, but there is no matching call to clear those bits. If those
788 * bits are not cleared, SDMMC tuning may fail.
789 *
790 * Luckily, there are PM_MMIO_READ/PM_MMIO_WRITE calls which seem to
791 * allow complete unrestricted access to all address space, including
792 * IOU_SLCR SD_ITAPDLY Register and all the other registers, access
793 * to which was supposed to be protected by the current firmware API.
794 *
795 * Use PM_MMIO_READ/PM_MMIO_WRITE to re-implement the missing counter
796 * part of IOCTL_SET_SD_TAPDELAY which clears SDx_ITAPDLYENA bits.
797 */
f922b16a 798 return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, NULL, 2, reg, mask);
426c8d85
RV
799}
800EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
801
802/**
803 * zynqmp_pm_sd_dll_reset() - Reset DLL logic
804 *
332bee16
MS
805 * @node_id: Node ID of the device
806 * @type: Reset type
426c8d85
RV
807 *
808 * This function resets DLL logic for the SD device.
809 *
332bee16 810 * Return: Returns status, either success or error+reason
426c8d85
RV
811 */
812int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
813{
f922b16a 814 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, node_id, IOCTL_SD_DLL_RESET, type);
3b0296b8 815}
426c8d85 816EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
3b0296b8 817
74e78adc
SKP
818/**
819 * zynqmp_pm_ospi_mux_select() - OSPI Mux selection
820 *
821 * @dev_id: Device Id of the OSPI device.
822 * @select: OSPI Mux select value.
823 *
824 * This function select the OSPI Mux.
825 *
826 * Return: Returns status, either success or error+reason
827 */
828int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
829{
f922b16a 830 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, dev_id, IOCTL_OSPI_MUX_SELECT, select);
74e78adc
SKP
831}
832EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select);
833
4f680b72
RV
834/**
835 * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
332bee16
MS
836 * @index: GGS register index
837 * @value: Register value to be written
4f680b72
RV
838 *
839 * This function writes value to GGS register.
840 *
332bee16 841 * Return: Returns status, either success or error+reason
4f680b72
RV
842 */
843int zynqmp_pm_write_ggs(u32 index, u32 value)
844{
f922b16a 845 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_WRITE_GGS, index, value);
4f680b72
RV
846}
847EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
848
849/**
2a8faf8d 850 * zynqmp_pm_read_ggs() - PM API for reading global general storage (ggs)
332bee16
MS
851 * @index: GGS register index
852 * @value: Register value to be written
4f680b72
RV
853 *
854 * This function returns GGS register value.
855 *
332bee16 856 * Return: Returns status, either success or error+reason
4f680b72
RV
857 */
858int zynqmp_pm_read_ggs(u32 index, u32 *value)
859{
f922b16a 860 return zynqmp_pm_invoke_fn(PM_IOCTL, value, 3, 0, IOCTL_READ_GGS, index);
4f680b72
RV
861}
862EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
863
864/**
865 * zynqmp_pm_write_pggs() - PM API for writing persistent global general
866 * storage (pggs)
332bee16
MS
867 * @index: PGGS register index
868 * @value: Register value to be written
4f680b72
RV
869 *
870 * This function writes value to PGGS register.
871 *
332bee16 872 * Return: Returns status, either success or error+reason
4f680b72
RV
873 */
874int zynqmp_pm_write_pggs(u32 index, u32 value)
875{
f922b16a 876 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_WRITE_PGGS, index, value);
4f680b72
RV
877}
878EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
879
880/**
2a8faf8d 881 * zynqmp_pm_read_pggs() - PM API for reading persistent global general
4f680b72 882 * storage (pggs)
332bee16
MS
883 * @index: PGGS register index
884 * @value: Register value to be written
4f680b72
RV
885 *
886 * This function returns PGGS register value.
887 *
332bee16 888 * Return: Returns status, either success or error+reason
4f680b72
RV
889 */
890int zynqmp_pm_read_pggs(u32 index, u32 *value)
891{
f922b16a 892 return zynqmp_pm_invoke_fn(PM_IOCTL, value, 3, 0, IOCTL_READ_PGGS, index);
4f680b72
RV
893}
894EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
895
1e400cb9
RV
896int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value)
897{
f922b16a 898 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_TAPDELAY_BYPASS, index, value);
1e400cb9
RV
899}
900EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass);
901
a2cc220a
RV
902/**
903 * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
332bee16 904 * @value: Status value to be written
a2cc220a
RV
905 *
906 * This function sets healthy bit value to indicate boot health status
907 * to firmware.
908 *
332bee16 909 * Return: Returns status, either success or error+reason
a2cc220a
RV
910 */
911int zynqmp_pm_set_boot_health_status(u32 value)
912{
f922b16a 913 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, 0, IOCTL_SET_BOOT_HEALTH_STATUS, value);
a2cc220a
RV
914}
915
bc3843d4
NM
916/**
917 * zynqmp_pm_reset_assert - Request setting of reset (1 - assert, 0 - release)
918 * @reset: Reset to be configured
919 * @assert_flag: Flag stating should reset be asserted (1) or
920 * released (0)
921 *
922 * Return: Returns status, either success or error+reason
923 */
cf23ec35
RV
924int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
925 const enum zynqmp_pm_reset_action assert_flag)
bc3843d4 926{
f922b16a 927 return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, NULL, 2, reset, assert_flag);
bc3843d4 928}
cf23ec35 929EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
bc3843d4
NM
930
931/**
932 * zynqmp_pm_reset_get_status - Get status of the reset
933 * @reset: Reset whose status should be returned
934 * @status: Returned status
935 *
936 * Return: Returns status, either success or error+reason
937 */
1b413581 938int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
bc3843d4
NM
939{
940 u32 ret_payload[PAYLOAD_ARG_CNT];
941 int ret;
942
943 if (!status)
944 return -EINVAL;
945
f922b16a 946 ret = zynqmp_pm_invoke_fn(PM_RESET_GET_STATUS, ret_payload, 1, reset);
bc3843d4
NM
947 *status = ret_payload[1];
948
949 return ret;
950}
1b413581 951EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
bc3843d4 952
e840decc
NM
953/**
954 * zynqmp_pm_fpga_load - Perform the fpga load
955 * @address: Address to write to
956 * @size: pl bitstream size
957 * @flags: Bitstream type
958 * -XILINX_ZYNQMP_PM_FPGA_FULL: FPGA full reconfiguration
959 * -XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
960 *
961 * This function provides access to pmufw. To transfer
962 * the required bitstream into PL.
963 *
964 * Return: Returns status, either success or error+reason
965 */
4db8180f 966int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
e840decc 967{
e2ebc05d
NM
968 u32 ret_payload[PAYLOAD_ARG_CNT];
969 int ret;
970
f922b16a
JB
971 ret = zynqmp_pm_invoke_fn(PM_FPGA_LOAD, ret_payload, 4, lower_32_bits(address),
972 upper_32_bits(address), size, flags);
e2ebc05d
NM
973 if (ret_payload[0])
974 return -ret_payload[0];
975
976 return ret;
e840decc 977}
56a9a806 978EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
e840decc
NM
979
980/**
981 * zynqmp_pm_fpga_get_status - Read value from PCAP status register
982 * @value: Value to read
983 *
984 * This function provides access to the pmufw to get the PCAP
985 * status
986 *
987 * Return: Returns status, either success or error+reason
988 */
4db8180f 989int zynqmp_pm_fpga_get_status(u32 *value)
e840decc
NM
990{
991 u32 ret_payload[PAYLOAD_ARG_CNT];
992 int ret;
993
994 if (!value)
995 return -EINVAL;
996
f922b16a 997 ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, ret_payload, 0);
e840decc
NM
998 *value = ret_payload[1];
999
1000 return ret;
1001}
56a9a806 1002EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
e840decc 1003
8f118f61
NM
1004/**
1005 * zynqmp_pm_fpga_get_config_status - Get the FPGA configuration status.
1006 * @value: Buffer to store FPGA configuration status.
1007 *
1008 * This function provides access to the pmufw to get the FPGA configuration
1009 * status
1010 *
1011 * Return: 0 on success, a negative value on error
1012 */
1013int zynqmp_pm_fpga_get_config_status(u32 *value)
1014{
1015 u32 ret_payload[PAYLOAD_ARG_CNT];
1016 u32 buf, lower_addr, upper_addr;
1017 int ret;
1018
1019 if (!value)
1020 return -EINVAL;
1021
1022 lower_addr = lower_32_bits((u64)&buf);
1023 upper_addr = upper_32_bits((u64)&buf);
1024
f922b16a
JB
1025 ret = zynqmp_pm_invoke_fn(PM_FPGA_READ, ret_payload, 4,
1026 XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, lower_addr, upper_addr,
1027 XILINX_ZYNQMP_PM_FPGA_READ_CONFIG_REG);
8f118f61
NM
1028
1029 *value = ret_payload[1];
1030
1031 return ret;
1032}
1033EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_config_status);
1034
fa989ae7
SKP
1035/**
1036 * zynqmp_pm_pinctrl_request - Request Pin from firmware
1037 * @pin: Pin number to request
1038 *
1039 * This function requests pin from firmware.
1040 *
1041 * Return: Returns status, either success or error+reason.
1042 */
1043int zynqmp_pm_pinctrl_request(const u32 pin)
1044{
f922b16a 1045 return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, NULL, 1, pin);
fa989ae7
SKP
1046}
1047EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request);
1048
1049/**
1050 * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
1051 * @pin: Pin number to release
1052 *
1053 * This function release pin from firmware.
1054 *
1055 * Return: Returns status, either success or error+reason.
1056 */
1057int zynqmp_pm_pinctrl_release(const u32 pin)
1058{
f922b16a 1059 return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, NULL, 1, pin);
fa989ae7
SKP
1060}
1061EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release);
1062
fa989ae7
SKP
1063/**
1064 * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
1065 * @pin: Pin number
1066 * @id: Function ID to set
1067 *
1068 * This function sets requested function for the given pin.
1069 *
1070 * Return: Returns status, either success or error+reason.
1071 */
1072int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
1073{
f922b16a 1074 return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, NULL, 2, pin, id);
fa989ae7
SKP
1075}
1076EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function);
1077
1078/**
1079 * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
1080 * @pin: Pin number
1081 * @param: Parameter to get
1082 * @value: Buffer to store parameter value
1083 *
1084 * This function gets requested configuration parameter for the given pin.
1085 *
1086 * Return: Returns status, either success or error+reason.
1087 */
1088int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
1089 u32 *value)
1090{
1091 u32 ret_payload[PAYLOAD_ARG_CNT];
1092 int ret;
1093
1094 if (!value)
1095 return -EINVAL;
1096
f922b16a 1097 ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, ret_payload, 2, pin, param);
fa989ae7
SKP
1098 *value = ret_payload[1];
1099
1100 return ret;
1101}
1102EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config);
1103
1104/**
1105 * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
1106 * @pin: Pin number
1107 * @param: Parameter to set
1108 * @value: Parameter value to set
1109 *
1110 * This function sets requested configuration parameter for the given pin.
1111 *
1112 * Return: Returns status, either success or error+reason.
1113 */
1114int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
1115 u32 value)
1116{
aa5ed7b3
SKP
1117 int ret;
1118
1119 if (pm_family_code == ZYNQMP_FAMILY_CODE &&
1120 param == PM_PINCTRL_CONFIG_TRI_STATE) {
1121 ret = zynqmp_pm_feature(PM_PINCTRL_CONFIG_PARAM_SET);
1122 if (ret < PM_PINCTRL_PARAM_SET_VERSION)
1123 return -EOPNOTSUPP;
1124 }
1125
f922b16a 1126 return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, NULL, 3, pin, param, value);
fa989ae7
SKP
1127}
1128EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config);
1129
23c64d76
PM
1130/**
1131 * zynqmp_pm_bootmode_read() - PM Config API for read bootpin status
1132 * @ps_mode: Returned output value of ps_mode
1133 *
1134 * This API function is to be used for notify the power management controller
1135 * to read bootpin status.
1136 *
1137 * Return: status, either success or error+reason
1138 */
1139unsigned int zynqmp_pm_bootmode_read(u32 *ps_mode)
1140{
1141 unsigned int ret;
1142 u32 ret_payload[PAYLOAD_ARG_CNT];
1143
f922b16a 1144 ret = zynqmp_pm_invoke_fn(PM_MMIO_READ, ret_payload, 1, CRL_APB_BOOT_PIN_CTRL);
23c64d76
PM
1145
1146 *ps_mode = ret_payload[1];
1147
1148 return ret;
1149}
1150EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_read);
1151
1152/**
1153 * zynqmp_pm_bootmode_write() - PM Config API for Configure bootpin
1154 * @ps_mode: Value to be written to the bootpin ctrl register
1155 *
1156 * This API function is to be used for notify the power management controller
1157 * to configure bootpin.
1158 *
1159 * Return: Returns status, either success or error+reason
1160 */
1161int zynqmp_pm_bootmode_write(u32 ps_mode)
1162{
f922b16a
JB
1163 return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, NULL, 3, CRL_APB_BOOT_PIN_CTRL,
1164 CRL_APB_BOOTPIN_CTRL_MASK, ps_mode);
23c64d76
PM
1165}
1166EXPORT_SYMBOL_GPL(zynqmp_pm_bootmode_write);
1167
e178df31
JS
1168/**
1169 * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
1170 * master has initialized its own power management
1171 *
332bee16
MS
1172 * Return: Returns status, either success or error+reason
1173 *
e178df31
JS
1174 * This API function is to be used for notify the power management controller
1175 * about the completed power management initialization.
e178df31 1176 */
9474da95 1177int zynqmp_pm_init_finalize(void)
e178df31 1178{
f922b16a 1179 return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, NULL, 0);
e178df31 1180}
9474da95 1181EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize);
e178df31
JS
1182
1183/**
1184 * zynqmp_pm_set_suspend_mode() - Set system suspend mode
1185 * @mode: Mode to set for system suspend
1186 *
1187 * This API function is used to set mode of system suspend.
1188 *
1189 * Return: Returns status, either success or error+reason
1190 */
951d0a97 1191int zynqmp_pm_set_suspend_mode(u32 mode)
e178df31 1192{
f922b16a 1193 return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, NULL, 1, mode);
e178df31 1194}
951d0a97 1195EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
e178df31 1196
c1986ac3
RV
1197/**
1198 * zynqmp_pm_request_node() - Request a node with specific capabilities
1199 * @node: Node ID of the slave
1200 * @capabilities: Requested capabilities of the slave
1201 * @qos: Quality of service (not supported)
1202 * @ack: Flag to specify whether acknowledge is requested
1203 *
1204 * This function is used by master to request particular node from firmware.
1205 * Every master must request node before using it.
1206 *
1207 * Return: Returns status, either success or error+reason
1208 */
bf8b27ed
RV
1209int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
1210 const u32 qos, const enum zynqmp_pm_request_ack ack)
c1986ac3 1211{
f922b16a 1212 return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, NULL, 4, node, capabilities, qos, ack);
c1986ac3 1213}
bf8b27ed 1214EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
c1986ac3
RV
1215
1216/**
1217 * zynqmp_pm_release_node() - Release a node
1218 * @node: Node ID of the slave
1219 *
1220 * This function is used by master to inform firmware that master
1221 * has released node. Once released, master must not use that node
1222 * without re-request.
1223 *
1224 * Return: Returns status, either success or error+reason
1225 */
07fb1a46 1226int zynqmp_pm_release_node(const u32 node)
c1986ac3 1227{
f922b16a 1228 return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, NULL, 1, node);
c1986ac3 1229}
07fb1a46 1230EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
c1986ac3 1231
a5e56980
BL
1232/**
1233 * zynqmp_pm_get_rpu_mode() - Get RPU mode
1234 * @node_id: Node ID of the device
1235 * @rpu_mode: return by reference value
1236 * either split or lockstep
1237 *
1238 * Return: return 0 on success or error+reason.
1239 * if success, then rpu_mode will be set
1240 * to current rpu mode.
1241 */
1242int zynqmp_pm_get_rpu_mode(u32 node_id, enum rpu_oper_mode *rpu_mode)
1243{
1244 u32 ret_payload[PAYLOAD_ARG_CNT];
1245 int ret;
1246
f922b16a 1247 ret = zynqmp_pm_invoke_fn(PM_IOCTL, ret_payload, 2, node_id, IOCTL_GET_RPU_OPER_MODE);
a5e56980
BL
1248
1249 /* only set rpu_mode if no error */
1250 if (ret == XST_PM_SUCCESS)
1251 *rpu_mode = ret_payload[0];
1252
1253 return ret;
1254}
1255EXPORT_SYMBOL_GPL(zynqmp_pm_get_rpu_mode);
1256
1257/**
1258 * zynqmp_pm_set_rpu_mode() - Set RPU mode
1259 * @node_id: Node ID of the device
1260 * @rpu_mode: Argument 1 to requested IOCTL call. either split or lockstep
1261 *
1262 * This function is used to set RPU mode to split or
1263 * lockstep
1264 *
1265 * Return: Returns status, either success or error+reason
1266 */
1267int zynqmp_pm_set_rpu_mode(u32 node_id, enum rpu_oper_mode rpu_mode)
1268{
f922b16a
JB
1269 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, node_id, IOCTL_SET_RPU_OPER_MODE,
1270 (u32)rpu_mode);
a5e56980
BL
1271}
1272EXPORT_SYMBOL_GPL(zynqmp_pm_set_rpu_mode);
1273
1274/**
1275 * zynqmp_pm_set_tcm_config - configure TCM
1276 * @node_id: Firmware specific TCM subsystem ID
1277 * @tcm_mode: Argument 1 to requested IOCTL call
1278 * either PM_RPU_TCM_COMB or PM_RPU_TCM_SPLIT
1279 *
1280 * This function is used to set RPU mode to split or combined
1281 *
1282 * Return: status: 0 for success, else failure
1283 */
1284int zynqmp_pm_set_tcm_config(u32 node_id, enum rpu_tcm_comb tcm_mode)
1285{
f922b16a
JB
1286 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 3, node_id, IOCTL_TCM_COMB_CONFIG,
1287 (u32)tcm_mode);
a5e56980
BL
1288}
1289EXPORT_SYMBOL_GPL(zynqmp_pm_set_tcm_config);
1290
da22a04f
BL
1291/**
1292 * zynqmp_pm_force_pwrdwn - PM call to request for another PU or subsystem to
1293 * be powered down forcefully
1294 * @node: Node ID of the targeted PU or subsystem
1295 * @ack: Flag to specify whether acknowledge is requested
1296 *
1297 * Return: status, either success or error+reason
1298 */
1299int zynqmp_pm_force_pwrdwn(const u32 node,
1300 const enum zynqmp_pm_request_ack ack)
1301{
f922b16a 1302 return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, NULL, 2, node, ack);
da22a04f
BL
1303}
1304EXPORT_SYMBOL_GPL(zynqmp_pm_force_pwrdwn);
1305
1306/**
1307 * zynqmp_pm_request_wake - PM call to wake up selected master or subsystem
1308 * @node: Node ID of the master or subsystem
1309 * @set_addr: Specifies whether the address argument is relevant
1310 * @address: Address from which to resume when woken up
1311 * @ack: Flag to specify whether acknowledge requested
1312 *
1313 * Return: status, either success or error+reason
1314 */
1315int zynqmp_pm_request_wake(const u32 node,
1316 const bool set_addr,
1317 const u64 address,
1318 const enum zynqmp_pm_request_ack ack)
1319{
1320 /* set_addr flag is encoded into 1st bit of address */
f922b16a
JB
1321 return zynqmp_pm_invoke_fn(PM_REQUEST_WAKEUP, NULL, 4, node, address | set_addr,
1322 address >> 32, ack);
da22a04f
BL
1323}
1324EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake);
1325
c1986ac3
RV
1326/**
1327 * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
1328 * @node: Node ID of the slave
1329 * @capabilities: Requested capabilities of the slave
1330 * @qos: Quality of service (not supported)
1331 * @ack: Flag to specify whether acknowledge is requested
1332 *
1333 * This API function is to be used for slaves a PU already has requested
1334 * to change its capabilities.
1335 *
1336 * Return: Returns status, either success or error+reason
1337 */
cbbbda71
RV
1338int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
1339 const u32 qos,
1340 const enum zynqmp_pm_request_ack ack)
c1986ac3 1341{
f922b16a 1342 return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, NULL, 4, node, capabilities, qos, ack);
c1986ac3 1343}
cbbbda71 1344EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
c1986ac3 1345
2b9fc773
NM
1346/**
1347 * zynqmp_pm_load_pdi - Load and process PDI
437cd966
MS
1348 * @src: Source device where PDI is located
1349 * @address: PDI src address
2b9fc773
NM
1350 *
1351 * This function provides support to load PDI from linux
1352 *
1353 * Return: Returns status, either success or error+reason
1354 */
1355int zynqmp_pm_load_pdi(const u32 src, const u64 address)
1356{
f922b16a
JB
1357 return zynqmp_pm_invoke_fn(PM_LOAD_PDI, NULL, 3, src, lower_32_bits(address),
1358 upper_32_bits(address));
2b9fc773
NM
1359}
1360EXPORT_SYMBOL_GPL(zynqmp_pm_load_pdi);
1361
057a0fb6 1362/**
2a8faf8d 1363 * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
057a0fb6
KA
1364 * AES-GCM core.
1365 * @address: Address of the AesParams structure.
1366 * @out: Returned output value
1367 *
1368 * Return: Returns status, either success or error code.
1369 */
bc86f9c5 1370int zynqmp_pm_aes_engine(const u64 address, u32 *out)
057a0fb6
KA
1371{
1372 u32 ret_payload[PAYLOAD_ARG_CNT];
1373 int ret;
1374
1375 if (!out)
1376 return -EINVAL;
1377
f922b16a
JB
1378 ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, ret_payload, 2, upper_32_bits(address),
1379 lower_32_bits(address));
057a0fb6
KA
1380 *out = ret_payload[1];
1381
1382 return ret;
1383}
bc86f9c5 1384EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
057a0fb6 1385
80f940ef
H
1386/**
1387 * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
1388 * @address: Address of the data/ Address of output buffer where
1389 * hash should be stored.
1390 * @size: Size of the data.
1391 * @flags:
1392 * BIT(0) - for initializing csudma driver and SHA3(Here address
1393 * and size inputs can be NULL).
1394 * BIT(1) - to call Sha3_Update API which can be called multiple
1395 * times when data is not contiguous.
1396 * BIT(2) - to get final hash of the whole updated data.
1397 * Hash will be overwritten at provided address with
1398 * 48 bytes.
1399 *
1400 * Return: Returns status, either success or error code.
1401 */
1402int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags)
1403{
1404 u32 lower_addr = lower_32_bits(address);
1405 u32 upper_addr = upper_32_bits(address);
1406
f922b16a 1407 return zynqmp_pm_invoke_fn(PM_SECURE_SHA, NULL, 4, upper_addr, lower_addr, size, flags);
80f940ef
H
1408}
1409EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash);
1410
1881eadb
AG
1411/**
1412 * zynqmp_pm_register_notifier() - PM API for register a subsystem
1413 * to be notified about specific
1414 * event/error.
1415 * @node: Node ID to which the event is related.
1416 * @event: Event Mask of Error events for which wants to get notified.
1417 * @wake: Wake subsystem upon capturing the event if value 1
1418 * @enable: Enable the registration for value 1, disable for value 0
1419 *
1420 * This function is used to register/un-register for particular node-event
1421 * combination in firmware.
1422 *
1423 * Return: Returns status, either success or error+reason
1424 */
1425
1426int zynqmp_pm_register_notifier(const u32 node, const u32 event,
1427 const u32 wake, const u32 enable)
1428{
f922b16a 1429 return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, NULL, 4, node, event, wake, enable);
1881eadb
AG
1430}
1431EXPORT_SYMBOL_GPL(zynqmp_pm_register_notifier);
1432
fdd2ed88
RV
1433/**
1434 * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
1435 * @type: Shutdown or restart? 0 for shutdown, 1 for restart
1436 * @subtype: Specifies which system should be restarted or shut down
1437 *
1438 * Return: Returns status, either success or error+reason
1439 */
1440int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
1441{
f922b16a 1442 return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, NULL, 2, type, subtype);
fdd2ed88
RV
1443}
1444
f1d0821b
RJ
1445/**
1446 * zynqmp_pm_set_feature_config - PM call to request IOCTL for feature config
1447 * @id: The config ID of the feature to be configured
1448 * @value: The config value of the feature to be configured
1449 *
1450 * Return: Returns 0 on success or error value on failure.
1451 */
1452int zynqmp_pm_set_feature_config(enum pm_feature_config_id id, u32 value)
1453{
f922b16a 1454 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, 0, IOCTL_SET_FEATURE_CONFIG, id, value);
f1d0821b
RJ
1455}
1456
1457/**
1458 * zynqmp_pm_get_feature_config - PM call to get value of configured feature
1459 * @id: The config id of the feature to be queried
1460 * @payload: Returned value array
1461 *
1462 * Return: Returns 0 on success or error value on failure.
1463 */
1464int zynqmp_pm_get_feature_config(enum pm_feature_config_id id,
1465 u32 *payload)
1466{
f922b16a 1467 return zynqmp_pm_invoke_fn(PM_IOCTL, payload, 3, 0, IOCTL_GET_FEATURE_CONFIG, id);
f1d0821b
RJ
1468}
1469
256dea91
RJ
1470/**
1471 * zynqmp_pm_set_sd_config - PM call to set value of SD config registers
1472 * @node: SD node ID
1473 * @config: The config type of SD registers
1474 * @value: Value to be set
1475 *
1476 * Return: Returns 0 on success or error value on failure.
1477 */
1478int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value)
1479{
f922b16a 1480 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, node, IOCTL_SET_SD_CONFIG, config, value);
256dea91
RJ
1481}
1482EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_config);
1483
1484/**
1485 * zynqmp_pm_set_gem_config - PM call to set value of GEM config registers
1486 * @node: GEM node ID
1487 * @config: The config type of GEM registers
1488 * @value: Value to be set
1489 *
1490 * Return: Returns 0 on success or error value on failure.
1491 */
1492int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
1493 u32 value)
1494{
f922b16a 1495 return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 4, node, IOCTL_SET_GEM_CONFIG, config, value);
256dea91
RJ
1496}
1497EXPORT_SYMBOL_GPL(zynqmp_pm_set_gem_config);
1498
b3ae24c4
RV
1499/**
1500 * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
1501 * @subtype: Shutdown subtype
1502 * @name: Matching string for scope argument
1503 *
1504 * This struct encapsulates mapping between shutdown scope ID and string.
1505 */
1506struct zynqmp_pm_shutdown_scope {
1507 const enum zynqmp_pm_shutdown_subtype subtype;
1508 const char *name;
1509};
1510
1511static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
1512 [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
1513 .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
1514 .name = "subsystem",
1515 },
1516 [ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
1517 .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
1518 .name = "ps_only",
1519 },
1520 [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
1521 .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
1522 .name = "system",
1523 },
1524};
1525
1526static struct zynqmp_pm_shutdown_scope *selected_scope =
1527 &shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
1528
1529/**
1530 * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
1531 * @scope_string: Shutdown scope string
1532 *
1533 * Return: Return pointer to matching shutdown scope struct from
1534 * array of available options in system if string is valid,
1535 * otherwise returns NULL.
1536 */
1537static struct zynqmp_pm_shutdown_scope*
1538 zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
1539{
1540 int count;
1541
1542 for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
1543 if (sysfs_streq(scope_string, shutdown_scopes[count].name))
1544 return &shutdown_scopes[count];
1545
1546 return NULL;
1547}
1548
1549static ssize_t shutdown_scope_show(struct device *device,
1550 struct device_attribute *attr,
1551 char *buf)
1552{
1553 int i;
1554
1555 for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
1556 if (&shutdown_scopes[i] == selected_scope) {
1557 strcat(buf, "[");
1558 strcat(buf, shutdown_scopes[i].name);
1559 strcat(buf, "]");
1560 } else {
1561 strcat(buf, shutdown_scopes[i].name);
1562 }
1563 strcat(buf, " ");
1564 }
1565 strcat(buf, "\n");
1566
1567 return strlen(buf);
1568}
1569
1570static ssize_t shutdown_scope_store(struct device *device,
1571 struct device_attribute *attr,
1572 const char *buf, size_t count)
1573{
1574 int ret;
1575 struct zynqmp_pm_shutdown_scope *scope;
1576
1577 scope = zynqmp_pm_is_shutdown_scope_valid(buf);
1578 if (!scope)
1579 return -EINVAL;
1580
1581 ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
1582 scope->subtype);
1583 if (ret) {
1584 pr_err("unable to set shutdown scope %s\n", buf);
1585 return ret;
1586 }
1587
1588 selected_scope = scope;
1589
1590 return count;
1591}
1592
1593static DEVICE_ATTR_RW(shutdown_scope);
1594
a2cc220a
RV
1595static ssize_t health_status_store(struct device *device,
1596 struct device_attribute *attr,
1597 const char *buf, size_t count)
1598{
1599 int ret;
1600 unsigned int value;
1601
1602 ret = kstrtouint(buf, 10, &value);
1603 if (ret)
1604 return ret;
1605
1606 ret = zynqmp_pm_set_boot_health_status(value);
1607 if (ret) {
1608 dev_err(device, "unable to set healthy bit value to %u\n",
1609 value);
1610 return ret;
1611 }
1612
1613 return count;
1614}
1615
1616static DEVICE_ATTR_WO(health_status);
1617
ae5c961d
RV
1618static ssize_t ggs_show(struct device *device,
1619 struct device_attribute *attr,
1620 char *buf,
1621 u32 reg)
1622{
1623 int ret;
1624 u32 ret_payload[PAYLOAD_ARG_CNT];
1625
1626 ret = zynqmp_pm_read_ggs(reg, ret_payload);
1627 if (ret)
1628 return ret;
1629
1630 return sprintf(buf, "0x%x\n", ret_payload[1]);
1631}
1632
1633static ssize_t ggs_store(struct device *device,
1634 struct device_attribute *attr,
1635 const char *buf, size_t count,
1636 u32 reg)
1637{
1638 long value;
1639 int ret;
1640
1641 if (reg >= GSS_NUM_REGS)
1642 return -EINVAL;
1643
1644 ret = kstrtol(buf, 16, &value);
1645 if (ret) {
1646 count = -EFAULT;
1647 goto err;
1648 }
1649
1650 ret = zynqmp_pm_write_ggs(reg, value);
1651 if (ret)
1652 count = -EFAULT;
ae5c961d
RV
1653err:
1654 return count;
1655}
1656
1657/* GGS register show functions */
1658#define GGS0_SHOW(N) \
1659 ssize_t ggs##N##_show(struct device *device, \
1660 struct device_attribute *attr, \
1661 char *buf) \
1662 { \
1663 return ggs_show(device, attr, buf, N); \
1664 }
1665
1666static GGS0_SHOW(0);
1667static GGS0_SHOW(1);
1668static GGS0_SHOW(2);
1669static GGS0_SHOW(3);
1670
1671/* GGS register store function */
1672#define GGS0_STORE(N) \
1673 ssize_t ggs##N##_store(struct device *device, \
1674 struct device_attribute *attr, \
1675 const char *buf, \
1676 size_t count) \
1677 { \
1678 return ggs_store(device, attr, buf, count, N); \
1679 }
1680
1681static GGS0_STORE(0);
1682static GGS0_STORE(1);
1683static GGS0_STORE(2);
1684static GGS0_STORE(3);
1685
1686static ssize_t pggs_show(struct device *device,
1687 struct device_attribute *attr,
1688 char *buf,
1689 u32 reg)
1690{
1691 int ret;
1692 u32 ret_payload[PAYLOAD_ARG_CNT];
1693
1694 ret = zynqmp_pm_read_pggs(reg, ret_payload);
1695 if (ret)
1696 return ret;
1697
1698 return sprintf(buf, "0x%x\n", ret_payload[1]);
1699}
1700
1701static ssize_t pggs_store(struct device *device,
1702 struct device_attribute *attr,
1703 const char *buf, size_t count,
1704 u32 reg)
1705{
1706 long value;
1707 int ret;
1708
1709 if (reg >= GSS_NUM_REGS)
1710 return -EINVAL;
1711
1712 ret = kstrtol(buf, 16, &value);
1713 if (ret) {
1714 count = -EFAULT;
1715 goto err;
1716 }
1717
1718 ret = zynqmp_pm_write_pggs(reg, value);
1719 if (ret)
1720 count = -EFAULT;
1721
1722err:
1723 return count;
1724}
1725
1726#define PGGS0_SHOW(N) \
1727 ssize_t pggs##N##_show(struct device *device, \
1728 struct device_attribute *attr, \
1729 char *buf) \
1730 { \
1731 return pggs_show(device, attr, buf, N); \
1732 }
1733
1734#define PGGS0_STORE(N) \
1735 ssize_t pggs##N##_store(struct device *device, \
1736 struct device_attribute *attr, \
1737 const char *buf, \
1738 size_t count) \
1739 { \
1740 return pggs_store(device, attr, buf, count, N); \
1741 }
1742
1743/* PGGS register show functions */
1744static PGGS0_SHOW(0);
1745static PGGS0_SHOW(1);
1746static PGGS0_SHOW(2);
1747static PGGS0_SHOW(3);
1748
1749/* PGGS register store functions */
1750static PGGS0_STORE(0);
1751static PGGS0_STORE(1);
1752static PGGS0_STORE(2);
1753static PGGS0_STORE(3);
1754
1755/* GGS register attributes */
1756static DEVICE_ATTR_RW(ggs0);
1757static DEVICE_ATTR_RW(ggs1);
1758static DEVICE_ATTR_RW(ggs2);
1759static DEVICE_ATTR_RW(ggs3);
1760
1761/* PGGS register attributes */
1762static DEVICE_ATTR_RW(pggs0);
1763static DEVICE_ATTR_RW(pggs1);
1764static DEVICE_ATTR_RW(pggs2);
1765static DEVICE_ATTR_RW(pggs3);
1766
2c5d8f7c
RJ
1767static ssize_t feature_config_id_show(struct device *device,
1768 struct device_attribute *attr,
1769 char *buf)
1770{
1771 struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1772
1773 return sysfs_emit(buf, "%d\n", devinfo->feature_conf_id);
1774}
1775
1776static ssize_t feature_config_id_store(struct device *device,
1777 struct device_attribute *attr,
1778 const char *buf, size_t count)
1779{
1780 u32 config_id;
1781 int ret;
1782 struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1783
1784 if (!buf)
1785 return -EINVAL;
1786
1787 ret = kstrtou32(buf, 10, &config_id);
1788 if (ret)
1789 return ret;
1790
1791 devinfo->feature_conf_id = config_id;
1792
1793 return count;
1794}
1795
1796static DEVICE_ATTR_RW(feature_config_id);
1797
1798static ssize_t feature_config_value_show(struct device *device,
1799 struct device_attribute *attr,
1800 char *buf)
1801{
1802 int ret;
1803 u32 ret_payload[PAYLOAD_ARG_CNT];
1804 struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1805
1806 ret = zynqmp_pm_get_feature_config(devinfo->feature_conf_id,
1807 ret_payload);
1808 if (ret)
1809 return ret;
1810
1811 return sysfs_emit(buf, "%d\n", ret_payload[1]);
1812}
1813
1814static ssize_t feature_config_value_store(struct device *device,
1815 struct device_attribute *attr,
1816 const char *buf, size_t count)
1817{
1818 u32 value;
1819 int ret;
1820 struct zynqmp_devinfo *devinfo = dev_get_drvdata(device);
1821
1822 if (!buf)
1823 return -EINVAL;
1824
1825 ret = kstrtou32(buf, 10, &value);
1826 if (ret)
1827 return ret;
1828
1829 ret = zynqmp_pm_set_feature_config(devinfo->feature_conf_id,
1830 value);
1831 if (ret)
1832 return ret;
1833
1834 return count;
1835}
1836
1837static DEVICE_ATTR_RW(feature_config_value);
1838
ae5c961d
RV
1839static struct attribute *zynqmp_firmware_attrs[] = {
1840 &dev_attr_ggs0.attr,
1841 &dev_attr_ggs1.attr,
1842 &dev_attr_ggs2.attr,
1843 &dev_attr_ggs3.attr,
1844 &dev_attr_pggs0.attr,
1845 &dev_attr_pggs1.attr,
1846 &dev_attr_pggs2.attr,
1847 &dev_attr_pggs3.attr,
b3ae24c4 1848 &dev_attr_shutdown_scope.attr,
a2cc220a 1849 &dev_attr_health_status.attr,
2c5d8f7c
RJ
1850 &dev_attr_feature_config_id.attr,
1851 &dev_attr_feature_config_value.attr,
ae5c961d
RV
1852 NULL,
1853};
1854
1855ATTRIBUTE_GROUPS(zynqmp_firmware);
1856
76582671
RV
1857static int zynqmp_firmware_probe(struct platform_device *pdev)
1858{
1859 struct device *dev = &pdev->dev;
2c5d8f7c 1860 struct zynqmp_devinfo *devinfo;
76582671
RV
1861 int ret;
1862
e5052bec
RJ
1863 ret = get_set_conduit_method(dev->of_node);
1864 if (ret)
1865 return ret;
1866
f689a0ca
JB
1867 ret = do_feature_check_call(PM_FEATURE_CHECK);
1868 if (ret >= 0 && ((ret & FIRMWARE_VERSION_MASK) >= PM_API_VERSION_1))
461011b1 1869 feature_check_enabled = true;
76582671 1870
2c5d8f7c
RJ
1871 devinfo = devm_kzalloc(dev, sizeof(*devinfo), GFP_KERNEL);
1872 if (!devinfo)
1873 return -ENOMEM;
1874
1875 devinfo->dev = dev;
1876
1877 platform_set_drvdata(pdev, devinfo);
1878
76582671 1879 /* Check PM API version number */
168e05c1
RV
1880 ret = zynqmp_pm_get_api_version(&pm_api_version);
1881 if (ret)
1882 return ret;
1883
76582671
RV
1884 if (pm_api_version < ZYNQMP_PM_VERSION) {
1885 panic("%s Platform Management API version error. Expected: v%d.%d - Found: v%d.%d\n",
1886 __func__,
1887 ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR,
1888 pm_api_version >> 16, pm_api_version & 0xFFFF);
1889 }
1890
1891 pr_info("%s Platform Management API v%d.%d\n", __func__,
1892 pm_api_version >> 16, pm_api_version & 0xFFFF);
1893
03ffa9af
DS
1894 /* Get the Family code and sub family code of platform */
1895 ret = zynqmp_pm_get_family_info(&pm_family_code, &pm_sub_family_code);
1896 if (ret < 0)
1897 return ret;
1898
76582671
RV
1899 /* Check trustzone version number */
1900 ret = zynqmp_pm_get_trustzone_version(&pm_tz_version);
1901 if (ret)
1902 panic("Legacy trustzone found without version support\n");
1903
1904 if (pm_tz_version < ZYNQMP_TZ_VERSION)
1905 panic("%s Trustzone version error. Expected: v%d.%d - Found: v%d.%d\n",
1906 __func__,
1907 ZYNQMP_TZ_VERSION_MAJOR, ZYNQMP_TZ_VERSION_MINOR,
1908 pm_tz_version >> 16, pm_tz_version & 0xFFFF);
1909
1910 pr_info("%s Trustzone version v%d.%d\n", __func__,
1911 pm_tz_version >> 16, pm_tz_version & 0xFFFF);
1912
e23d9c6d
JS
1913 ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
1914 ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
1915 if (ret) {
1916 dev_err(&pdev->dev, "failed to add MFD devices %d\n", ret);
1917 return ret;
1918 }
1919
65f0539b
CJ
1920 zynqmp_pm_api_debugfs_init();
1921
a9d06184 1922 if (pm_family_code == VERSAL_FAMILY_CODE) {
a515814e
AG
1923 em_dev = platform_device_register_data(&pdev->dev, "xlnx_event_manager",
1924 -1, NULL, 0);
1925 if (IS_ERR(em_dev))
1926 dev_err_probe(&pdev->dev, PTR_ERR(em_dev), "EM register fail with error\n");
1927 }
a515814e 1928
76582671
RV
1929 return of_platform_populate(dev->of_node, NULL, NULL, dev);
1930}
1931
1932static int zynqmp_firmware_remove(struct platform_device *pdev)
1933{
acfdd185 1934 struct pm_api_feature_data *feature_data;
f1f21bec 1935 struct hlist_node *tmp;
acfdd185
ASD
1936 int i;
1937
e23d9c6d 1938 mfd_remove_devices(&pdev->dev);
b3217252
RV
1939 zynqmp_pm_api_debugfs_exit();
1940
f1f21bec 1941 hash_for_each_safe(pm_api_features_map, i, tmp, feature_data, hentry) {
acfdd185
ASD
1942 hash_del(&feature_data->hentry);
1943 kfree(feature_data);
1944 }
1945
a515814e
AG
1946 platform_device_unregister(em_dev);
1947
76582671
RV
1948 return 0;
1949}
1950
1951static const struct of_device_id zynqmp_firmware_of_match[] = {
1952 {.compatible = "xlnx,zynqmp-firmware"},
af3f1afa 1953 {.compatible = "xlnx,versal-firmware"},
76582671
RV
1954 {},
1955};
1956MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
1957
1958static struct platform_driver zynqmp_firmware_driver = {
1959 .driver = {
1960 .name = "zynqmp_firmware",
1961 .of_match_table = zynqmp_firmware_of_match,
ae5c961d 1962 .dev_groups = zynqmp_firmware_groups,
76582671
RV
1963 },
1964 .probe = zynqmp_firmware_probe,
1965 .remove = zynqmp_firmware_remove,
1966};
1967module_platform_driver(zynqmp_firmware_driver);