blob: f12143a37e02d253560e029d9173273658b238ee [file] [log] [blame]
Rajan Vaja5529a012018-01-17 02:39:23 -08001/*
Ronak Jain325bad12021-12-21 01:39:59 -08002 * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
Rajan Vaja5529a012018-01-17 02:39:23 -08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
8 * ZynqMP system level PM-API functions for ioctl.
9 */
10
11#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000012#include <drivers/delay_timer.h>
13#include <lib/mmio.h>
14#include <plat/common/platform.h>
Jolly Shah16fe5ab2019-01-08 11:16:16 -080015#include <zynqmp_def.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016
Rajan Vaja35116132018-01-17 02:39:25 -080017#include "pm_api_clock.h"
Rajan Vaja5529a012018-01-17 02:39:23 -080018#include "pm_api_ioctl.h"
19#include "pm_api_sys.h"
20#include "pm_client.h"
21#include "pm_common.h"
22#include "pm_ipi.h"
Rajan Vaja5529a012018-01-17 02:39:23 -080023
24/**
25 * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode
26 * @mode Buffer to store value of oper mode(Split/Lock-step)
27 *
28 * This function provides current configured RPU operational mode.
29 *
30 * @return Returns status, either success or error+reason
31 */
32static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(unsigned int *mode)
33{
34 unsigned int val;
35
36 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
37 val &= ZYNQMP_SLSPLIT_MASK;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +053038 if (val == 0) {
Rajan Vaja5529a012018-01-17 02:39:23 -080039 *mode = PM_RPU_MODE_LOCKSTEP;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +053040 } else {
Jolly Shah69fb5bf2018-02-07 16:25:41 -080041 *mode = PM_RPU_MODE_SPLIT;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +053042 }
Rajan Vaja5529a012018-01-17 02:39:23 -080043
44 return PM_RET_SUCCESS;
45}
46
47/**
48 * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode
49 * @mode Value to set for oper mode(Split/Lock-step)
50 *
51 * This function configures RPU operational mode(Split/Lock-step).
52 * It also sets TCM combined mode in RPU lock-step and TCM non-combined
53 * mode for RPU split mode. In case of Lock step mode, RPU1's output is
54 * clamped.
55 *
56 * @return Returns status, either success or error+reason
57 */
58static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(unsigned int mode)
59{
60 unsigned int val;
61
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +053062 if (mmio_read_32(CRL_APB_RST_LPD_TOP) & CRL_APB_RPU_AMBA_RESET) {
Rajan Vaja5529a012018-01-17 02:39:23 -080063 return PM_RET_ERROR_ACCESS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +053064 }
Rajan Vaja5529a012018-01-17 02:39:23 -080065
66 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
67
68 if (mode == PM_RPU_MODE_SPLIT) {
69 val |= ZYNQMP_SLSPLIT_MASK;
70 val &= ~ZYNQMP_TCM_COMB_MASK;
71 val &= ~ZYNQMP_SLCLAMP_MASK;
72 } else if (mode == PM_RPU_MODE_LOCKSTEP) {
73 val &= ~ZYNQMP_SLSPLIT_MASK;
74 val |= ZYNQMP_TCM_COMB_MASK;
75 val |= ZYNQMP_SLCLAMP_MASK;
76 } else {
77 return PM_RET_ERROR_ARGS;
78 }
79
80 mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
81
82 return PM_RET_SUCCESS;
83}
84
85/**
86 * pm_ioctl_config_boot_addr() - Configure RPU boot address
87 * @nid Node ID of RPU
88 * @value Value to set for boot address (TCM/OCM)
89 *
90 * This function configures RPU boot address(memory).
91 *
92 * @return Returns status, either success or error+reason
93 */
94static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid,
95 unsigned int value)
96{
97 unsigned int rpu_cfg_addr, val;
98
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +053099 if (nid == NODE_RPU_0) {
Rajan Vaja5529a012018-01-17 02:39:23 -0800100 rpu_cfg_addr = ZYNQMP_RPU0_CFG;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530101 } else if (nid == NODE_RPU_1) {
Rajan Vaja5529a012018-01-17 02:39:23 -0800102 rpu_cfg_addr = ZYNQMP_RPU1_CFG;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530103 } else {
Rajan Vaja5529a012018-01-17 02:39:23 -0800104 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530105 }
Rajan Vaja5529a012018-01-17 02:39:23 -0800106
107 val = mmio_read_32(rpu_cfg_addr);
108
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530109 if (value == PM_RPU_BOOTMEM_LOVEC) {
Rajan Vaja5529a012018-01-17 02:39:23 -0800110 val &= ~ZYNQMP_VINITHI_MASK;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530111 } else if (value == PM_RPU_BOOTMEM_HIVEC) {
Rajan Vaja5529a012018-01-17 02:39:23 -0800112 val |= ZYNQMP_VINITHI_MASK;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530113 } else {
Rajan Vaja5529a012018-01-17 02:39:23 -0800114 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530115 }
Rajan Vaja5529a012018-01-17 02:39:23 -0800116
117 mmio_write_32(rpu_cfg_addr, val);
118
119 return PM_RET_SUCCESS;
120}
121
122/**
123 * pm_ioctl_config_tcm_comb() - Configure TCM combined mode
124 * @value Value to set (Split/Combined)
125 *
126 * This function configures TCM to be in split mode or combined
127 * mode.
128 *
129 * @return Returns status, either success or error+reason
130 */
131static enum pm_ret_status pm_ioctl_config_tcm_comb(unsigned int value)
132{
133 unsigned int val;
134
135 val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
136
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530137 if (value == PM_RPU_TCM_SPLIT) {
Rajan Vaja5529a012018-01-17 02:39:23 -0800138 val &= ~ZYNQMP_TCM_COMB_MASK;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530139 } else if (value == PM_RPU_TCM_COMB) {
Rajan Vaja5529a012018-01-17 02:39:23 -0800140 val |= ZYNQMP_TCM_COMB_MASK;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530141 } else {
Rajan Vaja5529a012018-01-17 02:39:23 -0800142 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530143 }
Rajan Vaja5529a012018-01-17 02:39:23 -0800144
145 mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
146
147 return PM_RET_SUCCESS;
148}
149
150/**
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800151 * pm_ioctl_set_tapdelay_bypass() - Enable/Disable tap delay bypass
152 * @type Type of tap delay to enable/disable (e.g. QSPI)
153 * @value Enable/Disable
154 *
155 * This function enable/disable tap delay bypass.
156 *
157 * @return Returns status, either success or error+reason
158 */
159static enum pm_ret_status pm_ioctl_set_tapdelay_bypass(unsigned int type,
160 unsigned int value)
161{
162 if ((value != PM_TAPDELAY_BYPASS_ENABLE &&
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530163 value != PM_TAPDELAY_BYPASS_DISABLE) || type >= PM_TAPDELAY_MAX) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800164 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530165 }
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800166
167 return pm_mmio_write(IOU_TAPDLY_BYPASS, TAP_DELAY_MASK, value << type);
168}
169
170/**
171 * pm_ioctl_set_sgmii_mode() - Set SGMII mode for the GEM device
172 * @nid Node ID of the device
173 * @value Enable/Disable
174 *
175 * This function enable/disable SGMII mode for the GEM device.
176 * While enabling SGMII mode, it also ties the GEM PCS Signal
177 * Detect to 1 and selects EMIO for RX clock generation.
178 *
179 * @return Returns status, either success or error+reason
180 */
181static enum pm_ret_status pm_ioctl_set_sgmii_mode(enum pm_node_id nid,
182 unsigned int value)
183{
184 unsigned int val, mask, shift;
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800185 enum pm_ret_status ret;
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800186
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530187 if (value != PM_SGMII_DISABLE && value != PM_SGMII_ENABLE) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800188 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530189 }
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800190
191 switch (nid) {
192 case NODE_ETH_0:
193 shift = 0;
194 break;
195 case NODE_ETH_1:
196 shift = 1;
197 break;
198 case NODE_ETH_2:
199 shift = 2;
200 break;
201 case NODE_ETH_3:
202 shift = 3;
203 break;
204 default:
205 return PM_RET_ERROR_ARGS;
206 }
207
208 if (value == PM_SGMII_DISABLE) {
209 mask = GEM_SGMII_MASK << GEM_CLK_CTRL_OFFSET * shift;
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800210 ret = pm_mmio_write(IOU_GEM_CLK_CTRL, mask, 0U);
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800211 } else {
212 /* Tie the GEM PCS Signal Detect to 1 */
213 mask = SGMII_SD_MASK << SGMII_SD_OFFSET * shift;
214 val = SGMII_PCS_SD_1 << SGMII_SD_OFFSET * shift;
215 ret = pm_mmio_write(IOU_GEM_CTRL, mask, val);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530216 if (ret != PM_RET_SUCCESS) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800217 return ret;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530218 }
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800219
220 /* Set the GEM to SGMII mode */
221 mask = GEM_CLK_CTRL_MASK << GEM_CLK_CTRL_OFFSET * shift;
222 val = GEM_RX_SRC_SEL_GTR | GEM_SGMII_MODE;
223 val <<= GEM_CLK_CTRL_OFFSET * shift;
224 ret = pm_mmio_write(IOU_GEM_CLK_CTRL, mask, val);
225 }
226
227 return ret;
228}
229
230/**
231 * pm_ioctl_sd_dll_reset() - Reset DLL logic
232 * @nid Node ID of the device
233 * @type Reset type
234 *
235 * This function resets DLL logic for the SD device.
236 *
237 * @return Returns status, either success or error+reason
238 */
239static enum pm_ret_status pm_ioctl_sd_dll_reset(enum pm_node_id nid,
240 unsigned int type)
241{
242 unsigned int mask, val;
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800243 enum pm_ret_status ret;
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800244
245 if (nid == NODE_SD_0) {
246 mask = ZYNQMP_SD0_DLL_RST_MASK;
247 val = ZYNQMP_SD0_DLL_RST;
248 } else if (nid == NODE_SD_1) {
249 mask = ZYNQMP_SD1_DLL_RST_MASK;
250 val = ZYNQMP_SD1_DLL_RST;
251 } else {
252 return PM_RET_ERROR_ARGS;
253 }
254
255 switch (type) {
256 case PM_DLL_RESET_ASSERT:
257 case PM_DLL_RESET_PULSE:
258 ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, val);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530259 if (ret != PM_RET_SUCCESS) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800260 return ret;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530261 }
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800262
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530263 if (type == PM_DLL_RESET_ASSERT) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800264 break;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530265 }
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800266 mdelay(1);
Daniel Boulby8942a1b2018-06-22 14:16:03 +0100267 /* Fallthrough */
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800268 case PM_DLL_RESET_RELEASE:
269 ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, 0);
270 break;
271 default:
272 ret = PM_RET_ERROR_ARGS;
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800273 break;
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800274 }
275
276 return ret;
277}
278
279/**
280 * pm_ioctl_sd_set_tapdelay() - Set tap delay for the SD device
281 * @nid Node ID of the device
282 * @type Type of tap delay to set (input/output)
283 * @value Value to set fot the tap delay
284 *
285 * This function sets input/output tap delay for the SD device.
286 *
287 * @return Returns status, either success or error+reason
288 */
289static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,
290 enum tap_delay_type type,
291 unsigned int value)
292{
293 unsigned int shift;
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800294 enum pm_ret_status ret;
Sai Krishna Potthuriad48c502020-10-20 07:00:06 -0600295 unsigned int val, mask;
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800296
Sai Krishna Potthuriad48c502020-10-20 07:00:06 -0600297 if (nid == NODE_SD_0) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800298 shift = 0;
Sai Krishna Potthuriad48c502020-10-20 07:00:06 -0600299 mask = ZYNQMP_SD0_DLL_RST_MASK;
300 } else if (nid == NODE_SD_1) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800301 shift = ZYNQMP_SD_TAP_OFFSET;
Sai Krishna Potthuriad48c502020-10-20 07:00:06 -0600302 mask = ZYNQMP_SD1_DLL_RST_MASK;
303 } else {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800304 return PM_RET_ERROR_ARGS;
Sai Krishna Potthuriad48c502020-10-20 07:00:06 -0600305 }
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800306
Sai Krishna Potthuriad48c502020-10-20 07:00:06 -0600307 ret = pm_mmio_read(ZYNQMP_SD_DLL_CTRL, &val);
308 if (ret != PM_RET_SUCCESS) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800309 return ret;
Sai Krishna Potthuriad48c502020-10-20 07:00:06 -0600310 }
311
312 if ((val & mask) == 0) {
313 ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT);
314 if (ret != PM_RET_SUCCESS) {
315 return ret;
316 }
317 }
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800318
319 if (type == PM_TAPDELAY_INPUT) {
320 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800321 (ZYNQMP_SD_ITAPCHGWIN_MASK << shift),
322 (ZYNQMP_SD_ITAPCHGWIN << shift));
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530323
324 if (ret != PM_RET_SUCCESS) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800325 goto reset_release;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530326 }
327
328 if (value == 0) {
Sai Krishna Potthuri15da5822020-10-30 00:09:43 -0600329 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
330 (ZYNQMP_SD_ITAPDLYENA_MASK <<
331 shift), 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530332 } else {
Sai Krishna Potthuri15da5822020-10-30 00:09:43 -0600333 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
334 (ZYNQMP_SD_ITAPDLYENA_MASK <<
335 shift), (ZYNQMP_SD_ITAPDLYENA <<
336 shift));
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530337 }
338
339 if (ret != PM_RET_SUCCESS) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800340 goto reset_release;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530341 }
342
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800343 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800344 (ZYNQMP_SD_ITAPDLYSEL_MASK << shift),
345 (value << shift));
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530346
347 if (ret != PM_RET_SUCCESS) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800348 goto reset_release;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530349 }
350
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800351 ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800352 (ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0);
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800353 } else if (type == PM_TAPDELAY_OUTPUT) {
354 ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
Sai Krishna Potthuri15da5822020-10-30 00:09:43 -0600355 (ZYNQMP_SD_OTAPDLYENA_MASK << shift), 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530356
357 if (ret != PM_RET_SUCCESS) {
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800358 goto reset_release;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530359 }
360
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800361 ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800362 (ZYNQMP_SD_OTAPDLYSEL_MASK << shift),
363 (value << shift));
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800364 } else {
365 ret = PM_RET_ERROR_ARGS;
366 }
367
368reset_release:
Sai Krishna Potthuriad48c502020-10-20 07:00:06 -0600369 if ((val & mask) == 0) {
370 (void)pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE);
371 }
372
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800373 return ret;
374}
375
376/**
Rajan Vaja35116132018-01-17 02:39:25 -0800377 * pm_ioctl_set_pll_frac_mode() - Ioctl function for
378 * setting pll mode
Jolly Shahcb5bc752019-01-02 12:46:46 -0800379 * @pll PLL clock id
Rajan Vaja35116132018-01-17 02:39:25 -0800380 * @mode Mode fraction/integar
381 *
382 * This function sets PLL mode
383 *
384 * @return Returns status, either success or error+reason
385 */
386static enum pm_ret_status pm_ioctl_set_pll_frac_mode
387 (unsigned int pll, unsigned int mode)
388{
Jolly Shahcb5bc752019-01-02 12:46:46 -0800389 return pm_clock_set_pll_mode(pll, mode);
Rajan Vaja35116132018-01-17 02:39:25 -0800390}
391
392/**
393 * pm_ioctl_get_pll_frac_mode() - Ioctl function for
394 * getting pll mode
Jolly Shah77eb52f2019-01-02 12:49:21 -0800395 * @pll PLL clock id
Rajan Vaja35116132018-01-17 02:39:25 -0800396 * @mode Mode fraction/integar
397 *
398 * This function return current PLL mode
399 *
400 * @return Returns status, either success or error+reason
401 */
402static enum pm_ret_status pm_ioctl_get_pll_frac_mode
403 (unsigned int pll, unsigned int *mode)
404{
Jolly Shah77eb52f2019-01-02 12:49:21 -0800405 return pm_clock_get_pll_mode(pll, mode);
Rajan Vaja35116132018-01-17 02:39:25 -0800406}
407
408/**
409 * pm_ioctl_set_pll_frac_data() - Ioctl function for
410 * setting pll fraction data
Jolly Shah68116ef2019-01-02 12:42:56 -0800411 * @pll PLL clock id
Rajan Vaja35116132018-01-17 02:39:25 -0800412 * @data fraction data
413 *
414 * This function sets fraction data.
415 * It is valid for fraction mode only.
416 *
417 * @return Returns status, either success or error+reason
418 */
419static enum pm_ret_status pm_ioctl_set_pll_frac_data
420 (unsigned int pll, unsigned int data)
421{
Jolly Shah68116ef2019-01-02 12:42:56 -0800422 enum pm_node_id pll_nid;
423 enum pm_ret_status status;
424
425 /* Get PLL node ID using PLL clock ID */
426 status = pm_clock_get_pll_node_id(pll, &pll_nid);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530427 if (status != PM_RET_SUCCESS) {
Jolly Shah68116ef2019-01-02 12:42:56 -0800428 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530429 }
Jolly Shah68116ef2019-01-02 12:42:56 -0800430
431 return pm_pll_set_parameter(pll_nid, PM_PLL_PARAM_DATA, data);
Rajan Vaja35116132018-01-17 02:39:25 -0800432}
433
434/**
435 * pm_ioctl_get_pll_frac_data() - Ioctl function for
436 * getting pll fraction data
Jolly Shahb4c99462019-01-02 12:40:17 -0800437 * @pll PLL clock id
Rajan Vaja35116132018-01-17 02:39:25 -0800438 * @data fraction data
439 *
440 * This function returns fraction data value.
441 *
442 * @return Returns status, either success or error+reason
443 */
444static enum pm_ret_status pm_ioctl_get_pll_frac_data
445 (unsigned int pll, unsigned int *data)
446{
Jolly Shahb4c99462019-01-02 12:40:17 -0800447 enum pm_node_id pll_nid;
448 enum pm_ret_status status;
449
450 /* Get PLL node ID using PLL clock ID */
451 status = pm_clock_get_pll_node_id(pll, &pll_nid);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530452 if (status != PM_RET_SUCCESS) {
Jolly Shahb4c99462019-01-02 12:40:17 -0800453 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530454 }
Jolly Shahb4c99462019-01-02 12:40:17 -0800455
456 return pm_pll_get_parameter(pll_nid, PM_PLL_PARAM_DATA, data);
Rajan Vaja35116132018-01-17 02:39:25 -0800457}
458
459/**
Rajan Vaja393c0a22018-01-17 02:39:27 -0800460 * pm_ioctl_write_ggs() - Ioctl function for writing
461 * global general storage (ggs)
462 * @index GGS register index
463 * @value Register value to be written
464 *
465 * This function writes value to GGS register.
466 *
467 * @return Returns status, either success or error+reason
468 */
469static enum pm_ret_status pm_ioctl_write_ggs(unsigned int index,
470 unsigned int value)
471{
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530472 if (index >= GGS_NUM_REGS) {
Rajan Vaja393c0a22018-01-17 02:39:27 -0800473 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530474 }
Rajan Vaja393c0a22018-01-17 02:39:27 -0800475
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800476 return pm_mmio_write(GGS_BASEADDR + (index << 2),
477 0xFFFFFFFFU, value);
Rajan Vaja393c0a22018-01-17 02:39:27 -0800478}
479
480/**
481 * pm_ioctl_read_ggs() - Ioctl function for reading
482 * global general storage (ggs)
483 * @index GGS register index
484 * @value Register value
485 *
486 * This function returns GGS register value.
487 *
488 * @return Returns status, either success or error+reason
489 */
490static enum pm_ret_status pm_ioctl_read_ggs(unsigned int index,
491 unsigned int *value)
492{
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530493 if (index >= GGS_NUM_REGS) {
Rajan Vaja393c0a22018-01-17 02:39:27 -0800494 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530495 }
Rajan Vaja393c0a22018-01-17 02:39:27 -0800496
497 return pm_mmio_read(GGS_BASEADDR + (index << 2), value);
498}
499
500/**
501 * pm_ioctl_write_pggs() - Ioctl function for writing persistent
502 * global general storage (pggs)
503 * @index PGGS register index
504 * @value Register value to be written
505 *
506 * This function writes value to PGGS register.
507 *
508 * @return Returns status, either success or error+reason
509 */
510static enum pm_ret_status pm_ioctl_write_pggs(unsigned int index,
511 unsigned int value)
512{
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530513 if (index >= PGGS_NUM_REGS) {
Rajan Vaja393c0a22018-01-17 02:39:27 -0800514 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530515 }
Rajan Vaja393c0a22018-01-17 02:39:27 -0800516
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800517 return pm_mmio_write(PGGS_BASEADDR + (index << 2),
518 0xFFFFFFFFU, value);
Rajan Vaja393c0a22018-01-17 02:39:27 -0800519}
520
521/**
Siva Durga Prasad Paladugua22b8852018-09-04 17:27:12 +0530522 * pm_ioctl_afi() - Ioctl function for writing afi values
523 *
524 * @index AFI register index
525 * @value Register value to be written
526 *
527 *
528 * @return Returns status, either success or error+reason
529 */
530static enum pm_ret_status pm_ioctl_afi(unsigned int index,
531 unsigned int value)
532{
533 unsigned int mask;
Venkatesh Yadav Abbarapued4f1e82022-04-29 09:58:30 +0530534 unsigned int regarr[] = {0xFD360000U,
535 0xFD360014U,
536 0xFD370000U,
537 0xFD370014U,
538 0xFD380000U,
539 0xFD380014U,
540 0xFD390000U,
541 0xFD390014U,
542 0xFD3a0000U,
543 0xFD3a0014U,
544 0xFD3b0000U,
545 0xFD3b0014U,
546 0xFF9b0000U,
547 0xFF9b0014U,
548 0xFD615000U,
549 0xFF419000U,
Siva Durga Prasad Paladugua22b8852018-09-04 17:27:12 +0530550 };
551
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530552 if (index >= ARRAY_SIZE(regarr)) {
Siva Durga Prasad Paladugua22b8852018-09-04 17:27:12 +0530553 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530554 }
Siva Durga Prasad Paladugua22b8852018-09-04 17:27:12 +0530555
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530556 if (index < AFIFM6_WRCTRL) {
Siva Durga Prasad Paladugua22b8852018-09-04 17:27:12 +0530557 mask = FABRIC_WIDTH;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530558 } else {
Siva Durga Prasad Paladugua22b8852018-09-04 17:27:12 +0530559 mask = 0xf00;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530560 }
Siva Durga Prasad Paladugua22b8852018-09-04 17:27:12 +0530561
562 return pm_mmio_write(regarr[index], mask, value);
563}
564
565/**
Rajan Vaja393c0a22018-01-17 02:39:27 -0800566 * pm_ioctl_read_pggs() - Ioctl function for reading persistent
567 * global general storage (pggs)
568 * @index PGGS register index
569 * @value Register value
570 *
571 * This function returns PGGS register value.
572 *
573 * @return Returns status, either success or error+reason
574 */
575static enum pm_ret_status pm_ioctl_read_pggs(unsigned int index,
576 unsigned int *value)
577{
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530578 if (index >= PGGS_NUM_REGS) {
Rajan Vaja393c0a22018-01-17 02:39:27 -0800579 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530580 }
Rajan Vaja393c0a22018-01-17 02:39:27 -0800581
582 return pm_mmio_read(PGGS_BASEADDR + (index << 2), value);
583}
584
585/**
Siva Durga Prasad Paladugued1d5cb2018-09-04 17:03:25 +0530586 * pm_ioctl_ulpi_reset() - Ioctl function for performing ULPI reset
587 *
588 * This function peerforms the ULPI reset sequence for resetting
589 * the ULPI transceiver.
590 *
591 * @return Returns status, either success or error+reason
592 */
593static enum pm_ret_status pm_ioctl_ulpi_reset(void)
594{
595 enum pm_ret_status ret;
596
597 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
598 ZYNQMP_ULPI_RESET_VAL_HIGH);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530599 if (ret != PM_RET_SUCCESS) {
Siva Durga Prasad Paladugued1d5cb2018-09-04 17:03:25 +0530600 return ret;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530601 }
Siva Durga Prasad Paladugued1d5cb2018-09-04 17:03:25 +0530602
603 /* Drive ULPI assert for atleast 1ms */
604 mdelay(1);
605
606 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
607 ZYNQMP_ULPI_RESET_VAL_LOW);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530608 if (ret != PM_RET_SUCCESS) {
Siva Durga Prasad Paladugued1d5cb2018-09-04 17:03:25 +0530609 return ret;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530610 }
Siva Durga Prasad Paladugued1d5cb2018-09-04 17:03:25 +0530611
612 /* Drive ULPI de-assert for atleast 1ms */
613 mdelay(1);
614
615 ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
616 ZYNQMP_ULPI_RESET_VAL_HIGH);
617
618 return ret;
619}
620
621/**
Siva Durga Prasad Paladuguac8526f2018-09-04 17:12:51 +0530622 * pm_ioctl_set_boot_health_status() - Ioctl for setting healthy boot status
623 *
624 * This function sets healthy bit value to indicate boot health status
625 * to firmware.
626 *
627 * @return Returns status, either success or error+reason
628 */
629static enum pm_ret_status pm_ioctl_set_boot_health_status(unsigned int value)
630{
Tejas Patel6552a552020-11-22 23:37:55 -0800631 return pm_mmio_write(PMU_GLOBAL_GEN_STORAGE4,
Siva Durga Prasad Paladuguac8526f2018-09-04 17:12:51 +0530632 PM_BOOT_HEALTH_STATUS_MASK, value);
633}
634
635/**
Rajan Vaja5529a012018-01-17 02:39:23 -0800636 * pm_api_ioctl() - PM IOCTL API for device control and configs
637 * @node_id Node ID of the device
638 * @ioctl_id ID of the requested IOCTL
639 * @arg1 Argument 1 to requested IOCTL call
640 * @arg2 Argument 2 to requested IOCTL call
641 * @value Returned output value
642 *
643 * This function calls IOCTL to firmware for device control and configuration.
644 *
645 * @return Returns status, either success or error+reason
646 */
647enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
648 unsigned int ioctl_id,
649 unsigned int arg1,
650 unsigned int arg2,
651 unsigned int *value)
652{
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800653 enum pm_ret_status ret;
Rajan Vaja0c0615a2021-10-12 03:30:09 -0700654 uint32_t payload[PAYLOAD_ARG_CNT];
Rajan Vaja5529a012018-01-17 02:39:23 -0800655
656 switch (ioctl_id) {
657 case IOCTL_GET_RPU_OPER_MODE:
658 ret = pm_ioctl_get_rpu_oper_mode(value);
659 break;
660 case IOCTL_SET_RPU_OPER_MODE:
661 ret = pm_ioctl_set_rpu_oper_mode(arg1);
662 break;
663 case IOCTL_RPU_BOOT_ADDR_CONFIG:
664 ret = pm_ioctl_config_boot_addr(nid, arg1);
665 break;
666 case IOCTL_TCM_COMB_CONFIG:
667 ret = pm_ioctl_config_tcm_comb(arg1);
668 break;
Rajan Vajaaea41bb2018-01-17 02:39:24 -0800669 case IOCTL_SET_TAPDELAY_BYPASS:
670 ret = pm_ioctl_set_tapdelay_bypass(arg1, arg2);
671 break;
672 case IOCTL_SET_SGMII_MODE:
673 ret = pm_ioctl_set_sgmii_mode(nid, arg1);
674 break;
675 case IOCTL_SD_DLL_RESET:
676 ret = pm_ioctl_sd_dll_reset(nid, arg1);
677 break;
678 case IOCTL_SET_SD_TAPDELAY:
679 ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2);
680 break;
Rajan Vaja35116132018-01-17 02:39:25 -0800681 case IOCTL_SET_PLL_FRAC_MODE:
682 ret = pm_ioctl_set_pll_frac_mode(arg1, arg2);
683 break;
684 case IOCTL_GET_PLL_FRAC_MODE:
685 ret = pm_ioctl_get_pll_frac_mode(arg1, value);
686 break;
687 case IOCTL_SET_PLL_FRAC_DATA:
688 ret = pm_ioctl_set_pll_frac_data(arg1, arg2);
689 break;
690 case IOCTL_GET_PLL_FRAC_DATA:
691 ret = pm_ioctl_get_pll_frac_data(arg1, value);
692 break;
Rajan Vaja393c0a22018-01-17 02:39:27 -0800693 case IOCTL_WRITE_GGS:
694 ret = pm_ioctl_write_ggs(arg1, arg2);
695 break;
696 case IOCTL_READ_GGS:
697 ret = pm_ioctl_read_ggs(arg1, value);
698 break;
699 case IOCTL_WRITE_PGGS:
700 ret = pm_ioctl_write_pggs(arg1, arg2);
701 break;
702 case IOCTL_READ_PGGS:
703 ret = pm_ioctl_read_pggs(arg1, value);
704 break;
Siva Durga Prasad Paladugued1d5cb2018-09-04 17:03:25 +0530705 case IOCTL_ULPI_RESET:
706 ret = pm_ioctl_ulpi_reset();
707 break;
Siva Durga Prasad Paladuguac8526f2018-09-04 17:12:51 +0530708 case IOCTL_SET_BOOT_HEALTH_STATUS:
709 ret = pm_ioctl_set_boot_health_status(arg1);
710 break;
Siva Durga Prasad Paladugua22b8852018-09-04 17:27:12 +0530711 case IOCTL_AFI:
712 ret = pm_ioctl_afi(arg1, arg2);
713 break;
Rajan Vaja5529a012018-01-17 02:39:23 -0800714 default:
Rajan Vaja0c0615a2021-10-12 03:30:09 -0700715 /* Send request to the PMU */
716 PM_PACK_PAYLOAD5(payload, PM_IOCTL, nid, ioctl_id, arg1, arg2);
717
718 ret = pm_ipi_send_sync(primary_proc, payload, value, 1);
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800719 break;
Rajan Vaja5529a012018-01-17 02:39:23 -0800720 }
721
722 return ret;
723}
Ronak Jain325bad12021-12-21 01:39:59 -0800724
725/**
726 * pm_update_ioctl_bitmask() - API to get supported IOCTL ID mask
727 * @bit_mask Returned bit mask of supported IOCTL IDs
728 */
729enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask)
730{
731 uint8_t supported_ids[] = {
732 IOCTL_GET_RPU_OPER_MODE,
733 IOCTL_SET_RPU_OPER_MODE,
734 IOCTL_RPU_BOOT_ADDR_CONFIG,
735 IOCTL_TCM_COMB_CONFIG,
736 IOCTL_SET_TAPDELAY_BYPASS,
737 IOCTL_SET_SGMII_MODE,
738 IOCTL_SD_DLL_RESET,
739 IOCTL_SET_SD_TAPDELAY,
740 IOCTL_SET_PLL_FRAC_MODE,
741 IOCTL_GET_PLL_FRAC_MODE,
742 IOCTL_SET_PLL_FRAC_DATA,
743 IOCTL_GET_PLL_FRAC_DATA,
744 IOCTL_WRITE_GGS,
745 IOCTL_READ_GGS,
746 IOCTL_WRITE_PGGS,
747 IOCTL_READ_PGGS,
748 IOCTL_ULPI_RESET,
749 IOCTL_SET_BOOT_HEALTH_STATUS,
750 IOCTL_AFI,
751 };
752 uint8_t i, ioctl_id;
753 int ret;
754
755 for (i = 0U; i < ARRAY_SIZE(supported_ids); i++) {
756 ioctl_id = supported_ids[i];
757 if (ioctl_id >= 64U) {
758 return PM_RET_ERROR_NOTSUPPORTED;
759 }
760 ret = check_api_dependency(ioctl_id);
761 if (ret == PM_RET_SUCCESS) {
762 bit_mask[ioctl_id / 32] |= BIT(ioctl_id % 32);
763 }
764 }
765
766 return PM_RET_SUCCESS;
767}