xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c (revision f76918a80602588408d6d7b6ba374df9c95d7261)
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_ioctl.h"
16 #include "pm_api_sys.h"
17 #include "pm_client.h"
18 #include "pm_common.h"
19 #include "pm_ipi.h"
20 #include "../zynqmp_def.h"
21 
22 /**
23  * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode
24  * @mode	Buffer to store value of oper mode(Split/Lock-step)
25  *
26  * This function provides current configured RPU operational mode.
27  *
28  * @return	Returns status, either success or error+reason
29  */
30 static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(unsigned int *mode)
31 {
32 	unsigned int val;
33 
34 	val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
35 	val &= ZYNQMP_SLSPLIT_MASK;
36 	if (val)
37 		*mode = PM_RPU_MODE_SPLIT;
38 	else
39 		*mode = PM_RPU_MODE_LOCKSTEP;
40 
41 	return PM_RET_SUCCESS;
42 }
43 
44 /**
45  * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode
46  * @mode	Value to set for oper mode(Split/Lock-step)
47  *
48  * This function configures RPU operational mode(Split/Lock-step).
49  * It also sets TCM combined mode in RPU lock-step and TCM non-combined
50  * mode for RPU split mode. In case of Lock step mode, RPU1's output is
51  * clamped.
52  *
53  * @return	Returns status, either success or error+reason
54  */
55 static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(unsigned int mode)
56 {
57 	unsigned int val;
58 
59 	if (mmio_read_32(CRL_APB_RST_LPD_TOP) && CRL_APB_RPU_AMBA_RESET)
60 		return PM_RET_ERROR_ACCESS;
61 
62 	val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
63 
64 	if (mode == PM_RPU_MODE_SPLIT) {
65 		val |= ZYNQMP_SLSPLIT_MASK;
66 		val &= ~ZYNQMP_TCM_COMB_MASK;
67 		val &= ~ZYNQMP_SLCLAMP_MASK;
68 	} else if (mode == PM_RPU_MODE_LOCKSTEP) {
69 		val &= ~ZYNQMP_SLSPLIT_MASK;
70 		val |= ZYNQMP_TCM_COMB_MASK;
71 		val |= ZYNQMP_SLCLAMP_MASK;
72 	} else {
73 		return PM_RET_ERROR_ARGS;
74 	}
75 
76 	mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
77 
78 	return PM_RET_SUCCESS;
79 }
80 
81 /**
82  * pm_ioctl_config_boot_addr() - Configure RPU boot address
83  * @nid		Node ID of RPU
84  * @value	Value to set for boot address (TCM/OCM)
85  *
86  * This function configures RPU boot address(memory).
87  *
88  * @return	Returns status, either success or error+reason
89  */
90 static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid,
91 						    unsigned int value)
92 {
93 	unsigned int rpu_cfg_addr, val;
94 
95 	if (nid == NODE_RPU_0)
96 		rpu_cfg_addr = ZYNQMP_RPU0_CFG;
97 	else if (nid == NODE_RPU_1)
98 		rpu_cfg_addr = ZYNQMP_RPU1_CFG;
99 	else
100 		return PM_RET_ERROR_ARGS;
101 
102 	val = mmio_read_32(rpu_cfg_addr);
103 
104 	if (value == PM_RPU_BOOTMEM_LOVEC)
105 		val &= ~ZYNQMP_VINITHI_MASK;
106 	else if (value == PM_RPU_BOOTMEM_HIVEC)
107 		val |= ZYNQMP_VINITHI_MASK;
108 	else
109 		return PM_RET_ERROR_ARGS;
110 
111 	mmio_write_32(rpu_cfg_addr, val);
112 
113 	return PM_RET_SUCCESS;
114 }
115 
116 /**
117  * pm_ioctl_config_tcm_comb() - Configure TCM combined mode
118  * @value	Value to set (Split/Combined)
119  *
120  * This function configures TCM to be in split mode or combined
121  * mode.
122  *
123  * @return	Returns status, either success or error+reason
124  */
125 static enum pm_ret_status pm_ioctl_config_tcm_comb(unsigned int value)
126 {
127 	unsigned int val;
128 
129 	val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
130 
131 	if (value == PM_RPU_TCM_SPLIT)
132 		val &= ~ZYNQMP_TCM_COMB_MASK;
133 	else if (value == PM_RPU_TCM_COMB)
134 		val |= ZYNQMP_TCM_COMB_MASK;
135 	else
136 		return PM_RET_ERROR_ARGS;
137 
138 	mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
139 
140 	return PM_RET_SUCCESS;
141 }
142 
143 /**
144  * pm_api_ioctl() -  PM IOCTL API for device control and configs
145  * @node_id	Node ID of the device
146  * @ioctl_id	ID of the requested IOCTL
147  * @arg1	Argument 1 to requested IOCTL call
148  * @arg2	Argument 2 to requested IOCTL call
149  * @value	Returned output value
150  *
151  * This function calls IOCTL to firmware for device control and configuration.
152  *
153  * @return	Returns status, either success or error+reason
154  */
155 enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
156 				unsigned int ioctl_id,
157 				unsigned int arg1,
158 				unsigned int arg2,
159 				unsigned int *value)
160 {
161 	int ret;
162 
163 	switch (ioctl_id) {
164 	case IOCTL_GET_RPU_OPER_MODE:
165 		ret = pm_ioctl_get_rpu_oper_mode(value);
166 		break;
167 	case IOCTL_SET_RPU_OPER_MODE:
168 		ret = pm_ioctl_set_rpu_oper_mode(arg1);
169 		break;
170 	case IOCTL_RPU_BOOT_ADDR_CONFIG:
171 		ret = pm_ioctl_config_boot_addr(nid, arg1);
172 		break;
173 	case IOCTL_TCM_COMB_CONFIG:
174 		ret = pm_ioctl_config_tcm_comb(arg1);
175 		break;
176 	default:
177 		ret = PM_RET_ERROR_NOTSUPPORTED;
178 	}
179 
180 	return ret;
181 }
182