xref: /rk3399_ARM-atf/drivers/ti/ti_sci/ti_sci.c (revision 936afd9f747719012afd9764599e5ba276382f87)
1*936afd9fSDhruva Gole /*
2*936afd9fSDhruva Gole  * Texas Instruments System Control Interface Driver
3*936afd9fSDhruva Gole  *   Based on Linux and U-Boot implementation
4*936afd9fSDhruva Gole  *
5*936afd9fSDhruva Gole  * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/
6*936afd9fSDhruva Gole  *
7*936afd9fSDhruva Gole  * SPDX-License-Identifier: BSD-3-Clause
8*936afd9fSDhruva Gole  */
9*936afd9fSDhruva Gole 
10*936afd9fSDhruva Gole #include <errno.h>
11*936afd9fSDhruva Gole #include <stdbool.h>
12*936afd9fSDhruva Gole #include <stddef.h>
13*936afd9fSDhruva Gole #include <string.h>
14*936afd9fSDhruva Gole 
15*936afd9fSDhruva Gole #include <platform_def.h>
16*936afd9fSDhruva Gole #include <lib/bakery_lock.h>
17*936afd9fSDhruva Gole 
18*936afd9fSDhruva Gole #include <common/debug.h>
19*936afd9fSDhruva Gole #include <sec_proxy.h>
20*936afd9fSDhruva Gole 
21*936afd9fSDhruva Gole #include "ti_sci_protocol.h"
22*936afd9fSDhruva Gole #include "ti_sci.h"
23*936afd9fSDhruva Gole 
24*936afd9fSDhruva Gole #if USE_COHERENT_MEM
25*936afd9fSDhruva Gole __section(".tzfw_coherent_mem")
26*936afd9fSDhruva Gole #endif
27*936afd9fSDhruva Gole static uint8_t message_sequence;
28*936afd9fSDhruva Gole 
29*936afd9fSDhruva Gole DEFINE_BAKERY_LOCK(ti_sci_xfer_lock);
30*936afd9fSDhruva Gole 
31*936afd9fSDhruva Gole /**
32*936afd9fSDhruva Gole  * struct ti_sci_xfer - Structure representing a message flow
33*936afd9fSDhruva Gole  * @tx_message:	Transmit message
34*936afd9fSDhruva Gole  * @rx_message:	Receive message
35*936afd9fSDhruva Gole  */
36*936afd9fSDhruva Gole struct ti_sci_xfer {
37*936afd9fSDhruva Gole 	struct k3_sec_proxy_msg tx_message;
38*936afd9fSDhruva Gole 	struct k3_sec_proxy_msg rx_message;
39*936afd9fSDhruva Gole };
40*936afd9fSDhruva Gole 
41*936afd9fSDhruva Gole /**
42*936afd9fSDhruva Gole  * ti_sci_setup_one_xfer() - Setup one message type
43*936afd9fSDhruva Gole  *
44*936afd9fSDhruva Gole  * @msg_type:	Message type
45*936afd9fSDhruva Gole  * @msg_flags:	Flag to set for the message
46*936afd9fSDhruva Gole  * @tx_buf:	Buffer to be sent to mailbox channel
47*936afd9fSDhruva Gole  * @tx_message_size: transmit message size
48*936afd9fSDhruva Gole  * @rx_buf:	Buffer to be received from mailbox channel
49*936afd9fSDhruva Gole  * @rx_message_size: receive message size
50*936afd9fSDhruva Gole  *
51*936afd9fSDhruva Gole  * Helper function which is used by various command functions that are
52*936afd9fSDhruva Gole  * exposed to clients of this driver for allocating a message traffic event.
53*936afd9fSDhruva Gole  *
54*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
55*936afd9fSDhruva Gole  */
56*936afd9fSDhruva Gole static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags,
57*936afd9fSDhruva Gole 				 void *tx_buf,
58*936afd9fSDhruva Gole 				 size_t tx_message_size,
59*936afd9fSDhruva Gole 				 void *rx_buf,
60*936afd9fSDhruva Gole 				 size_t rx_message_size,
61*936afd9fSDhruva Gole 				 struct ti_sci_xfer *xfer)
62*936afd9fSDhruva Gole {
63*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr *hdr;
64*936afd9fSDhruva Gole 
65*936afd9fSDhruva Gole 	/* Ensure we have sane transfer sizes */
66*936afd9fSDhruva Gole 	if (rx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
67*936afd9fSDhruva Gole 	    tx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
68*936afd9fSDhruva Gole 	    tx_message_size < sizeof(*hdr))
69*936afd9fSDhruva Gole 		return -ERANGE;
70*936afd9fSDhruva Gole 
71*936afd9fSDhruva Gole 	hdr = (struct ti_sci_msg_hdr *)tx_buf;
72*936afd9fSDhruva Gole 	hdr->seq = ++message_sequence;
73*936afd9fSDhruva Gole 	hdr->type = msg_type;
74*936afd9fSDhruva Gole 	hdr->host = TI_SCI_HOST_ID;
75*936afd9fSDhruva Gole 	hdr->flags = msg_flags;
76*936afd9fSDhruva Gole 	/* Request a response if rx_message_size is non-zero */
77*936afd9fSDhruva Gole 	if (rx_message_size != 0U) {
78*936afd9fSDhruva Gole 		hdr->flags |= TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;
79*936afd9fSDhruva Gole 	}
80*936afd9fSDhruva Gole 
81*936afd9fSDhruva Gole 	xfer->tx_message.buf = tx_buf;
82*936afd9fSDhruva Gole 	xfer->tx_message.len = tx_message_size;
83*936afd9fSDhruva Gole 
84*936afd9fSDhruva Gole 	xfer->rx_message.buf = rx_buf;
85*936afd9fSDhruva Gole 	xfer->rx_message.len = rx_message_size;
86*936afd9fSDhruva Gole 
87*936afd9fSDhruva Gole 	return 0;
88*936afd9fSDhruva Gole }
89*936afd9fSDhruva Gole 
90*936afd9fSDhruva Gole /**
91*936afd9fSDhruva Gole  * ti_sci_get_response() - Receive response from mailbox channel
92*936afd9fSDhruva Gole  *
93*936afd9fSDhruva Gole  * @xfer:	Transfer to initiate and wait for response
94*936afd9fSDhruva Gole  * @chan:	Channel to receive the response
95*936afd9fSDhruva Gole  *
96*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
97*936afd9fSDhruva Gole  */
98*936afd9fSDhruva Gole static int ti_sci_get_response(struct k3_sec_proxy_msg *msg,
99*936afd9fSDhruva Gole 			       enum k3_sec_proxy_chan_id chan)
100*936afd9fSDhruva Gole {
101*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr *hdr;
102*936afd9fSDhruva Gole 	unsigned int retry = 5;
103*936afd9fSDhruva Gole 	int ret;
104*936afd9fSDhruva Gole 
105*936afd9fSDhruva Gole 	for (; retry > 0; retry--) {
106*936afd9fSDhruva Gole 		/* Receive the response */
107*936afd9fSDhruva Gole 		ret = k3_sec_proxy_recv(chan, msg);
108*936afd9fSDhruva Gole 		if (ret) {
109*936afd9fSDhruva Gole 			ERROR("Message receive failed (%d)\n", ret);
110*936afd9fSDhruva Gole 			return ret;
111*936afd9fSDhruva Gole 		}
112*936afd9fSDhruva Gole 
113*936afd9fSDhruva Gole 		/* msg is updated by Secure Proxy driver */
114*936afd9fSDhruva Gole 		hdr = (struct ti_sci_msg_hdr *)msg->buf;
115*936afd9fSDhruva Gole 
116*936afd9fSDhruva Gole 		/* Sanity check for message response */
117*936afd9fSDhruva Gole 		if (hdr->seq == message_sequence)
118*936afd9fSDhruva Gole 			break;
119*936afd9fSDhruva Gole 		else
120*936afd9fSDhruva Gole 			WARN("Message with sequence ID %u is not expected\n", hdr->seq);
121*936afd9fSDhruva Gole 	}
122*936afd9fSDhruva Gole 	if (!retry) {
123*936afd9fSDhruva Gole 		ERROR("Timed out waiting for message\n");
124*936afd9fSDhruva Gole 		return -EINVAL;
125*936afd9fSDhruva Gole 	}
126*936afd9fSDhruva Gole 
127*936afd9fSDhruva Gole 	if (msg->len > TI_SCI_MAX_MESSAGE_SIZE) {
128*936afd9fSDhruva Gole 		ERROR("Unable to handle %lu xfer (max %d)\n",
129*936afd9fSDhruva Gole 		      msg->len, TI_SCI_MAX_MESSAGE_SIZE);
130*936afd9fSDhruva Gole 		return -EINVAL;
131*936afd9fSDhruva Gole 	}
132*936afd9fSDhruva Gole 
133*936afd9fSDhruva Gole 	if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK))
134*936afd9fSDhruva Gole 		return -ENODEV;
135*936afd9fSDhruva Gole 
136*936afd9fSDhruva Gole 	return 0;
137*936afd9fSDhruva Gole }
138*936afd9fSDhruva Gole 
139*936afd9fSDhruva Gole /**
140*936afd9fSDhruva Gole  * ti_sci_do_xfer() - Do one transfer
141*936afd9fSDhruva Gole  *
142*936afd9fSDhruva Gole  * @xfer:	Transfer to initiate and wait for response
143*936afd9fSDhruva Gole  *
144*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
145*936afd9fSDhruva Gole  */
146*936afd9fSDhruva Gole static int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
147*936afd9fSDhruva Gole {
148*936afd9fSDhruva Gole 	struct k3_sec_proxy_msg *tx_msg = &xfer->tx_message;
149*936afd9fSDhruva Gole 	struct k3_sec_proxy_msg *rx_msg = &xfer->rx_message;
150*936afd9fSDhruva Gole 	int ret;
151*936afd9fSDhruva Gole 
152*936afd9fSDhruva Gole 	bakery_lock_get(&ti_sci_xfer_lock);
153*936afd9fSDhruva Gole 
154*936afd9fSDhruva Gole 	/* Clear any spurious messages in receive queue */
155*936afd9fSDhruva Gole 	ret = k3_sec_proxy_clear_rx_thread(SP_RESPONSE);
156*936afd9fSDhruva Gole 	if (ret) {
157*936afd9fSDhruva Gole 		ERROR("Could not clear response queue (%d)\n", ret);
158*936afd9fSDhruva Gole 		goto unlock;
159*936afd9fSDhruva Gole 	}
160*936afd9fSDhruva Gole 
161*936afd9fSDhruva Gole 	/* Send the message */
162*936afd9fSDhruva Gole 	ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, tx_msg);
163*936afd9fSDhruva Gole 	if (ret) {
164*936afd9fSDhruva Gole 		ERROR("Message sending failed (%d)\n", ret);
165*936afd9fSDhruva Gole 		goto unlock;
166*936afd9fSDhruva Gole 	}
167*936afd9fSDhruva Gole 
168*936afd9fSDhruva Gole 	/* Get the response if requested */
169*936afd9fSDhruva Gole 	if (rx_msg->len != 0U) {
170*936afd9fSDhruva Gole 		ret = ti_sci_get_response(rx_msg, SP_RESPONSE);
171*936afd9fSDhruva Gole 		if (ret != 0U) {
172*936afd9fSDhruva Gole 			ERROR("Failed to get response (%d)\n", ret);
173*936afd9fSDhruva Gole 			goto unlock;
174*936afd9fSDhruva Gole 		}
175*936afd9fSDhruva Gole 	}
176*936afd9fSDhruva Gole 
177*936afd9fSDhruva Gole unlock:
178*936afd9fSDhruva Gole 	bakery_lock_release(&ti_sci_xfer_lock);
179*936afd9fSDhruva Gole 
180*936afd9fSDhruva Gole 	return ret;
181*936afd9fSDhruva Gole }
182*936afd9fSDhruva Gole 
183*936afd9fSDhruva Gole /**
184*936afd9fSDhruva Gole  * ti_sci_get_revision() - Get the revision of the SCI entity
185*936afd9fSDhruva Gole  *
186*936afd9fSDhruva Gole  * Updates the SCI information in the internal data structure.
187*936afd9fSDhruva Gole  *
188*936afd9fSDhruva Gole  * @version: Structure containing the version info
189*936afd9fSDhruva Gole  *
190*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
191*936afd9fSDhruva Gole  */
192*936afd9fSDhruva Gole int ti_sci_get_revision(struct ti_sci_msg_version *version)
193*936afd9fSDhruva Gole {
194*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_version rev_info;
195*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr hdr;
196*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
197*936afd9fSDhruva Gole 	int ret;
198*936afd9fSDhruva Gole 
199*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_VERSION, 0x0,
200*936afd9fSDhruva Gole 				    &hdr, sizeof(hdr),
201*936afd9fSDhruva Gole 				    &rev_info, sizeof(rev_info),
202*936afd9fSDhruva Gole 				    &xfer);
203*936afd9fSDhruva Gole 	if (ret) {
204*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
205*936afd9fSDhruva Gole 		return ret;
206*936afd9fSDhruva Gole 	}
207*936afd9fSDhruva Gole 
208*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
209*936afd9fSDhruva Gole 	if (ret) {
210*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
211*936afd9fSDhruva Gole 		return ret;
212*936afd9fSDhruva Gole 	}
213*936afd9fSDhruva Gole 
214*936afd9fSDhruva Gole 	memcpy(version->firmware_description, rev_info.firmware_description,
215*936afd9fSDhruva Gole 		sizeof(rev_info.firmware_description));
216*936afd9fSDhruva Gole 	version->abi_major = rev_info.abi_major;
217*936afd9fSDhruva Gole 	version->abi_minor = rev_info.abi_minor;
218*936afd9fSDhruva Gole 	version->firmware_revision = rev_info.firmware_revision;
219*936afd9fSDhruva Gole 	version->sub_version = rev_info.sub_version;
220*936afd9fSDhruva Gole 	version->patch_version = rev_info.patch_version;
221*936afd9fSDhruva Gole 
222*936afd9fSDhruva Gole 	return 0;
223*936afd9fSDhruva Gole }
224*936afd9fSDhruva Gole 
225*936afd9fSDhruva Gole /**
226*936afd9fSDhruva Gole  * ti_sci_query_fw_caps() - Get the FW/SoC capabilities
227*936afd9fSDhruva Gole  * @handle:		Pointer to TI SCI handle
228*936afd9fSDhruva Gole  * @fw_caps:		Each bit in fw_caps indicating one FW/SOC capability
229*936afd9fSDhruva Gole  *
230*936afd9fSDhruva Gole  * Return: 0 if all went well, else returns appropriate error value.
231*936afd9fSDhruva Gole  */
232*936afd9fSDhruva Gole int ti_sci_query_fw_caps(uint64_t *fw_caps)
233*936afd9fSDhruva Gole {
234*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr req;
235*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_query_fw_caps resp;
236*936afd9fSDhruva Gole 
237*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
238*936afd9fSDhruva Gole 	int ret;
239*936afd9fSDhruva Gole 
240*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_FW_CAPS, 0,
241*936afd9fSDhruva Gole 				    &req, sizeof(req),
242*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
243*936afd9fSDhruva Gole 				    &xfer);
244*936afd9fSDhruva Gole 	if (ret != 0U) {
245*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
246*936afd9fSDhruva Gole 		return ret;
247*936afd9fSDhruva Gole 	}
248*936afd9fSDhruva Gole 
249*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
250*936afd9fSDhruva Gole 	if (ret != 0U) {
251*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
252*936afd9fSDhruva Gole 		return ret;
253*936afd9fSDhruva Gole 	}
254*936afd9fSDhruva Gole 
255*936afd9fSDhruva Gole 	if (fw_caps)
256*936afd9fSDhruva Gole 		*fw_caps = resp.fw_caps;
257*936afd9fSDhruva Gole 
258*936afd9fSDhruva Gole 	return 0;
259*936afd9fSDhruva Gole }
260*936afd9fSDhruva Gole 
261*936afd9fSDhruva Gole /**
262*936afd9fSDhruva Gole  * ti_sci_device_set_state() - Set device state
263*936afd9fSDhruva Gole  *
264*936afd9fSDhruva Gole  * @id:		Device identifier
265*936afd9fSDhruva Gole  * @flags:	flags to setup for the device
266*936afd9fSDhruva Gole  * @state:	State to move the device to
267*936afd9fSDhruva Gole  *
268*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
269*936afd9fSDhruva Gole  */
270*936afd9fSDhruva Gole static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state)
271*936afd9fSDhruva Gole {
272*936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_device_state req;
273*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
274*936afd9fSDhruva Gole 
275*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
276*936afd9fSDhruva Gole 	int ret;
277*936afd9fSDhruva Gole 
278*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags,
279*936afd9fSDhruva Gole 				    &req, sizeof(req),
280*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
281*936afd9fSDhruva Gole 				    &xfer);
282*936afd9fSDhruva Gole 	if (ret) {
283*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
284*936afd9fSDhruva Gole 		return ret;
285*936afd9fSDhruva Gole 	}
286*936afd9fSDhruva Gole 
287*936afd9fSDhruva Gole 	req.id = id;
288*936afd9fSDhruva Gole 	req.state = state;
289*936afd9fSDhruva Gole 
290*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
291*936afd9fSDhruva Gole 	if (ret) {
292*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
293*936afd9fSDhruva Gole 		return ret;
294*936afd9fSDhruva Gole 	}
295*936afd9fSDhruva Gole 
296*936afd9fSDhruva Gole 	return 0;
297*936afd9fSDhruva Gole }
298*936afd9fSDhruva Gole 
299*936afd9fSDhruva Gole /**
300*936afd9fSDhruva Gole  * ti_sci_device_get_state() - Get device state
301*936afd9fSDhruva Gole  *
302*936afd9fSDhruva Gole  * @id:		Device Identifier
303*936afd9fSDhruva Gole  * @clcnt:	Pointer to Context Loss Count
304*936afd9fSDhruva Gole  * @resets:	pointer to resets
305*936afd9fSDhruva Gole  * @p_state:	pointer to p_state
306*936afd9fSDhruva Gole  * @c_state:	pointer to c_state
307*936afd9fSDhruva Gole  *
308*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
309*936afd9fSDhruva Gole  */
310*936afd9fSDhruva Gole static int ti_sci_device_get_state(uint32_t id,  uint32_t *clcnt,
311*936afd9fSDhruva Gole 				   uint32_t *resets, uint8_t *p_state,
312*936afd9fSDhruva Gole 				   uint8_t *c_state)
313*936afd9fSDhruva Gole {
314*936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_device_state req;
315*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_device_state resp;
316*936afd9fSDhruva Gole 
317*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
318*936afd9fSDhruva Gole 	int ret;
319*936afd9fSDhruva Gole 
320*936afd9fSDhruva Gole 	if (!clcnt && !resets && !p_state && !c_state)
321*936afd9fSDhruva Gole 		return -EINVAL;
322*936afd9fSDhruva Gole 
323*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0,
324*936afd9fSDhruva Gole 				    &req, sizeof(req),
325*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
326*936afd9fSDhruva Gole 				    &xfer);
327*936afd9fSDhruva Gole 	if (ret) {
328*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
329*936afd9fSDhruva Gole 		return ret;
330*936afd9fSDhruva Gole 	}
331*936afd9fSDhruva Gole 
332*936afd9fSDhruva Gole 	req.id = id;
333*936afd9fSDhruva Gole 
334*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
335*936afd9fSDhruva Gole 	if (ret) {
336*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
337*936afd9fSDhruva Gole 		return ret;
338*936afd9fSDhruva Gole 	}
339*936afd9fSDhruva Gole 
340*936afd9fSDhruva Gole 	if (clcnt)
341*936afd9fSDhruva Gole 		*clcnt = resp.context_loss_count;
342*936afd9fSDhruva Gole 	if (resets)
343*936afd9fSDhruva Gole 		*resets = resp.resets;
344*936afd9fSDhruva Gole 	if (p_state)
345*936afd9fSDhruva Gole 		*p_state = resp.programmed_state;
346*936afd9fSDhruva Gole 	if (c_state)
347*936afd9fSDhruva Gole 		*c_state = resp.current_state;
348*936afd9fSDhruva Gole 
349*936afd9fSDhruva Gole 	return 0;
350*936afd9fSDhruva Gole }
351*936afd9fSDhruva Gole 
352*936afd9fSDhruva Gole /**
353*936afd9fSDhruva Gole  * ti_sci_device_get() - Request for device managed by TISCI
354*936afd9fSDhruva Gole  *
355*936afd9fSDhruva Gole  * @id:		Device Identifier
356*936afd9fSDhruva Gole  *
357*936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
358*936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
359*936afd9fSDhruva Gole  * managed by driver for that purpose.
360*936afd9fSDhruva Gole  *
361*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
362*936afd9fSDhruva Gole  */
363*936afd9fSDhruva Gole int ti_sci_device_get(uint32_t id)
364*936afd9fSDhruva Gole {
365*936afd9fSDhruva Gole 	return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON);
366*936afd9fSDhruva Gole }
367*936afd9fSDhruva Gole 
368*936afd9fSDhruva Gole /**
369*936afd9fSDhruva Gole  * ti_sci_device_get_exclusive() - Exclusive request for device managed by TISCI
370*936afd9fSDhruva Gole  *
371*936afd9fSDhruva Gole  * @id:		Device Identifier
372*936afd9fSDhruva Gole  *
373*936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
374*936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
375*936afd9fSDhruva Gole  * managed by driver for that purpose.
376*936afd9fSDhruva Gole  *
377*936afd9fSDhruva Gole  * NOTE: This _exclusive version of the get API is for exclusive access to the
378*936afd9fSDhruva Gole  * device. Any other host in the system will fail to get this device after this
379*936afd9fSDhruva Gole  * call until exclusive access is released with device_put or a non-exclusive
380*936afd9fSDhruva Gole  * set call.
381*936afd9fSDhruva Gole  *
382*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
383*936afd9fSDhruva Gole  */
384*936afd9fSDhruva Gole int ti_sci_device_get_exclusive(uint32_t id)
385*936afd9fSDhruva Gole {
386*936afd9fSDhruva Gole 	return ti_sci_device_set_state(id,
387*936afd9fSDhruva Gole 				       MSG_FLAG_DEVICE_EXCLUSIVE,
388*936afd9fSDhruva Gole 				       MSG_DEVICE_SW_STATE_ON);
389*936afd9fSDhruva Gole }
390*936afd9fSDhruva Gole 
391*936afd9fSDhruva Gole /**
392*936afd9fSDhruva Gole  * ti_sci_device_idle() - Idle a device managed by TISCI
393*936afd9fSDhruva Gole  *
394*936afd9fSDhruva Gole  * @id:		Device Identifier
395*936afd9fSDhruva Gole  *
396*936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
397*936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
398*936afd9fSDhruva Gole  * managed by driver for that purpose.
399*936afd9fSDhruva Gole  *
400*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
401*936afd9fSDhruva Gole  */
402*936afd9fSDhruva Gole int ti_sci_device_idle(uint32_t id)
403*936afd9fSDhruva Gole {
404*936afd9fSDhruva Gole 	return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_RETENTION);
405*936afd9fSDhruva Gole }
406*936afd9fSDhruva Gole 
407*936afd9fSDhruva Gole /**
408*936afd9fSDhruva Gole  * ti_sci_device_idle_exclusive() - Exclusive idle a device managed by TISCI
409*936afd9fSDhruva Gole  *
410*936afd9fSDhruva Gole  * @id:		Device Identifier
411*936afd9fSDhruva Gole  *
412*936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
413*936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
414*936afd9fSDhruva Gole  * managed by driver for that purpose.
415*936afd9fSDhruva Gole  *
416*936afd9fSDhruva Gole  * NOTE: This _exclusive version of the idle API is for exclusive access to
417*936afd9fSDhruva Gole  * the device. Any other host in the system will fail to get this device after
418*936afd9fSDhruva Gole  * this call until exclusive access is released with device_put or a
419*936afd9fSDhruva Gole  * non-exclusive set call.
420*936afd9fSDhruva Gole  *
421*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
422*936afd9fSDhruva Gole  */
423*936afd9fSDhruva Gole int ti_sci_device_idle_exclusive(uint32_t id)
424*936afd9fSDhruva Gole {
425*936afd9fSDhruva Gole 	return ti_sci_device_set_state(id,
426*936afd9fSDhruva Gole 				       MSG_FLAG_DEVICE_EXCLUSIVE,
427*936afd9fSDhruva Gole 				       MSG_DEVICE_SW_STATE_RETENTION);
428*936afd9fSDhruva Gole }
429*936afd9fSDhruva Gole 
430*936afd9fSDhruva Gole /**
431*936afd9fSDhruva Gole  * ti_sci_device_put() - Release a device managed by TISCI
432*936afd9fSDhruva Gole  *
433*936afd9fSDhruva Gole  * @id:		Device Identifier
434*936afd9fSDhruva Gole  *
435*936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
436*936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
437*936afd9fSDhruva Gole  * managed by driver for that purpose.
438*936afd9fSDhruva Gole  *
439*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
440*936afd9fSDhruva Gole  */
441*936afd9fSDhruva Gole int ti_sci_device_put(uint32_t id)
442*936afd9fSDhruva Gole {
443*936afd9fSDhruva Gole 	return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF);
444*936afd9fSDhruva Gole }
445*936afd9fSDhruva Gole 
446*936afd9fSDhruva Gole /**
447*936afd9fSDhruva Gole  * ti_sci_device_put_no_wait() - Release a device without requesting or waiting
448*936afd9fSDhruva Gole  *				 for a response.
449*936afd9fSDhruva Gole  *
450*936afd9fSDhruva Gole  * @id:		Device Identifier
451*936afd9fSDhruva Gole  *
452*936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
453*936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
454*936afd9fSDhruva Gole  * managed by driver for that purpose.
455*936afd9fSDhruva Gole  *
456*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
457*936afd9fSDhruva Gole  */
458*936afd9fSDhruva Gole int ti_sci_device_put_no_wait(uint32_t id)
459*936afd9fSDhruva Gole {
460*936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_device_state req;
461*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
462*936afd9fSDhruva Gole 	int ret;
463*936afd9fSDhruva Gole 
464*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, 0,
465*936afd9fSDhruva Gole 				    &req, sizeof(req),
466*936afd9fSDhruva Gole 				    NULL, 0,
467*936afd9fSDhruva Gole 				    &xfer);
468*936afd9fSDhruva Gole 	if (ret != 0U) {
469*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
470*936afd9fSDhruva Gole 		return ret;
471*936afd9fSDhruva Gole 	}
472*936afd9fSDhruva Gole 
473*936afd9fSDhruva Gole 	req.id = id;
474*936afd9fSDhruva Gole 	req.state = MSG_DEVICE_SW_STATE_AUTO_OFF;
475*936afd9fSDhruva Gole 
476*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
477*936afd9fSDhruva Gole 	if (ret != 0U) {
478*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
479*936afd9fSDhruva Gole 		return ret;
480*936afd9fSDhruva Gole 	}
481*936afd9fSDhruva Gole 
482*936afd9fSDhruva Gole 	return 0;
483*936afd9fSDhruva Gole }
484*936afd9fSDhruva Gole 
485*936afd9fSDhruva Gole /**
486*936afd9fSDhruva Gole  * ti_sci_device_is_valid() - Is the device valid
487*936afd9fSDhruva Gole  *
488*936afd9fSDhruva Gole  * @id:		Device Identifier
489*936afd9fSDhruva Gole  *
490*936afd9fSDhruva Gole  * Return: 0 if all goes well and the device ID is valid, else return
491*936afd9fSDhruva Gole  *         appropriate error
492*936afd9fSDhruva Gole  */
493*936afd9fSDhruva Gole int ti_sci_device_is_valid(uint32_t id)
494*936afd9fSDhruva Gole {
495*936afd9fSDhruva Gole 	uint8_t unused;
496*936afd9fSDhruva Gole 
497*936afd9fSDhruva Gole 	/* check the device state which will also tell us if the ID is valid */
498*936afd9fSDhruva Gole 	return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused);
499*936afd9fSDhruva Gole }
500*936afd9fSDhruva Gole 
501*936afd9fSDhruva Gole /**
502*936afd9fSDhruva Gole  * ti_sci_device_get_clcnt() - Get context loss counter
503*936afd9fSDhruva Gole  *
504*936afd9fSDhruva Gole  * @id:		Device Identifier
505*936afd9fSDhruva Gole  * @count:	Pointer to Context Loss counter to populate
506*936afd9fSDhruva Gole  *
507*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
508*936afd9fSDhruva Gole  */
509*936afd9fSDhruva Gole int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count)
510*936afd9fSDhruva Gole {
511*936afd9fSDhruva Gole 	return ti_sci_device_get_state(id, count, NULL, NULL, NULL);
512*936afd9fSDhruva Gole }
513*936afd9fSDhruva Gole 
514*936afd9fSDhruva Gole /**
515*936afd9fSDhruva Gole  * ti_sci_device_is_idle() - Check if the device is requested to be idle
516*936afd9fSDhruva Gole  *
517*936afd9fSDhruva Gole  * @id:		Device Identifier
518*936afd9fSDhruva Gole  * @r_state:	true if requested to be idle
519*936afd9fSDhruva Gole  *
520*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
521*936afd9fSDhruva Gole  */
522*936afd9fSDhruva Gole int ti_sci_device_is_idle(uint32_t id, bool *r_state)
523*936afd9fSDhruva Gole {
524*936afd9fSDhruva Gole 	int ret;
525*936afd9fSDhruva Gole 	uint8_t state;
526*936afd9fSDhruva Gole 
527*936afd9fSDhruva Gole 	if (!r_state)
528*936afd9fSDhruva Gole 		return -EINVAL;
529*936afd9fSDhruva Gole 
530*936afd9fSDhruva Gole 	ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL);
531*936afd9fSDhruva Gole 	if (ret)
532*936afd9fSDhruva Gole 		return ret;
533*936afd9fSDhruva Gole 
534*936afd9fSDhruva Gole 	*r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
535*936afd9fSDhruva Gole 
536*936afd9fSDhruva Gole 	return 0;
537*936afd9fSDhruva Gole }
538*936afd9fSDhruva Gole 
539*936afd9fSDhruva Gole /**
540*936afd9fSDhruva Gole  * ti_sci_device_is_stop() - Check if the device is requested to be stopped
541*936afd9fSDhruva Gole  *
542*936afd9fSDhruva Gole  * @id:		Device Identifier
543*936afd9fSDhruva Gole  * @r_state:	true if requested to be stopped
544*936afd9fSDhruva Gole  * @curr_state:	true if currently stopped
545*936afd9fSDhruva Gole  *
546*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
547*936afd9fSDhruva Gole  */
548*936afd9fSDhruva Gole int ti_sci_device_is_stop(uint32_t id, bool *r_state,  bool *curr_state)
549*936afd9fSDhruva Gole {
550*936afd9fSDhruva Gole 	int ret;
551*936afd9fSDhruva Gole 	uint8_t p_state, c_state;
552*936afd9fSDhruva Gole 
553*936afd9fSDhruva Gole 	if (!r_state && !curr_state)
554*936afd9fSDhruva Gole 		return -EINVAL;
555*936afd9fSDhruva Gole 
556*936afd9fSDhruva Gole 	ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
557*936afd9fSDhruva Gole 	if (ret)
558*936afd9fSDhruva Gole 		return ret;
559*936afd9fSDhruva Gole 
560*936afd9fSDhruva Gole 	if (r_state)
561*936afd9fSDhruva Gole 		*r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
562*936afd9fSDhruva Gole 	if (curr_state)
563*936afd9fSDhruva Gole 		*curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
564*936afd9fSDhruva Gole 
565*936afd9fSDhruva Gole 	return 0;
566*936afd9fSDhruva Gole }
567*936afd9fSDhruva Gole 
568*936afd9fSDhruva Gole /**
569*936afd9fSDhruva Gole  * ti_sci_device_is_on() - Check if the device is requested to be ON
570*936afd9fSDhruva Gole  *
571*936afd9fSDhruva Gole  * @id:		Device Identifier
572*936afd9fSDhruva Gole  * @r_state:	true if requested to be ON
573*936afd9fSDhruva Gole  * @curr_state:	true if currently ON and active
574*936afd9fSDhruva Gole  *
575*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
576*936afd9fSDhruva Gole  */
577*936afd9fSDhruva Gole int ti_sci_device_is_on(uint32_t id, bool *r_state,  bool *curr_state)
578*936afd9fSDhruva Gole {
579*936afd9fSDhruva Gole 	int ret;
580*936afd9fSDhruva Gole 	uint8_t p_state, c_state;
581*936afd9fSDhruva Gole 
582*936afd9fSDhruva Gole 	if (!r_state && !curr_state)
583*936afd9fSDhruva Gole 		return -EINVAL;
584*936afd9fSDhruva Gole 
585*936afd9fSDhruva Gole 	ret =
586*936afd9fSDhruva Gole 	    ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
587*936afd9fSDhruva Gole 	if (ret)
588*936afd9fSDhruva Gole 		return ret;
589*936afd9fSDhruva Gole 
590*936afd9fSDhruva Gole 	if (r_state)
591*936afd9fSDhruva Gole 		*r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
592*936afd9fSDhruva Gole 	if (curr_state)
593*936afd9fSDhruva Gole 		*curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
594*936afd9fSDhruva Gole 
595*936afd9fSDhruva Gole 	return 0;
596*936afd9fSDhruva Gole }
597*936afd9fSDhruva Gole 
598*936afd9fSDhruva Gole /**
599*936afd9fSDhruva Gole  * ti_sci_device_is_trans() - Check if the device is currently transitioning
600*936afd9fSDhruva Gole  *
601*936afd9fSDhruva Gole  * @id:		Device Identifier
602*936afd9fSDhruva Gole  * @curr_state:	true if currently transitioning
603*936afd9fSDhruva Gole  *
604*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
605*936afd9fSDhruva Gole  */
606*936afd9fSDhruva Gole int ti_sci_device_is_trans(uint32_t id, bool *curr_state)
607*936afd9fSDhruva Gole {
608*936afd9fSDhruva Gole 	int ret;
609*936afd9fSDhruva Gole 	uint8_t state;
610*936afd9fSDhruva Gole 
611*936afd9fSDhruva Gole 	if (!curr_state)
612*936afd9fSDhruva Gole 		return -EINVAL;
613*936afd9fSDhruva Gole 
614*936afd9fSDhruva Gole 	ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state);
615*936afd9fSDhruva Gole 	if (ret)
616*936afd9fSDhruva Gole 		return ret;
617*936afd9fSDhruva Gole 
618*936afd9fSDhruva Gole 	*curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
619*936afd9fSDhruva Gole 
620*936afd9fSDhruva Gole 	return 0;
621*936afd9fSDhruva Gole }
622*936afd9fSDhruva Gole 
623*936afd9fSDhruva Gole /**
624*936afd9fSDhruva Gole  * ti_sci_device_set_resets() - Set resets for device managed by TISCI
625*936afd9fSDhruva Gole  *
626*936afd9fSDhruva Gole  * @id:			Device Identifier
627*936afd9fSDhruva Gole  * @reset_state:	Device specific reset bit field
628*936afd9fSDhruva Gole  *
629*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
630*936afd9fSDhruva Gole  */
631*936afd9fSDhruva Gole int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state)
632*936afd9fSDhruva Gole {
633*936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_device_resets req;
634*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
635*936afd9fSDhruva Gole 
636*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
637*936afd9fSDhruva Gole 	int ret;
638*936afd9fSDhruva Gole 
639*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS, 0,
640*936afd9fSDhruva Gole 				    &req, sizeof(req),
641*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
642*936afd9fSDhruva Gole 				    &xfer);
643*936afd9fSDhruva Gole 	if (ret) {
644*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
645*936afd9fSDhruva Gole 		return ret;
646*936afd9fSDhruva Gole 	}
647*936afd9fSDhruva Gole 
648*936afd9fSDhruva Gole 	req.id = id;
649*936afd9fSDhruva Gole 	req.resets = reset_state;
650*936afd9fSDhruva Gole 
651*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
652*936afd9fSDhruva Gole 	if (ret) {
653*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
654*936afd9fSDhruva Gole 		return ret;
655*936afd9fSDhruva Gole 	}
656*936afd9fSDhruva Gole 
657*936afd9fSDhruva Gole 	return 0;
658*936afd9fSDhruva Gole }
659*936afd9fSDhruva Gole 
660*936afd9fSDhruva Gole /**
661*936afd9fSDhruva Gole  * ti_sci_device_get_resets() - Get reset state for device managed by TISCI
662*936afd9fSDhruva Gole  *
663*936afd9fSDhruva Gole  * @id:			Device Identifier
664*936afd9fSDhruva Gole  * @reset_state:	Pointer to reset state to populate
665*936afd9fSDhruva Gole  *
666*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
667*936afd9fSDhruva Gole  */
668*936afd9fSDhruva Gole int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state)
669*936afd9fSDhruva Gole {
670*936afd9fSDhruva Gole 	return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL);
671*936afd9fSDhruva Gole }
672*936afd9fSDhruva Gole 
673*936afd9fSDhruva Gole /**
674*936afd9fSDhruva Gole  * ti_sci_clock_set_state() - Set clock state helper
675*936afd9fSDhruva Gole  *
676*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
677*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request,
678*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs, This indexes
679*936afd9fSDhruva Gole  *		which clock input to modify
680*936afd9fSDhruva Gole  * @flags:	Header flags as needed
681*936afd9fSDhruva Gole  * @state:	State to request for the clock
682*936afd9fSDhruva Gole  *
683*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
684*936afd9fSDhruva Gole  */
685*936afd9fSDhruva Gole int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id,
686*936afd9fSDhruva Gole 			   uint32_t flags, uint8_t state)
687*936afd9fSDhruva Gole {
688*936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_clock_state req;
689*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
690*936afd9fSDhruva Gole 
691*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
692*936afd9fSDhruva Gole 	int ret;
693*936afd9fSDhruva Gole 
694*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_STATE, flags,
695*936afd9fSDhruva Gole 				    &req, sizeof(req),
696*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
697*936afd9fSDhruva Gole 				    &xfer);
698*936afd9fSDhruva Gole 	if (ret) {
699*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
700*936afd9fSDhruva Gole 		return ret;
701*936afd9fSDhruva Gole 	}
702*936afd9fSDhruva Gole 
703*936afd9fSDhruva Gole 	req.dev_id = dev_id;
704*936afd9fSDhruva Gole 	req.clk_id = clk_id;
705*936afd9fSDhruva Gole 	req.request_state = state;
706*936afd9fSDhruva Gole 
707*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
708*936afd9fSDhruva Gole 	if (ret) {
709*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
710*936afd9fSDhruva Gole 		return ret;
711*936afd9fSDhruva Gole 	}
712*936afd9fSDhruva Gole 
713*936afd9fSDhruva Gole 	return 0;
714*936afd9fSDhruva Gole }
715*936afd9fSDhruva Gole 
716*936afd9fSDhruva Gole /**
717*936afd9fSDhruva Gole  * ti_sci_clock_get_state() - Get clock state helper
718*936afd9fSDhruva Gole  *
719*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
720*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
721*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
722*936afd9fSDhruva Gole  *		which clock input to modify.
723*936afd9fSDhruva Gole  * @programmed_state:	State requested for clock to move to
724*936afd9fSDhruva Gole  * @current_state:	State that the clock is currently in
725*936afd9fSDhruva Gole  *
726*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
727*936afd9fSDhruva Gole  */
728*936afd9fSDhruva Gole int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id,
729*936afd9fSDhruva Gole 			   uint8_t *programmed_state,
730*936afd9fSDhruva Gole 			   uint8_t *current_state)
731*936afd9fSDhruva Gole {
732*936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_clock_state req;
733*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_clock_state resp;
734*936afd9fSDhruva Gole 
735*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
736*936afd9fSDhruva Gole 	int ret;
737*936afd9fSDhruva Gole 
738*936afd9fSDhruva Gole 	if (!programmed_state && !current_state)
739*936afd9fSDhruva Gole 		return -EINVAL;
740*936afd9fSDhruva Gole 
741*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_STATE, 0,
742*936afd9fSDhruva Gole 				    &req, sizeof(req),
743*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
744*936afd9fSDhruva Gole 				    &xfer);
745*936afd9fSDhruva Gole 	if (ret) {
746*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
747*936afd9fSDhruva Gole 		return ret;
748*936afd9fSDhruva Gole 	}
749*936afd9fSDhruva Gole 
750*936afd9fSDhruva Gole 	req.dev_id = dev_id;
751*936afd9fSDhruva Gole 	req.clk_id = clk_id;
752*936afd9fSDhruva Gole 
753*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
754*936afd9fSDhruva Gole 	if (ret) {
755*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
756*936afd9fSDhruva Gole 		return ret;
757*936afd9fSDhruva Gole 	}
758*936afd9fSDhruva Gole 
759*936afd9fSDhruva Gole 	if (programmed_state)
760*936afd9fSDhruva Gole 		*programmed_state = resp.programmed_state;
761*936afd9fSDhruva Gole 	if (current_state)
762*936afd9fSDhruva Gole 		*current_state = resp.current_state;
763*936afd9fSDhruva Gole 
764*936afd9fSDhruva Gole 	return 0;
765*936afd9fSDhruva Gole }
766*936afd9fSDhruva Gole 
767*936afd9fSDhruva Gole /**
768*936afd9fSDhruva Gole  * ti_sci_clock_get() - Get control of a clock from TI SCI
769*936afd9fSDhruva Gole 
770*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
771*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
772*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
773*936afd9fSDhruva Gole  *		which clock input to modify.
774*936afd9fSDhruva Gole  * @needs_ssc: 'true' iff Spread Spectrum clock is desired
775*936afd9fSDhruva Gole  * @can_change_freq: 'true' iff frequency change is desired
776*936afd9fSDhruva Gole  * @enable_input_term: 'true' iff input termination is desired
777*936afd9fSDhruva Gole  *
778*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
779*936afd9fSDhruva Gole  */
780*936afd9fSDhruva Gole int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id,
781*936afd9fSDhruva Gole 		     bool needs_ssc, bool can_change_freq,
782*936afd9fSDhruva Gole 		     bool enable_input_term)
783*936afd9fSDhruva Gole {
784*936afd9fSDhruva Gole 	uint32_t flags = 0;
785*936afd9fSDhruva Gole 
786*936afd9fSDhruva Gole 	flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
787*936afd9fSDhruva Gole 	flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
788*936afd9fSDhruva Gole 	flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
789*936afd9fSDhruva Gole 
790*936afd9fSDhruva Gole 	return ti_sci_clock_set_state(dev_id, clk_id, flags,
791*936afd9fSDhruva Gole 				      MSG_CLOCK_SW_STATE_REQ);
792*936afd9fSDhruva Gole }
793*936afd9fSDhruva Gole 
794*936afd9fSDhruva Gole /**
795*936afd9fSDhruva Gole  * ti_sci_clock_idle() - Idle a clock which is in our control
796*936afd9fSDhruva Gole 
797*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
798*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
799*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
800*936afd9fSDhruva Gole  *		which clock input to modify.
801*936afd9fSDhruva Gole  *
802*936afd9fSDhruva Gole  * NOTE: This clock must have been requested by get_clock previously.
803*936afd9fSDhruva Gole  *
804*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
805*936afd9fSDhruva Gole  */
806*936afd9fSDhruva Gole int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id)
807*936afd9fSDhruva Gole {
808*936afd9fSDhruva Gole 	return ti_sci_clock_set_state(dev_id, clk_id, 0,
809*936afd9fSDhruva Gole 				      MSG_CLOCK_SW_STATE_UNREQ);
810*936afd9fSDhruva Gole }
811*936afd9fSDhruva Gole 
812*936afd9fSDhruva Gole /**
813*936afd9fSDhruva Gole  * ti_sci_clock_put() - Release a clock from our control
814*936afd9fSDhruva Gole  *
815*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
816*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
817*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
818*936afd9fSDhruva Gole  *		which clock input to modify.
819*936afd9fSDhruva Gole  *
820*936afd9fSDhruva Gole  * NOTE: This clock must have been requested by get_clock previously.
821*936afd9fSDhruva Gole  *
822*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
823*936afd9fSDhruva Gole  */
824*936afd9fSDhruva Gole int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id)
825*936afd9fSDhruva Gole {
826*936afd9fSDhruva Gole 	return ti_sci_clock_set_state(dev_id, clk_id, 0,
827*936afd9fSDhruva Gole 				      MSG_CLOCK_SW_STATE_AUTO);
828*936afd9fSDhruva Gole }
829*936afd9fSDhruva Gole 
830*936afd9fSDhruva Gole /**
831*936afd9fSDhruva Gole  * ti_sci_clock_is_auto() - Is the clock being auto managed
832*936afd9fSDhruva Gole  *
833*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
834*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
835*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
836*936afd9fSDhruva Gole  *		which clock input to modify.
837*936afd9fSDhruva Gole  * @req_state: state indicating if the clock is auto managed
838*936afd9fSDhruva Gole  *
839*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
840*936afd9fSDhruva Gole  */
841*936afd9fSDhruva Gole int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, bool *req_state)
842*936afd9fSDhruva Gole {
843*936afd9fSDhruva Gole 	uint8_t state = 0;
844*936afd9fSDhruva Gole 	int ret;
845*936afd9fSDhruva Gole 
846*936afd9fSDhruva Gole 	if (!req_state)
847*936afd9fSDhruva Gole 		return -EINVAL;
848*936afd9fSDhruva Gole 
849*936afd9fSDhruva Gole 	ret = ti_sci_clock_get_state(dev_id, clk_id, &state, NULL);
850*936afd9fSDhruva Gole 	if (ret)
851*936afd9fSDhruva Gole 		return ret;
852*936afd9fSDhruva Gole 
853*936afd9fSDhruva Gole 	*req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
854*936afd9fSDhruva Gole 
855*936afd9fSDhruva Gole 	return 0;
856*936afd9fSDhruva Gole }
857*936afd9fSDhruva Gole 
858*936afd9fSDhruva Gole /**
859*936afd9fSDhruva Gole  * ti_sci_clock_is_on() - Is the clock ON
860*936afd9fSDhruva Gole  *
861*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
862*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
863*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
864*936afd9fSDhruva Gole  *		which clock input to modify.
865*936afd9fSDhruva Gole  * @req_state: state indicating if the clock is managed by us and enabled
866*936afd9fSDhruva Gole  * @curr_state: state indicating if the clock is ready for operation
867*936afd9fSDhruva Gole  *
868*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
869*936afd9fSDhruva Gole  */
870*936afd9fSDhruva Gole int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id,
871*936afd9fSDhruva Gole 		       bool *req_state, bool *curr_state)
872*936afd9fSDhruva Gole {
873*936afd9fSDhruva Gole 	uint8_t c_state = 0, r_state = 0;
874*936afd9fSDhruva Gole 	int ret;
875*936afd9fSDhruva Gole 
876*936afd9fSDhruva Gole 	if (!req_state && !curr_state)
877*936afd9fSDhruva Gole 		return -EINVAL;
878*936afd9fSDhruva Gole 
879*936afd9fSDhruva Gole 	ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
880*936afd9fSDhruva Gole 	if (ret)
881*936afd9fSDhruva Gole 		return ret;
882*936afd9fSDhruva Gole 
883*936afd9fSDhruva Gole 	if (req_state)
884*936afd9fSDhruva Gole 		*req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
885*936afd9fSDhruva Gole 	if (curr_state)
886*936afd9fSDhruva Gole 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
887*936afd9fSDhruva Gole 
888*936afd9fSDhruva Gole 	return 0;
889*936afd9fSDhruva Gole }
890*936afd9fSDhruva Gole 
891*936afd9fSDhruva Gole /**
892*936afd9fSDhruva Gole  * ti_sci_clock_is_off() - Is the clock OFF
893*936afd9fSDhruva Gole  *
894*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
895*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
896*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
897*936afd9fSDhruva Gole  *		which clock input to modify.
898*936afd9fSDhruva Gole  * @req_state: state indicating if the clock is managed by us and disabled
899*936afd9fSDhruva Gole  * @curr_state: state indicating if the clock is NOT ready for operation
900*936afd9fSDhruva Gole  *
901*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
902*936afd9fSDhruva Gole  */
903*936afd9fSDhruva Gole int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id,
904*936afd9fSDhruva Gole 			bool *req_state, bool *curr_state)
905*936afd9fSDhruva Gole {
906*936afd9fSDhruva Gole 	uint8_t c_state = 0, r_state = 0;
907*936afd9fSDhruva Gole 	int ret;
908*936afd9fSDhruva Gole 
909*936afd9fSDhruva Gole 	if (!req_state && !curr_state)
910*936afd9fSDhruva Gole 		return -EINVAL;
911*936afd9fSDhruva Gole 
912*936afd9fSDhruva Gole 	ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
913*936afd9fSDhruva Gole 	if (ret)
914*936afd9fSDhruva Gole 		return ret;
915*936afd9fSDhruva Gole 
916*936afd9fSDhruva Gole 	if (req_state)
917*936afd9fSDhruva Gole 		*req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
918*936afd9fSDhruva Gole 	if (curr_state)
919*936afd9fSDhruva Gole 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
920*936afd9fSDhruva Gole 
921*936afd9fSDhruva Gole 	return 0;
922*936afd9fSDhruva Gole }
923*936afd9fSDhruva Gole 
924*936afd9fSDhruva Gole /**
925*936afd9fSDhruva Gole  * ti_sci_clock_set_parent() - Set the clock source of a specific device clock
926*936afd9fSDhruva Gole  *
927*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
928*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
929*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
930*936afd9fSDhruva Gole  *		which clock input to modify.
931*936afd9fSDhruva Gole  * @parent_id:	Parent clock identifier to set
932*936afd9fSDhruva Gole  *
933*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
934*936afd9fSDhruva Gole  */
935*936afd9fSDhruva Gole int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, uint8_t parent_id)
936*936afd9fSDhruva Gole {
937*936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_clock_parent req;
938*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
939*936afd9fSDhruva Gole 
940*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
941*936afd9fSDhruva Gole 	int ret;
942*936afd9fSDhruva Gole 
943*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_PARENT, 0,
944*936afd9fSDhruva Gole 				    &req, sizeof(req),
945*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
946*936afd9fSDhruva Gole 				    &xfer);
947*936afd9fSDhruva Gole 	if (ret) {
948*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
949*936afd9fSDhruva Gole 		return ret;
950*936afd9fSDhruva Gole 	}
951*936afd9fSDhruva Gole 
952*936afd9fSDhruva Gole 	req.dev_id = dev_id;
953*936afd9fSDhruva Gole 	req.clk_id = clk_id;
954*936afd9fSDhruva Gole 	req.parent_id = parent_id;
955*936afd9fSDhruva Gole 
956*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
957*936afd9fSDhruva Gole 	if (ret) {
958*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
959*936afd9fSDhruva Gole 		return ret;
960*936afd9fSDhruva Gole 	}
961*936afd9fSDhruva Gole 
962*936afd9fSDhruva Gole 	return 0;
963*936afd9fSDhruva Gole }
964*936afd9fSDhruva Gole 
965*936afd9fSDhruva Gole /**
966*936afd9fSDhruva Gole  * ti_sci_clock_get_parent() - Get current parent clock source
967*936afd9fSDhruva Gole  *
968*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
969*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
970*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
971*936afd9fSDhruva Gole  *		which clock input to modify.
972*936afd9fSDhruva Gole  * @parent_id:	Current clock parent
973*936afd9fSDhruva Gole  *
974*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
975*936afd9fSDhruva Gole  */
976*936afd9fSDhruva Gole int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, uint8_t *parent_id)
977*936afd9fSDhruva Gole {
978*936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_clock_parent req;
979*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_clock_parent resp;
980*936afd9fSDhruva Gole 
981*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
982*936afd9fSDhruva Gole 	int ret;
983*936afd9fSDhruva Gole 
984*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_PARENT, 0,
985*936afd9fSDhruva Gole 				    &req, sizeof(req),
986*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
987*936afd9fSDhruva Gole 				    &xfer);
988*936afd9fSDhruva Gole 	if (ret) {
989*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
990*936afd9fSDhruva Gole 		return ret;
991*936afd9fSDhruva Gole 	}
992*936afd9fSDhruva Gole 
993*936afd9fSDhruva Gole 	req.dev_id = dev_id;
994*936afd9fSDhruva Gole 	req.clk_id = clk_id;
995*936afd9fSDhruva Gole 
996*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
997*936afd9fSDhruva Gole 	if (ret) {
998*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
999*936afd9fSDhruva Gole 		return ret;
1000*936afd9fSDhruva Gole 	}
1001*936afd9fSDhruva Gole 
1002*936afd9fSDhruva Gole 	*parent_id = resp.parent_id;
1003*936afd9fSDhruva Gole 
1004*936afd9fSDhruva Gole 	return 0;
1005*936afd9fSDhruva Gole }
1006*936afd9fSDhruva Gole 
1007*936afd9fSDhruva Gole /**
1008*936afd9fSDhruva Gole  * ti_sci_clock_get_num_parents() - Get num parents of the current clk source
1009*936afd9fSDhruva Gole  *
1010*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
1011*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
1012*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
1013*936afd9fSDhruva Gole  *		which clock input to modify.
1014*936afd9fSDhruva Gole  * @num_parents: Returns he number of parents to the current clock.
1015*936afd9fSDhruva Gole  *
1016*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1017*936afd9fSDhruva Gole  */
1018*936afd9fSDhruva Gole int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id,
1019*936afd9fSDhruva Gole 				 uint8_t *num_parents)
1020*936afd9fSDhruva Gole {
1021*936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_clock_num_parents req;
1022*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_clock_num_parents resp;
1023*936afd9fSDhruva Gole 
1024*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1025*936afd9fSDhruva Gole 	int ret;
1026*936afd9fSDhruva Gole 
1027*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, 0,
1028*936afd9fSDhruva Gole 				    &req, sizeof(req),
1029*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1030*936afd9fSDhruva Gole 				    &xfer);
1031*936afd9fSDhruva Gole 	if (ret) {
1032*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1033*936afd9fSDhruva Gole 		return ret;
1034*936afd9fSDhruva Gole 	}
1035*936afd9fSDhruva Gole 
1036*936afd9fSDhruva Gole 	req.dev_id = dev_id;
1037*936afd9fSDhruva Gole 	req.clk_id = clk_id;
1038*936afd9fSDhruva Gole 
1039*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1040*936afd9fSDhruva Gole 	if (ret) {
1041*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1042*936afd9fSDhruva Gole 		return ret;
1043*936afd9fSDhruva Gole 	}
1044*936afd9fSDhruva Gole 
1045*936afd9fSDhruva Gole 	*num_parents = resp.num_parents;
1046*936afd9fSDhruva Gole 
1047*936afd9fSDhruva Gole 	return 0;
1048*936afd9fSDhruva Gole }
1049*936afd9fSDhruva Gole 
1050*936afd9fSDhruva Gole /**
1051*936afd9fSDhruva Gole  * ti_sci_clock_get_match_freq() - Find a good match for frequency
1052*936afd9fSDhruva Gole  *
1053*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
1054*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
1055*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
1056*936afd9fSDhruva Gole  *		which clock input to modify.
1057*936afd9fSDhruva Gole  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
1058*936afd9fSDhruva Gole  *		allowable programmed frequency and does not account for clock
1059*936afd9fSDhruva Gole  *		tolerances and jitter.
1060*936afd9fSDhruva Gole  * @target_freq: The target clock frequency in Hz. A frequency will be
1061*936afd9fSDhruva Gole  *		processed as close to this target frequency as possible.
1062*936afd9fSDhruva Gole  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
1063*936afd9fSDhruva Gole  *		allowable programmed frequency and does not account for clock
1064*936afd9fSDhruva Gole  *		tolerances and jitter.
1065*936afd9fSDhruva Gole  * @match_freq:	Frequency match in Hz response.
1066*936afd9fSDhruva Gole  *
1067*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1068*936afd9fSDhruva Gole  */
1069*936afd9fSDhruva Gole int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id,
1070*936afd9fSDhruva Gole 				uint64_t min_freq, uint64_t target_freq,
1071*936afd9fSDhruva Gole 				uint64_t max_freq, uint64_t *match_freq)
1072*936afd9fSDhruva Gole {
1073*936afd9fSDhruva Gole 	struct ti_sci_msg_req_query_clock_freq req;
1074*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_query_clock_freq resp;
1075*936afd9fSDhruva Gole 
1076*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1077*936afd9fSDhruva Gole 	int ret;
1078*936afd9fSDhruva Gole 
1079*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_CLOCK_FREQ, 0,
1080*936afd9fSDhruva Gole 				    &req, sizeof(req),
1081*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1082*936afd9fSDhruva Gole 				    &xfer);
1083*936afd9fSDhruva Gole 	if (ret) {
1084*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1085*936afd9fSDhruva Gole 		return ret;
1086*936afd9fSDhruva Gole 	}
1087*936afd9fSDhruva Gole 
1088*936afd9fSDhruva Gole 	req.dev_id = dev_id;
1089*936afd9fSDhruva Gole 	req.clk_id = clk_id;
1090*936afd9fSDhruva Gole 	req.min_freq_hz = min_freq;
1091*936afd9fSDhruva Gole 	req.target_freq_hz = target_freq;
1092*936afd9fSDhruva Gole 	req.max_freq_hz = max_freq;
1093*936afd9fSDhruva Gole 
1094*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1095*936afd9fSDhruva Gole 	if (ret) {
1096*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1097*936afd9fSDhruva Gole 		return ret;
1098*936afd9fSDhruva Gole 	}
1099*936afd9fSDhruva Gole 
1100*936afd9fSDhruva Gole 	*match_freq = resp.freq_hz;
1101*936afd9fSDhruva Gole 
1102*936afd9fSDhruva Gole 	return 0;
1103*936afd9fSDhruva Gole }
1104*936afd9fSDhruva Gole 
1105*936afd9fSDhruva Gole /**
1106*936afd9fSDhruva Gole  * ti_sci_clock_set_freq() - Set a frequency for clock
1107*936afd9fSDhruva Gole  *
1108*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
1109*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
1110*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
1111*936afd9fSDhruva Gole  *		which clock input to modify.
1112*936afd9fSDhruva Gole  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
1113*936afd9fSDhruva Gole  *		allowable programmed frequency and does not account for clock
1114*936afd9fSDhruva Gole  *		tolerances and jitter.
1115*936afd9fSDhruva Gole  * @target_freq: The target clock frequency in Hz. A frequency will be
1116*936afd9fSDhruva Gole  *		processed as close to this target frequency as possible.
1117*936afd9fSDhruva Gole  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
1118*936afd9fSDhruva Gole  *		allowable programmed frequency and does not account for clock
1119*936afd9fSDhruva Gole  *		tolerances and jitter.
1120*936afd9fSDhruva Gole  *
1121*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1122*936afd9fSDhruva Gole  */
1123*936afd9fSDhruva Gole int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, uint64_t min_freq,
1124*936afd9fSDhruva Gole 			  uint64_t target_freq, uint64_t max_freq)
1125*936afd9fSDhruva Gole {
1126*936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_clock_freq req;
1127*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1128*936afd9fSDhruva Gole 
1129*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1130*936afd9fSDhruva Gole 	int ret;
1131*936afd9fSDhruva Gole 
1132*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_FREQ, 0,
1133*936afd9fSDhruva Gole 				    &req, sizeof(req),
1134*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1135*936afd9fSDhruva Gole 				    &xfer);
1136*936afd9fSDhruva Gole 	if (ret) {
1137*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1138*936afd9fSDhruva Gole 		return ret;
1139*936afd9fSDhruva Gole 	}
1140*936afd9fSDhruva Gole 	req.dev_id = dev_id;
1141*936afd9fSDhruva Gole 	req.clk_id = clk_id;
1142*936afd9fSDhruva Gole 	req.min_freq_hz = min_freq;
1143*936afd9fSDhruva Gole 	req.target_freq_hz = target_freq;
1144*936afd9fSDhruva Gole 	req.max_freq_hz = max_freq;
1145*936afd9fSDhruva Gole 
1146*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1147*936afd9fSDhruva Gole 	if (ret) {
1148*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1149*936afd9fSDhruva Gole 		return ret;
1150*936afd9fSDhruva Gole 	}
1151*936afd9fSDhruva Gole 
1152*936afd9fSDhruva Gole 	return 0;
1153*936afd9fSDhruva Gole }
1154*936afd9fSDhruva Gole 
1155*936afd9fSDhruva Gole /**
1156*936afd9fSDhruva Gole  * ti_sci_clock_get_freq() - Get current frequency
1157*936afd9fSDhruva Gole  *
1158*936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
1159*936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
1160*936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
1161*936afd9fSDhruva Gole  *		which clock input to modify.
1162*936afd9fSDhruva Gole  * @freq:	Currently frequency in Hz
1163*936afd9fSDhruva Gole  *
1164*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1165*936afd9fSDhruva Gole  */
1166*936afd9fSDhruva Gole int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq)
1167*936afd9fSDhruva Gole {
1168*936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_clock_freq req;
1169*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_clock_freq resp;
1170*936afd9fSDhruva Gole 
1171*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1172*936afd9fSDhruva Gole 	int ret;
1173*936afd9fSDhruva Gole 
1174*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_FREQ, 0,
1175*936afd9fSDhruva Gole 				    &req, sizeof(req),
1176*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1177*936afd9fSDhruva Gole 				    &xfer);
1178*936afd9fSDhruva Gole 	if (ret) {
1179*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1180*936afd9fSDhruva Gole 		return ret;
1181*936afd9fSDhruva Gole 	}
1182*936afd9fSDhruva Gole 
1183*936afd9fSDhruva Gole 	req.dev_id = dev_id;
1184*936afd9fSDhruva Gole 	req.clk_id = clk_id;
1185*936afd9fSDhruva Gole 
1186*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1187*936afd9fSDhruva Gole 	if (ret) {
1188*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1189*936afd9fSDhruva Gole 		return ret;
1190*936afd9fSDhruva Gole 	}
1191*936afd9fSDhruva Gole 
1192*936afd9fSDhruva Gole 	*freq = resp.freq_hz;
1193*936afd9fSDhruva Gole 
1194*936afd9fSDhruva Gole 	return 0;
1195*936afd9fSDhruva Gole }
1196*936afd9fSDhruva Gole 
1197*936afd9fSDhruva Gole /**
1198*936afd9fSDhruva Gole  * ti_sci_core_reboot() - Command to request system reset
1199*936afd9fSDhruva Gole  *
1200*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1201*936afd9fSDhruva Gole  */
1202*936afd9fSDhruva Gole int ti_sci_core_reboot(void)
1203*936afd9fSDhruva Gole {
1204*936afd9fSDhruva Gole 	struct ti_sci_msg_req_reboot req;
1205*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1206*936afd9fSDhruva Gole 
1207*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1208*936afd9fSDhruva Gole 	int ret;
1209*936afd9fSDhruva Gole 
1210*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SYS_RESET, 0,
1211*936afd9fSDhruva Gole 				    &req, sizeof(req),
1212*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1213*936afd9fSDhruva Gole 				    &xfer);
1214*936afd9fSDhruva Gole 	if (ret) {
1215*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1216*936afd9fSDhruva Gole 		return ret;
1217*936afd9fSDhruva Gole 	}
1218*936afd9fSDhruva Gole 	req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET;
1219*936afd9fSDhruva Gole 
1220*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1221*936afd9fSDhruva Gole 	if (ret) {
1222*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1223*936afd9fSDhruva Gole 		return ret;
1224*936afd9fSDhruva Gole 	}
1225*936afd9fSDhruva Gole 
1226*936afd9fSDhruva Gole 	return 0;
1227*936afd9fSDhruva Gole }
1228*936afd9fSDhruva Gole 
1229*936afd9fSDhruva Gole /**
1230*936afd9fSDhruva Gole  * ti_sci_proc_request() - Request a physical processor control
1231*936afd9fSDhruva Gole  *
1232*936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1233*936afd9fSDhruva Gole  *
1234*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1235*936afd9fSDhruva Gole  */
1236*936afd9fSDhruva Gole int ti_sci_proc_request(uint8_t proc_id)
1237*936afd9fSDhruva Gole {
1238*936afd9fSDhruva Gole 	struct ti_sci_msg_req_proc_request req;
1239*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1240*936afd9fSDhruva Gole 
1241*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1242*936afd9fSDhruva Gole 	int ret;
1243*936afd9fSDhruva Gole 
1244*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST, 0,
1245*936afd9fSDhruva Gole 				    &req, sizeof(req),
1246*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1247*936afd9fSDhruva Gole 				    &xfer);
1248*936afd9fSDhruva Gole 	if (ret) {
1249*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1250*936afd9fSDhruva Gole 		return ret;
1251*936afd9fSDhruva Gole 	}
1252*936afd9fSDhruva Gole 
1253*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1254*936afd9fSDhruva Gole 
1255*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1256*936afd9fSDhruva Gole 	if (ret) {
1257*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1258*936afd9fSDhruva Gole 		return ret;
1259*936afd9fSDhruva Gole 	}
1260*936afd9fSDhruva Gole 
1261*936afd9fSDhruva Gole 	return 0;
1262*936afd9fSDhruva Gole }
1263*936afd9fSDhruva Gole 
1264*936afd9fSDhruva Gole /**
1265*936afd9fSDhruva Gole  * ti_sci_proc_release() - Release a physical processor control
1266*936afd9fSDhruva Gole  *
1267*936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1268*936afd9fSDhruva Gole  *
1269*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1270*936afd9fSDhruva Gole  */
1271*936afd9fSDhruva Gole int ti_sci_proc_release(uint8_t proc_id)
1272*936afd9fSDhruva Gole {
1273*936afd9fSDhruva Gole 	struct ti_sci_msg_req_proc_release req;
1274*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1275*936afd9fSDhruva Gole 
1276*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1277*936afd9fSDhruva Gole 	int ret;
1278*936afd9fSDhruva Gole 
1279*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE, 0,
1280*936afd9fSDhruva Gole 				    &req, sizeof(req),
1281*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1282*936afd9fSDhruva Gole 				    &xfer);
1283*936afd9fSDhruva Gole 	if (ret) {
1284*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1285*936afd9fSDhruva Gole 		return ret;
1286*936afd9fSDhruva Gole 	}
1287*936afd9fSDhruva Gole 
1288*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1289*936afd9fSDhruva Gole 
1290*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1291*936afd9fSDhruva Gole 	if (ret) {
1292*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1293*936afd9fSDhruva Gole 		return ret;
1294*936afd9fSDhruva Gole 	}
1295*936afd9fSDhruva Gole 
1296*936afd9fSDhruva Gole 	return 0;
1297*936afd9fSDhruva Gole }
1298*936afd9fSDhruva Gole 
1299*936afd9fSDhruva Gole /**
1300*936afd9fSDhruva Gole  * ti_sci_proc_handover() - Handover a physical processor control to a host in
1301*936afd9fSDhruva Gole  *                          the processor's access control list.
1302*936afd9fSDhruva Gole  *
1303*936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1304*936afd9fSDhruva Gole  * @host_id:	Host ID to get the control of the processor
1305*936afd9fSDhruva Gole  *
1306*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1307*936afd9fSDhruva Gole  */
1308*936afd9fSDhruva Gole int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id)
1309*936afd9fSDhruva Gole {
1310*936afd9fSDhruva Gole 	struct ti_sci_msg_req_proc_handover req;
1311*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1312*936afd9fSDhruva Gole 
1313*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1314*936afd9fSDhruva Gole 	int ret;
1315*936afd9fSDhruva Gole 
1316*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER, 0,
1317*936afd9fSDhruva Gole 				    &req, sizeof(req),
1318*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1319*936afd9fSDhruva Gole 				    &xfer);
1320*936afd9fSDhruva Gole 	if (ret) {
1321*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1322*936afd9fSDhruva Gole 		return ret;
1323*936afd9fSDhruva Gole 	}
1324*936afd9fSDhruva Gole 
1325*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1326*936afd9fSDhruva Gole 	req.host_id = host_id;
1327*936afd9fSDhruva Gole 
1328*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1329*936afd9fSDhruva Gole 	if (ret) {
1330*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1331*936afd9fSDhruva Gole 		return ret;
1332*936afd9fSDhruva Gole 	}
1333*936afd9fSDhruva Gole 
1334*936afd9fSDhruva Gole 	return 0;
1335*936afd9fSDhruva Gole }
1336*936afd9fSDhruva Gole 
1337*936afd9fSDhruva Gole /**
1338*936afd9fSDhruva Gole  * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags
1339*936afd9fSDhruva Gole  *
1340*936afd9fSDhruva Gole  * @proc_id:		Processor ID this request is for
1341*936afd9fSDhruva Gole  * @config_flags_set:	Configuration flags to be set
1342*936afd9fSDhruva Gole  * @config_flags_clear:	Configuration flags to be cleared
1343*936afd9fSDhruva Gole  *
1344*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1345*936afd9fSDhruva Gole  */
1346*936afd9fSDhruva Gole int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector,
1347*936afd9fSDhruva Gole 			     uint32_t config_flags_set,
1348*936afd9fSDhruva Gole 			     uint32_t config_flags_clear)
1349*936afd9fSDhruva Gole {
1350*936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_proc_boot_config req;
1351*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1352*936afd9fSDhruva Gole 
1353*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1354*936afd9fSDhruva Gole 	int ret;
1355*936afd9fSDhruva Gole 
1356*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG, 0,
1357*936afd9fSDhruva Gole 				    &req, sizeof(req),
1358*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1359*936afd9fSDhruva Gole 				    &xfer);
1360*936afd9fSDhruva Gole 	if (ret) {
1361*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1362*936afd9fSDhruva Gole 		return ret;
1363*936afd9fSDhruva Gole 	}
1364*936afd9fSDhruva Gole 
1365*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1366*936afd9fSDhruva Gole 	req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
1367*936afd9fSDhruva Gole 	req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
1368*936afd9fSDhruva Gole 				TISCI_ADDR_HIGH_SHIFT;
1369*936afd9fSDhruva Gole 	req.config_flags_set = config_flags_set;
1370*936afd9fSDhruva Gole 	req.config_flags_clear = config_flags_clear;
1371*936afd9fSDhruva Gole 
1372*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1373*936afd9fSDhruva Gole 	if (ret) {
1374*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1375*936afd9fSDhruva Gole 		return ret;
1376*936afd9fSDhruva Gole 	}
1377*936afd9fSDhruva Gole 
1378*936afd9fSDhruva Gole 	return 0;
1379*936afd9fSDhruva Gole }
1380*936afd9fSDhruva Gole 
1381*936afd9fSDhruva Gole /**
1382*936afd9fSDhruva Gole  * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags
1383*936afd9fSDhruva Gole  *
1384*936afd9fSDhruva Gole  * @proc_id:			Processor ID this request is for
1385*936afd9fSDhruva Gole  * @control_flags_set:		Control flags to be set
1386*936afd9fSDhruva Gole  * @control_flags_clear:	Control flags to be cleared
1387*936afd9fSDhruva Gole  *
1388*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1389*936afd9fSDhruva Gole  */
1390*936afd9fSDhruva Gole int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set,
1391*936afd9fSDhruva Gole 			      uint32_t control_flags_clear)
1392*936afd9fSDhruva Gole {
1393*936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_proc_boot_ctrl req;
1394*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1395*936afd9fSDhruva Gole 
1396*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1397*936afd9fSDhruva Gole 	int ret;
1398*936afd9fSDhruva Gole 
1399*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0,
1400*936afd9fSDhruva Gole 				    &req, sizeof(req),
1401*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1402*936afd9fSDhruva Gole 				    &xfer);
1403*936afd9fSDhruva Gole 	if (ret) {
1404*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1405*936afd9fSDhruva Gole 		return ret;
1406*936afd9fSDhruva Gole 	}
1407*936afd9fSDhruva Gole 
1408*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1409*936afd9fSDhruva Gole 	req.control_flags_set = control_flags_set;
1410*936afd9fSDhruva Gole 	req.control_flags_clear = control_flags_clear;
1411*936afd9fSDhruva Gole 
1412*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1413*936afd9fSDhruva Gole 	if (ret) {
1414*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1415*936afd9fSDhruva Gole 		return ret;
1416*936afd9fSDhruva Gole 	}
1417*936afd9fSDhruva Gole 
1418*936afd9fSDhruva Gole 	return 0;
1419*936afd9fSDhruva Gole }
1420*936afd9fSDhruva Gole 
1421*936afd9fSDhruva Gole /**
1422*936afd9fSDhruva Gole  * ti_sci_proc_set_boot_ctrl_no_wait() - Set the processor boot control flags
1423*936afd9fSDhruva Gole  *					 without requesting or waiting for a
1424*936afd9fSDhruva Gole  *					 response.
1425*936afd9fSDhruva Gole  *
1426*936afd9fSDhruva Gole  * @proc_id:			Processor ID this request is for
1427*936afd9fSDhruva Gole  * @control_flags_set:		Control flags to be set
1428*936afd9fSDhruva Gole  * @control_flags_clear:	Control flags to be cleared
1429*936afd9fSDhruva Gole  *
1430*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1431*936afd9fSDhruva Gole  */
1432*936afd9fSDhruva Gole int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id,
1433*936afd9fSDhruva Gole 				      uint32_t control_flags_set,
1434*936afd9fSDhruva Gole 				      uint32_t control_flags_clear)
1435*936afd9fSDhruva Gole {
1436*936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_proc_boot_ctrl req;
1437*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1438*936afd9fSDhruva Gole 	int ret;
1439*936afd9fSDhruva Gole 
1440*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0,
1441*936afd9fSDhruva Gole 				    &req, sizeof(req),
1442*936afd9fSDhruva Gole 				    NULL, 0,
1443*936afd9fSDhruva Gole 				    &xfer);
1444*936afd9fSDhruva Gole 	if (ret != 0U) {
1445*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1446*936afd9fSDhruva Gole 		return ret;
1447*936afd9fSDhruva Gole 	}
1448*936afd9fSDhruva Gole 
1449*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1450*936afd9fSDhruva Gole 	req.control_flags_set = control_flags_set;
1451*936afd9fSDhruva Gole 	req.control_flags_clear = control_flags_clear;
1452*936afd9fSDhruva Gole 
1453*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1454*936afd9fSDhruva Gole 	if (ret != 0U) {
1455*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1456*936afd9fSDhruva Gole 		return ret;
1457*936afd9fSDhruva Gole 	}
1458*936afd9fSDhruva Gole 
1459*936afd9fSDhruva Gole 	return 0;
1460*936afd9fSDhruva Gole }
1461*936afd9fSDhruva Gole 
1462*936afd9fSDhruva Gole /**
1463*936afd9fSDhruva Gole  * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the
1464*936afd9fSDhruva Gole  *                                 processor configuration flags
1465*936afd9fSDhruva Gole  *
1466*936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1467*936afd9fSDhruva Gole  * @cert_addr:	Memory address at which payload image certificate is located
1468*936afd9fSDhruva Gole  *
1469*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1470*936afd9fSDhruva Gole  */
1471*936afd9fSDhruva Gole int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr)
1472*936afd9fSDhruva Gole {
1473*936afd9fSDhruva Gole 	struct ti_sci_msg_req_proc_auth_boot_image req;
1474*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1475*936afd9fSDhruva Gole 
1476*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1477*936afd9fSDhruva Gole 	int ret;
1478*936afd9fSDhruva Gole 
1479*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMAGE, 0,
1480*936afd9fSDhruva Gole 				    &req, sizeof(req),
1481*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1482*936afd9fSDhruva Gole 				    &xfer);
1483*936afd9fSDhruva Gole 	if (ret) {
1484*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1485*936afd9fSDhruva Gole 		return ret;
1486*936afd9fSDhruva Gole 	}
1487*936afd9fSDhruva Gole 
1488*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1489*936afd9fSDhruva Gole 	req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
1490*936afd9fSDhruva Gole 	req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
1491*936afd9fSDhruva Gole 				TISCI_ADDR_HIGH_SHIFT;
1492*936afd9fSDhruva Gole 
1493*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1494*936afd9fSDhruva Gole 	if (ret) {
1495*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1496*936afd9fSDhruva Gole 		return ret;
1497*936afd9fSDhruva Gole 	}
1498*936afd9fSDhruva Gole 
1499*936afd9fSDhruva Gole 	return 0;
1500*936afd9fSDhruva Gole }
1501*936afd9fSDhruva Gole 
1502*936afd9fSDhruva Gole /**
1503*936afd9fSDhruva Gole  * ti_sci_proc_get_boot_status() - Get the processor boot status
1504*936afd9fSDhruva Gole  *
1505*936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1506*936afd9fSDhruva Gole  *
1507*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1508*936afd9fSDhruva Gole  */
1509*936afd9fSDhruva Gole int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv,
1510*936afd9fSDhruva Gole 				uint32_t *cfg_flags,
1511*936afd9fSDhruva Gole 				uint32_t *ctrl_flags,
1512*936afd9fSDhruva Gole 				uint32_t *sts_flags)
1513*936afd9fSDhruva Gole {
1514*936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_proc_boot_status req;
1515*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_proc_boot_status resp;
1516*936afd9fSDhruva Gole 
1517*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1518*936afd9fSDhruva Gole 	int ret;
1519*936afd9fSDhruva Gole 
1520*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS, 0,
1521*936afd9fSDhruva Gole 				    &req, sizeof(req),
1522*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1523*936afd9fSDhruva Gole 				    &xfer);
1524*936afd9fSDhruva Gole 	if (ret) {
1525*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1526*936afd9fSDhruva Gole 		return ret;
1527*936afd9fSDhruva Gole 	}
1528*936afd9fSDhruva Gole 
1529*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1530*936afd9fSDhruva Gole 
1531*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1532*936afd9fSDhruva Gole 	if (ret) {
1533*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1534*936afd9fSDhruva Gole 		return ret;
1535*936afd9fSDhruva Gole 	}
1536*936afd9fSDhruva Gole 
1537*936afd9fSDhruva Gole 	*bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) |
1538*936afd9fSDhruva Gole 	      (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) &
1539*936afd9fSDhruva Gole 	       TISCI_ADDR_HIGH_MASK);
1540*936afd9fSDhruva Gole 	*cfg_flags = resp.config_flags;
1541*936afd9fSDhruva Gole 	*ctrl_flags = resp.control_flags;
1542*936afd9fSDhruva Gole 	*sts_flags = resp.status_flags;
1543*936afd9fSDhruva Gole 
1544*936afd9fSDhruva Gole 	return 0;
1545*936afd9fSDhruva Gole }
1546*936afd9fSDhruva Gole 
1547*936afd9fSDhruva Gole /**
1548*936afd9fSDhruva Gole  * ti_sci_proc_wait_boot_status() - Wait for a processor boot status
1549*936afd9fSDhruva Gole  *
1550*936afd9fSDhruva Gole  * @proc_id:			Processor ID this request is for
1551*936afd9fSDhruva Gole  * @num_wait_iterations		Total number of iterations we will check before
1552*936afd9fSDhruva Gole  *				we will timeout and give up
1553*936afd9fSDhruva Gole  * @num_match_iterations	How many iterations should we have continued
1554*936afd9fSDhruva Gole  *				status to account for status bits glitching.
1555*936afd9fSDhruva Gole  *				This is to make sure that match occurs for
1556*936afd9fSDhruva Gole  *				consecutive checks. This implies that the
1557*936afd9fSDhruva Gole  *				worst case should consider that the stable
1558*936afd9fSDhruva Gole  *				time should at the worst be num_wait_iterations
1559*936afd9fSDhruva Gole  *				num_match_iterations to prevent timeout.
1560*936afd9fSDhruva Gole  * @delay_per_iteration_us	Specifies how long to wait (in micro seconds)
1561*936afd9fSDhruva Gole  *				between each status checks. This is the minimum
1562*936afd9fSDhruva Gole  *				duration, and overhead of register reads and
1563*936afd9fSDhruva Gole  *				checks are on top of this and can vary based on
1564*936afd9fSDhruva Gole  *				varied conditions.
1565*936afd9fSDhruva Gole  * @delay_before_iterations_us	Specifies how long to wait (in micro seconds)
1566*936afd9fSDhruva Gole  *				before the very first check in the first
1567*936afd9fSDhruva Gole  *				iteration of status check loop. This is the
1568*936afd9fSDhruva Gole  *				minimum duration, and overhead of register
1569*936afd9fSDhruva Gole  *				reads and checks are.
1570*936afd9fSDhruva Gole  * @status_flags_1_set_all_wait	If non-zero, Specifies that all bits of the
1571*936afd9fSDhruva Gole  *				status matching this field requested MUST be 1.
1572*936afd9fSDhruva Gole  * @status_flags_1_set_any_wait	If non-zero, Specifies that at least one of the
1573*936afd9fSDhruva Gole  *				bits matching this field requested MUST be 1.
1574*936afd9fSDhruva Gole  * @status_flags_1_clr_all_wait	If non-zero, Specifies that all bits of the
1575*936afd9fSDhruva Gole  *				status matching this field requested MUST be 0.
1576*936afd9fSDhruva Gole  * @status_flags_1_clr_any_wait	If non-zero, Specifies that at least one of the
1577*936afd9fSDhruva Gole  *				bits matching this field requested MUST be 0.
1578*936afd9fSDhruva Gole  *
1579*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1580*936afd9fSDhruva Gole  */
1581*936afd9fSDhruva Gole int ti_sci_proc_wait_boot_status(uint8_t proc_id, uint8_t num_wait_iterations,
1582*936afd9fSDhruva Gole 				 uint8_t num_match_iterations,
1583*936afd9fSDhruva Gole 				 uint8_t delay_per_iteration_us,
1584*936afd9fSDhruva Gole 				 uint8_t delay_before_iterations_us,
1585*936afd9fSDhruva Gole 				 uint32_t status_flags_1_set_all_wait,
1586*936afd9fSDhruva Gole 				 uint32_t status_flags_1_set_any_wait,
1587*936afd9fSDhruva Gole 				 uint32_t status_flags_1_clr_all_wait,
1588*936afd9fSDhruva Gole 				 uint32_t status_flags_1_clr_any_wait)
1589*936afd9fSDhruva Gole {
1590*936afd9fSDhruva Gole 	struct ti_sci_msg_req_wait_proc_boot_status req;
1591*936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1592*936afd9fSDhruva Gole 
1593*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1594*936afd9fSDhruva Gole 	int ret;
1595*936afd9fSDhruva Gole 
1596*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0,
1597*936afd9fSDhruva Gole 				    &req, sizeof(req),
1598*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1599*936afd9fSDhruva Gole 				    &xfer);
1600*936afd9fSDhruva Gole 	if (ret) {
1601*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1602*936afd9fSDhruva Gole 		return ret;
1603*936afd9fSDhruva Gole 	}
1604*936afd9fSDhruva Gole 
1605*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1606*936afd9fSDhruva Gole 	req.num_wait_iterations = num_wait_iterations;
1607*936afd9fSDhruva Gole 	req.num_match_iterations = num_match_iterations;
1608*936afd9fSDhruva Gole 	req.delay_per_iteration_us = delay_per_iteration_us;
1609*936afd9fSDhruva Gole 	req.delay_before_iterations_us = delay_before_iterations_us;
1610*936afd9fSDhruva Gole 	req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
1611*936afd9fSDhruva Gole 	req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
1612*936afd9fSDhruva Gole 	req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
1613*936afd9fSDhruva Gole 	req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
1614*936afd9fSDhruva Gole 
1615*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1616*936afd9fSDhruva Gole 	if (ret) {
1617*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1618*936afd9fSDhruva Gole 		return ret;
1619*936afd9fSDhruva Gole 	}
1620*936afd9fSDhruva Gole 
1621*936afd9fSDhruva Gole 	return 0;
1622*936afd9fSDhruva Gole }
1623*936afd9fSDhruva Gole 
1624*936afd9fSDhruva Gole /**
1625*936afd9fSDhruva Gole  * ti_sci_proc_wait_boot_status_no_wait() - Wait for a processor boot status
1626*936afd9fSDhruva Gole  *					    without requesting or waiting for
1627*936afd9fSDhruva Gole  *					    a response.
1628*936afd9fSDhruva Gole  *
1629*936afd9fSDhruva Gole  * @proc_id:			Processor ID this request is for
1630*936afd9fSDhruva Gole  * @num_wait_iterations		Total number of iterations we will check before
1631*936afd9fSDhruva Gole  *				we will timeout and give up
1632*936afd9fSDhruva Gole  * @num_match_iterations	How many iterations should we have continued
1633*936afd9fSDhruva Gole  *				status to account for status bits glitching.
1634*936afd9fSDhruva Gole  *				This is to make sure that match occurs for
1635*936afd9fSDhruva Gole  *				consecutive checks. This implies that the
1636*936afd9fSDhruva Gole  *				worst case should consider that the stable
1637*936afd9fSDhruva Gole  *				time should at the worst be num_wait_iterations
1638*936afd9fSDhruva Gole  *				num_match_iterations to prevent timeout.
1639*936afd9fSDhruva Gole  * @delay_per_iteration_us	Specifies how long to wait (in micro seconds)
1640*936afd9fSDhruva Gole  *				between each status checks. This is the minimum
1641*936afd9fSDhruva Gole  *				duration, and overhead of register reads and
1642*936afd9fSDhruva Gole  *				checks are on top of this and can vary based on
1643*936afd9fSDhruva Gole  *				varied conditions.
1644*936afd9fSDhruva Gole  * @delay_before_iterations_us	Specifies how long to wait (in micro seconds)
1645*936afd9fSDhruva Gole  *				before the very first check in the first
1646*936afd9fSDhruva Gole  *				iteration of status check loop. This is the
1647*936afd9fSDhruva Gole  *				minimum duration, and overhead of register
1648*936afd9fSDhruva Gole  *				reads and checks are.
1649*936afd9fSDhruva Gole  * @status_flags_1_set_all_wait	If non-zero, Specifies that all bits of the
1650*936afd9fSDhruva Gole  *				status matching this field requested MUST be 1.
1651*936afd9fSDhruva Gole  * @status_flags_1_set_any_wait	If non-zero, Specifies that at least one of the
1652*936afd9fSDhruva Gole  *				bits matching this field requested MUST be 1.
1653*936afd9fSDhruva Gole  * @status_flags_1_clr_all_wait	If non-zero, Specifies that all bits of the
1654*936afd9fSDhruva Gole  *				status matching this field requested MUST be 0.
1655*936afd9fSDhruva Gole  * @status_flags_1_clr_any_wait	If non-zero, Specifies that at least one of the
1656*936afd9fSDhruva Gole  *				bits matching this field requested MUST be 0.
1657*936afd9fSDhruva Gole  *
1658*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1659*936afd9fSDhruva Gole  */
1660*936afd9fSDhruva Gole int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id,
1661*936afd9fSDhruva Gole 					 uint8_t num_wait_iterations,
1662*936afd9fSDhruva Gole 					 uint8_t num_match_iterations,
1663*936afd9fSDhruva Gole 					 uint8_t delay_per_iteration_us,
1664*936afd9fSDhruva Gole 					 uint8_t delay_before_iterations_us,
1665*936afd9fSDhruva Gole 					 uint32_t status_flags_1_set_all_wait,
1666*936afd9fSDhruva Gole 					 uint32_t status_flags_1_set_any_wait,
1667*936afd9fSDhruva Gole 					 uint32_t status_flags_1_clr_all_wait,
1668*936afd9fSDhruva Gole 					 uint32_t status_flags_1_clr_any_wait)
1669*936afd9fSDhruva Gole {
1670*936afd9fSDhruva Gole 	struct ti_sci_msg_req_wait_proc_boot_status req;
1671*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1672*936afd9fSDhruva Gole 	int ret;
1673*936afd9fSDhruva Gole 
1674*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0,
1675*936afd9fSDhruva Gole 				    &req, sizeof(req),
1676*936afd9fSDhruva Gole 				    NULL, 0,
1677*936afd9fSDhruva Gole 				    &xfer);
1678*936afd9fSDhruva Gole 	if (ret != 0U) {
1679*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1680*936afd9fSDhruva Gole 		return ret;
1681*936afd9fSDhruva Gole 	}
1682*936afd9fSDhruva Gole 
1683*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1684*936afd9fSDhruva Gole 	req.num_wait_iterations = num_wait_iterations;
1685*936afd9fSDhruva Gole 	req.num_match_iterations = num_match_iterations;
1686*936afd9fSDhruva Gole 	req.delay_per_iteration_us = delay_per_iteration_us;
1687*936afd9fSDhruva Gole 	req.delay_before_iterations_us = delay_before_iterations_us;
1688*936afd9fSDhruva Gole 	req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
1689*936afd9fSDhruva Gole 	req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
1690*936afd9fSDhruva Gole 	req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
1691*936afd9fSDhruva Gole 	req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
1692*936afd9fSDhruva Gole 
1693*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1694*936afd9fSDhruva Gole 	if (ret != 0U) {
1695*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1696*936afd9fSDhruva Gole 		return ret;
1697*936afd9fSDhruva Gole 	}
1698*936afd9fSDhruva Gole 
1699*936afd9fSDhruva Gole 	return 0;
1700*936afd9fSDhruva Gole }
1701*936afd9fSDhruva Gole 
1702*936afd9fSDhruva Gole /**
1703*936afd9fSDhruva Gole  * ti_sci_enter_sleep - Command to initiate system transition into suspend.
1704*936afd9fSDhruva Gole  *
1705*936afd9fSDhruva Gole  * @proc_id: Processor ID.
1706*936afd9fSDhruva Gole  * @mode: Low power mode to enter.
1707*936afd9fSDhruva Gole  * @core_resume_addr: Address that core should be
1708*936afd9fSDhruva Gole  *		      resumed from after low power transition.
1709*936afd9fSDhruva Gole  *
1710*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1711*936afd9fSDhruva Gole  */
1712*936afd9fSDhruva Gole int ti_sci_enter_sleep(uint8_t proc_id,
1713*936afd9fSDhruva Gole 		       uint8_t mode,
1714*936afd9fSDhruva Gole 		       uint64_t core_resume_addr)
1715*936afd9fSDhruva Gole {
1716*936afd9fSDhruva Gole 	struct ti_sci_msg_req_enter_sleep req;
1717*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1718*936afd9fSDhruva Gole 	int ret;
1719*936afd9fSDhruva Gole 
1720*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_ENTER_SLEEP, 0,
1721*936afd9fSDhruva Gole 				    &req, sizeof(req),
1722*936afd9fSDhruva Gole 				    NULL, 0,
1723*936afd9fSDhruva Gole 				    &xfer);
1724*936afd9fSDhruva Gole 	if (ret != 0U) {
1725*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1726*936afd9fSDhruva Gole 		return ret;
1727*936afd9fSDhruva Gole 	}
1728*936afd9fSDhruva Gole 
1729*936afd9fSDhruva Gole 	req.processor_id = proc_id;
1730*936afd9fSDhruva Gole 	req.mode = mode;
1731*936afd9fSDhruva Gole 	req.core_resume_lo = core_resume_addr & TISCI_ADDR_LOW_MASK;
1732*936afd9fSDhruva Gole 	req.core_resume_hi = (core_resume_addr & TISCI_ADDR_HIGH_MASK) >>
1733*936afd9fSDhruva Gole 			     TISCI_ADDR_HIGH_SHIFT;
1734*936afd9fSDhruva Gole 
1735*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1736*936afd9fSDhruva Gole 	if (ret != 0U) {
1737*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1738*936afd9fSDhruva Gole 		return ret;
1739*936afd9fSDhruva Gole 	}
1740*936afd9fSDhruva Gole 
1741*936afd9fSDhruva Gole 	return 0;
1742*936afd9fSDhruva Gole }
1743*936afd9fSDhruva Gole 
1744*936afd9fSDhruva Gole /**
1745*936afd9fSDhruva Gole  * ti_sci_lpm_get_next_sys_mode() - Get next LPM system mode
1746*936afd9fSDhruva Gole  *
1747*936afd9fSDhruva Gole  * @next_mode:	pointer to a variable that will store the next mode
1748*936afd9fSDhruva Gole  *
1749*936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1750*936afd9fSDhruva Gole  */
1751*936afd9fSDhruva Gole int ti_sci_lpm_get_next_sys_mode(uint8_t *next_mode)
1752*936afd9fSDhruva Gole {
1753*936afd9fSDhruva Gole 	struct ti_sci_msg_req_lpm_get_next_sys_mode req;
1754*936afd9fSDhruva Gole 	struct ti_sci_msg_resp_lpm_get_next_sys_mode resp;
1755*936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1756*936afd9fSDhruva Gole 	int ret;
1757*936afd9fSDhruva Gole 
1758*936afd9fSDhruva Gole 	if (next_mode == NULL) {
1759*936afd9fSDhruva Gole 		return -EINVAL;
1760*936afd9fSDhruva Gole 	}
1761*936afd9fSDhruva Gole 
1762*936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_LPM_GET_NEXT_SYS_MODE, 0,
1763*936afd9fSDhruva Gole 				    &req, sizeof(req),
1764*936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1765*936afd9fSDhruva Gole 				    &xfer);
1766*936afd9fSDhruva Gole 	if (ret != 0) {
1767*936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1768*936afd9fSDhruva Gole 		return ret;
1769*936afd9fSDhruva Gole 	}
1770*936afd9fSDhruva Gole 
1771*936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1772*936afd9fSDhruva Gole 	if (ret != 0) {
1773*936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1774*936afd9fSDhruva Gole 		return ret;
1775*936afd9fSDhruva Gole 	}
1776*936afd9fSDhruva Gole 
1777*936afd9fSDhruva Gole 	*next_mode = resp.mode;
1778*936afd9fSDhruva Gole 
1779*936afd9fSDhruva Gole 	return 0;
1780*936afd9fSDhruva Gole }
1781