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