xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c (revision 61f72a34250d063da67f4fc2b0eb8c3fda3376be)
1 /*
2  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3  *
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>
12 #include <delay_timer.h>
13 #include <mmio.h>
14 #include <platform.h>
15 #include "pm_api_clock.h"
16 #include "pm_api_ioctl.h"
17 #include "pm_api_sys.h"
18 #include "pm_client.h"
19 #include "pm_common.h"
20 #include "pm_ipi.h"
21 #include "../zynqmp_def.h"
22 
23 /**
24  * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode
25  * @mode	Buffer to store value of oper mode(Split/Lock-step)
26  *
27  * This function provides current configured RPU operational mode.
28  *
29  * @return	Returns status, either success or error+reason
30  */
31 static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(unsigned int *mode)
32 {
33 	unsigned int val;
34 
35 	val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
36 	val &= ZYNQMP_SLSPLIT_MASK;
37 	if (val == 0)
38 		*mode = PM_RPU_MODE_LOCKSTEP;
39 	else
40 		*mode = PM_RPU_MODE_SPLIT;
41 
42 	return PM_RET_SUCCESS;
43 }
44 
45 /**
46  * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode
47  * @mode	Value to set for oper mode(Split/Lock-step)
48  *
49  * This function configures RPU operational mode(Split/Lock-step).
50  * It also sets TCM combined mode in RPU lock-step and TCM non-combined
51  * mode for RPU split mode. In case of Lock step mode, RPU1's output is
52  * clamped.
53  *
54  * @return	Returns status, either success or error+reason
55  */
56 static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(unsigned int mode)
57 {
58 	unsigned int val;
59 
60 	if (mmio_read_32(CRL_APB_RST_LPD_TOP) && CRL_APB_RPU_AMBA_RESET)
61 		return PM_RET_ERROR_ACCESS;
62 
63 	val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
64 
65 	if (mode == PM_RPU_MODE_SPLIT) {
66 		val |= ZYNQMP_SLSPLIT_MASK;
67 		val &= ~ZYNQMP_TCM_COMB_MASK;
68 		val &= ~ZYNQMP_SLCLAMP_MASK;
69 	} else if (mode == PM_RPU_MODE_LOCKSTEP) {
70 		val &= ~ZYNQMP_SLSPLIT_MASK;
71 		val |= ZYNQMP_TCM_COMB_MASK;
72 		val |= ZYNQMP_SLCLAMP_MASK;
73 	} else {
74 		return PM_RET_ERROR_ARGS;
75 	}
76 
77 	mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
78 
79 	return PM_RET_SUCCESS;
80 }
81 
82 /**
83  * pm_ioctl_config_boot_addr() - Configure RPU boot address
84  * @nid		Node ID of RPU
85  * @value	Value to set for boot address (TCM/OCM)
86  *
87  * This function configures RPU boot address(memory).
88  *
89  * @return	Returns status, either success or error+reason
90  */
91 static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid,
92 						    unsigned int value)
93 {
94 	unsigned int rpu_cfg_addr, val;
95 
96 	if (nid == NODE_RPU_0)
97 		rpu_cfg_addr = ZYNQMP_RPU0_CFG;
98 	else if (nid == NODE_RPU_1)
99 		rpu_cfg_addr = ZYNQMP_RPU1_CFG;
100 	else
101 		return PM_RET_ERROR_ARGS;
102 
103 	val = mmio_read_32(rpu_cfg_addr);
104 
105 	if (value == PM_RPU_BOOTMEM_LOVEC)
106 		val &= ~ZYNQMP_VINITHI_MASK;
107 	else if (value == PM_RPU_BOOTMEM_HIVEC)
108 		val |= ZYNQMP_VINITHI_MASK;
109 	else
110 		return PM_RET_ERROR_ARGS;
111 
112 	mmio_write_32(rpu_cfg_addr, val);
113 
114 	return PM_RET_SUCCESS;
115 }
116 
117 /**
118  * pm_ioctl_config_tcm_comb() - Configure TCM combined mode
119  * @value	Value to set (Split/Combined)
120  *
121  * This function configures TCM to be in split mode or combined
122  * mode.
123  *
124  * @return	Returns status, either success or error+reason
125  */
126 static enum pm_ret_status pm_ioctl_config_tcm_comb(unsigned int value)
127 {
128 	unsigned int val;
129 
130 	val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
131 
132 	if (value == PM_RPU_TCM_SPLIT)
133 		val &= ~ZYNQMP_TCM_COMB_MASK;
134 	else if (value == PM_RPU_TCM_COMB)
135 		val |= ZYNQMP_TCM_COMB_MASK;
136 	else
137 		return PM_RET_ERROR_ARGS;
138 
139 	mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
140 
141 	return PM_RET_SUCCESS;
142 }
143 
144 /**
145  * pm_ioctl_set_tapdelay_bypass() -  Enable/Disable tap delay bypass
146  * @type	Type of tap delay to enable/disable (e.g. QSPI)
147  * @value	Enable/Disable
148  *
149  * This function enable/disable tap delay bypass.
150  *
151  * @return	Returns status, either success or error+reason
152  */
153 static enum pm_ret_status pm_ioctl_set_tapdelay_bypass(unsigned int type,
154 						       unsigned int value)
155 {
156 	if ((value != PM_TAPDELAY_BYPASS_ENABLE &&
157 	     value != PM_TAPDELAY_BYPASS_DISABLE) || type >= PM_TAPDELAY_MAX)
158 		return PM_RET_ERROR_ARGS;
159 
160 	return pm_mmio_write(IOU_TAPDLY_BYPASS, TAP_DELAY_MASK, value << type);
161 }
162 
163 /**
164  * pm_ioctl_set_sgmii_mode() -  Set SGMII mode for the GEM device
165  * @nid		Node ID of the device
166  * @value	Enable/Disable
167  *
168  * This function enable/disable SGMII mode for the GEM device.
169  * While enabling SGMII mode, it also ties the GEM PCS Signal
170  * Detect to 1 and selects EMIO for RX clock generation.
171  *
172  * @return	Returns status, either success or error+reason
173  */
174 static enum pm_ret_status pm_ioctl_set_sgmii_mode(enum pm_node_id nid,
175 						  unsigned int value)
176 {
177 	unsigned int val, mask, shift;
178 	enum pm_ret_status ret;
179 
180 	if (value != PM_SGMII_DISABLE && value != PM_SGMII_ENABLE)
181 		return PM_RET_ERROR_ARGS;
182 
183 	switch (nid) {
184 	case NODE_ETH_0:
185 		shift = 0;
186 		break;
187 	case NODE_ETH_1:
188 		shift = 1;
189 		break;
190 	case NODE_ETH_2:
191 		shift = 2;
192 		break;
193 	case NODE_ETH_3:
194 		shift = 3;
195 		break;
196 	default:
197 		return PM_RET_ERROR_ARGS;
198 	}
199 
200 	if (value == PM_SGMII_DISABLE) {
201 		mask = GEM_SGMII_MASK << GEM_CLK_CTRL_OFFSET * shift;
202 		ret = pm_mmio_write(IOU_GEM_CLK_CTRL, mask, 0U);
203 	} else {
204 		/* Tie the GEM PCS Signal Detect to 1 */
205 		mask = SGMII_SD_MASK << SGMII_SD_OFFSET * shift;
206 		val = SGMII_PCS_SD_1 << SGMII_SD_OFFSET * shift;
207 		ret = pm_mmio_write(IOU_GEM_CTRL, mask, val);
208 		if (ret != PM_RET_SUCCESS)
209 			return ret;
210 
211 		/* Set the GEM to SGMII mode */
212 		mask = GEM_CLK_CTRL_MASK << GEM_CLK_CTRL_OFFSET * shift;
213 		val = GEM_RX_SRC_SEL_GTR | GEM_SGMII_MODE;
214 		val <<= GEM_CLK_CTRL_OFFSET * shift;
215 		ret =  pm_mmio_write(IOU_GEM_CLK_CTRL, mask, val);
216 	}
217 
218 	return ret;
219 }
220 
221 /**
222  * pm_ioctl_sd_dll_reset() -  Reset DLL logic
223  * @nid		Node ID of the device
224  * @type	Reset type
225  *
226  * This function resets DLL logic for the SD device.
227  *
228  * @return	Returns status, either success or error+reason
229  */
230 static enum pm_ret_status pm_ioctl_sd_dll_reset(enum pm_node_id nid,
231 						unsigned int type)
232 {
233 	unsigned int mask, val;
234 	enum pm_ret_status ret;
235 
236 	if (nid == NODE_SD_0) {
237 		mask = ZYNQMP_SD0_DLL_RST_MASK;
238 		val = ZYNQMP_SD0_DLL_RST;
239 	} else if (nid == NODE_SD_1) {
240 		mask = ZYNQMP_SD1_DLL_RST_MASK;
241 		val = ZYNQMP_SD1_DLL_RST;
242 	} else {
243 		return PM_RET_ERROR_ARGS;
244 	}
245 
246 	switch (type) {
247 	case PM_DLL_RESET_ASSERT:
248 	case PM_DLL_RESET_PULSE:
249 		ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, val);
250 		if (ret != PM_RET_SUCCESS)
251 			return ret;
252 
253 		if (type == PM_DLL_RESET_ASSERT)
254 			break;
255 		mdelay(1);
256 	case PM_DLL_RESET_RELEASE:
257 		ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, 0);
258 		break;
259 	default:
260 		ret = PM_RET_ERROR_ARGS;
261 		break;
262 	}
263 
264 	return ret;
265 }
266 
267 /**
268  * pm_ioctl_sd_set_tapdelay() -  Set tap delay for the SD device
269  * @nid		Node ID of the device
270  * @type	Type of tap delay to set (input/output)
271  * @value	Value to set fot the tap delay
272  *
273  * This function sets input/output tap delay for the SD device.
274  *
275  * @return	Returns status, either success or error+reason
276  */
277 static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,
278 						   enum tap_delay_type type,
279 						   unsigned int value)
280 {
281 	unsigned int shift;
282 	enum pm_ret_status ret;
283 
284 	if (nid == NODE_SD_0)
285 		shift = 0;
286 	else if (nid == NODE_SD_1)
287 		shift = ZYNQMP_SD_TAP_OFFSET;
288 	else
289 		return PM_RET_ERROR_ARGS;
290 
291 	ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT);
292 	if (ret != PM_RET_SUCCESS)
293 		return ret;
294 
295 	if (type == PM_TAPDELAY_INPUT) {
296 		ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
297 				    (ZYNQMP_SD_ITAPCHGWIN_MASK << shift),
298 				    (ZYNQMP_SD_ITAPCHGWIN << shift));
299 		if (ret != PM_RET_SUCCESS)
300 			goto reset_release;
301 		ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
302 				    (ZYNQMP_SD_ITAPDLYENA_MASK << shift),
303 				    (ZYNQMP_SD_ITAPDLYENA << shift));
304 		if (ret != PM_RET_SUCCESS)
305 			goto reset_release;
306 		ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
307 				    (ZYNQMP_SD_ITAPDLYSEL_MASK << shift),
308 				    (value << shift));
309 		if (ret != PM_RET_SUCCESS)
310 			goto reset_release;
311 		ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
312 				    (ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0);
313 	} else if (type == PM_TAPDELAY_OUTPUT) {
314 		ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
315 				    (ZYNQMP_SD_OTAPDLYENA_MASK << shift),
316 				    (ZYNQMP_SD_OTAPDLYENA << shift));
317 		if (ret != PM_RET_SUCCESS)
318 			goto reset_release;
319 		ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
320 				    (ZYNQMP_SD_OTAPDLYSEL_MASK << shift),
321 				    (value << shift));
322 	} else {
323 		ret = PM_RET_ERROR_ARGS;
324 	}
325 
326 reset_release:
327 	pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE);
328 	return ret;
329 }
330 
331 /**
332  * pm_ioctl_set_pll_frac_mode() -  Ioctl function for
333  *				   setting pll mode
334  * @pll     PLL id
335  * @mode    Mode fraction/integar
336  *
337  * This function sets PLL mode
338  *
339  * @return      Returns status, either success or error+reason
340  */
341 static enum pm_ret_status pm_ioctl_set_pll_frac_mode
342 			(unsigned int pll, unsigned int mode)
343 {
344 	return pm_api_clk_set_pll_mode(pll, mode);
345 }
346 
347 /**
348  * pm_ioctl_get_pll_frac_mode() -  Ioctl function for
349  *				   getting pll mode
350  * @pll     PLL id
351  * @mode    Mode fraction/integar
352  *
353  * This function return current PLL mode
354  *
355  * @return      Returns status, either success or error+reason
356  */
357 static enum pm_ret_status pm_ioctl_get_pll_frac_mode
358 			(unsigned int pll, unsigned int *mode)
359 {
360 	return pm_api_clk_get_pll_mode(pll, mode);
361 }
362 
363 /**
364  * pm_ioctl_set_pll_frac_data() -  Ioctl function for
365  *				   setting pll fraction data
366  * @pll     PLL id
367  * @data    fraction data
368  *
369  * This function sets fraction data.
370  * It is valid for fraction mode only.
371  *
372  * @return      Returns status, either success or error+reason
373  */
374 static enum pm_ret_status pm_ioctl_set_pll_frac_data
375 			(unsigned int pll, unsigned int data)
376 {
377 	return pm_api_clk_set_pll_frac_data(pll, data);
378 }
379 
380 /**
381  * pm_ioctl_get_pll_frac_data() -  Ioctl function for
382  *				   getting pll fraction data
383  * @pll     PLL id
384  * @data    fraction data
385  *
386  * This function returns fraction data value.
387  *
388  * @return      Returns status, either success or error+reason
389  */
390 static enum pm_ret_status pm_ioctl_get_pll_frac_data
391 			(unsigned int pll, unsigned int *data)
392 {
393 	return pm_api_clk_get_pll_frac_data(pll, data);
394 }
395 
396 /**
397  * pm_ioctl_write_ggs() - Ioctl function for writing
398  *			  global general storage (ggs)
399  * @index	GGS register index
400  * @value	Register value to be written
401  *
402  * This function writes value to GGS register.
403  *
404  * @return      Returns status, either success or error+reason
405  */
406 static enum pm_ret_status pm_ioctl_write_ggs(unsigned int index,
407 					     unsigned int value)
408 {
409 	if (index >= GGS_NUM_REGS)
410 		return PM_RET_ERROR_ARGS;
411 
412 	return pm_mmio_write(GGS_BASEADDR + (index << 2),
413 			     0xFFFFFFFFU, value);
414 }
415 
416 /**
417  * pm_ioctl_read_ggs() - Ioctl function for reading
418  *			 global general storage (ggs)
419  * @index	GGS register index
420  * @value	Register value
421  *
422  * This function returns GGS register value.
423  *
424  * @return      Returns status, either success or error+reason
425  */
426 static enum pm_ret_status pm_ioctl_read_ggs(unsigned int index,
427 					    unsigned int *value)
428 {
429 	if (index >= GGS_NUM_REGS)
430 		return PM_RET_ERROR_ARGS;
431 
432 	return pm_mmio_read(GGS_BASEADDR + (index << 2), value);
433 }
434 
435 /**
436  * pm_ioctl_write_pggs() - Ioctl function for writing persistent
437  *			   global general storage (pggs)
438  * @index	PGGS register index
439  * @value	Register value to be written
440  *
441  * This function writes value to PGGS register.
442  *
443  * @return      Returns status, either success or error+reason
444  */
445 static enum pm_ret_status pm_ioctl_write_pggs(unsigned int index,
446 					      unsigned int value)
447 {
448 	if (index >= PGGS_NUM_REGS)
449 		return PM_RET_ERROR_ARGS;
450 
451 	return pm_mmio_write(PGGS_BASEADDR + (index << 2),
452 			     0xFFFFFFFFU, value);
453 }
454 
455 /**
456  * pm_ioctl_read_pggs() - Ioctl function for reading persistent
457  *			  global general storage (pggs)
458  * @index	PGGS register index
459  * @value	Register value
460  *
461  * This function returns PGGS register value.
462  *
463  * @return      Returns status, either success or error+reason
464  */
465 static enum pm_ret_status pm_ioctl_read_pggs(unsigned int index,
466 					     unsigned int *value)
467 {
468 	if (index >= PGGS_NUM_REGS)
469 		return PM_RET_ERROR_ARGS;
470 
471 	return pm_mmio_read(PGGS_BASEADDR + (index << 2), value);
472 }
473 
474 /**
475  * pm_api_ioctl() -  PM IOCTL API for device control and configs
476  * @node_id	Node ID of the device
477  * @ioctl_id	ID of the requested IOCTL
478  * @arg1	Argument 1 to requested IOCTL call
479  * @arg2	Argument 2 to requested IOCTL call
480  * @value	Returned output value
481  *
482  * This function calls IOCTL to firmware for device control and configuration.
483  *
484  * @return	Returns status, either success or error+reason
485  */
486 enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
487 				unsigned int ioctl_id,
488 				unsigned int arg1,
489 				unsigned int arg2,
490 				unsigned int *value)
491 {
492 	enum pm_ret_status ret;
493 
494 	switch (ioctl_id) {
495 	case IOCTL_GET_RPU_OPER_MODE:
496 		ret = pm_ioctl_get_rpu_oper_mode(value);
497 		break;
498 	case IOCTL_SET_RPU_OPER_MODE:
499 		ret = pm_ioctl_set_rpu_oper_mode(arg1);
500 		break;
501 	case IOCTL_RPU_BOOT_ADDR_CONFIG:
502 		ret = pm_ioctl_config_boot_addr(nid, arg1);
503 		break;
504 	case IOCTL_TCM_COMB_CONFIG:
505 		ret = pm_ioctl_config_tcm_comb(arg1);
506 		break;
507 	case IOCTL_SET_TAPDELAY_BYPASS:
508 		ret = pm_ioctl_set_tapdelay_bypass(arg1, arg2);
509 		break;
510 	case IOCTL_SET_SGMII_MODE:
511 		ret = pm_ioctl_set_sgmii_mode(nid, arg1);
512 		break;
513 	case IOCTL_SD_DLL_RESET:
514 		ret = pm_ioctl_sd_dll_reset(nid, arg1);
515 		break;
516 	case IOCTL_SET_SD_TAPDELAY:
517 		ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2);
518 		break;
519 	case IOCTL_SET_PLL_FRAC_MODE:
520 		ret = pm_ioctl_set_pll_frac_mode(arg1, arg2);
521 		break;
522 	case IOCTL_GET_PLL_FRAC_MODE:
523 		ret = pm_ioctl_get_pll_frac_mode(arg1, value);
524 		break;
525 	case IOCTL_SET_PLL_FRAC_DATA:
526 		ret = pm_ioctl_set_pll_frac_data(arg1, arg2);
527 		break;
528 	case IOCTL_GET_PLL_FRAC_DATA:
529 		ret = pm_ioctl_get_pll_frac_data(arg1, value);
530 		break;
531 	case IOCTL_WRITE_GGS:
532 		ret = pm_ioctl_write_ggs(arg1, arg2);
533 		break;
534 	case IOCTL_READ_GGS:
535 		ret = pm_ioctl_read_ggs(arg1, value);
536 		break;
537 	case IOCTL_WRITE_PGGS:
538 		ret = pm_ioctl_write_pggs(arg1, arg2);
539 		break;
540 	case IOCTL_READ_PGGS:
541 		ret = pm_ioctl_read_pggs(arg1, value);
542 		break;
543 	default:
544 		ret = PM_RET_ERROR_NOTSUPPORTED;
545 		break;
546 	}
547 
548 	return ret;
549 }
550