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