xref: /arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
4*91f16700Schasinglulu  *
5*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
6*91f16700Schasinglulu  */
7*91f16700Schasinglulu 
8*91f16700Schasinglulu /*
9*91f16700Schasinglulu  * ZynqMP system level PM-API functions and communication with PMU via
10*91f16700Schasinglulu  * IPI interrupts
11*91f16700Schasinglulu  */
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #include <arch_helpers.h>
14*91f16700Schasinglulu #include <plat/common/platform.h>
15*91f16700Schasinglulu 
16*91f16700Schasinglulu #include "pm_api_clock.h"
17*91f16700Schasinglulu #include "pm_api_ioctl.h"
18*91f16700Schasinglulu #include "pm_api_pinctrl.h"
19*91f16700Schasinglulu #include "pm_client.h"
20*91f16700Schasinglulu #include "pm_common.h"
21*91f16700Schasinglulu #include "pm_ipi.h"
22*91f16700Schasinglulu #include "zynqmp_pm_api_sys.h"
23*91f16700Schasinglulu 
24*91f16700Schasinglulu #define PM_QUERY_FEATURE_BITMASK ( \
25*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \
26*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) |	\
27*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \
28*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \
29*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \
30*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \
31*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \
32*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \
33*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \
34*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \
35*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \
36*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \
37*91f16700Schasinglulu 	(1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR))
38*91f16700Schasinglulu 
39*91f16700Schasinglulu /**
40*91f16700Schasinglulu  * typedef eemi_api_dependency - Dependent EEMI APIs which are implemented
41*91f16700Schasinglulu  *                               on both the TF-A and firmware.
42*91f16700Schasinglulu  * @id: EEMI API id or IOCTL id to be checked.
43*91f16700Schasinglulu  * @api_id: Dependent EEMI API.
44*91f16700Schasinglulu  *
45*91f16700Schasinglulu  */
46*91f16700Schasinglulu typedef struct __attribute__((packed)) {
47*91f16700Schasinglulu 	uint8_t id;
48*91f16700Schasinglulu 	uint8_t api_id;
49*91f16700Schasinglulu } eemi_api_dependency;
50*91f16700Schasinglulu 
51*91f16700Schasinglulu /* Dependent APIs for TF-A to check their version from firmware */
52*91f16700Schasinglulu static const eemi_api_dependency api_dep_table[] = {
53*91f16700Schasinglulu 	{
54*91f16700Schasinglulu 		.id = PM_SELF_SUSPEND,
55*91f16700Schasinglulu 		.api_id = PM_SELF_SUSPEND,
56*91f16700Schasinglulu 	},
57*91f16700Schasinglulu 	{
58*91f16700Schasinglulu 		.id = PM_REQ_WAKEUP,
59*91f16700Schasinglulu 		.api_id = PM_REQ_WAKEUP,
60*91f16700Schasinglulu 	},
61*91f16700Schasinglulu 	{
62*91f16700Schasinglulu 		.id = PM_ABORT_SUSPEND,
63*91f16700Schasinglulu 		.api_id = PM_ABORT_SUSPEND,
64*91f16700Schasinglulu 	},
65*91f16700Schasinglulu 	{
66*91f16700Schasinglulu 		.id = PM_SET_WAKEUP_SOURCE,
67*91f16700Schasinglulu 		.api_id = PM_SET_WAKEUP_SOURCE,
68*91f16700Schasinglulu 	},
69*91f16700Schasinglulu 	{
70*91f16700Schasinglulu 		.id = PM_SYSTEM_SHUTDOWN,
71*91f16700Schasinglulu 		.api_id = PM_SYSTEM_SHUTDOWN,
72*91f16700Schasinglulu 	},
73*91f16700Schasinglulu 	{
74*91f16700Schasinglulu 		.id = PM_GET_API_VERSION,
75*91f16700Schasinglulu 		.api_id = PM_GET_API_VERSION,
76*91f16700Schasinglulu 	},
77*91f16700Schasinglulu 	{
78*91f16700Schasinglulu 		.id = PM_CLOCK_ENABLE,
79*91f16700Schasinglulu 		.api_id = PM_PLL_SET_MODE,
80*91f16700Schasinglulu 	},
81*91f16700Schasinglulu 	{
82*91f16700Schasinglulu 		.id = PM_CLOCK_ENABLE,
83*91f16700Schasinglulu 		.api_id = PM_CLOCK_ENABLE,
84*91f16700Schasinglulu 	},
85*91f16700Schasinglulu 	{
86*91f16700Schasinglulu 		.id = PM_CLOCK_DISABLE,
87*91f16700Schasinglulu 		.api_id = PM_PLL_SET_MODE,
88*91f16700Schasinglulu 	},
89*91f16700Schasinglulu 	{
90*91f16700Schasinglulu 		.id = PM_CLOCK_DISABLE,
91*91f16700Schasinglulu 		.api_id = PM_CLOCK_DISABLE,
92*91f16700Schasinglulu 	},
93*91f16700Schasinglulu 	{
94*91f16700Schasinglulu 		.id = PM_CLOCK_GETSTATE,
95*91f16700Schasinglulu 		.api_id = PM_PLL_GET_MODE,
96*91f16700Schasinglulu 	},
97*91f16700Schasinglulu 	{
98*91f16700Schasinglulu 		.id = PM_CLOCK_GETSTATE,
99*91f16700Schasinglulu 		.api_id = PM_CLOCK_GETSTATE,
100*91f16700Schasinglulu 	},
101*91f16700Schasinglulu 	{
102*91f16700Schasinglulu 		.id = PM_CLOCK_SETDIVIDER,
103*91f16700Schasinglulu 		.api_id = PM_PLL_SET_PARAMETER,
104*91f16700Schasinglulu 	},
105*91f16700Schasinglulu 	{
106*91f16700Schasinglulu 		.id = PM_CLOCK_SETDIVIDER,
107*91f16700Schasinglulu 		.api_id = PM_CLOCK_SETDIVIDER,
108*91f16700Schasinglulu 	},
109*91f16700Schasinglulu 	{
110*91f16700Schasinglulu 		.id = PM_CLOCK_GETDIVIDER,
111*91f16700Schasinglulu 		.api_id = PM_PLL_GET_PARAMETER,
112*91f16700Schasinglulu 	},
113*91f16700Schasinglulu 	{
114*91f16700Schasinglulu 		.id = PM_CLOCK_GETDIVIDER,
115*91f16700Schasinglulu 		.api_id = PM_CLOCK_GETDIVIDER,
116*91f16700Schasinglulu 	},
117*91f16700Schasinglulu 	{
118*91f16700Schasinglulu 		.id = PM_CLOCK_SETPARENT,
119*91f16700Schasinglulu 		.api_id = PM_PLL_SET_PARAMETER,
120*91f16700Schasinglulu 	},
121*91f16700Schasinglulu 	{
122*91f16700Schasinglulu 		.id = PM_CLOCK_SETPARENT,
123*91f16700Schasinglulu 		.api_id = PM_CLOCK_SETPARENT,
124*91f16700Schasinglulu 	},
125*91f16700Schasinglulu 	{
126*91f16700Schasinglulu 		.id = PM_CLOCK_GETPARENT,
127*91f16700Schasinglulu 		.api_id = PM_PLL_GET_PARAMETER,
128*91f16700Schasinglulu 	},
129*91f16700Schasinglulu 	{
130*91f16700Schasinglulu 		.id = PM_CLOCK_GETPARENT,
131*91f16700Schasinglulu 		.api_id = PM_CLOCK_GETPARENT,
132*91f16700Schasinglulu 	},
133*91f16700Schasinglulu 	{
134*91f16700Schasinglulu 		.id = PM_PLL_SET_PARAMETER,
135*91f16700Schasinglulu 		.api_id = PM_PLL_SET_PARAMETER,
136*91f16700Schasinglulu 	},
137*91f16700Schasinglulu 	{
138*91f16700Schasinglulu 		.id = PM_PLL_GET_PARAMETER,
139*91f16700Schasinglulu 		.api_id = PM_PLL_GET_PARAMETER,
140*91f16700Schasinglulu 	},
141*91f16700Schasinglulu 	{
142*91f16700Schasinglulu 		.id = PM_PLL_SET_MODE,
143*91f16700Schasinglulu 		.api_id = PM_PLL_SET_MODE,
144*91f16700Schasinglulu 	},
145*91f16700Schasinglulu 	{
146*91f16700Schasinglulu 		.id = PM_PLL_GET_MODE,
147*91f16700Schasinglulu 		.api_id = PM_PLL_GET_MODE,
148*91f16700Schasinglulu 	},
149*91f16700Schasinglulu 	{
150*91f16700Schasinglulu 		.id = PM_REGISTER_ACCESS,
151*91f16700Schasinglulu 		.api_id = PM_MMIO_WRITE,
152*91f16700Schasinglulu 	},
153*91f16700Schasinglulu 	{
154*91f16700Schasinglulu 		.id = PM_REGISTER_ACCESS,
155*91f16700Schasinglulu 		.api_id = PM_MMIO_READ,
156*91f16700Schasinglulu 	},
157*91f16700Schasinglulu 	{
158*91f16700Schasinglulu 		.id = PM_FEATURE_CHECK,
159*91f16700Schasinglulu 		.api_id = PM_FEATURE_CHECK,
160*91f16700Schasinglulu 	},
161*91f16700Schasinglulu 	{
162*91f16700Schasinglulu 		.id = IOCTL_SET_TAPDELAY_BYPASS,
163*91f16700Schasinglulu 		.api_id = PM_MMIO_WRITE,
164*91f16700Schasinglulu 	},
165*91f16700Schasinglulu 	{
166*91f16700Schasinglulu 		.id = IOCTL_SD_DLL_RESET,
167*91f16700Schasinglulu 		.api_id = PM_MMIO_WRITE,
168*91f16700Schasinglulu 	},
169*91f16700Schasinglulu 	{
170*91f16700Schasinglulu 		.id = IOCTL_SET_SD_TAPDELAY,
171*91f16700Schasinglulu 		.api_id = PM_MMIO_WRITE,
172*91f16700Schasinglulu 	},
173*91f16700Schasinglulu 	{
174*91f16700Schasinglulu 		.id = IOCTL_SET_SD_TAPDELAY,
175*91f16700Schasinglulu 		.api_id = PM_MMIO_READ,
176*91f16700Schasinglulu 	},
177*91f16700Schasinglulu 	{
178*91f16700Schasinglulu 		.id = IOCTL_SET_PLL_FRAC_DATA,
179*91f16700Schasinglulu 		.api_id = PM_PLL_SET_PARAMETER,
180*91f16700Schasinglulu 	},
181*91f16700Schasinglulu 	{
182*91f16700Schasinglulu 		.id = IOCTL_GET_PLL_FRAC_DATA,
183*91f16700Schasinglulu 		.api_id = PM_PLL_GET_PARAMETER,
184*91f16700Schasinglulu 	},
185*91f16700Schasinglulu 	{
186*91f16700Schasinglulu 		.id = IOCTL_WRITE_GGS,
187*91f16700Schasinglulu 		.api_id = PM_MMIO_WRITE,
188*91f16700Schasinglulu 	},
189*91f16700Schasinglulu 	{
190*91f16700Schasinglulu 		.id = IOCTL_READ_GGS,
191*91f16700Schasinglulu 		.api_id = PM_MMIO_READ,
192*91f16700Schasinglulu 	},
193*91f16700Schasinglulu 	{
194*91f16700Schasinglulu 		.id = IOCTL_WRITE_PGGS,
195*91f16700Schasinglulu 		.api_id = PM_MMIO_WRITE,
196*91f16700Schasinglulu 	},
197*91f16700Schasinglulu 	{
198*91f16700Schasinglulu 		.id = IOCTL_READ_PGGS,
199*91f16700Schasinglulu 		.api_id = PM_MMIO_READ,
200*91f16700Schasinglulu 	},
201*91f16700Schasinglulu 	{
202*91f16700Schasinglulu 		.id = IOCTL_ULPI_RESET,
203*91f16700Schasinglulu 		.api_id = PM_MMIO_WRITE,
204*91f16700Schasinglulu 	},
205*91f16700Schasinglulu 	{
206*91f16700Schasinglulu 		.id = IOCTL_SET_BOOT_HEALTH_STATUS,
207*91f16700Schasinglulu 		.api_id = PM_MMIO_WRITE,
208*91f16700Schasinglulu 	},
209*91f16700Schasinglulu 	{
210*91f16700Schasinglulu 		.id = IOCTL_AFI,
211*91f16700Schasinglulu 		.api_id = PM_MMIO_WRITE,
212*91f16700Schasinglulu 	},
213*91f16700Schasinglulu };
214*91f16700Schasinglulu 
215*91f16700Schasinglulu /* Expected firmware API version to TF-A */
216*91f16700Schasinglulu static const uint8_t tfa_expected_ver_id[] = {
217*91f16700Schasinglulu 	[PM_SELF_SUSPEND] = FW_API_BASE_VERSION,
218*91f16700Schasinglulu 	[PM_REQ_WAKEUP] = FW_API_BASE_VERSION,
219*91f16700Schasinglulu 	[PM_ABORT_SUSPEND] = FW_API_BASE_VERSION,
220*91f16700Schasinglulu 	[PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION,
221*91f16700Schasinglulu 	[PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION,
222*91f16700Schasinglulu 	[PM_GET_API_VERSION] = FW_API_BASE_VERSION,
223*91f16700Schasinglulu 	[PM_PLL_SET_MODE] = FW_API_BASE_VERSION,
224*91f16700Schasinglulu 	[PM_PLL_GET_MODE] = FW_API_BASE_VERSION,
225*91f16700Schasinglulu 	[PM_CLOCK_ENABLE] = FW_API_BASE_VERSION,
226*91f16700Schasinglulu 	[PM_CLOCK_DISABLE] = FW_API_BASE_VERSION,
227*91f16700Schasinglulu 	[PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION,
228*91f16700Schasinglulu 	[PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION,
229*91f16700Schasinglulu 	[PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION,
230*91f16700Schasinglulu 	[PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION,
231*91f16700Schasinglulu 	[PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION,
232*91f16700Schasinglulu 	[PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION,
233*91f16700Schasinglulu 	[PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION,
234*91f16700Schasinglulu 	[PM_MMIO_WRITE] = FW_API_BASE_VERSION,
235*91f16700Schasinglulu 	[PM_MMIO_READ] = FW_API_BASE_VERSION,
236*91f16700Schasinglulu 	[PM_FEATURE_CHECK] = FW_API_VERSION_2,
237*91f16700Schasinglulu };
238*91f16700Schasinglulu 
239*91f16700Schasinglulu /* default shutdown/reboot scope is system(2) */
240*91f16700Schasinglulu static uint32_t pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
241*91f16700Schasinglulu 
242*91f16700Schasinglulu /**
243*91f16700Schasinglulu  * pm_get_shutdown_scope() - Get the currently set shutdown scope.
244*91f16700Schasinglulu  *
245*91f16700Schasinglulu  * Return: Shutdown scope value.
246*91f16700Schasinglulu  *
247*91f16700Schasinglulu  */
248*91f16700Schasinglulu uint32_t pm_get_shutdown_scope(void)
249*91f16700Schasinglulu {
250*91f16700Schasinglulu 	return pm_shutdown_scope;
251*91f16700Schasinglulu }
252*91f16700Schasinglulu 
253*91f16700Schasinglulu /**
254*91f16700Schasinglulu  * pm_self_suspend() - PM call for processor to suspend itself.
255*91f16700Schasinglulu  * @nid: Node id of the processor or subsystem.
256*91f16700Schasinglulu  * @latency: Requested maximum wakeup latency (not supported).
257*91f16700Schasinglulu  * @state: Requested state.
258*91f16700Schasinglulu  * @address: Resume address.
259*91f16700Schasinglulu  *
260*91f16700Schasinglulu  * This is a blocking call, it will return only once PMU has responded.
261*91f16700Schasinglulu  * On a wakeup, resume address will be automatically set by PMU.
262*91f16700Schasinglulu  *
263*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
264*91f16700Schasinglulu  *
265*91f16700Schasinglulu  */
266*91f16700Schasinglulu enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
267*91f16700Schasinglulu 				   uint32_t latency,
268*91f16700Schasinglulu 				   uint32_t state,
269*91f16700Schasinglulu 				   uintptr_t address)
270*91f16700Schasinglulu {
271*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
272*91f16700Schasinglulu 	uint32_t cpuid = plat_my_core_pos();
273*91f16700Schasinglulu 	const struct pm_proc *proc = pm_get_proc(cpuid);
274*91f16700Schasinglulu 
275*91f16700Schasinglulu 	/*
276*91f16700Schasinglulu 	 * Do client specific suspend operations
277*91f16700Schasinglulu 	 * (e.g. set powerdown request bit)
278*91f16700Schasinglulu 	 */
279*91f16700Schasinglulu 	pm_client_suspend(proc, state);
280*91f16700Schasinglulu 	/* Send request to the PMU */
281*91f16700Schasinglulu 	PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
282*91f16700Schasinglulu 			 state, address, (address >> 32));
283*91f16700Schasinglulu 	return pm_ipi_send_sync(proc, payload, NULL, 0);
284*91f16700Schasinglulu }
285*91f16700Schasinglulu 
286*91f16700Schasinglulu /**
287*91f16700Schasinglulu  * pm_req_suspend() - PM call to request for another PU or subsystem to
288*91f16700Schasinglulu  *                    be suspended gracefully.
289*91f16700Schasinglulu  * @target: Node id of the targeted PU or subsystem.
290*91f16700Schasinglulu  * @ack: Flag to specify whether acknowledge is requested.
291*91f16700Schasinglulu  * @latency: Requested wakeup latency (not supported).
292*91f16700Schasinglulu  * @state: Requested state (not supported).
293*91f16700Schasinglulu  *
294*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
295*91f16700Schasinglulu  *
296*91f16700Schasinglulu  */
297*91f16700Schasinglulu enum pm_ret_status pm_req_suspend(enum pm_node_id target,
298*91f16700Schasinglulu 				  enum pm_request_ack ack,
299*91f16700Schasinglulu 				  uint32_t latency, uint32_t state)
300*91f16700Schasinglulu {
301*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
302*91f16700Schasinglulu 
303*91f16700Schasinglulu 	/* Send request to the PMU */
304*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
305*91f16700Schasinglulu 	if (ack == REQ_ACK_BLOCKING) {
306*91f16700Schasinglulu 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
307*91f16700Schasinglulu 	} else {
308*91f16700Schasinglulu 		return pm_ipi_send(primary_proc, payload);
309*91f16700Schasinglulu 	}
310*91f16700Schasinglulu }
311*91f16700Schasinglulu 
312*91f16700Schasinglulu /**
313*91f16700Schasinglulu  * pm_req_wakeup() - PM call for processor to wake up selected processor
314*91f16700Schasinglulu  *		     or subsystem.
315*91f16700Schasinglulu  * @target: Node id of the processor or subsystem to wake up.
316*91f16700Schasinglulu  * @ack: Flag to specify whether acknowledge requested.
317*91f16700Schasinglulu  * @set_address: Resume address presence indicator.
318*91f16700Schasinglulu  *               1 resume address specified, 0 otherwise.
319*91f16700Schasinglulu  * @address: Resume address.
320*91f16700Schasinglulu  *
321*91f16700Schasinglulu  * This API function is either used to power up another APU core for SMP
322*91f16700Schasinglulu  * (by PSCI) or to power up an entirely different PU or subsystem, such
323*91f16700Schasinglulu  * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
324*91f16700Schasinglulu  * automatically set by PMU.
325*91f16700Schasinglulu  *
326*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
327*91f16700Schasinglulu  *
328*91f16700Schasinglulu  */
329*91f16700Schasinglulu enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
330*91f16700Schasinglulu 				 uint32_t set_address,
331*91f16700Schasinglulu 				 uintptr_t address,
332*91f16700Schasinglulu 				 enum pm_request_ack ack)
333*91f16700Schasinglulu {
334*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
335*91f16700Schasinglulu 	uint64_t encoded_address;
336*91f16700Schasinglulu 
337*91f16700Schasinglulu 
338*91f16700Schasinglulu 	/* encode set Address into 1st bit of address */
339*91f16700Schasinglulu 	encoded_address = address;
340*91f16700Schasinglulu 	encoded_address |= !!set_address;
341*91f16700Schasinglulu 
342*91f16700Schasinglulu 	/* Send request to the PMU to perform the wake of the PU */
343*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
344*91f16700Schasinglulu 			 encoded_address >> 32, ack);
345*91f16700Schasinglulu 
346*91f16700Schasinglulu 	if (ack == REQ_ACK_BLOCKING) {
347*91f16700Schasinglulu 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
348*91f16700Schasinglulu 	} else {
349*91f16700Schasinglulu 		return pm_ipi_send(primary_proc, payload);
350*91f16700Schasinglulu 	}
351*91f16700Schasinglulu }
352*91f16700Schasinglulu 
353*91f16700Schasinglulu /**
354*91f16700Schasinglulu  * pm_force_powerdown() - PM call to request for another PU or subsystem to
355*91f16700Schasinglulu  *                        be powered down forcefully.
356*91f16700Schasinglulu  * @target: Node id of the targeted PU or subsystem.
357*91f16700Schasinglulu  * @ack: Flag to specify whether acknowledge is requested.
358*91f16700Schasinglulu  *
359*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
360*91f16700Schasinglulu  *
361*91f16700Schasinglulu  */
362*91f16700Schasinglulu enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
363*91f16700Schasinglulu 				      enum pm_request_ack ack)
364*91f16700Schasinglulu {
365*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
366*91f16700Schasinglulu 
367*91f16700Schasinglulu 	/* Send request to the PMU */
368*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
369*91f16700Schasinglulu 
370*91f16700Schasinglulu 	if (ack == REQ_ACK_BLOCKING) {
371*91f16700Schasinglulu 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
372*91f16700Schasinglulu 	} else {
373*91f16700Schasinglulu 		return pm_ipi_send(primary_proc, payload);
374*91f16700Schasinglulu 	}
375*91f16700Schasinglulu }
376*91f16700Schasinglulu 
377*91f16700Schasinglulu /**
378*91f16700Schasinglulu  * pm_abort_suspend() - PM call to announce that a prior suspend request
379*91f16700Schasinglulu  *                      is to be aborted.
380*91f16700Schasinglulu  * @reason: Reason for the abort.
381*91f16700Schasinglulu  *
382*91f16700Schasinglulu  * Calling PU expects the PMU to abort the initiated suspend procedure.
383*91f16700Schasinglulu  * This is a non-blocking call without any acknowledge.
384*91f16700Schasinglulu  *
385*91f16700Schasinglulu  * Return: Returns status, either success or error+reason
386*91f16700Schasinglulu  *
387*91f16700Schasinglulu  */
388*91f16700Schasinglulu enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
389*91f16700Schasinglulu {
390*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
391*91f16700Schasinglulu 
392*91f16700Schasinglulu 	/*
393*91f16700Schasinglulu 	 * Do client specific abort suspend operations
394*91f16700Schasinglulu 	 * (e.g. enable interrupts and clear powerdown request bit)
395*91f16700Schasinglulu 	 */
396*91f16700Schasinglulu 	pm_client_abort_suspend();
397*91f16700Schasinglulu 	/* Send request to the PMU */
398*91f16700Schasinglulu 	/* TODO: allow passing the node ID of the affected CPU */
399*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
400*91f16700Schasinglulu 			 primary_proc->node_id);
401*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
402*91f16700Schasinglulu }
403*91f16700Schasinglulu 
404*91f16700Schasinglulu /**
405*91f16700Schasinglulu  * pm_set_wakeup_source() - PM call to specify the wakeup source while
406*91f16700Schasinglulu  *                          suspended.
407*91f16700Schasinglulu  * @target: Node id of the targeted PU or subsystem.
408*91f16700Schasinglulu  * @wkup_node: Node id of the wakeup peripheral.
409*91f16700Schasinglulu  * @enable: Enable or disable the specified peripheral as wake source.
410*91f16700Schasinglulu  *
411*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
412*91f16700Schasinglulu  *
413*91f16700Schasinglulu  */
414*91f16700Schasinglulu enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
415*91f16700Schasinglulu 					enum pm_node_id wkup_node,
416*91f16700Schasinglulu 					uint32_t enable)
417*91f16700Schasinglulu {
418*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
419*91f16700Schasinglulu 
420*91f16700Schasinglulu 	PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
421*91f16700Schasinglulu 			 enable);
422*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
423*91f16700Schasinglulu }
424*91f16700Schasinglulu 
425*91f16700Schasinglulu /**
426*91f16700Schasinglulu  * pm_system_shutdown() - PM call to request a system shutdown or restart.
427*91f16700Schasinglulu  * @type: Shutdown or restart? 0=shutdown, 1=restart, 2=setscope.
428*91f16700Schasinglulu  * @subtype: Scope: 0=APU-subsystem, 1=PS, 2=system.
429*91f16700Schasinglulu  *
430*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
431*91f16700Schasinglulu  *
432*91f16700Schasinglulu  */
433*91f16700Schasinglulu enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
434*91f16700Schasinglulu {
435*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
436*91f16700Schasinglulu 
437*91f16700Schasinglulu 	if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
438*91f16700Schasinglulu 		/* Setting scope for subsequent PSCI reboot or shutdown */
439*91f16700Schasinglulu 		pm_shutdown_scope = subtype;
440*91f16700Schasinglulu 		return PM_RET_SUCCESS;
441*91f16700Schasinglulu 	}
442*91f16700Schasinglulu 
443*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
444*91f16700Schasinglulu 	return pm_ipi_send_non_blocking(primary_proc, payload);
445*91f16700Schasinglulu }
446*91f16700Schasinglulu 
447*91f16700Schasinglulu /* APIs for managing PM slaves: */
448*91f16700Schasinglulu 
449*91f16700Schasinglulu /**
450*91f16700Schasinglulu  * pm_req_node() - PM call to request a node with specific capabilities.
451*91f16700Schasinglulu  * @nid: Node id of the slave.
452*91f16700Schasinglulu  * @capabilities: Requested capabilities of the slave.
453*91f16700Schasinglulu  * @qos: Quality of service (not supported).
454*91f16700Schasinglulu  * @ack: Flag to specify whether acknowledge is requested.
455*91f16700Schasinglulu  *
456*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
457*91f16700Schasinglulu  *
458*91f16700Schasinglulu  */
459*91f16700Schasinglulu enum pm_ret_status pm_req_node(enum pm_node_id nid,
460*91f16700Schasinglulu 			       uint32_t capabilities,
461*91f16700Schasinglulu 			       uint32_t qos,
462*91f16700Schasinglulu 			       enum pm_request_ack ack)
463*91f16700Schasinglulu {
464*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
465*91f16700Schasinglulu 
466*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
467*91f16700Schasinglulu 
468*91f16700Schasinglulu 	if (ack == REQ_ACK_BLOCKING) {
469*91f16700Schasinglulu 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
470*91f16700Schasinglulu 	} else {
471*91f16700Schasinglulu 		return pm_ipi_send(primary_proc, payload);
472*91f16700Schasinglulu 	}
473*91f16700Schasinglulu }
474*91f16700Schasinglulu 
475*91f16700Schasinglulu /**
476*91f16700Schasinglulu  * pm_set_requirement() - PM call to set requirement for PM slaves.
477*91f16700Schasinglulu  * @nid: Node id of the slave.
478*91f16700Schasinglulu  * @capabilities: Requested capabilities of the slave.
479*91f16700Schasinglulu  * @qos: Quality of service (not supported).
480*91f16700Schasinglulu  * @ack: Flag to specify whether acknowledge is requested.
481*91f16700Schasinglulu  *
482*91f16700Schasinglulu  * This API function is to be used for slaves a PU already has requested.
483*91f16700Schasinglulu  *
484*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
485*91f16700Schasinglulu  *
486*91f16700Schasinglulu  */
487*91f16700Schasinglulu enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
488*91f16700Schasinglulu 				      uint32_t capabilities,
489*91f16700Schasinglulu 				      uint32_t qos,
490*91f16700Schasinglulu 				      enum pm_request_ack ack)
491*91f16700Schasinglulu {
492*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
493*91f16700Schasinglulu 
494*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
495*91f16700Schasinglulu 			 ack);
496*91f16700Schasinglulu 
497*91f16700Schasinglulu 	if (ack == REQ_ACK_BLOCKING) {
498*91f16700Schasinglulu 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
499*91f16700Schasinglulu 	} else {
500*91f16700Schasinglulu 		return pm_ipi_send(primary_proc, payload);
501*91f16700Schasinglulu 	}
502*91f16700Schasinglulu }
503*91f16700Schasinglulu 
504*91f16700Schasinglulu /* Miscellaneous API functions */
505*91f16700Schasinglulu 
506*91f16700Schasinglulu /**
507*91f16700Schasinglulu  * pm_get_api_version() - Get version number of PMU PM firmware.
508*91f16700Schasinglulu  * @version: Returns 32-bit version number of PMU Power Management Firmware.
509*91f16700Schasinglulu  *
510*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
511*91f16700Schasinglulu  *
512*91f16700Schasinglulu  */
513*91f16700Schasinglulu enum pm_ret_status pm_get_api_version(uint32_t *version)
514*91f16700Schasinglulu {
515*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
516*91f16700Schasinglulu 
517*91f16700Schasinglulu 	/* Send request to the PMU */
518*91f16700Schasinglulu 	PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
519*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, version, 1);
520*91f16700Schasinglulu }
521*91f16700Schasinglulu 
522*91f16700Schasinglulu /**
523*91f16700Schasinglulu  * pm_get_node_status() - PM call to request a node's current status.
524*91f16700Schasinglulu  * @nid: Node id.
525*91f16700Schasinglulu  * @ret_buff: Buffer for the return values
526*91f16700Schasinglulu  *            [0] - Current power state of the node
527*91f16700Schasinglulu  *            [1] - Current requirements for the node (slave nodes only)
528*91f16700Schasinglulu  *            [2] - Current usage status for the node (slave nodes only)
529*91f16700Schasinglulu  *
530*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
531*91f16700Schasinglulu  *
532*91f16700Schasinglulu  */
533*91f16700Schasinglulu enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
534*91f16700Schasinglulu 				      uint32_t *ret_buff)
535*91f16700Schasinglulu {
536*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
537*91f16700Schasinglulu 
538*91f16700Schasinglulu 	PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
539*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
540*91f16700Schasinglulu }
541*91f16700Schasinglulu 
542*91f16700Schasinglulu /**
543*91f16700Schasinglulu  * pm_mmio_write() - Perform write to protected mmio.
544*91f16700Schasinglulu  * @address: Address to write to.
545*91f16700Schasinglulu  * @mask: Mask to apply.
546*91f16700Schasinglulu  * @value: Value to write.
547*91f16700Schasinglulu  *
548*91f16700Schasinglulu  * This function provides access to PM-related control registers
549*91f16700Schasinglulu  * that may not be directly accessible by a particular PU.
550*91f16700Schasinglulu  *
551*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
552*91f16700Schasinglulu  *
553*91f16700Schasinglulu  */
554*91f16700Schasinglulu enum pm_ret_status pm_mmio_write(uintptr_t address,
555*91f16700Schasinglulu 				 uint32_t mask,
556*91f16700Schasinglulu 				 uint32_t value)
557*91f16700Schasinglulu {
558*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
559*91f16700Schasinglulu 
560*91f16700Schasinglulu 	/* Send request to the PMU */
561*91f16700Schasinglulu 	PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
562*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
563*91f16700Schasinglulu }
564*91f16700Schasinglulu 
565*91f16700Schasinglulu /**
566*91f16700Schasinglulu  * pm_mmio_read() - Read value from protected mmio.
567*91f16700Schasinglulu  * @address: Address to write to.
568*91f16700Schasinglulu  * @value: Value to write.
569*91f16700Schasinglulu  *
570*91f16700Schasinglulu  * This function provides access to PM-related control registers
571*91f16700Schasinglulu  * that may not be directly accessible by a particular PU.
572*91f16700Schasinglulu  *
573*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
574*91f16700Schasinglulu  *
575*91f16700Schasinglulu  */
576*91f16700Schasinglulu enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value)
577*91f16700Schasinglulu {
578*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
579*91f16700Schasinglulu 
580*91f16700Schasinglulu 	/* Send request to the PMU */
581*91f16700Schasinglulu 	PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
582*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
583*91f16700Schasinglulu }
584*91f16700Schasinglulu 
585*91f16700Schasinglulu /**
586*91f16700Schasinglulu  * pm_fpga_load() - Load the bitstream into the PL. This function provides
587*91f16700Schasinglulu  *                  access to the xilfpga library to load the Bit-stream
588*91f16700Schasinglulu  *                  into PL.
589*91f16700Schasinglulu  * @address_low: lower 32-bit Linear memory space address.
590*91f16700Schasinglulu  * @address_high: higher 32-bit Linear memory space address.
591*91f16700Schasinglulu  * @size: Number of 32bit words.
592*91f16700Schasinglulu  * @flags: Additional flags or settings for the fpga operation.
593*91f16700Schasinglulu  *
594*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
595*91f16700Schasinglulu  *
596*91f16700Schasinglulu  */
597*91f16700Schasinglulu enum pm_ret_status pm_fpga_load(uint32_t address_low,
598*91f16700Schasinglulu 				uint32_t address_high,
599*91f16700Schasinglulu 				uint32_t size,
600*91f16700Schasinglulu 				uint32_t flags)
601*91f16700Schasinglulu {
602*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
603*91f16700Schasinglulu 
604*91f16700Schasinglulu 	/* Send request to the PMU */
605*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
606*91f16700Schasinglulu 						size, flags);
607*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
608*91f16700Schasinglulu }
609*91f16700Schasinglulu 
610*91f16700Schasinglulu /**
611*91f16700Schasinglulu  * pm_fpga_get_status() - Read value from fpga status register.
612*91f16700Schasinglulu  * @value: Value to read.
613*91f16700Schasinglulu  *
614*91f16700Schasinglulu  * This function provides access to the xilfpga library to get
615*91f16700Schasinglulu  * the fpga status.
616*91f16700Schasinglulu  *
617*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
618*91f16700Schasinglulu  *
619*91f16700Schasinglulu  */
620*91f16700Schasinglulu enum pm_ret_status pm_fpga_get_status(uint32_t *value)
621*91f16700Schasinglulu {
622*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
623*91f16700Schasinglulu 
624*91f16700Schasinglulu 	/* Send request to the PMU */
625*91f16700Schasinglulu 	PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
626*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
627*91f16700Schasinglulu }
628*91f16700Schasinglulu 
629*91f16700Schasinglulu /**
630*91f16700Schasinglulu  * pm_get_chipid() - Read silicon ID registers.
631*91f16700Schasinglulu  * @value: Buffer for return values. Must be large enough to hold 8 bytes.
632*91f16700Schasinglulu  *
633*91f16700Schasinglulu  * Return: Returns silicon ID registers.
634*91f16700Schasinglulu  *
635*91f16700Schasinglulu  */
636*91f16700Schasinglulu enum pm_ret_status pm_get_chipid(uint32_t *value)
637*91f16700Schasinglulu {
638*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
639*91f16700Schasinglulu 
640*91f16700Schasinglulu 	/* Send request to the PMU */
641*91f16700Schasinglulu 	PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
642*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 2);
643*91f16700Schasinglulu }
644*91f16700Schasinglulu 
645*91f16700Schasinglulu /**
646*91f16700Schasinglulu  * pm_secure_rsaaes() - Load the secure images.
647*91f16700Schasinglulu  * @address_low: lower 32-bit Linear memory space address.
648*91f16700Schasinglulu  * @address_high: higher 32-bit Linear memory space address.
649*91f16700Schasinglulu  * @size: Number of 32bit words.
650*91f16700Schasinglulu  * @flags: Additional flags or settings for the fpga operation.
651*91f16700Schasinglulu  *
652*91f16700Schasinglulu  * This function provides access to the xilsecure library to load the
653*91f16700Schasinglulu  * authenticated, encrypted, and authenticated/encrypted images.
654*91f16700Schasinglulu  *
655*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
656*91f16700Schasinglulu  *
657*91f16700Schasinglulu  */
658*91f16700Schasinglulu enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
659*91f16700Schasinglulu 				uint32_t address_high,
660*91f16700Schasinglulu 				uint32_t size,
661*91f16700Schasinglulu 				uint32_t flags)
662*91f16700Schasinglulu {
663*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
664*91f16700Schasinglulu 
665*91f16700Schasinglulu 	/* Send request to the PMU */
666*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
667*91f16700Schasinglulu 			 size, flags);
668*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
669*91f16700Schasinglulu }
670*91f16700Schasinglulu 
671*91f16700Schasinglulu /**
672*91f16700Schasinglulu  * pm_aes_engine() - Aes data blob encryption/decryption.
673*91f16700Schasinglulu  * @address_low: lower 32-bit address of the AesParams structure.
674*91f16700Schasinglulu  * @address_high: higher 32-bit address of the AesParams structure.
675*91f16700Schasinglulu  * @value: Returned output value.
676*91f16700Schasinglulu  *
677*91f16700Schasinglulu  * This function provides access to the xilsecure library to
678*91f16700Schasinglulu  * encrypt/decrypt data blobs.
679*91f16700Schasinglulu  *
680*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
681*91f16700Schasinglulu  *
682*91f16700Schasinglulu  */
683*91f16700Schasinglulu enum pm_ret_status pm_aes_engine(uint32_t address_high,
684*91f16700Schasinglulu 				 uint32_t address_low,
685*91f16700Schasinglulu 				 uint32_t *value)
686*91f16700Schasinglulu {
687*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
688*91f16700Schasinglulu 
689*91f16700Schasinglulu 	/* Send request to the PMU */
690*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
691*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
692*91f16700Schasinglulu }
693*91f16700Schasinglulu 
694*91f16700Schasinglulu /**
695*91f16700Schasinglulu  * pm_get_callbackdata() - Read from IPI response buffer.
696*91f16700Schasinglulu  * @data: array of PAYLOAD_ARG_CNT elements.
697*91f16700Schasinglulu  * @count: Number of values to return.
698*91f16700Schasinglulu  *
699*91f16700Schasinglulu  * Read value from ipi buffer response buffer.
700*91f16700Schasinglulu  * Return: Returns status, either success or error.
701*91f16700Schasinglulu  *
702*91f16700Schasinglulu  */
703*91f16700Schasinglulu enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count)
704*91f16700Schasinglulu {
705*91f16700Schasinglulu 	enum pm_ret_status ret = PM_RET_SUCCESS;
706*91f16700Schasinglulu 	/* Return if interrupt is not from PMU */
707*91f16700Schasinglulu 	if (!pm_ipi_irq_status(primary_proc)) {
708*91f16700Schasinglulu 		return ret;
709*91f16700Schasinglulu 	}
710*91f16700Schasinglulu 
711*91f16700Schasinglulu 	ret = pm_ipi_buff_read_callb(data, count);
712*91f16700Schasinglulu 	pm_ipi_irq_clear(primary_proc);
713*91f16700Schasinglulu 	return ret;
714*91f16700Schasinglulu }
715*91f16700Schasinglulu 
716*91f16700Schasinglulu /**
717*91f16700Schasinglulu  * pm_ioctl() - PM IOCTL API for device control and configs.
718*91f16700Schasinglulu  * @nid: Node ID of the device.
719*91f16700Schasinglulu  * @ioctl_id: ID of the requested IOCTL.
720*91f16700Schasinglulu  * @arg1: Argument 1 to requested IOCTL call.
721*91f16700Schasinglulu  * @arg2: Argument 2 to requested IOCTL call.
722*91f16700Schasinglulu  * @value: Returned output value.
723*91f16700Schasinglulu  *
724*91f16700Schasinglulu  * This function calls IOCTL to firmware for device control and configuration.
725*91f16700Schasinglulu  *
726*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
727*91f16700Schasinglulu  *
728*91f16700Schasinglulu  */
729*91f16700Schasinglulu enum pm_ret_status pm_ioctl(enum pm_node_id nid,
730*91f16700Schasinglulu 			    uint32_t ioctl_id,
731*91f16700Schasinglulu 			    uint32_t arg1,
732*91f16700Schasinglulu 			    uint32_t arg2,
733*91f16700Schasinglulu 			    uint32_t *value)
734*91f16700Schasinglulu {
735*91f16700Schasinglulu 	return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
736*91f16700Schasinglulu }
737*91f16700Schasinglulu 
738*91f16700Schasinglulu /**
739*91f16700Schasinglulu  * fw_api_version() - Returns API version implemented in firmware.
740*91f16700Schasinglulu  * @id: API ID to check.
741*91f16700Schasinglulu  * @version: Returned supported API version.
742*91f16700Schasinglulu  * @len: Number of words to be returned.
743*91f16700Schasinglulu  *
744*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
745*91f16700Schasinglulu  *
746*91f16700Schasinglulu  */
747*91f16700Schasinglulu static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version,
748*91f16700Schasinglulu 					 uint32_t len)
749*91f16700Schasinglulu {
750*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
751*91f16700Schasinglulu 
752*91f16700Schasinglulu 	PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id);
753*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, version, len);
754*91f16700Schasinglulu }
755*91f16700Schasinglulu 
756*91f16700Schasinglulu /**
757*91f16700Schasinglulu  * check_api_dependency() -  API to check dependent EEMI API version.
758*91f16700Schasinglulu  * @id: EEMI API ID to check.
759*91f16700Schasinglulu  *
760*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
761*91f16700Schasinglulu  *
762*91f16700Schasinglulu  */
763*91f16700Schasinglulu enum pm_ret_status check_api_dependency(uint8_t id)
764*91f16700Schasinglulu {
765*91f16700Schasinglulu 	uint8_t i;
766*91f16700Schasinglulu 	uint32_t version;
767*91f16700Schasinglulu 	int ret;
768*91f16700Schasinglulu 
769*91f16700Schasinglulu 	for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
770*91f16700Schasinglulu 		if (api_dep_table[i].id == id) {
771*91f16700Schasinglulu 			if (api_dep_table[i].api_id == 0U) {
772*91f16700Schasinglulu 				break;
773*91f16700Schasinglulu 			}
774*91f16700Schasinglulu 
775*91f16700Schasinglulu 			ret = fw_api_version(api_dep_table[i].api_id,
776*91f16700Schasinglulu 					     &version, 1);
777*91f16700Schasinglulu 			if (ret != PM_RET_SUCCESS) {
778*91f16700Schasinglulu 				return ret;
779*91f16700Schasinglulu 			}
780*91f16700Schasinglulu 
781*91f16700Schasinglulu 			/* Check if fw version matches TF-A expected version */
782*91f16700Schasinglulu 			if (version != tfa_expected_ver_id[api_dep_table[i].api_id]) {
783*91f16700Schasinglulu 				return PM_RET_ERROR_NOTSUPPORTED;
784*91f16700Schasinglulu 			}
785*91f16700Schasinglulu 		}
786*91f16700Schasinglulu 	}
787*91f16700Schasinglulu 
788*91f16700Schasinglulu 	return PM_RET_SUCCESS;
789*91f16700Schasinglulu }
790*91f16700Schasinglulu 
791*91f16700Schasinglulu /**
792*91f16700Schasinglulu  * feature_check_tfa() - These are API's completely implemented in TF-A.
793*91f16700Schasinglulu  * @api_id: API ID to check.
794*91f16700Schasinglulu  * @version: Returned supported API version.
795*91f16700Schasinglulu  * @bit_mask: Returned supported IOCTL id version.
796*91f16700Schasinglulu  *
797*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
798*91f16700Schasinglulu  *
799*91f16700Schasinglulu  */
800*91f16700Schasinglulu static enum pm_ret_status feature_check_tfa(uint32_t api_id, uint32_t *version,
801*91f16700Schasinglulu 					    uint32_t *bit_mask)
802*91f16700Schasinglulu {
803*91f16700Schasinglulu 	switch (api_id) {
804*91f16700Schasinglulu 	case PM_QUERY_DATA:
805*91f16700Schasinglulu 		*version = TFA_API_QUERY_DATA_VERSION;
806*91f16700Schasinglulu 		bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
807*91f16700Schasinglulu 		bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
808*91f16700Schasinglulu 		return PM_RET_SUCCESS;
809*91f16700Schasinglulu 	case PM_GET_CALLBACK_DATA:
810*91f16700Schasinglulu 	case PM_GET_TRUSTZONE_VERSION:
811*91f16700Schasinglulu 	case PM_SET_SUSPEND_MODE:
812*91f16700Schasinglulu 		*version = TFA_API_BASE_VERSION;
813*91f16700Schasinglulu 		return PM_RET_SUCCESS;
814*91f16700Schasinglulu 	default:
815*91f16700Schasinglulu 		return PM_RET_ERROR_NO_FEATURE;
816*91f16700Schasinglulu 	}
817*91f16700Schasinglulu }
818*91f16700Schasinglulu 
819*91f16700Schasinglulu /**
820*91f16700Schasinglulu  * get_tfa_version_for_partial_apis() - Return TF-A version for partially.
821*91f16700Schasinglulu  *                                      implemented APIs
822*91f16700Schasinglulu  * @api_id: API ID to check.
823*91f16700Schasinglulu  * @version: Returned supported API version.
824*91f16700Schasinglulu  *
825*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
826*91f16700Schasinglulu  *
827*91f16700Schasinglulu  */
828*91f16700Schasinglulu static enum pm_ret_status get_tfa_version_for_partial_apis(uint32_t api_id,
829*91f16700Schasinglulu 							   uint32_t *version)
830*91f16700Schasinglulu {
831*91f16700Schasinglulu 	switch (api_id) {
832*91f16700Schasinglulu 	case PM_SELF_SUSPEND:
833*91f16700Schasinglulu 	case PM_REQ_WAKEUP:
834*91f16700Schasinglulu 	case PM_ABORT_SUSPEND:
835*91f16700Schasinglulu 	case PM_SET_WAKEUP_SOURCE:
836*91f16700Schasinglulu 	case PM_SYSTEM_SHUTDOWN:
837*91f16700Schasinglulu 	case PM_GET_API_VERSION:
838*91f16700Schasinglulu 	case PM_CLOCK_ENABLE:
839*91f16700Schasinglulu 	case PM_CLOCK_DISABLE:
840*91f16700Schasinglulu 	case PM_CLOCK_GETSTATE:
841*91f16700Schasinglulu 	case PM_CLOCK_SETDIVIDER:
842*91f16700Schasinglulu 	case PM_CLOCK_GETDIVIDER:
843*91f16700Schasinglulu 	case PM_CLOCK_SETPARENT:
844*91f16700Schasinglulu 	case PM_CLOCK_GETPARENT:
845*91f16700Schasinglulu 	case PM_PLL_SET_PARAMETER:
846*91f16700Schasinglulu 	case PM_PLL_GET_PARAMETER:
847*91f16700Schasinglulu 	case PM_PLL_SET_MODE:
848*91f16700Schasinglulu 	case PM_PLL_GET_MODE:
849*91f16700Schasinglulu 	case PM_REGISTER_ACCESS:
850*91f16700Schasinglulu 		*version = TFA_API_BASE_VERSION;
851*91f16700Schasinglulu 		return PM_RET_SUCCESS;
852*91f16700Schasinglulu 	case PM_FEATURE_CHECK:
853*91f16700Schasinglulu 		*version = FW_API_VERSION_2;
854*91f16700Schasinglulu 		return PM_RET_SUCCESS;
855*91f16700Schasinglulu 	default:
856*91f16700Schasinglulu 		return PM_RET_ERROR_ARGS;
857*91f16700Schasinglulu 	}
858*91f16700Schasinglulu }
859*91f16700Schasinglulu 
860*91f16700Schasinglulu /**
861*91f16700Schasinglulu  * feature_check_partial() - These are API's partially implemented in
862*91f16700Schasinglulu  *                           TF-A and firmware both.
863*91f16700Schasinglulu  * @api_id: API ID to check.
864*91f16700Schasinglulu  * @version: Returned supported API version.
865*91f16700Schasinglulu  *
866*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
867*91f16700Schasinglulu  *
868*91f16700Schasinglulu  */
869*91f16700Schasinglulu static enum pm_ret_status feature_check_partial(uint32_t api_id,
870*91f16700Schasinglulu 						uint32_t *version)
871*91f16700Schasinglulu {
872*91f16700Schasinglulu 	uint32_t status;
873*91f16700Schasinglulu 
874*91f16700Schasinglulu 	switch (api_id) {
875*91f16700Schasinglulu 	case PM_SELF_SUSPEND:
876*91f16700Schasinglulu 	case PM_REQ_WAKEUP:
877*91f16700Schasinglulu 	case PM_ABORT_SUSPEND:
878*91f16700Schasinglulu 	case PM_SET_WAKEUP_SOURCE:
879*91f16700Schasinglulu 	case PM_SYSTEM_SHUTDOWN:
880*91f16700Schasinglulu 	case PM_GET_API_VERSION:
881*91f16700Schasinglulu 	case PM_CLOCK_ENABLE:
882*91f16700Schasinglulu 	case PM_CLOCK_DISABLE:
883*91f16700Schasinglulu 	case PM_CLOCK_GETSTATE:
884*91f16700Schasinglulu 	case PM_CLOCK_SETDIVIDER:
885*91f16700Schasinglulu 	case PM_CLOCK_GETDIVIDER:
886*91f16700Schasinglulu 	case PM_CLOCK_SETPARENT:
887*91f16700Schasinglulu 	case PM_CLOCK_GETPARENT:
888*91f16700Schasinglulu 	case PM_PLL_SET_PARAMETER:
889*91f16700Schasinglulu 	case PM_PLL_GET_PARAMETER:
890*91f16700Schasinglulu 	case PM_PLL_SET_MODE:
891*91f16700Schasinglulu 	case PM_PLL_GET_MODE:
892*91f16700Schasinglulu 	case PM_REGISTER_ACCESS:
893*91f16700Schasinglulu 	case PM_FEATURE_CHECK:
894*91f16700Schasinglulu 		status = check_api_dependency(api_id);
895*91f16700Schasinglulu 		if (status != PM_RET_SUCCESS) {
896*91f16700Schasinglulu 			return status;
897*91f16700Schasinglulu 		}
898*91f16700Schasinglulu 		return get_tfa_version_for_partial_apis(api_id, version);
899*91f16700Schasinglulu 	default:
900*91f16700Schasinglulu 		return PM_RET_ERROR_NO_FEATURE;
901*91f16700Schasinglulu 	}
902*91f16700Schasinglulu }
903*91f16700Schasinglulu 
904*91f16700Schasinglulu /**
905*91f16700Schasinglulu  * pm_feature_check() - Returns the supported API version if supported.
906*91f16700Schasinglulu  * @api_id: API ID to check.
907*91f16700Schasinglulu  * @version: Returned supported API version.
908*91f16700Schasinglulu  * @bit_mask: Returned supported IOCTL id version.
909*91f16700Schasinglulu  * @len: Number of bytes to be returned in bit_mask variable.
910*91f16700Schasinglulu  *
911*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
912*91f16700Schasinglulu  *
913*91f16700Schasinglulu  */
914*91f16700Schasinglulu enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
915*91f16700Schasinglulu 				    uint32_t *bit_mask, uint8_t len)
916*91f16700Schasinglulu {
917*91f16700Schasinglulu 	uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
918*91f16700Schasinglulu 	uint32_t status;
919*91f16700Schasinglulu 
920*91f16700Schasinglulu 	/* Get API version implemented in TF-A */
921*91f16700Schasinglulu 	status = feature_check_tfa(api_id, version, bit_mask);
922*91f16700Schasinglulu 	if (status != PM_RET_ERROR_NO_FEATURE) {
923*91f16700Schasinglulu 		return status;
924*91f16700Schasinglulu 	}
925*91f16700Schasinglulu 
926*91f16700Schasinglulu 	/* Get API version implemented by firmware and TF-A both */
927*91f16700Schasinglulu 	status = feature_check_partial(api_id, version);
928*91f16700Schasinglulu 	if (status != PM_RET_ERROR_NO_FEATURE) {
929*91f16700Schasinglulu 		return status;
930*91f16700Schasinglulu 	}
931*91f16700Schasinglulu 
932*91f16700Schasinglulu 	/* Get API version implemented by firmware */
933*91f16700Schasinglulu 	status = fw_api_version(api_id, ret_payload, 3);
934*91f16700Schasinglulu 	/* IOCTL call may return failure whose ID is not implemented in
935*91f16700Schasinglulu 	 * firmware but implemented in TF-A
936*91f16700Schasinglulu 	 */
937*91f16700Schasinglulu 	if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) {
938*91f16700Schasinglulu 		return status;
939*91f16700Schasinglulu 	}
940*91f16700Schasinglulu 
941*91f16700Schasinglulu 	*version = ret_payload[0];
942*91f16700Schasinglulu 
943*91f16700Schasinglulu 	/* Update IOCTL bit mask which are implemented in TF-A */
944*91f16700Schasinglulu 	if ((api_id == PM_IOCTL) || (api_id == PM_GET_OP_CHARACTERISTIC)) {
945*91f16700Schasinglulu 		if (len < 2) {
946*91f16700Schasinglulu 			return PM_RET_ERROR_ARGS;
947*91f16700Schasinglulu 		}
948*91f16700Schasinglulu 		bit_mask[0] = ret_payload[1];
949*91f16700Schasinglulu 		bit_mask[1] = ret_payload[2];
950*91f16700Schasinglulu 		if (api_id == PM_IOCTL) {
951*91f16700Schasinglulu 			/* Get IOCTL's implemented by TF-A */
952*91f16700Schasinglulu 			status = tfa_ioctl_bitmask(bit_mask);
953*91f16700Schasinglulu 		}
954*91f16700Schasinglulu 	} else {
955*91f16700Schasinglulu 		/* Requires for MISRA */
956*91f16700Schasinglulu 	}
957*91f16700Schasinglulu 
958*91f16700Schasinglulu 	return status;
959*91f16700Schasinglulu }
960*91f16700Schasinglulu 
961*91f16700Schasinglulu /**
962*91f16700Schasinglulu  * pm_clock_get_max_divisor - PM call to get max divisor.
963*91f16700Schasinglulu  * @clock_id: Clock ID.
964*91f16700Schasinglulu  * @div_type: Divisor ID (TYPE_DIV1 or TYPE_DIV2).
965*91f16700Schasinglulu  * @max_div: Maximum supported divisor.
966*91f16700Schasinglulu  *
967*91f16700Schasinglulu  * This function is used by master to get maximum supported value.
968*91f16700Schasinglulu  *
969*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
970*91f16700Schasinglulu  *
971*91f16700Schasinglulu  */
972*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_max_divisor(uint32_t clock_id,
973*91f16700Schasinglulu 						   uint8_t div_type,
974*91f16700Schasinglulu 						   uint32_t *max_div)
975*91f16700Schasinglulu {
976*91f16700Schasinglulu 	return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
977*91f16700Schasinglulu }
978*91f16700Schasinglulu 
979*91f16700Schasinglulu /**
980*91f16700Schasinglulu  * pm_clock_get_num_clocks - PM call to request number of clocks.
981*91f16700Schasinglulu  * @nclocks: Number of clocks.
982*91f16700Schasinglulu  *
983*91f16700Schasinglulu  * This function is used by master to get number of clocks.
984*91f16700Schasinglulu  *
985*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
986*91f16700Schasinglulu  *
987*91f16700Schasinglulu  */
988*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
989*91f16700Schasinglulu {
990*91f16700Schasinglulu 	return pm_api_clock_get_num_clocks(nclocks);
991*91f16700Schasinglulu }
992*91f16700Schasinglulu 
993*91f16700Schasinglulu /**
994*91f16700Schasinglulu  * pm_clock_get_name() - PM call to request a clock's name.
995*91f16700Schasinglulu  * @clock_id: Clock ID.
996*91f16700Schasinglulu  * @name: Name of clock (max 16 bytes).
997*91f16700Schasinglulu  *
998*91f16700Schasinglulu  * This function is used by master to get nmae of clock specified
999*91f16700Schasinglulu  * by given clock ID.
1000*91f16700Schasinglulu  *
1001*91f16700Schasinglulu  */
1002*91f16700Schasinglulu static void pm_clock_get_name(uint32_t clock_id, char *name)
1003*91f16700Schasinglulu {
1004*91f16700Schasinglulu 	pm_api_clock_get_name(clock_id, name);
1005*91f16700Schasinglulu }
1006*91f16700Schasinglulu 
1007*91f16700Schasinglulu /**
1008*91f16700Schasinglulu  * pm_clock_get_topology() - PM call to request a clock's topology.
1009*91f16700Schasinglulu  * @clock_id: Clock ID.
1010*91f16700Schasinglulu  * @index: Topology index for next toplogy node.
1011*91f16700Schasinglulu  * @topology: Buffer to store nodes in topology and flags.
1012*91f16700Schasinglulu  *
1013*91f16700Schasinglulu  * This function is used by master to get topology information for the
1014*91f16700Schasinglulu  * clock specified by given clock ID. Each response would return 3
1015*91f16700Schasinglulu  * topology nodes. To get next nodes, caller needs to call this API with
1016*91f16700Schasinglulu  * index of next node. Index starts from 0.
1017*91f16700Schasinglulu  *
1018*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1019*91f16700Schasinglulu  *
1020*91f16700Schasinglulu  */
1021*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_topology(uint32_t clock_id,
1022*91f16700Schasinglulu 						uint32_t index,
1023*91f16700Schasinglulu 						uint32_t *topology)
1024*91f16700Schasinglulu {
1025*91f16700Schasinglulu 	return pm_api_clock_get_topology(clock_id, index, topology);
1026*91f16700Schasinglulu }
1027*91f16700Schasinglulu 
1028*91f16700Schasinglulu /**
1029*91f16700Schasinglulu  * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
1030*91f16700Schasinglulu  *                                     parameters for fixed clock.
1031*91f16700Schasinglulu  * @clock_id: Clock ID.
1032*91f16700Schasinglulu  * @mul: Multiplication value.
1033*91f16700Schasinglulu  * @div: Divisor value.
1034*91f16700Schasinglulu  *
1035*91f16700Schasinglulu  * This function is used by master to get fixed factor parameers for the
1036*91f16700Schasinglulu  * fixed clock. This API is application only for the fixed clock.
1037*91f16700Schasinglulu  *
1038*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1039*91f16700Schasinglulu  *
1040*91f16700Schasinglulu  */
1041*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_fixedfactor_params(uint32_t clock_id,
1042*91f16700Schasinglulu 							  uint32_t *mul,
1043*91f16700Schasinglulu 							  uint32_t *div)
1044*91f16700Schasinglulu {
1045*91f16700Schasinglulu 	return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
1046*91f16700Schasinglulu }
1047*91f16700Schasinglulu 
1048*91f16700Schasinglulu /**
1049*91f16700Schasinglulu  * pm_clock_get_parents() - PM call to request a clock's first 3 parents.
1050*91f16700Schasinglulu  * @clock_id: Clock ID.
1051*91f16700Schasinglulu  * @index: Index of next parent.
1052*91f16700Schasinglulu  * @parents: Parents of the given clock.
1053*91f16700Schasinglulu  *
1054*91f16700Schasinglulu  * This function is used by master to get clock's parents information.
1055*91f16700Schasinglulu  * This API will return 3 parents with a single response. To get other
1056*91f16700Schasinglulu  * parents, master should call same API in loop with new parent index
1057*91f16700Schasinglulu  * till error is returned.
1058*91f16700Schasinglulu  *
1059*91f16700Schasinglulu  * E.g First call should have index 0 which will return parents 0, 1 and
1060*91f16700Schasinglulu  * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
1061*91f16700Schasinglulu  * so on.
1062*91f16700Schasinglulu  *
1063*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1064*91f16700Schasinglulu  *
1065*91f16700Schasinglulu  */
1066*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_parents(uint32_t clock_id,
1067*91f16700Schasinglulu 					       uint32_t index,
1068*91f16700Schasinglulu 					       uint32_t *parents)
1069*91f16700Schasinglulu {
1070*91f16700Schasinglulu 	return pm_api_clock_get_parents(clock_id, index, parents);
1071*91f16700Schasinglulu }
1072*91f16700Schasinglulu 
1073*91f16700Schasinglulu /**
1074*91f16700Schasinglulu  * pm_clock_get_attributes() - PM call to request a clock's attributes.
1075*91f16700Schasinglulu  * @clock_id: Clock ID.
1076*91f16700Schasinglulu  * @attr: Clock attributes.
1077*91f16700Schasinglulu  *
1078*91f16700Schasinglulu  * This function is used by master to get clock's attributes
1079*91f16700Schasinglulu  * (e.g. valid, clock type, etc).
1080*91f16700Schasinglulu  *
1081*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1082*91f16700Schasinglulu  *
1083*91f16700Schasinglulu  */
1084*91f16700Schasinglulu static enum pm_ret_status pm_clock_get_attributes(uint32_t clock_id,
1085*91f16700Schasinglulu 						  uint32_t *attr)
1086*91f16700Schasinglulu {
1087*91f16700Schasinglulu 	return pm_api_clock_get_attributes(clock_id, attr);
1088*91f16700Schasinglulu }
1089*91f16700Schasinglulu 
1090*91f16700Schasinglulu /**
1091*91f16700Schasinglulu  * pm_clock_gate() - Configure clock gate.
1092*91f16700Schasinglulu  * @clock_id: Id of the clock to be configured.
1093*91f16700Schasinglulu  * @enable: Flag 0=disable (gate the clock), !0=enable (activate the clock).
1094*91f16700Schasinglulu  *
1095*91f16700Schasinglulu  * Return: Error if an argument is not valid or status as returned by the
1096*91f16700Schasinglulu  *         PM controller (PMU).
1097*91f16700Schasinglulu  *
1098*91f16700Schasinglulu  */
1099*91f16700Schasinglulu static enum pm_ret_status pm_clock_gate(uint32_t clock_id,
1100*91f16700Schasinglulu 					uint8_t enable)
1101*91f16700Schasinglulu {
1102*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1103*91f16700Schasinglulu 	enum pm_ret_status status;
1104*91f16700Schasinglulu 	enum pm_api_id api_id;
1105*91f16700Schasinglulu 
1106*91f16700Schasinglulu 	/* Check if clock ID is valid and return an error if it is not */
1107*91f16700Schasinglulu 	status = pm_clock_id_is_valid(clock_id);
1108*91f16700Schasinglulu 	if (status != PM_RET_SUCCESS) {
1109*91f16700Schasinglulu 		return status;
1110*91f16700Schasinglulu 	}
1111*91f16700Schasinglulu 
1112*91f16700Schasinglulu 	if (enable) {
1113*91f16700Schasinglulu 		api_id = PM_CLOCK_ENABLE;
1114*91f16700Schasinglulu 	} else {
1115*91f16700Schasinglulu 		api_id = PM_CLOCK_DISABLE;
1116*91f16700Schasinglulu 	}
1117*91f16700Schasinglulu 
1118*91f16700Schasinglulu 	/* Send request to the PMU */
1119*91f16700Schasinglulu 	PM_PACK_PAYLOAD2(payload, api_id, clock_id);
1120*91f16700Schasinglulu 	status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1121*91f16700Schasinglulu 
1122*91f16700Schasinglulu 	/* If action fails due to the lack of permissions filter the error */
1123*91f16700Schasinglulu 	if (status == PM_RET_ERROR_ACCESS) {
1124*91f16700Schasinglulu 		status = PM_RET_SUCCESS;
1125*91f16700Schasinglulu 	}
1126*91f16700Schasinglulu 
1127*91f16700Schasinglulu 	return status;
1128*91f16700Schasinglulu }
1129*91f16700Schasinglulu 
1130*91f16700Schasinglulu /**
1131*91f16700Schasinglulu  * pm_clock_enable() - Enable the clock for given id.
1132*91f16700Schasinglulu  * @clock_id: Id of the clock to be enabled.
1133*91f16700Schasinglulu  *
1134*91f16700Schasinglulu  * This function is used by master to enable the clock
1135*91f16700Schasinglulu  * including peripherals and PLL clocks.
1136*91f16700Schasinglulu  *
1137*91f16700Schasinglulu  * Return: Error if an argument is not valid or status as returned by the
1138*91f16700Schasinglulu  *         pm_clock_gate.
1139*91f16700Schasinglulu  *
1140*91f16700Schasinglulu  */
1141*91f16700Schasinglulu enum pm_ret_status pm_clock_enable(uint32_t clock_id)
1142*91f16700Schasinglulu {
1143*91f16700Schasinglulu 	struct pm_pll *pll;
1144*91f16700Schasinglulu 
1145*91f16700Schasinglulu 	/* First try to handle it as a PLL */
1146*91f16700Schasinglulu 	pll = pm_clock_get_pll(clock_id);
1147*91f16700Schasinglulu 	if (pll) {
1148*91f16700Schasinglulu 		return pm_clock_pll_enable(pll);
1149*91f16700Schasinglulu 	}
1150*91f16700Schasinglulu 
1151*91f16700Schasinglulu 	/* It's an on-chip clock, PMU should configure clock's gate */
1152*91f16700Schasinglulu 	return pm_clock_gate(clock_id, 1);
1153*91f16700Schasinglulu }
1154*91f16700Schasinglulu 
1155*91f16700Schasinglulu /**
1156*91f16700Schasinglulu  * pm_clock_disable - Disable the clock for given id.
1157*91f16700Schasinglulu  * @clock_id: Id of the clock to be disable.
1158*91f16700Schasinglulu  *
1159*91f16700Schasinglulu  * This function is used by master to disable the clock
1160*91f16700Schasinglulu  * including peripherals and PLL clocks.
1161*91f16700Schasinglulu  *
1162*91f16700Schasinglulu  * Return: Error if an argument is not valid or status as returned by the
1163*91f16700Schasinglulu  *         pm_clock_gate
1164*91f16700Schasinglulu  *
1165*91f16700Schasinglulu  */
1166*91f16700Schasinglulu enum pm_ret_status pm_clock_disable(uint32_t clock_id)
1167*91f16700Schasinglulu {
1168*91f16700Schasinglulu 	struct pm_pll *pll;
1169*91f16700Schasinglulu 
1170*91f16700Schasinglulu 	/* First try to handle it as a PLL */
1171*91f16700Schasinglulu 	pll = pm_clock_get_pll(clock_id);
1172*91f16700Schasinglulu 	if (pll) {
1173*91f16700Schasinglulu 		return pm_clock_pll_disable(pll);
1174*91f16700Schasinglulu 	}
1175*91f16700Schasinglulu 
1176*91f16700Schasinglulu 	/* It's an on-chip clock, PMU should configure clock's gate */
1177*91f16700Schasinglulu 	return pm_clock_gate(clock_id, 0);
1178*91f16700Schasinglulu }
1179*91f16700Schasinglulu 
1180*91f16700Schasinglulu /**
1181*91f16700Schasinglulu  * pm_clock_getstate - Get the clock state for given id.
1182*91f16700Schasinglulu  * @clock_id: Id of the clock to be queried.
1183*91f16700Schasinglulu  * @state: 1/0 (Enabled/Disabled).
1184*91f16700Schasinglulu  *
1185*91f16700Schasinglulu  * This function is used by master to get the state of clock
1186*91f16700Schasinglulu  * including peripherals and PLL clocks.
1187*91f16700Schasinglulu  *
1188*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1189*91f16700Schasinglulu  *
1190*91f16700Schasinglulu  */
1191*91f16700Schasinglulu enum pm_ret_status pm_clock_getstate(uint32_t clock_id,
1192*91f16700Schasinglulu 				     uint32_t *state)
1193*91f16700Schasinglulu {
1194*91f16700Schasinglulu 	struct pm_pll *pll;
1195*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1196*91f16700Schasinglulu 	enum pm_ret_status status;
1197*91f16700Schasinglulu 
1198*91f16700Schasinglulu 	/* First try to handle it as a PLL */
1199*91f16700Schasinglulu 	pll = pm_clock_get_pll(clock_id);
1200*91f16700Schasinglulu 	if (pll)
1201*91f16700Schasinglulu 		return pm_clock_pll_get_state(pll, state);
1202*91f16700Schasinglulu 
1203*91f16700Schasinglulu 	/* Check if clock ID is a valid on-chip clock */
1204*91f16700Schasinglulu 	status = pm_clock_id_is_valid(clock_id);
1205*91f16700Schasinglulu 	if (status != PM_RET_SUCCESS) {
1206*91f16700Schasinglulu 		return status;
1207*91f16700Schasinglulu 	}
1208*91f16700Schasinglulu 
1209*91f16700Schasinglulu 	/* Send request to the PMU */
1210*91f16700Schasinglulu 	PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
1211*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, state, 1);
1212*91f16700Schasinglulu }
1213*91f16700Schasinglulu 
1214*91f16700Schasinglulu /**
1215*91f16700Schasinglulu  * pm_clock_setdivider - Set the clock divider for given id.
1216*91f16700Schasinglulu  * @clock_id: Id of the clock.
1217*91f16700Schasinglulu  * @divider: divider value.
1218*91f16700Schasinglulu  *
1219*91f16700Schasinglulu  * This function is used by master to set divider for any clock
1220*91f16700Schasinglulu  * to achieve desired rate.
1221*91f16700Schasinglulu  *
1222*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1223*91f16700Schasinglulu  *
1224*91f16700Schasinglulu  */
1225*91f16700Schasinglulu enum pm_ret_status pm_clock_setdivider(uint32_t clock_id,
1226*91f16700Schasinglulu 				       uint32_t divider)
1227*91f16700Schasinglulu {
1228*91f16700Schasinglulu 	enum pm_ret_status status;
1229*91f16700Schasinglulu 	enum pm_node_id nid;
1230*91f16700Schasinglulu 	enum pm_clock_div_id div_id;
1231*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1232*91f16700Schasinglulu 	const uint32_t div0 = 0xFFFF0000;
1233*91f16700Schasinglulu 	const uint32_t div1 = 0x0000FFFF;
1234*91f16700Schasinglulu 	uint32_t val;
1235*91f16700Schasinglulu 
1236*91f16700Schasinglulu 	/* Get PLL node ID using PLL clock ID */
1237*91f16700Schasinglulu 	status = pm_clock_get_pll_node_id(clock_id, &nid);
1238*91f16700Schasinglulu 	if (status == PM_RET_SUCCESS) {
1239*91f16700Schasinglulu 		return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1240*91f16700Schasinglulu 	}
1241*91f16700Schasinglulu 
1242*91f16700Schasinglulu 	/* Check if clock ID is a valid on-chip clock */
1243*91f16700Schasinglulu 	status = pm_clock_id_is_valid(clock_id);
1244*91f16700Schasinglulu 	if (status != PM_RET_SUCCESS) {
1245*91f16700Schasinglulu 		return status;
1246*91f16700Schasinglulu 	}
1247*91f16700Schasinglulu 
1248*91f16700Schasinglulu 	if (div0 == (divider & div0)) {
1249*91f16700Schasinglulu 		div_id = PM_CLOCK_DIV0_ID;
1250*91f16700Schasinglulu 		val = divider & ~div0;
1251*91f16700Schasinglulu 	} else if (div1 == (divider & div1)) {
1252*91f16700Schasinglulu 		div_id = PM_CLOCK_DIV1_ID;
1253*91f16700Schasinglulu 		val = (divider & ~div1) >> 16;
1254*91f16700Schasinglulu 	} else {
1255*91f16700Schasinglulu 		return PM_RET_ERROR_ARGS;
1256*91f16700Schasinglulu 	}
1257*91f16700Schasinglulu 
1258*91f16700Schasinglulu 	/* Send request to the PMU */
1259*91f16700Schasinglulu 	PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
1260*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1261*91f16700Schasinglulu }
1262*91f16700Schasinglulu 
1263*91f16700Schasinglulu /**
1264*91f16700Schasinglulu  * pm_clock_getdivider - Get the clock divider for given id.
1265*91f16700Schasinglulu  * @clock_id: Id of the clock.
1266*91f16700Schasinglulu  * @divider: divider value.
1267*91f16700Schasinglulu  *
1268*91f16700Schasinglulu  * This function is used by master to get divider values
1269*91f16700Schasinglulu  * for any clock.
1270*91f16700Schasinglulu  *
1271*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1272*91f16700Schasinglulu  *
1273*91f16700Schasinglulu  */
1274*91f16700Schasinglulu enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
1275*91f16700Schasinglulu 				       uint32_t *divider)
1276*91f16700Schasinglulu {
1277*91f16700Schasinglulu 	enum pm_ret_status status;
1278*91f16700Schasinglulu 	enum pm_node_id nid;
1279*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1280*91f16700Schasinglulu 	uint32_t val;
1281*91f16700Schasinglulu 
1282*91f16700Schasinglulu 	/* Get PLL node ID using PLL clock ID */
1283*91f16700Schasinglulu 	status = pm_clock_get_pll_node_id(clock_id, &nid);
1284*91f16700Schasinglulu 	if (status == PM_RET_SUCCESS) {
1285*91f16700Schasinglulu 		return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1286*91f16700Schasinglulu 	}
1287*91f16700Schasinglulu 
1288*91f16700Schasinglulu 	/* Check if clock ID is a valid on-chip clock */
1289*91f16700Schasinglulu 	status = pm_clock_id_is_valid(clock_id);
1290*91f16700Schasinglulu 	if (status != PM_RET_SUCCESS) {
1291*91f16700Schasinglulu 		return status;
1292*91f16700Schasinglulu 	}
1293*91f16700Schasinglulu 
1294*91f16700Schasinglulu 	if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
1295*91f16700Schasinglulu 		/* Send request to the PMU to get div0 */
1296*91f16700Schasinglulu 		PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1297*91f16700Schasinglulu 				 PM_CLOCK_DIV0_ID);
1298*91f16700Schasinglulu 		status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1299*91f16700Schasinglulu 		if (status != PM_RET_SUCCESS) {
1300*91f16700Schasinglulu 			return status;
1301*91f16700Schasinglulu 		}
1302*91f16700Schasinglulu 		*divider = val;
1303*91f16700Schasinglulu 	}
1304*91f16700Schasinglulu 
1305*91f16700Schasinglulu 	if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
1306*91f16700Schasinglulu 		/* Send request to the PMU to get div1 */
1307*91f16700Schasinglulu 		PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1308*91f16700Schasinglulu 				 PM_CLOCK_DIV1_ID);
1309*91f16700Schasinglulu 		status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1310*91f16700Schasinglulu 		if (status != PM_RET_SUCCESS) {
1311*91f16700Schasinglulu 			return status;
1312*91f16700Schasinglulu 		}
1313*91f16700Schasinglulu 		*divider |= val << 16;
1314*91f16700Schasinglulu 	}
1315*91f16700Schasinglulu 
1316*91f16700Schasinglulu 	return status;
1317*91f16700Schasinglulu }
1318*91f16700Schasinglulu 
1319*91f16700Schasinglulu /**
1320*91f16700Schasinglulu  * pm_clock_setparent - Set the clock parent for given id.
1321*91f16700Schasinglulu  * @clock_id: Id of the clock.
1322*91f16700Schasinglulu  * @parent_index: Index of the parent clock into clock's parents array.
1323*91f16700Schasinglulu  *
1324*91f16700Schasinglulu  * This function is used by master to set parent for any clock.
1325*91f16700Schasinglulu  *
1326*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1327*91f16700Schasinglulu  *
1328*91f16700Schasinglulu  */
1329*91f16700Schasinglulu enum pm_ret_status pm_clock_setparent(uint32_t clock_id,
1330*91f16700Schasinglulu 				      uint32_t parent_index)
1331*91f16700Schasinglulu {
1332*91f16700Schasinglulu 	struct pm_pll *pll;
1333*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1334*91f16700Schasinglulu 	enum pm_ret_status status;
1335*91f16700Schasinglulu 
1336*91f16700Schasinglulu 	/* First try to handle it as a PLL */
1337*91f16700Schasinglulu 	pll = pm_clock_get_pll_by_related_clk(clock_id);
1338*91f16700Schasinglulu 	if (pll) {
1339*91f16700Schasinglulu 		return pm_clock_pll_set_parent(pll, clock_id, parent_index);
1340*91f16700Schasinglulu 	}
1341*91f16700Schasinglulu 
1342*91f16700Schasinglulu 	/* Check if clock ID is a valid on-chip clock */
1343*91f16700Schasinglulu 	status = pm_clock_id_is_valid(clock_id);
1344*91f16700Schasinglulu 	if (status != PM_RET_SUCCESS) {
1345*91f16700Schasinglulu 		return status;
1346*91f16700Schasinglulu 	}
1347*91f16700Schasinglulu 
1348*91f16700Schasinglulu 	/* Send request to the PMU */
1349*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
1350*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1351*91f16700Schasinglulu }
1352*91f16700Schasinglulu 
1353*91f16700Schasinglulu /**
1354*91f16700Schasinglulu  * pm_clock_getparent - Get the clock parent for given id.
1355*91f16700Schasinglulu  * @clock_id: Id of the clock.
1356*91f16700Schasinglulu  * @parent_index: parent index.
1357*91f16700Schasinglulu  *
1358*91f16700Schasinglulu  * This function is used by master to get parent index
1359*91f16700Schasinglulu  * for any clock.
1360*91f16700Schasinglulu  *
1361*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1362*91f16700Schasinglulu  *
1363*91f16700Schasinglulu  */
1364*91f16700Schasinglulu enum pm_ret_status pm_clock_getparent(uint32_t clock_id,
1365*91f16700Schasinglulu 				      uint32_t *parent_index)
1366*91f16700Schasinglulu {
1367*91f16700Schasinglulu 	struct pm_pll *pll;
1368*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1369*91f16700Schasinglulu 	enum pm_ret_status status;
1370*91f16700Schasinglulu 
1371*91f16700Schasinglulu 	/* First try to handle it as a PLL */
1372*91f16700Schasinglulu 	pll = pm_clock_get_pll_by_related_clk(clock_id);
1373*91f16700Schasinglulu 	if (pll) {
1374*91f16700Schasinglulu 		return pm_clock_pll_get_parent(pll, clock_id, parent_index);
1375*91f16700Schasinglulu 	}
1376*91f16700Schasinglulu 
1377*91f16700Schasinglulu 	/* Check if clock ID is a valid on-chip clock */
1378*91f16700Schasinglulu 	status = pm_clock_id_is_valid(clock_id);
1379*91f16700Schasinglulu 	if (status != PM_RET_SUCCESS) {
1380*91f16700Schasinglulu 		return status;
1381*91f16700Schasinglulu 	}
1382*91f16700Schasinglulu 
1383*91f16700Schasinglulu 	/* Send request to the PMU */
1384*91f16700Schasinglulu 	PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
1385*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
1386*91f16700Schasinglulu }
1387*91f16700Schasinglulu 
1388*91f16700Schasinglulu /**
1389*91f16700Schasinglulu  * pm_pinctrl_get_num_pins - PM call to request number of pins.
1390*91f16700Schasinglulu  * @npins: Number of pins.
1391*91f16700Schasinglulu  *
1392*91f16700Schasinglulu  * This function is used by master to get number of pins.
1393*91f16700Schasinglulu  *
1394*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1395*91f16700Schasinglulu  *
1396*91f16700Schasinglulu  */
1397*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
1398*91f16700Schasinglulu {
1399*91f16700Schasinglulu 	return pm_api_pinctrl_get_num_pins(npins);
1400*91f16700Schasinglulu }
1401*91f16700Schasinglulu 
1402*91f16700Schasinglulu /**
1403*91f16700Schasinglulu  * pm_pinctrl_get_num_functions - PM call to request number of functions.
1404*91f16700Schasinglulu  * @nfuncs: Number of functions.
1405*91f16700Schasinglulu  *
1406*91f16700Schasinglulu  * This function is used by master to get number of functions.
1407*91f16700Schasinglulu  *
1408*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1409*91f16700Schasinglulu  *
1410*91f16700Schasinglulu  */
1411*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
1412*91f16700Schasinglulu {
1413*91f16700Schasinglulu 	return pm_api_pinctrl_get_num_functions(nfuncs);
1414*91f16700Schasinglulu }
1415*91f16700Schasinglulu 
1416*91f16700Schasinglulu /**
1417*91f16700Schasinglulu  * pm_pinctrl_get_num_function_groups - PM call to request number of
1418*91f16700Schasinglulu  *                                      function groups.
1419*91f16700Schasinglulu  * @fid: Id of function.
1420*91f16700Schasinglulu  * @ngroups: Number of function groups.
1421*91f16700Schasinglulu  *
1422*91f16700Schasinglulu  * This function is used by master to get number of function groups specified
1423*91f16700Schasinglulu  * by given function Id.
1424*91f16700Schasinglulu  *
1425*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1426*91f16700Schasinglulu  *
1427*91f16700Schasinglulu  */
1428*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_num_function_groups(uint32_t fid,
1429*91f16700Schasinglulu 							     uint32_t *ngroups)
1430*91f16700Schasinglulu {
1431*91f16700Schasinglulu 	return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
1432*91f16700Schasinglulu }
1433*91f16700Schasinglulu 
1434*91f16700Schasinglulu /**
1435*91f16700Schasinglulu  * pm_pinctrl_get_function_name - PM call to request function name.
1436*91f16700Schasinglulu  * @fid: Id of function.
1437*91f16700Schasinglulu  * @name: Name of function.
1438*91f16700Schasinglulu  *
1439*91f16700Schasinglulu  * This function is used by master to get name of function specified
1440*91f16700Schasinglulu  * by given function Id.
1441*91f16700Schasinglulu  *
1442*91f16700Schasinglulu  */
1443*91f16700Schasinglulu static void pm_pinctrl_get_function_name(uint32_t fid, char *name)
1444*91f16700Schasinglulu {
1445*91f16700Schasinglulu 	pm_api_pinctrl_get_function_name(fid, name);
1446*91f16700Schasinglulu }
1447*91f16700Schasinglulu 
1448*91f16700Schasinglulu /**
1449*91f16700Schasinglulu  * pm_pinctrl_get_function_groups - PM call to request function groups.
1450*91f16700Schasinglulu  * @fid: Id of function.
1451*91f16700Schasinglulu  * @index: Index of next function groups.
1452*91f16700Schasinglulu  * @groups: Function groups.
1453*91f16700Schasinglulu  *
1454*91f16700Schasinglulu  * This function is used by master to get function groups specified
1455*91f16700Schasinglulu  * by given function Id. This API will return 6 function groups with
1456*91f16700Schasinglulu  * a single response. To get other function groups, master should call
1457*91f16700Schasinglulu  * same API in loop with new function groups index till error is returned.
1458*91f16700Schasinglulu  *
1459*91f16700Schasinglulu  * E.g First call should have index 0 which will return function groups
1460*91f16700Schasinglulu  * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1461*91f16700Schasinglulu  * function groups 6, 7, 8, 9, 10 and 11 and so on.
1462*91f16700Schasinglulu  *
1463*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1464*91f16700Schasinglulu  *
1465*91f16700Schasinglulu  */
1466*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_function_groups(uint32_t fid,
1467*91f16700Schasinglulu 							 uint32_t index,
1468*91f16700Schasinglulu 							 uint16_t *groups)
1469*91f16700Schasinglulu {
1470*91f16700Schasinglulu 	return pm_api_pinctrl_get_function_groups(fid, index, groups);
1471*91f16700Schasinglulu }
1472*91f16700Schasinglulu 
1473*91f16700Schasinglulu /**
1474*91f16700Schasinglulu  * pm_pinctrl_get_pin_groups - PM call to request pin groups.
1475*91f16700Schasinglulu  * @pin_id: Id of pin.
1476*91f16700Schasinglulu  * @index: Index of next pin groups.
1477*91f16700Schasinglulu  * @groups: pin groups.
1478*91f16700Schasinglulu  *
1479*91f16700Schasinglulu  * This function is used by master to get pin groups specified
1480*91f16700Schasinglulu  * by given pin Id. This API will return 6 pin groups with
1481*91f16700Schasinglulu  * a single response. To get other pin groups, master should call
1482*91f16700Schasinglulu  * same API in loop with new pin groups index till error is returned.
1483*91f16700Schasinglulu  *
1484*91f16700Schasinglulu  * E.g First call should have index 0 which will return pin groups
1485*91f16700Schasinglulu  * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1486*91f16700Schasinglulu  * pin groups 6, 7, 8, 9, 10 and 11 and so on.
1487*91f16700Schasinglulu  *
1488*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1489*91f16700Schasinglulu  *
1490*91f16700Schasinglulu  */
1491*91f16700Schasinglulu static enum pm_ret_status pm_pinctrl_get_pin_groups(uint32_t pin_id,
1492*91f16700Schasinglulu 						    uint32_t index,
1493*91f16700Schasinglulu 						    uint16_t *groups)
1494*91f16700Schasinglulu {
1495*91f16700Schasinglulu 	return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
1496*91f16700Schasinglulu }
1497*91f16700Schasinglulu 
1498*91f16700Schasinglulu /**
1499*91f16700Schasinglulu  * pm_query_data() - PM API for querying firmware data.
1500*91f16700Schasinglulu  * @qid:  represents the query identifiers for PM.
1501*91f16700Schasinglulu  * @arg1: Argument 1 to requested IOCTL call.
1502*91f16700Schasinglulu  * @arg2: Argument 2 to requested IOCTL call.
1503*91f16700Schasinglulu  * @arg3: Argument 3 to requested IOCTL call.
1504*91f16700Schasinglulu  * @data: Returned output data.
1505*91f16700Schasinglulu  *
1506*91f16700Schasinglulu  * This function returns requested data.
1507*91f16700Schasinglulu  *
1508*91f16700Schasinglulu  */
1509*91f16700Schasinglulu void pm_query_data(enum pm_query_ids qid, uint32_t arg1, uint32_t arg2,
1510*91f16700Schasinglulu 		   uint32_t arg3, uint32_t *data)
1511*91f16700Schasinglulu {
1512*91f16700Schasinglulu 	switch (qid) {
1513*91f16700Schasinglulu 	case PM_QID_CLOCK_GET_NAME:
1514*91f16700Schasinglulu 		pm_clock_get_name(arg1, (char *)data);
1515*91f16700Schasinglulu 		break;
1516*91f16700Schasinglulu 	case PM_QID_CLOCK_GET_TOPOLOGY:
1517*91f16700Schasinglulu 		data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
1518*91f16700Schasinglulu 		break;
1519*91f16700Schasinglulu 	case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
1520*91f16700Schasinglulu 		data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
1521*91f16700Schasinglulu 							  &data[2]);
1522*91f16700Schasinglulu 		break;
1523*91f16700Schasinglulu 	case PM_QID_CLOCK_GET_PARENTS:
1524*91f16700Schasinglulu 		data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
1525*91f16700Schasinglulu 		break;
1526*91f16700Schasinglulu 	case PM_QID_CLOCK_GET_ATTRIBUTES:
1527*91f16700Schasinglulu 		data[0] = pm_clock_get_attributes(arg1, &data[1]);
1528*91f16700Schasinglulu 		break;
1529*91f16700Schasinglulu 	case PM_QID_PINCTRL_GET_NUM_PINS:
1530*91f16700Schasinglulu 		data[0] = pm_pinctrl_get_num_pins(&data[1]);
1531*91f16700Schasinglulu 		break;
1532*91f16700Schasinglulu 	case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
1533*91f16700Schasinglulu 		data[0] = pm_pinctrl_get_num_functions(&data[1]);
1534*91f16700Schasinglulu 		break;
1535*91f16700Schasinglulu 	case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
1536*91f16700Schasinglulu 		data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
1537*91f16700Schasinglulu 		break;
1538*91f16700Schasinglulu 	case PM_QID_PINCTRL_GET_FUNCTION_NAME:
1539*91f16700Schasinglulu 		pm_pinctrl_get_function_name(arg1, (char *)data);
1540*91f16700Schasinglulu 		break;
1541*91f16700Schasinglulu 	case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
1542*91f16700Schasinglulu 		data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
1543*91f16700Schasinglulu 							 (uint16_t *)&data[1]);
1544*91f16700Schasinglulu 		break;
1545*91f16700Schasinglulu 	case PM_QID_PINCTRL_GET_PIN_GROUPS:
1546*91f16700Schasinglulu 		data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
1547*91f16700Schasinglulu 						    (uint16_t *)&data[1]);
1548*91f16700Schasinglulu 		break;
1549*91f16700Schasinglulu 	case PM_QID_CLOCK_GET_NUM_CLOCKS:
1550*91f16700Schasinglulu 		data[0] = pm_clock_get_num_clocks(&data[1]);
1551*91f16700Schasinglulu 		break;
1552*91f16700Schasinglulu 
1553*91f16700Schasinglulu 	case PM_QID_CLOCK_GET_MAX_DIVISOR:
1554*91f16700Schasinglulu 		data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
1555*91f16700Schasinglulu 		break;
1556*91f16700Schasinglulu 	default:
1557*91f16700Schasinglulu 		data[0] = PM_RET_ERROR_ARGS;
1558*91f16700Schasinglulu 		WARN("Unimplemented query service call: 0x%x\n", qid);
1559*91f16700Schasinglulu 		break;
1560*91f16700Schasinglulu 	}
1561*91f16700Schasinglulu }
1562*91f16700Schasinglulu 
1563*91f16700Schasinglulu enum pm_ret_status pm_sha_hash(uint32_t address_high,
1564*91f16700Schasinglulu 				    uint32_t address_low,
1565*91f16700Schasinglulu 				    uint32_t size,
1566*91f16700Schasinglulu 				    uint32_t flags)
1567*91f16700Schasinglulu {
1568*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1569*91f16700Schasinglulu 
1570*91f16700Schasinglulu 	/* Send request to the PMU */
1571*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
1572*91f16700Schasinglulu 				 size, flags);
1573*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1574*91f16700Schasinglulu }
1575*91f16700Schasinglulu 
1576*91f16700Schasinglulu enum pm_ret_status pm_rsa_core(uint32_t address_high,
1577*91f16700Schasinglulu 				    uint32_t address_low,
1578*91f16700Schasinglulu 				    uint32_t size,
1579*91f16700Schasinglulu 				    uint32_t flags)
1580*91f16700Schasinglulu {
1581*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1582*91f16700Schasinglulu 
1583*91f16700Schasinglulu 	/* Send request to the PMU */
1584*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
1585*91f16700Schasinglulu 				 size, flags);
1586*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1587*91f16700Schasinglulu }
1588*91f16700Schasinglulu 
1589*91f16700Schasinglulu enum pm_ret_status pm_secure_image(uint32_t address_low,
1590*91f16700Schasinglulu 				   uint32_t address_high,
1591*91f16700Schasinglulu 				   uint32_t key_lo,
1592*91f16700Schasinglulu 				   uint32_t key_hi,
1593*91f16700Schasinglulu 				   uint32_t *value)
1594*91f16700Schasinglulu {
1595*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1596*91f16700Schasinglulu 
1597*91f16700Schasinglulu 	/* Send request to the PMU */
1598*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
1599*91f16700Schasinglulu 			 key_hi, key_lo);
1600*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 2);
1601*91f16700Schasinglulu }
1602*91f16700Schasinglulu 
1603*91f16700Schasinglulu /**
1604*91f16700Schasinglulu  * pm_fpga_read - Perform the fpga configuration readback.
1605*91f16700Schasinglulu  * @reg_numframes: Configuration register offset (or) Number of frames to read.
1606*91f16700Schasinglulu  * @address_low: lower 32-bit Linear memory space address.
1607*91f16700Schasinglulu  * @address_high: higher 32-bit Linear memory space address.
1608*91f16700Schasinglulu  * @readback_type: Type of fpga readback operation.
1609*91f16700Schasinglulu  *		   0 -- Configuration Register readback.
1610*91f16700Schasinglulu  *		   1 -- Configuration Data readback.
1611*91f16700Schasinglulu  * @value: Value to read.
1612*91f16700Schasinglulu  *
1613*91f16700Schasinglulu  * This function provides access to the xilfpga library to read
1614*91f16700Schasinglulu  * the PL configuration.
1615*91f16700Schasinglulu  *
1616*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1617*91f16700Schasinglulu  *
1618*91f16700Schasinglulu  */
1619*91f16700Schasinglulu enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
1620*91f16700Schasinglulu 				uint32_t address_low,
1621*91f16700Schasinglulu 				uint32_t address_high,
1622*91f16700Schasinglulu 				uint32_t readback_type,
1623*91f16700Schasinglulu 				uint32_t *value)
1624*91f16700Schasinglulu {
1625*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1626*91f16700Schasinglulu 
1627*91f16700Schasinglulu 	/* Send request to the PMU */
1628*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
1629*91f16700Schasinglulu 			 address_high, readback_type);
1630*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
1631*91f16700Schasinglulu }
1632*91f16700Schasinglulu 
1633*91f16700Schasinglulu /*
1634*91f16700Schasinglulu  * pm_pll_set_parameter() - Set the PLL parameter value.
1635*91f16700Schasinglulu  * @nid: Node id of the target PLL.
1636*91f16700Schasinglulu  * @param_id: ID of the PLL parameter.
1637*91f16700Schasinglulu  * @value: Parameter value to be set.
1638*91f16700Schasinglulu  *
1639*91f16700Schasinglulu  * Setting the parameter will have physical effect once the PLL mode is set to
1640*91f16700Schasinglulu  * integer or fractional.
1641*91f16700Schasinglulu  *
1642*91f16700Schasinglulu  * Return: Error if an argument is not valid or status as returned by the
1643*91f16700Schasinglulu  *         PM controller (PMU).
1644*91f16700Schasinglulu  *
1645*91f16700Schasinglulu  */
1646*91f16700Schasinglulu enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
1647*91f16700Schasinglulu 					enum pm_pll_param param_id,
1648*91f16700Schasinglulu 					uint32_t value)
1649*91f16700Schasinglulu {
1650*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1651*91f16700Schasinglulu 
1652*91f16700Schasinglulu 	/* Check if given node ID is a PLL node */
1653*91f16700Schasinglulu 	if (nid < NODE_APLL || nid > NODE_IOPLL) {
1654*91f16700Schasinglulu 		return PM_RET_ERROR_ARGS;
1655*91f16700Schasinglulu 	}
1656*91f16700Schasinglulu 
1657*91f16700Schasinglulu 	/* Check if parameter ID is valid and return an error if it's not */
1658*91f16700Schasinglulu 	if (param_id >= PM_PLL_PARAM_MAX) {
1659*91f16700Schasinglulu 		return PM_RET_ERROR_ARGS;
1660*91f16700Schasinglulu 	}
1661*91f16700Schasinglulu 
1662*91f16700Schasinglulu 	/* Send request to the PMU */
1663*91f16700Schasinglulu 	PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
1664*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1665*91f16700Schasinglulu }
1666*91f16700Schasinglulu 
1667*91f16700Schasinglulu /**
1668*91f16700Schasinglulu  * pm_pll_get_parameter() - Get the PLL parameter value.
1669*91f16700Schasinglulu  * @nid: Node id of the target PLL.
1670*91f16700Schasinglulu  * @param_id: ID of the PLL parameter.
1671*91f16700Schasinglulu  * @value: Location to store the parameter value.
1672*91f16700Schasinglulu  *
1673*91f16700Schasinglulu  * Return: Error if an argument is not valid or status as returned by the
1674*91f16700Schasinglulu  *         PM controller (PMU).
1675*91f16700Schasinglulu  *
1676*91f16700Schasinglulu  */
1677*91f16700Schasinglulu enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
1678*91f16700Schasinglulu 					enum pm_pll_param param_id,
1679*91f16700Schasinglulu 					uint32_t *value)
1680*91f16700Schasinglulu {
1681*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1682*91f16700Schasinglulu 
1683*91f16700Schasinglulu 	/* Check if given node ID is a PLL node */
1684*91f16700Schasinglulu 	if (nid < NODE_APLL || nid > NODE_IOPLL) {
1685*91f16700Schasinglulu 		return PM_RET_ERROR_ARGS;
1686*91f16700Schasinglulu 	}
1687*91f16700Schasinglulu 
1688*91f16700Schasinglulu 	/* Check if parameter ID is valid and return an error if it's not */
1689*91f16700Schasinglulu 	if (param_id >= PM_PLL_PARAM_MAX) {
1690*91f16700Schasinglulu 		return PM_RET_ERROR_ARGS;
1691*91f16700Schasinglulu 	}
1692*91f16700Schasinglulu 
1693*91f16700Schasinglulu 	/* Send request to the PMU */
1694*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
1695*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
1696*91f16700Schasinglulu }
1697*91f16700Schasinglulu 
1698*91f16700Schasinglulu /**
1699*91f16700Schasinglulu  * pm_pll_set_mode() - Set the PLL mode.
1700*91f16700Schasinglulu  * @nid: Node id of the target PLL.
1701*91f16700Schasinglulu  * @mode: PLL mode to be set.
1702*91f16700Schasinglulu  *
1703*91f16700Schasinglulu  * If reset mode is set the PM controller will first bypass the PLL and then
1704*91f16700Schasinglulu  * assert the reset. If integer or fractional mode is set the PM controller will
1705*91f16700Schasinglulu  * ensure that the complete PLL programming sequence is satisfied. After this
1706*91f16700Schasinglulu  * function returns success the PLL is locked and its bypass is deasserted.
1707*91f16700Schasinglulu  *
1708*91f16700Schasinglulu  * Return: Error if an argument is not valid or status as returned by the
1709*91f16700Schasinglulu  *         PM controller (PMU).
1710*91f16700Schasinglulu  *
1711*91f16700Schasinglulu  */
1712*91f16700Schasinglulu enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
1713*91f16700Schasinglulu {
1714*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1715*91f16700Schasinglulu 
1716*91f16700Schasinglulu 	/* Check if given node ID is a PLL node */
1717*91f16700Schasinglulu 	if (nid < NODE_APLL || nid > NODE_IOPLL) {
1718*91f16700Schasinglulu 		return PM_RET_ERROR_ARGS;
1719*91f16700Schasinglulu 	}
1720*91f16700Schasinglulu 
1721*91f16700Schasinglulu 	/* Check if PLL mode is valid */
1722*91f16700Schasinglulu 	if (mode >= PM_PLL_MODE_MAX) {
1723*91f16700Schasinglulu 		return PM_RET_ERROR_ARGS;
1724*91f16700Schasinglulu 	}
1725*91f16700Schasinglulu 
1726*91f16700Schasinglulu 	/* Send request to the PMU */
1727*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
1728*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1729*91f16700Schasinglulu }
1730*91f16700Schasinglulu 
1731*91f16700Schasinglulu /**
1732*91f16700Schasinglulu  * pm_pll_get_mode() - Get the PLL mode.
1733*91f16700Schasinglulu  * @nid: Node id of the target PLL.
1734*91f16700Schasinglulu  * @mode: Location to store the mode of the PLL.
1735*91f16700Schasinglulu  *
1736*91f16700Schasinglulu  * Return: Error if an argument is not valid or status as returned by the
1737*91f16700Schasinglulu  *         PM controller (PMU).
1738*91f16700Schasinglulu  *
1739*91f16700Schasinglulu  */
1740*91f16700Schasinglulu enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
1741*91f16700Schasinglulu {
1742*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1743*91f16700Schasinglulu 
1744*91f16700Schasinglulu 	/* Check if given node ID is a PLL node */
1745*91f16700Schasinglulu 	if (nid < NODE_APLL || nid > NODE_IOPLL) {
1746*91f16700Schasinglulu 		return PM_RET_ERROR_ARGS;
1747*91f16700Schasinglulu 	}
1748*91f16700Schasinglulu 
1749*91f16700Schasinglulu 	/* Send request to the PMU */
1750*91f16700Schasinglulu 	PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
1751*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, mode, 1);
1752*91f16700Schasinglulu }
1753*91f16700Schasinglulu 
1754*91f16700Schasinglulu /**
1755*91f16700Schasinglulu  * pm_register_access() -  PM API for register read/write access data.
1756*91f16700Schasinglulu  * @register_access_id: Register_access_id which says register read/write.
1757*91f16700Schasinglulu  * @address: Address of the register to be accessed.
1758*91f16700Schasinglulu  * @mask: Mask value to be used while writing value.
1759*91f16700Schasinglulu  * @value: Value to be written to register.
1760*91f16700Schasinglulu  * @out: Returned output data.
1761*91f16700Schasinglulu  *
1762*91f16700Schasinglulu  * This function returns requested data.
1763*91f16700Schasinglulu  *
1764*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1765*91f16700Schasinglulu  *
1766*91f16700Schasinglulu  */
1767*91f16700Schasinglulu enum pm_ret_status pm_register_access(uint32_t register_access_id,
1768*91f16700Schasinglulu 				      uint32_t address,
1769*91f16700Schasinglulu 				      uint32_t mask,
1770*91f16700Schasinglulu 				      uint32_t value,
1771*91f16700Schasinglulu 				      uint32_t *out)
1772*91f16700Schasinglulu {
1773*91f16700Schasinglulu 	enum pm_ret_status ret;
1774*91f16700Schasinglulu 
1775*91f16700Schasinglulu 	if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
1776*91f16700Schasinglulu 			((CSUDMA_BASE & address) != CSUDMA_BASE) &&
1777*91f16700Schasinglulu 			((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
1778*91f16700Schasinglulu 			((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) {
1779*91f16700Schasinglulu 		return PM_RET_ERROR_ACCESS;
1780*91f16700Schasinglulu 	}
1781*91f16700Schasinglulu 
1782*91f16700Schasinglulu 	switch (register_access_id) {
1783*91f16700Schasinglulu 	case CONFIG_REG_WRITE:
1784*91f16700Schasinglulu 		ret = pm_mmio_write(address, mask, value);
1785*91f16700Schasinglulu 		break;
1786*91f16700Schasinglulu 	case CONFIG_REG_READ:
1787*91f16700Schasinglulu 		ret = pm_mmio_read(address, out);
1788*91f16700Schasinglulu 		break;
1789*91f16700Schasinglulu 	default:
1790*91f16700Schasinglulu 		ret = PM_RET_ERROR_ARGS;
1791*91f16700Schasinglulu 		WARN("Unimplemented register_access call\n\r");
1792*91f16700Schasinglulu 		break;
1793*91f16700Schasinglulu 	}
1794*91f16700Schasinglulu 	return ret;
1795*91f16700Schasinglulu }
1796*91f16700Schasinglulu 
1797*91f16700Schasinglulu /**
1798*91f16700Schasinglulu  * pm_efuse_access() - To program or read efuse bits. This function provides
1799*91f16700Schasinglulu  *                     access to the xilskey library to program/read
1800*91f16700Schasinglulu  *                     efuse bits.
1801*91f16700Schasinglulu  * @address_low: lower 32-bit Linear memory space address.
1802*91f16700Schasinglulu  * @address_high: higher 32-bit Linear memory space address.
1803*91f16700Schasinglulu  * @value: Returned output value.
1804*91f16700Schasinglulu  *
1805*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
1806*91f16700Schasinglulu  *
1807*91f16700Schasinglulu  */
1808*91f16700Schasinglulu enum pm_ret_status pm_efuse_access(uint32_t address_high,
1809*91f16700Schasinglulu 				   uint32_t address_low,
1810*91f16700Schasinglulu 				   uint32_t *value)
1811*91f16700Schasinglulu {
1812*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
1813*91f16700Schasinglulu 
1814*91f16700Schasinglulu 	/* Send request to the PMU */
1815*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
1816*91f16700Schasinglulu 
1817*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
1818*91f16700Schasinglulu }
1819