1 /*
2 * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
3 * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 /*
9 * ZynqMP system level PM-API functions for ioctl.
10 */
11
12 #include <arch_helpers.h>
13 #include <drivers/delay_timer.h>
14 #include <lib/mmio.h>
15 #include <plat/common/platform.h>
16 #include <plat_pm_common.h>
17
18 #include "pm_api_clock.h"
19 #include "pm_api_ioctl.h"
20 #include "pm_client.h"
21 #include "pm_common.h"
22 #include "pm_ipi.h"
23 #include <zynqmp_def.h>
24 #include "zynqmp_pm_api_sys.h"
25
26 /**
27 * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode.
28 * @mode: Buffer to store value of oper mode(Split/Lock-step)
29 *
30 * This function provides current configured RPU operational mode.
31 *
32 * Return: Returns status, either success or error+reason.
33 *
34 */
pm_ioctl_get_rpu_oper_mode(uint32_t * mode)35 static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(uint32_t *mode)
36 {
37 uint32_t val;
38
39 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
40 val &= ZYNQMP_SLSPLIT_MASK;
41 if (val == 0U) {
42 *mode = PM_RPU_MODE_LOCKSTEP;
43 } else {
44 *mode = PM_RPU_MODE_SPLIT;
45 }
46
47 return PM_RET_SUCCESS;
48 }
49
50 /**
51 * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode.
52 * @mode: Value to set for oper mode(Split/Lock-step).
53 *
54 * This function configures RPU operational mode(Split/Lock-step).
55 * It also sets TCM combined mode in RPU lock-step and TCM non-combined
56 * mode for RPU split mode. In case of Lock step mode, RPU1's output is
57 * clamped.
58 *
59 * Return: Returns status, either success or error+reason.
60 *
61 */
pm_ioctl_set_rpu_oper_mode(uint32_t mode)62 static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(uint32_t mode)
63 {
64 uint32_t val;
65 enum pm_ret_status status = PM_RET_SUCCESS;
66
67 if ((mmio_read_32(CRL_APB_RST_LPD_TOP) & CRL_APB_RPU_AMBA_RESET) != 0U) {
68 status = PM_RET_ERROR_ACCESS;
69 goto exit_label;
70 }
71
72 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
73
74 if (mode == PM_RPU_MODE_SPLIT) {
75 val |= ZYNQMP_SLSPLIT_MASK;
76 val &= ~ZYNQMP_TCM_COMB_MASK;
77 val &= ~ZYNQMP_SLCLAMP_MASK;
78 } else if (mode == PM_RPU_MODE_LOCKSTEP) {
79 val &= ~ZYNQMP_SLSPLIT_MASK;
80 val |= ZYNQMP_TCM_COMB_MASK;
81 val |= ZYNQMP_SLCLAMP_MASK;
82 } else {
83 status = PM_RET_ERROR_ARGS;
84 goto exit_label;
85 }
86
87 mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
88
89 exit_label:
90 return status;
91 }
92
93 /**
94 * pm_ioctl_config_boot_addr() - Configure RPU boot address.
95 * @nid: Node ID of RPU.
96 * @value: Value to set for boot address (TCM/OCM).
97 *
98 * This function configures RPU boot address(memory).
99 *
100 * Return: Returns status, either success or error+reason.
101 *
102 */
pm_ioctl_config_boot_addr(enum pm_node_id nid,uint32_t value)103 static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid,
104 uint32_t value)
105 {
106 uint32_t rpu_cfg_addr, val;
107
108 if (nid == NODE_RPU_0) {
109 rpu_cfg_addr = ZYNQMP_RPU0_CFG;
110 } else if (nid == NODE_RPU_1) {
111 rpu_cfg_addr = ZYNQMP_RPU1_CFG;
112 } else {
113 return PM_RET_ERROR_ARGS;
114 }
115
116 val = mmio_read_32(rpu_cfg_addr);
117
118 if (value == PM_RPU_BOOTMEM_LOVEC) {
119 val &= ~ZYNQMP_VINITHI_MASK;
120 } else if (value == PM_RPU_BOOTMEM_HIVEC) {
121 val |= ZYNQMP_VINITHI_MASK;
122 } else {
123 return PM_RET_ERROR_ARGS;
124 }
125
126 mmio_write_32(rpu_cfg_addr, val);
127
128 return PM_RET_SUCCESS;
129 }
130
131 /**
132 * pm_ioctl_config_tcm_comb() - Configure TCM combined mode.
133 * @value: Value to set (Split/Combined).
134 *
135 * This function configures TCM to be in split mode or combined
136 * mode.
137 *
138 * Return: Returns status, either success or error+reason.
139 *
140 */
pm_ioctl_config_tcm_comb(uint32_t value)141 static enum pm_ret_status pm_ioctl_config_tcm_comb(uint32_t value)
142 {
143 uint32_t val;
144 enum pm_ret_status status = PM_RET_SUCCESS;
145
146 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
147
148 if (value == PM_RPU_TCM_SPLIT) {
149 val &= ~ZYNQMP_TCM_COMB_MASK;
150 } else if (value == PM_RPU_TCM_COMB) {
151 val |= ZYNQMP_TCM_COMB_MASK;
152 } else {
153 status = PM_RET_ERROR_ARGS;
154 goto exit_label;
155 }
156
157 mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
158
159 exit_label:
160 return status;
161 }
162
163 /**
164 * pm_ioctl_set_tapdelay_bypass() - Enable/Disable tap delay bypass.
165 * @type: Type of tap delay to enable/disable (e.g. QSPI).
166 * @value: Enable/Disable.
167 * @flag: 0 - Call from secure source.
168 * 1 - Call from non-secure source.
169 *
170 * This function enable/disable tap delay bypass.
171 *
172 * Return: Returns status, either success or error+reason.
173 *
174 */
pm_ioctl_set_tapdelay_bypass(uint32_t type,uint32_t value,uint32_t flag)175 static enum pm_ret_status pm_ioctl_set_tapdelay_bypass(uint32_t type,
176 uint32_t value,
177 uint32_t flag)
178 {
179 enum pm_ret_status status = PM_RET_SUCCESS;
180
181 if ((((value != PM_TAPDELAY_BYPASS_ENABLE) &&
182 (value != PM_TAPDELAY_BYPASS_DISABLE)) || (type >= PM_TAPDELAY_MAX))) {
183 status = PM_RET_ERROR_ARGS;
184 } else {
185 status = pm_mmio_write(IOU_TAPDLY_BYPASS, TAP_DELAY_MASK,
186 value << type, flag);
187 }
188
189 return status;
190 }
191
192 /**
193 * pm_ioctl_sd_dll_reset() - Reset DLL logic.
194 * @nid: Node ID of the device.
195 * @type: Reset type.
196 * @flag: 0 - Call from secure source.
197 * 1 - Call from non-secure source.
198 *
199 * This function resets DLL logic for the SD device.
200 *
201 * Return: Returns status, either success or error+reason.
202 *
203 */
pm_ioctl_sd_dll_reset(enum pm_node_id nid,uint32_t type,uint32_t flag)204 static enum pm_ret_status pm_ioctl_sd_dll_reset(enum pm_node_id nid,
205 uint32_t type,
206 uint32_t flag)
207 {
208 uint32_t mask, val;
209 enum pm_ret_status ret;
210
211 if (nid == NODE_SD_0) {
212 mask = ZYNQMP_SD0_DLL_RST_MASK;
213 val = ZYNQMP_SD0_DLL_RST;
214 } else if (nid == NODE_SD_1) {
215 mask = ZYNQMP_SD1_DLL_RST_MASK;
216 val = ZYNQMP_SD1_DLL_RST;
217 } else {
218 return PM_RET_ERROR_ARGS;
219 }
220
221 switch (type) {
222 case PM_DLL_RESET_ASSERT:
223 case PM_DLL_RESET_PULSE:
224 ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, val, flag);
225 if (ret != PM_RET_SUCCESS) {
226 return ret;
227 }
228
229 if (type == PM_DLL_RESET_ASSERT) {
230 break;
231 }
232 mdelay(1);
233 /* Fallthrough */
234 case PM_DLL_RESET_RELEASE:
235 ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, 0, flag);
236 break;
237 default:
238 ret = PM_RET_ERROR_ARGS;
239 break;
240 }
241
242 return ret;
243 }
244
245 /**
246 * pm_ioctl_sd_set_tapdelay() - Set tap delay for the SD device.
247 * @nid: Node ID of the device.
248 * @type: Type of tap delay to set (input/output).
249 * @value: Value to set fot the tap delay.
250 * @flag: 0 - Call from secure source.
251 * 1 - Call from non-secure source.
252 *
253 * This function sets input/output tap delay for the SD device.
254 *
255 * Return: Returns status, either success or error+reason.
256 *
257 */
pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,enum tap_delay_type type,uint32_t value,uint32_t flag)258 static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,
259 enum tap_delay_type type,
260 uint32_t value,
261 uint32_t flag)
262 {
263 uint32_t shift;
264 enum pm_ret_status ret;
265 uint32_t val, mask;
266
267 if (nid == NODE_SD_0) {
268 shift = 0;
269 mask = ZYNQMP_SD0_DLL_RST_MASK;
270 } else if (nid == NODE_SD_1) {
271 shift = ZYNQMP_SD_TAP_OFFSET;
272 mask = ZYNQMP_SD1_DLL_RST_MASK;
273 } else {
274 return PM_RET_ERROR_ARGS;
275 }
276
277 ret = pm_mmio_read(ZYNQMP_SD_DLL_CTRL, &val, flag);
278 if (ret != PM_RET_SUCCESS) {
279 return ret;
280 }
281
282 if ((val & mask) == 0U) {
283 ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT, flag);
284 if (ret != PM_RET_SUCCESS) {
285 return ret;
286 }
287 }
288
289 if (type == PM_TAPDELAY_INPUT) {
290 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
291 (uint64_t)(ZYNQMP_SD_ITAPCHGWIN_MASK << shift),
292 (ZYNQMP_SD_ITAPCHGWIN << shift),
293 flag);
294
295 if (ret != PM_RET_SUCCESS) {
296 goto reset_release;
297 }
298
299 if (value == 0U) {
300 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
301 (uint64_t)(ZYNQMP_SD_ITAPDLYENA_MASK <<
302 shift), 0, flag);
303 } else {
304 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
305 (uint64_t)(ZYNQMP_SD_ITAPDLYENA_MASK <<
306 shift), (uint64_t)(ZYNQMP_SD_ITAPDLYENA <<
307 shift), flag);
308 }
309
310 if (ret != PM_RET_SUCCESS) {
311 goto reset_release;
312 }
313
314 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
315 (uint64_t)(ZYNQMP_SD_ITAPDLYSEL_MASK << shift),
316 (value << shift),
317 flag);
318
319 if (ret != PM_RET_SUCCESS) {
320 goto reset_release;
321 }
322
323 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
324 (uint64_t)(ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0,
325 flag);
326 } else if (type == PM_TAPDELAY_OUTPUT) {
327 ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
328 (uint64_t)(ZYNQMP_SD_OTAPDLYENA_MASK << shift), 0,
329 flag);
330
331 if (ret != PM_RET_SUCCESS) {
332 goto reset_release;
333 }
334
335 ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
336 (uint64_t)(ZYNQMP_SD_OTAPDLYSEL_MASK << shift),
337 (value << shift),
338 flag);
339 } else {
340 ret = PM_RET_ERROR_ARGS;
341 }
342
343 reset_release:
344 if ((val & mask) == 0) {
345 (void)pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE, flag);
346 }
347
348 return ret;
349 }
350
351 /**
352 * pm_ioctl_set_pll_frac_mode() - Ioctl function for setting pll mode.
353 * @pll: PLL clock id.
354 * @mode: Mode fraction/integar.
355 *
356 * This function sets PLL mode.
357 *
358 * Return: Returns status, either success or error+reason.
359 *
360 */
pm_ioctl_set_pll_frac_mode(uint32_t pll,uint32_t mode)361 static enum pm_ret_status pm_ioctl_set_pll_frac_mode
362 (uint32_t pll, uint32_t mode)
363 {
364 return pm_clock_set_pll_mode(pll, mode);
365 }
366
367 /**
368 * pm_ioctl_get_pll_frac_mode() - Ioctl function for getting pll mode.
369 * @pll: PLL clock id.
370 * @mode: Mode fraction/integar.
371 *
372 * This function return current PLL mode.
373 *
374 * Return: Returns status, either success or error+reason.
375 *
376 */
pm_ioctl_get_pll_frac_mode(uint32_t pll,uint32_t * mode)377 static enum pm_ret_status pm_ioctl_get_pll_frac_mode
378 (uint32_t pll, uint32_t *mode)
379 {
380 return pm_clock_get_pll_mode(pll, mode);
381 }
382
383 /**
384 * pm_ioctl_set_pll_frac_data() - Ioctl function for setting pll fraction data.
385 * @pll: PLL clock id.
386 * @data: fraction data.
387 * @flag: 0 - Call from secure source.
388 * 1 - Call from non-secure source.
389 *
390 * This function sets fraction data.
391 * It is valid for fraction mode only.
392 *
393 * Return: Returns status, either success or error+reason.
394 *
395 */
pm_ioctl_set_pll_frac_data(uint32_t pll,uint32_t data,uint32_t flag)396 static enum pm_ret_status pm_ioctl_set_pll_frac_data
397 (uint32_t pll, uint32_t data, uint32_t flag)
398 {
399 enum pm_node_id pll_nid;
400 enum pm_ret_status status;
401
402 /* Get PLL node ID using PLL clock ID */
403 status = pm_clock_get_pll_node_id(pll, &pll_nid);
404 if (status == PM_RET_SUCCESS) {
405 status = pm_pll_set_parameter(pll_nid, PM_PLL_PARAM_DATA,
406 data, flag);
407 }
408
409 return status;
410 }
411
412 /**
413 * pm_ioctl_get_pll_frac_data() - Ioctl function for getting pll fraction data.
414 * @pll: PLL clock id.
415 * @data: fraction data.
416 * @flag: 0 - Call from secure source.
417 * 1 - Call from non-secure source.
418 *
419 * This function returns fraction data value.
420 *
421 * Return: Returns status, either success or error+reason.
422 *
423 */
pm_ioctl_get_pll_frac_data(uint32_t pll,uint32_t * data,uint32_t flag)424 static enum pm_ret_status pm_ioctl_get_pll_frac_data
425 (uint32_t pll, uint32_t *data, uint32_t flag)
426 {
427 enum pm_node_id pll_nid;
428 enum pm_ret_status status;
429
430 /* Get PLL node ID using PLL clock ID */
431 status = pm_clock_get_pll_node_id(pll, &pll_nid);
432 if (status == PM_RET_SUCCESS) {
433 status = pm_pll_get_parameter(pll_nid, PM_PLL_PARAM_DATA,
434 data, flag);
435 }
436
437 return status;
438 }
439
440 /**
441 * pm_ioctl_write_ggs() - Ioctl function for writing global general storage
442 * (ggs).
443 * @index: GGS register index.
444 * @value: Register value to be written.
445 * @flag: 0 - Call from secure source.
446 * 1 - Call from non-secure source.
447 *
448 * This function writes value to GGS register.
449 *
450 * Return: Returns status, either success or error+reason.
451 *
452 */
pm_ioctl_write_ggs(uint32_t index,uint32_t value,uint32_t flag)453 static enum pm_ret_status pm_ioctl_write_ggs(uint32_t index,
454 uint32_t value,
455 uint32_t flag)
456 {
457 enum pm_ret_status ret_status = PM_RET_SUCCESS;
458
459 if (index >= GGS_NUM_REGS) {
460 ret_status = PM_RET_ERROR_ARGS;
461 } else {
462 ret_status = pm_mmio_write((uint64_t)GGS_BASEADDR + (index << 2),
463 0xFFFFFFFFU, value, flag);
464 }
465
466 return ret_status;
467 }
468
469 /**
470 * pm_ioctl_read_ggs() - Ioctl function for reading global general storage
471 * (ggs).
472 * @index: GGS register index.
473 * @value: Register value.
474 * @flag: 0 - Call from secure source.
475 * 1 - Call from non-secure source.
476 *
477 * This function returns GGS register value.
478 *
479 * Return: Returns status, either success or error+reason.
480 *
481 */
pm_ioctl_read_ggs(uint32_t index,uint32_t * value,uint32_t flag)482 static enum pm_ret_status pm_ioctl_read_ggs(uint32_t index,
483 uint32_t *value,
484 uint32_t flag)
485 {
486 enum pm_ret_status ret_status = PM_RET_SUCCESS;
487
488 if (index >= GGS_NUM_REGS) {
489 ret_status = PM_RET_ERROR_ARGS;
490 } else {
491 ret_status = pm_mmio_read((uint64_t)GGS_BASEADDR + (index << 2),
492 value, flag);
493 }
494
495 return ret_status;
496 }
497
498 /**
499 * pm_ioctl_write_pggs() - Ioctl function for writing persistent global general
500 * storage (pggs).
501 * @index: PGGS register index.
502 * @value: Register value to be written.
503 * @flag: 0 - Call from secure source.
504 * 1 - Call from non-secure source.
505 *
506 * This function writes value to PGGS register.
507 *
508 * Return: Returns status, either success or error+reason.
509 *
510 */
pm_ioctl_write_pggs(uint32_t index,uint32_t value,uint32_t flag)511 static enum pm_ret_status pm_ioctl_write_pggs(uint32_t index,
512 uint32_t value,
513 uint32_t flag)
514 {
515 enum pm_ret_status ret_status = PM_RET_SUCCESS;
516
517 if (index >= PGGS_NUM_REGS) {
518 ret_status = PM_RET_ERROR_ARGS;
519 } else {
520 ret_status = pm_mmio_write((uint64_t)PGGS_BASEADDR + (index << 2),
521 0xFFFFFFFFU, value, flag);
522 }
523
524 return ret_status;
525 }
526
527 /**
528 * pm_ioctl_afi() - Ioctl function for writing afi values.
529 * @index: AFI register index.
530 * @value: Register value to be written.
531 * @flag: 0 - Call from secure source.
532 * 1 - Call from non-secure source.
533 *
534 * Return: Returns status, either success or error+reason.
535 *
536 */
pm_ioctl_afi(uint32_t index,uint32_t value,uint32_t flag)537 static enum pm_ret_status pm_ioctl_afi(uint32_t index,
538 uint32_t value,
539 uint32_t flag)
540 {
541 uint32_t mask;
542 enum pm_ret_status status = PM_RET_ERROR_ARGS;
543 const uint32_t regarr[] = {0xFD360000U,
544 0xFD360014U,
545 0xFD370000U,
546 0xFD370014U,
547 0xFD380000U,
548 0xFD380014U,
549 0xFD390000U,
550 0xFD390014U,
551 0xFD3a0000U,
552 0xFD3a0014U,
553 0xFD3b0000U,
554 0xFD3b0014U,
555 0xFF9b0000U,
556 0xFF9b0014U,
557 0xFD615000U,
558 0xFF419000U,
559 };
560
561 if (index < ARRAY_SIZE(regarr)) {
562 if (index <= AFIFM6_WRCTRL) {
563 mask = FABRIC_WIDTH;
564 } else {
565 mask = 0xf00;
566 }
567 status = pm_mmio_write(regarr[index], mask, value, flag);
568 }
569
570 return status;
571 }
572
573 /**
574 * pm_ioctl_read_pggs() - Ioctl function for reading persistent global general
575 * storage (pggs).
576 * @index: PGGS register index.
577 * @value: Register value.
578 * @flag: 0 - Call from secure source.
579 * 1 - Call from non-secure source.
580 *
581 * This function returns PGGS register value.
582 *
583 * Return: Returns status, either success or error+reason.
584 *
585 */
pm_ioctl_read_pggs(uint32_t index,uint32_t * value,uint32_t flag)586 static enum pm_ret_status pm_ioctl_read_pggs(uint32_t index,
587 uint32_t *value,
588 uint32_t flag)
589 {
590 enum pm_ret_status status = 0;
591
592 if (index >= PGGS_NUM_REGS) {
593 status = PM_RET_ERROR_ARGS;
594 } else {
595 status = pm_mmio_read((uint64_t)PGGS_BASEADDR + (index << 2),
596 value, flag);
597 }
598
599 return status;
600 }
601
602 /**
603 * pm_ioctl_ulpi_reset() - Ioctl function for performing ULPI reset.
604 *
605 * @flag: 0 - Call from secure source.
606 * 1 - Call from non-secure source.
607 *
608 * Return: Returns status, either success or error+reason.
609 *
610 * This function peerforms the ULPI reset sequence for resetting
611 * the ULPI transceiver.
612 */
pm_ioctl_ulpi_reset(uint32_t flag)613 static enum pm_ret_status pm_ioctl_ulpi_reset(uint32_t flag)
614 {
615 enum pm_ret_status ret;
616
617 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
618 ZYNQMP_ULPI_RESET_VAL_HIGH, flag);
619 if (ret != PM_RET_SUCCESS) {
620 goto exit_label;
621 }
622
623 /* Drive ULPI assert for atleast 1ms */
624 mdelay(1);
625
626 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
627 ZYNQMP_ULPI_RESET_VAL_LOW, flag);
628 if (ret != PM_RET_SUCCESS) {
629 goto exit_label;
630 }
631
632 /* Drive ULPI de-assert for atleast 1ms */
633 mdelay(1);
634
635 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
636 ZYNQMP_ULPI_RESET_VAL_HIGH, flag);
637
638 exit_label:
639 return ret;
640 }
641
642 /**
643 * pm_ioctl_set_boot_health_status() - Ioctl for setting healthy boot status.
644 * @value: Value to write.
645 * @flag: 0 - Call from secure source.
646 * 1 - Call from non-secure source.
647 *
648 * This function sets healthy bit value to indicate boot health status
649 * to firmware.
650 *
651 * Return: Returns status, either success or error+reason.
652 *
653 */
pm_ioctl_set_boot_health_status(uint32_t value,uint32_t flag)654 static enum pm_ret_status pm_ioctl_set_boot_health_status(uint32_t value,
655 uint32_t flag)
656 {
657 return pm_mmio_write(PMU_GLOBAL_GEN_STORAGE4,
658 PM_BOOT_HEALTH_STATUS_MASK, value, flag);
659 }
660
661 /**
662 * pm_api_ioctl() - PM IOCTL API for device control and configs.
663 * @nid: Node ID of the device.
664 * @ioctl_id: ID of the requested IOCTL.
665 * @arg1: Argument 1 to requested IOCTL call.
666 * @arg2: Argument 2 to requested IOCTL call.
667 * @value: Returned output value.
668 * @flag: 0 - Call from secure source.
669 * 1 - Call from non-secure source.
670 *
671 * This function calls IOCTL to firmware for device control and configuration.
672 *
673 * Return: Returns status, either success or error+reason.
674 *
675 */
pm_api_ioctl(enum pm_node_id nid,uint32_t ioctl_id,uint32_t arg1,uint32_t arg2,uint32_t * value,uint32_t flag)676 enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
677 uint32_t ioctl_id,
678 uint32_t arg1,
679 uint32_t arg2,
680 uint32_t *value,
681 uint32_t flag)
682 {
683 enum pm_ret_status ret;
684 uint32_t payload[PAYLOAD_ARG_CNT];
685
686 switch (ioctl_id) {
687 case IOCTL_GET_RPU_OPER_MODE:
688 ret = pm_ioctl_get_rpu_oper_mode(value);
689 break;
690 case IOCTL_SET_RPU_OPER_MODE:
691 ret = pm_ioctl_set_rpu_oper_mode(arg1);
692 break;
693 case IOCTL_RPU_BOOT_ADDR_CONFIG:
694 ret = pm_ioctl_config_boot_addr(nid, arg1);
695 break;
696 case IOCTL_TCM_COMB_CONFIG:
697 ret = pm_ioctl_config_tcm_comb(arg1);
698 break;
699 case IOCTL_SET_TAPDELAY_BYPASS:
700 ret = pm_ioctl_set_tapdelay_bypass(arg1, arg2, flag);
701 break;
702 case IOCTL_SD_DLL_RESET:
703 ret = pm_ioctl_sd_dll_reset(nid, arg1, flag);
704 break;
705 case IOCTL_SET_SD_TAPDELAY:
706 ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2, flag);
707 break;
708 case IOCTL_SET_PLL_FRAC_MODE:
709 ret = pm_ioctl_set_pll_frac_mode(arg1, arg2);
710 break;
711 case IOCTL_GET_PLL_FRAC_MODE:
712 ret = pm_ioctl_get_pll_frac_mode(arg1, value);
713 break;
714 case IOCTL_SET_PLL_FRAC_DATA:
715 ret = pm_ioctl_set_pll_frac_data(arg1, arg2, flag);
716 break;
717 case IOCTL_GET_PLL_FRAC_DATA:
718 ret = pm_ioctl_get_pll_frac_data(arg1, value, flag);
719 break;
720 case IOCTL_WRITE_GGS:
721 ret = pm_ioctl_write_ggs(arg1, arg2, flag);
722 break;
723 case IOCTL_READ_GGS:
724 ret = pm_ioctl_read_ggs(arg1, value, flag);
725 break;
726 case IOCTL_WRITE_PGGS:
727 ret = pm_ioctl_write_pggs(arg1, arg2, flag);
728 break;
729 case IOCTL_READ_PGGS:
730 ret = pm_ioctl_read_pggs(arg1, value, flag);
731 break;
732 case IOCTL_ULPI_RESET:
733 ret = pm_ioctl_ulpi_reset(flag);
734 break;
735 case IOCTL_SET_BOOT_HEALTH_STATUS:
736 ret = pm_ioctl_set_boot_health_status(arg1, flag);
737 break;
738 case IOCTL_AFI:
739 ret = pm_ioctl_afi(arg1, arg2, flag);
740 break;
741 default:
742 /* Send request to the PMU */
743 PM_PACK_PAYLOAD5(payload, flag, PM_IOCTL, nid, ioctl_id, arg1, arg2);
744
745 ret = pm_ipi_send_sync(primary_proc, payload, value, 1);
746 break;
747 }
748
749 return ret;
750 }
751
752 /**
753 * tfa_ioctl_bitmask() - API to get supported IOCTL ID mask.
754 * @bit_mask: Returned bit mask of supported IOCTL IDs.
755 * @flag: 0 - Call from secure source.
756 * 1 - Call from non-secure source.
757 *
758 * Return: 0 success, negative value for errors.
759 *
760 */
tfa_ioctl_bitmask(uint32_t * bit_mask,uint32_t flag)761 enum pm_ret_status tfa_ioctl_bitmask(uint32_t *bit_mask, uint32_t flag)
762 {
763 const uint8_t supported_ids[] = {
764 IOCTL_GET_RPU_OPER_MODE,
765 IOCTL_SET_RPU_OPER_MODE,
766 IOCTL_RPU_BOOT_ADDR_CONFIG,
767 IOCTL_TCM_COMB_CONFIG,
768 IOCTL_SET_TAPDELAY_BYPASS,
769 IOCTL_SD_DLL_RESET,
770 IOCTL_SET_SD_TAPDELAY,
771 IOCTL_SET_PLL_FRAC_MODE,
772 IOCTL_GET_PLL_FRAC_MODE,
773 IOCTL_SET_PLL_FRAC_DATA,
774 IOCTL_GET_PLL_FRAC_DATA,
775 IOCTL_WRITE_GGS,
776 IOCTL_READ_GGS,
777 IOCTL_WRITE_PGGS,
778 IOCTL_READ_PGGS,
779 IOCTL_ULPI_RESET,
780 IOCTL_SET_BOOT_HEALTH_STATUS,
781 IOCTL_AFI,
782 };
783 uint8_t i, ioctl_id;
784 enum pm_ret_status ret = PM_RET_SUCCESS;
785
786 for (i = 0U; i < ARRAY_SIZE(supported_ids); i++) {
787 ioctl_id = supported_ids[i];
788 if (ioctl_id >= 64U) {
789 ret = PM_RET_ERROR_NOTSUPPORTED;
790 break;
791 }
792 ret = check_api_dependency(ioctl_id, flag);
793 if (ret == PM_RET_SUCCESS) {
794 bit_mask[ioctl_id / 32U] |= BIT(ioctl_id % 32U);
795 }
796 }
797
798 return ret;
799 }
800