xref: /rk3399_ARM-atf/drivers/ti/ti_sci/ti_sci.c (revision 7bff7bf968f9f27d95f0622116aa8e9485577039)
1936afd9fSDhruva Gole /*
2936afd9fSDhruva Gole  * Texas Instruments System Control Interface Driver
3936afd9fSDhruva Gole  *   Based on Linux and U-Boot implementation
4936afd9fSDhruva Gole  *
5*7bff7bf9SDhruva Gole  * Copyright (C) 2018-2025 Texas Instruments Incorporated - https://www.ti.com/
6936afd9fSDhruva Gole  *
7936afd9fSDhruva Gole  * SPDX-License-Identifier: BSD-3-Clause
8936afd9fSDhruva Gole  */
9936afd9fSDhruva Gole 
10936afd9fSDhruva Gole #include <errno.h>
11936afd9fSDhruva Gole #include <stdbool.h>
12936afd9fSDhruva Gole #include <stddef.h>
13936afd9fSDhruva Gole #include <string.h>
14936afd9fSDhruva Gole 
15936afd9fSDhruva Gole #include <platform_def.h>
16936afd9fSDhruva Gole #include <lib/bakery_lock.h>
17936afd9fSDhruva Gole 
18936afd9fSDhruva Gole #include <common/debug.h>
19f70572eeSDhruva Gole #include <ti_sci_transport.h>
20936afd9fSDhruva Gole 
21936afd9fSDhruva Gole #include "ti_sci_protocol.h"
22936afd9fSDhruva Gole #include "ti_sci.h"
23936afd9fSDhruva Gole 
24936afd9fSDhruva Gole #if USE_COHERENT_MEM
25936afd9fSDhruva Gole __section(".tzfw_coherent_mem")
26936afd9fSDhruva Gole #endif
27936afd9fSDhruva Gole static uint8_t message_sequence;
28936afd9fSDhruva Gole 
29936afd9fSDhruva Gole DEFINE_BAKERY_LOCK(ti_sci_xfer_lock);
30936afd9fSDhruva Gole 
31936afd9fSDhruva Gole /**
32936afd9fSDhruva Gole  * struct ti_sci_xfer - Structure representing a message flow
33936afd9fSDhruva Gole  * @tx_message:	Transmit message
34936afd9fSDhruva Gole  * @rx_message:	Receive message
35936afd9fSDhruva Gole  */
36936afd9fSDhruva Gole struct ti_sci_xfer {
37*7bff7bf9SDhruva Gole 	struct ti_sci_msg tx_message;
38*7bff7bf9SDhruva Gole 	struct ti_sci_msg rx_message;
39936afd9fSDhruva Gole };
40936afd9fSDhruva Gole 
41936afd9fSDhruva Gole /**
42936afd9fSDhruva Gole  * ti_sci_setup_one_xfer() - Setup one message type
43936afd9fSDhruva Gole  *
44936afd9fSDhruva Gole  * @msg_type:	Message type
45936afd9fSDhruva Gole  * @msg_flags:	Flag to set for the message
46936afd9fSDhruva Gole  * @tx_buf:	Buffer to be sent to mailbox channel
47936afd9fSDhruva Gole  * @tx_message_size: transmit message size
48936afd9fSDhruva Gole  * @rx_buf:	Buffer to be received from mailbox channel
49936afd9fSDhruva Gole  * @rx_message_size: receive message size
50936afd9fSDhruva Gole  *
51936afd9fSDhruva Gole  * Helper function which is used by various command functions that are
52936afd9fSDhruva Gole  * exposed to clients of this driver for allocating a message traffic event.
53936afd9fSDhruva Gole  *
54936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
55936afd9fSDhruva Gole  */
56936afd9fSDhruva Gole static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags,
57936afd9fSDhruva Gole 				 void *tx_buf,
58936afd9fSDhruva Gole 				 size_t tx_message_size,
59936afd9fSDhruva Gole 				 void *rx_buf,
60936afd9fSDhruva Gole 				 size_t rx_message_size,
61936afd9fSDhruva Gole 				 struct ti_sci_xfer *xfer)
62936afd9fSDhruva Gole {
63936afd9fSDhruva Gole 	struct ti_sci_msg_hdr *hdr;
64936afd9fSDhruva Gole 
65936afd9fSDhruva Gole 	/* Ensure we have sane transfer sizes */
66936afd9fSDhruva Gole 	if (rx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
67936afd9fSDhruva Gole 	    tx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
68936afd9fSDhruva Gole 	    tx_message_size < sizeof(*hdr))
69936afd9fSDhruva Gole 		return -ERANGE;
70936afd9fSDhruva Gole 
71936afd9fSDhruva Gole 	hdr = (struct ti_sci_msg_hdr *)tx_buf;
72936afd9fSDhruva Gole 	hdr->seq = ++message_sequence;
73936afd9fSDhruva Gole 	hdr->type = msg_type;
74936afd9fSDhruva Gole 	hdr->host = TI_SCI_HOST_ID;
75936afd9fSDhruva Gole 	hdr->flags = msg_flags;
76936afd9fSDhruva Gole 	/* Request a response if rx_message_size is non-zero */
77936afd9fSDhruva Gole 	if (rx_message_size != 0U) {
78936afd9fSDhruva Gole 		hdr->flags |= TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;
79936afd9fSDhruva Gole 	}
80936afd9fSDhruva Gole 
81936afd9fSDhruva Gole 	xfer->tx_message.buf = tx_buf;
82936afd9fSDhruva Gole 	xfer->tx_message.len = tx_message_size;
83936afd9fSDhruva Gole 
84936afd9fSDhruva Gole 	xfer->rx_message.buf = rx_buf;
85936afd9fSDhruva Gole 	xfer->rx_message.len = rx_message_size;
86936afd9fSDhruva Gole 
87936afd9fSDhruva Gole 	return 0;
88936afd9fSDhruva Gole }
89936afd9fSDhruva Gole 
90936afd9fSDhruva Gole /**
91936afd9fSDhruva Gole  * ti_sci_get_response() - Receive response from mailbox channel
92936afd9fSDhruva Gole  *
93936afd9fSDhruva Gole  * @xfer:	Transfer to initiate and wait for response
94936afd9fSDhruva Gole  * @chan:	Channel to receive the response
95936afd9fSDhruva Gole  *
96936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
97936afd9fSDhruva Gole  */
98*7bff7bf9SDhruva Gole static int ti_sci_get_response(struct ti_sci_msg *msg,
99936afd9fSDhruva Gole 			       enum k3_sec_proxy_chan_id chan)
100936afd9fSDhruva Gole {
101936afd9fSDhruva Gole 	struct ti_sci_msg_hdr *hdr;
102936afd9fSDhruva Gole 	unsigned int retry = 5;
103936afd9fSDhruva Gole 	int ret;
104936afd9fSDhruva Gole 
105936afd9fSDhruva Gole 	for (; retry > 0; retry--) {
106936afd9fSDhruva Gole 		/* Receive the response */
107*7bff7bf9SDhruva Gole 		ret = ti_sci_transport_recv(chan, msg);
108936afd9fSDhruva Gole 		if (ret) {
109936afd9fSDhruva Gole 			ERROR("Message receive failed (%d)\n", ret);
110936afd9fSDhruva Gole 			return ret;
111936afd9fSDhruva Gole 		}
112936afd9fSDhruva Gole 
113936afd9fSDhruva Gole 		/* msg is updated by Secure Proxy driver */
114936afd9fSDhruva Gole 		hdr = (struct ti_sci_msg_hdr *)msg->buf;
115936afd9fSDhruva Gole 
116936afd9fSDhruva Gole 		/* Sanity check for message response */
117936afd9fSDhruva Gole 		if (hdr->seq == message_sequence)
118936afd9fSDhruva Gole 			break;
119936afd9fSDhruva Gole 		else
120936afd9fSDhruva Gole 			WARN("Message with sequence ID %u is not expected\n", hdr->seq);
121936afd9fSDhruva Gole 	}
122936afd9fSDhruva Gole 	if (!retry) {
123936afd9fSDhruva Gole 		ERROR("Timed out waiting for message\n");
124936afd9fSDhruva Gole 		return -EINVAL;
125936afd9fSDhruva Gole 	}
126936afd9fSDhruva Gole 
127936afd9fSDhruva Gole 	if (msg->len > TI_SCI_MAX_MESSAGE_SIZE) {
128936afd9fSDhruva Gole 		ERROR("Unable to handle %lu xfer (max %d)\n",
129936afd9fSDhruva Gole 		      msg->len, TI_SCI_MAX_MESSAGE_SIZE);
130936afd9fSDhruva Gole 		return -EINVAL;
131936afd9fSDhruva Gole 	}
132936afd9fSDhruva Gole 
133936afd9fSDhruva Gole 	if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK))
134936afd9fSDhruva Gole 		return -ENODEV;
135936afd9fSDhruva Gole 
136936afd9fSDhruva Gole 	return 0;
137936afd9fSDhruva Gole }
138936afd9fSDhruva Gole 
139936afd9fSDhruva Gole /**
140936afd9fSDhruva Gole  * ti_sci_do_xfer() - Do one transfer
141936afd9fSDhruva Gole  *
142936afd9fSDhruva Gole  * @xfer:	Transfer to initiate and wait for response
143936afd9fSDhruva Gole  *
144936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
145936afd9fSDhruva Gole  */
146936afd9fSDhruva Gole static int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
147936afd9fSDhruva Gole {
148*7bff7bf9SDhruva Gole 	struct ti_sci_msg *tx_msg = &xfer->tx_message;
149*7bff7bf9SDhruva Gole 	struct ti_sci_msg *rx_msg = &xfer->rx_message;
150936afd9fSDhruva Gole 	int ret;
151936afd9fSDhruva Gole 
152936afd9fSDhruva Gole 	bakery_lock_get(&ti_sci_xfer_lock);
153936afd9fSDhruva Gole 
154936afd9fSDhruva Gole 	/* Clear any spurious messages in receive queue */
155*7bff7bf9SDhruva Gole 	ret = ti_sci_transport_clear_rx_thread(SP_RESPONSE);
156936afd9fSDhruva Gole 	if (ret) {
157936afd9fSDhruva Gole 		ERROR("Could not clear response queue (%d)\n", ret);
158936afd9fSDhruva Gole 		goto unlock;
159936afd9fSDhruva Gole 	}
160936afd9fSDhruva Gole 
161936afd9fSDhruva Gole 	/* Send the message */
162*7bff7bf9SDhruva Gole 	ret = ti_sci_transport_send(SP_HIGH_PRIORITY, tx_msg);
163936afd9fSDhruva Gole 	if (ret) {
164936afd9fSDhruva Gole 		ERROR("Message sending failed (%d)\n", ret);
165936afd9fSDhruva Gole 		goto unlock;
166936afd9fSDhruva Gole 	}
167936afd9fSDhruva Gole 
168936afd9fSDhruva Gole 	/* Get the response if requested */
169936afd9fSDhruva Gole 	if (rx_msg->len != 0U) {
170936afd9fSDhruva Gole 		ret = ti_sci_get_response(rx_msg, SP_RESPONSE);
171936afd9fSDhruva Gole 		if (ret != 0U) {
172936afd9fSDhruva Gole 			ERROR("Failed to get response (%d)\n", ret);
173936afd9fSDhruva Gole 			goto unlock;
174936afd9fSDhruva Gole 		}
175936afd9fSDhruva Gole 	}
176936afd9fSDhruva Gole 
177936afd9fSDhruva Gole unlock:
178936afd9fSDhruva Gole 	bakery_lock_release(&ti_sci_xfer_lock);
179936afd9fSDhruva Gole 
180936afd9fSDhruva Gole 	return ret;
181936afd9fSDhruva Gole }
182936afd9fSDhruva Gole 
183936afd9fSDhruva Gole /**
184936afd9fSDhruva Gole  * ti_sci_get_revision() - Get the revision of the SCI entity
185936afd9fSDhruva Gole  *
186936afd9fSDhruva Gole  * Updates the SCI information in the internal data structure.
187936afd9fSDhruva Gole  *
188936afd9fSDhruva Gole  * @version: Structure containing the version info
189936afd9fSDhruva Gole  *
190936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
191936afd9fSDhruva Gole  */
192936afd9fSDhruva Gole int ti_sci_get_revision(struct ti_sci_msg_version *version)
193936afd9fSDhruva Gole {
194936afd9fSDhruva Gole 	struct ti_sci_msg_resp_version rev_info;
195936afd9fSDhruva Gole 	struct ti_sci_msg_hdr hdr;
196936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
197936afd9fSDhruva Gole 	int ret;
198936afd9fSDhruva Gole 
199936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_VERSION, 0x0,
200936afd9fSDhruva Gole 				    &hdr, sizeof(hdr),
201936afd9fSDhruva Gole 				    &rev_info, sizeof(rev_info),
202936afd9fSDhruva Gole 				    &xfer);
203936afd9fSDhruva Gole 	if (ret) {
204936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
205936afd9fSDhruva Gole 		return ret;
206936afd9fSDhruva Gole 	}
207936afd9fSDhruva Gole 
208936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
209936afd9fSDhruva Gole 	if (ret) {
210936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
211936afd9fSDhruva Gole 		return ret;
212936afd9fSDhruva Gole 	}
213936afd9fSDhruva Gole 
214936afd9fSDhruva Gole 	memcpy(version->firmware_description, rev_info.firmware_description,
215936afd9fSDhruva Gole 		sizeof(rev_info.firmware_description));
216936afd9fSDhruva Gole 	version->abi_major = rev_info.abi_major;
217936afd9fSDhruva Gole 	version->abi_minor = rev_info.abi_minor;
218936afd9fSDhruva Gole 	version->firmware_revision = rev_info.firmware_revision;
219936afd9fSDhruva Gole 	version->sub_version = rev_info.sub_version;
220936afd9fSDhruva Gole 	version->patch_version = rev_info.patch_version;
221936afd9fSDhruva Gole 
222936afd9fSDhruva Gole 	return 0;
223936afd9fSDhruva Gole }
224936afd9fSDhruva Gole 
225936afd9fSDhruva Gole /**
226936afd9fSDhruva Gole  * ti_sci_query_fw_caps() - Get the FW/SoC capabilities
227936afd9fSDhruva Gole  * @handle:		Pointer to TI SCI handle
228936afd9fSDhruva Gole  * @fw_caps:		Each bit in fw_caps indicating one FW/SOC capability
229936afd9fSDhruva Gole  *
230936afd9fSDhruva Gole  * Return: 0 if all went well, else returns appropriate error value.
231936afd9fSDhruva Gole  */
232936afd9fSDhruva Gole int ti_sci_query_fw_caps(uint64_t *fw_caps)
233936afd9fSDhruva Gole {
234936afd9fSDhruva Gole 	struct ti_sci_msg_hdr req;
235936afd9fSDhruva Gole 	struct ti_sci_msg_resp_query_fw_caps resp;
236936afd9fSDhruva Gole 
237936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
238936afd9fSDhruva Gole 	int ret;
239936afd9fSDhruva Gole 
240936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_FW_CAPS, 0,
241936afd9fSDhruva Gole 				    &req, sizeof(req),
242936afd9fSDhruva Gole 				    &resp, sizeof(resp),
243936afd9fSDhruva Gole 				    &xfer);
244936afd9fSDhruva Gole 	if (ret != 0U) {
245936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
246936afd9fSDhruva Gole 		return ret;
247936afd9fSDhruva Gole 	}
248936afd9fSDhruva Gole 
249936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
250936afd9fSDhruva Gole 	if (ret != 0U) {
251936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
252936afd9fSDhruva Gole 		return ret;
253936afd9fSDhruva Gole 	}
254936afd9fSDhruva Gole 
255936afd9fSDhruva Gole 	if (fw_caps)
256936afd9fSDhruva Gole 		*fw_caps = resp.fw_caps;
257936afd9fSDhruva Gole 
258936afd9fSDhruva Gole 	return 0;
259936afd9fSDhruva Gole }
260936afd9fSDhruva Gole 
261936afd9fSDhruva Gole /**
262936afd9fSDhruva Gole  * ti_sci_device_set_state() - Set device state
263936afd9fSDhruva Gole  *
264936afd9fSDhruva Gole  * @id:		Device identifier
265936afd9fSDhruva Gole  * @flags:	flags to setup for the device
266936afd9fSDhruva Gole  * @state:	State to move the device to
267936afd9fSDhruva Gole  *
268936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
269936afd9fSDhruva Gole  */
270936afd9fSDhruva Gole static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state)
271936afd9fSDhruva Gole {
272936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_device_state req;
273936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
274936afd9fSDhruva Gole 
275936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
276936afd9fSDhruva Gole 	int ret;
277936afd9fSDhruva Gole 
278936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags,
279936afd9fSDhruva Gole 				    &req, sizeof(req),
280936afd9fSDhruva Gole 				    &resp, sizeof(resp),
281936afd9fSDhruva Gole 				    &xfer);
282936afd9fSDhruva Gole 	if (ret) {
283936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
284936afd9fSDhruva Gole 		return ret;
285936afd9fSDhruva Gole 	}
286936afd9fSDhruva Gole 
287936afd9fSDhruva Gole 	req.id = id;
288936afd9fSDhruva Gole 	req.state = state;
289936afd9fSDhruva Gole 
290936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
291936afd9fSDhruva Gole 	if (ret) {
292936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
293936afd9fSDhruva Gole 		return ret;
294936afd9fSDhruva Gole 	}
295936afd9fSDhruva Gole 
296936afd9fSDhruva Gole 	return 0;
297936afd9fSDhruva Gole }
298936afd9fSDhruva Gole 
299936afd9fSDhruva Gole /**
300936afd9fSDhruva Gole  * ti_sci_device_get_state() - Get device state
301936afd9fSDhruva Gole  *
302936afd9fSDhruva Gole  * @id:		Device Identifier
303936afd9fSDhruva Gole  * @clcnt:	Pointer to Context Loss Count
304936afd9fSDhruva Gole  * @resets:	pointer to resets
305936afd9fSDhruva Gole  * @p_state:	pointer to p_state
306936afd9fSDhruva Gole  * @c_state:	pointer to c_state
307936afd9fSDhruva Gole  *
308936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
309936afd9fSDhruva Gole  */
310936afd9fSDhruva Gole static int ti_sci_device_get_state(uint32_t id,  uint32_t *clcnt,
311936afd9fSDhruva Gole 				   uint32_t *resets, uint8_t *p_state,
312936afd9fSDhruva Gole 				   uint8_t *c_state)
313936afd9fSDhruva Gole {
314936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_device_state req;
315936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_device_state resp;
316936afd9fSDhruva Gole 
317936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
318936afd9fSDhruva Gole 	int ret;
319936afd9fSDhruva Gole 
320936afd9fSDhruva Gole 	if (!clcnt && !resets && !p_state && !c_state)
321936afd9fSDhruva Gole 		return -EINVAL;
322936afd9fSDhruva Gole 
323936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0,
324936afd9fSDhruva Gole 				    &req, sizeof(req),
325936afd9fSDhruva Gole 				    &resp, sizeof(resp),
326936afd9fSDhruva Gole 				    &xfer);
327936afd9fSDhruva Gole 	if (ret) {
328936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
329936afd9fSDhruva Gole 		return ret;
330936afd9fSDhruva Gole 	}
331936afd9fSDhruva Gole 
332936afd9fSDhruva Gole 	req.id = id;
333936afd9fSDhruva Gole 
334936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
335936afd9fSDhruva Gole 	if (ret) {
336936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
337936afd9fSDhruva Gole 		return ret;
338936afd9fSDhruva Gole 	}
339936afd9fSDhruva Gole 
340936afd9fSDhruva Gole 	if (clcnt)
341936afd9fSDhruva Gole 		*clcnt = resp.context_loss_count;
342936afd9fSDhruva Gole 	if (resets)
343936afd9fSDhruva Gole 		*resets = resp.resets;
344936afd9fSDhruva Gole 	if (p_state)
345936afd9fSDhruva Gole 		*p_state = resp.programmed_state;
346936afd9fSDhruva Gole 	if (c_state)
347936afd9fSDhruva Gole 		*c_state = resp.current_state;
348936afd9fSDhruva Gole 
349936afd9fSDhruva Gole 	return 0;
350936afd9fSDhruva Gole }
351936afd9fSDhruva Gole 
352936afd9fSDhruva Gole /**
353936afd9fSDhruva Gole  * ti_sci_device_get() - Request for device managed by TISCI
354936afd9fSDhruva Gole  *
355936afd9fSDhruva Gole  * @id:		Device Identifier
356936afd9fSDhruva Gole  *
357936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
358936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
359936afd9fSDhruva Gole  * managed by driver for that purpose.
360936afd9fSDhruva Gole  *
361936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
362936afd9fSDhruva Gole  */
363936afd9fSDhruva Gole int ti_sci_device_get(uint32_t id)
364936afd9fSDhruva Gole {
365936afd9fSDhruva Gole 	return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON);
366936afd9fSDhruva Gole }
367936afd9fSDhruva Gole 
368936afd9fSDhruva Gole /**
369936afd9fSDhruva Gole  * ti_sci_device_get_exclusive() - Exclusive request for device managed by TISCI
370936afd9fSDhruva Gole  *
371936afd9fSDhruva Gole  * @id:		Device Identifier
372936afd9fSDhruva Gole  *
373936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
374936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
375936afd9fSDhruva Gole  * managed by driver for that purpose.
376936afd9fSDhruva Gole  *
377936afd9fSDhruva Gole  * NOTE: This _exclusive version of the get API is for exclusive access to the
378936afd9fSDhruva Gole  * device. Any other host in the system will fail to get this device after this
379936afd9fSDhruva Gole  * call until exclusive access is released with device_put or a non-exclusive
380936afd9fSDhruva Gole  * set call.
381936afd9fSDhruva Gole  *
382936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
383936afd9fSDhruva Gole  */
384936afd9fSDhruva Gole int ti_sci_device_get_exclusive(uint32_t id)
385936afd9fSDhruva Gole {
386936afd9fSDhruva Gole 	return ti_sci_device_set_state(id,
387936afd9fSDhruva Gole 				       MSG_FLAG_DEVICE_EXCLUSIVE,
388936afd9fSDhruva Gole 				       MSG_DEVICE_SW_STATE_ON);
389936afd9fSDhruva Gole }
390936afd9fSDhruva Gole 
391936afd9fSDhruva Gole /**
392936afd9fSDhruva Gole  * ti_sci_device_idle() - Idle a device managed by TISCI
393936afd9fSDhruva Gole  *
394936afd9fSDhruva Gole  * @id:		Device Identifier
395936afd9fSDhruva Gole  *
396936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
397936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
398936afd9fSDhruva Gole  * managed by driver for that purpose.
399936afd9fSDhruva Gole  *
400936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
401936afd9fSDhruva Gole  */
402936afd9fSDhruva Gole int ti_sci_device_idle(uint32_t id)
403936afd9fSDhruva Gole {
404936afd9fSDhruva Gole 	return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_RETENTION);
405936afd9fSDhruva Gole }
406936afd9fSDhruva Gole 
407936afd9fSDhruva Gole /**
408936afd9fSDhruva Gole  * ti_sci_device_idle_exclusive() - Exclusive idle a device managed by TISCI
409936afd9fSDhruva Gole  *
410936afd9fSDhruva Gole  * @id:		Device Identifier
411936afd9fSDhruva Gole  *
412936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
413936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
414936afd9fSDhruva Gole  * managed by driver for that purpose.
415936afd9fSDhruva Gole  *
416936afd9fSDhruva Gole  * NOTE: This _exclusive version of the idle API is for exclusive access to
417936afd9fSDhruva Gole  * the device. Any other host in the system will fail to get this device after
418936afd9fSDhruva Gole  * this call until exclusive access is released with device_put or a
419936afd9fSDhruva Gole  * non-exclusive set call.
420936afd9fSDhruva Gole  *
421936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
422936afd9fSDhruva Gole  */
423936afd9fSDhruva Gole int ti_sci_device_idle_exclusive(uint32_t id)
424936afd9fSDhruva Gole {
425936afd9fSDhruva Gole 	return ti_sci_device_set_state(id,
426936afd9fSDhruva Gole 				       MSG_FLAG_DEVICE_EXCLUSIVE,
427936afd9fSDhruva Gole 				       MSG_DEVICE_SW_STATE_RETENTION);
428936afd9fSDhruva Gole }
429936afd9fSDhruva Gole 
430936afd9fSDhruva Gole /**
431936afd9fSDhruva Gole  * ti_sci_device_put() - Release a device managed by TISCI
432936afd9fSDhruva Gole  *
433936afd9fSDhruva Gole  * @id:		Device Identifier
434936afd9fSDhruva Gole  *
435936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
436936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
437936afd9fSDhruva Gole  * managed by driver for that purpose.
438936afd9fSDhruva Gole  *
439936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
440936afd9fSDhruva Gole  */
441936afd9fSDhruva Gole int ti_sci_device_put(uint32_t id)
442936afd9fSDhruva Gole {
443936afd9fSDhruva Gole 	return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF);
444936afd9fSDhruva Gole }
445936afd9fSDhruva Gole 
446936afd9fSDhruva Gole /**
447936afd9fSDhruva Gole  * ti_sci_device_put_no_wait() - Release a device without requesting or waiting
448936afd9fSDhruva Gole  *				 for a response.
449936afd9fSDhruva Gole  *
450936afd9fSDhruva Gole  * @id:		Device Identifier
451936afd9fSDhruva Gole  *
452936afd9fSDhruva Gole  * Request for the device - NOTE: the client MUST maintain integrity of
453936afd9fSDhruva Gole  * usage count by balancing get_device with put_device. No refcounting is
454936afd9fSDhruva Gole  * managed by driver for that purpose.
455936afd9fSDhruva Gole  *
456936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
457936afd9fSDhruva Gole  */
458936afd9fSDhruva Gole int ti_sci_device_put_no_wait(uint32_t id)
459936afd9fSDhruva Gole {
460936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_device_state req;
461936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
462936afd9fSDhruva Gole 	int ret;
463936afd9fSDhruva Gole 
464936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, 0,
465936afd9fSDhruva Gole 				    &req, sizeof(req),
466936afd9fSDhruva Gole 				    NULL, 0,
467936afd9fSDhruva Gole 				    &xfer);
468936afd9fSDhruva Gole 	if (ret != 0U) {
469936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
470936afd9fSDhruva Gole 		return ret;
471936afd9fSDhruva Gole 	}
472936afd9fSDhruva Gole 
473936afd9fSDhruva Gole 	req.id = id;
474936afd9fSDhruva Gole 	req.state = MSG_DEVICE_SW_STATE_AUTO_OFF;
475936afd9fSDhruva Gole 
476936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
477936afd9fSDhruva Gole 	if (ret != 0U) {
478936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
479936afd9fSDhruva Gole 		return ret;
480936afd9fSDhruva Gole 	}
481936afd9fSDhruva Gole 
482936afd9fSDhruva Gole 	return 0;
483936afd9fSDhruva Gole }
484936afd9fSDhruva Gole 
485936afd9fSDhruva Gole /**
486936afd9fSDhruva Gole  * ti_sci_device_is_valid() - Is the device valid
487936afd9fSDhruva Gole  *
488936afd9fSDhruva Gole  * @id:		Device Identifier
489936afd9fSDhruva Gole  *
490936afd9fSDhruva Gole  * Return: 0 if all goes well and the device ID is valid, else return
491936afd9fSDhruva Gole  *         appropriate error
492936afd9fSDhruva Gole  */
493936afd9fSDhruva Gole int ti_sci_device_is_valid(uint32_t id)
494936afd9fSDhruva Gole {
495936afd9fSDhruva Gole 	uint8_t unused;
496936afd9fSDhruva Gole 
497936afd9fSDhruva Gole 	/* check the device state which will also tell us if the ID is valid */
498936afd9fSDhruva Gole 	return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused);
499936afd9fSDhruva Gole }
500936afd9fSDhruva Gole 
501936afd9fSDhruva Gole /**
502936afd9fSDhruva Gole  * ti_sci_device_get_clcnt() - Get context loss counter
503936afd9fSDhruva Gole  *
504936afd9fSDhruva Gole  * @id:		Device Identifier
505936afd9fSDhruva Gole  * @count:	Pointer to Context Loss counter to populate
506936afd9fSDhruva Gole  *
507936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
508936afd9fSDhruva Gole  */
509936afd9fSDhruva Gole int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count)
510936afd9fSDhruva Gole {
511936afd9fSDhruva Gole 	return ti_sci_device_get_state(id, count, NULL, NULL, NULL);
512936afd9fSDhruva Gole }
513936afd9fSDhruva Gole 
514936afd9fSDhruva Gole /**
515936afd9fSDhruva Gole  * ti_sci_device_is_idle() - Check if the device is requested to be idle
516936afd9fSDhruva Gole  *
517936afd9fSDhruva Gole  * @id:		Device Identifier
518936afd9fSDhruva Gole  * @r_state:	true if requested to be idle
519936afd9fSDhruva Gole  *
520936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
521936afd9fSDhruva Gole  */
522936afd9fSDhruva Gole int ti_sci_device_is_idle(uint32_t id, bool *r_state)
523936afd9fSDhruva Gole {
524936afd9fSDhruva Gole 	int ret;
525936afd9fSDhruva Gole 	uint8_t state;
526936afd9fSDhruva Gole 
527936afd9fSDhruva Gole 	if (!r_state)
528936afd9fSDhruva Gole 		return -EINVAL;
529936afd9fSDhruva Gole 
530936afd9fSDhruva Gole 	ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL);
531936afd9fSDhruva Gole 	if (ret)
532936afd9fSDhruva Gole 		return ret;
533936afd9fSDhruva Gole 
534936afd9fSDhruva Gole 	*r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
535936afd9fSDhruva Gole 
536936afd9fSDhruva Gole 	return 0;
537936afd9fSDhruva Gole }
538936afd9fSDhruva Gole 
539936afd9fSDhruva Gole /**
540936afd9fSDhruva Gole  * ti_sci_device_is_stop() - Check if the device is requested to be stopped
541936afd9fSDhruva Gole  *
542936afd9fSDhruva Gole  * @id:		Device Identifier
543936afd9fSDhruva Gole  * @r_state:	true if requested to be stopped
544936afd9fSDhruva Gole  * @curr_state:	true if currently stopped
545936afd9fSDhruva Gole  *
546936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
547936afd9fSDhruva Gole  */
548936afd9fSDhruva Gole int ti_sci_device_is_stop(uint32_t id, bool *r_state,  bool *curr_state)
549936afd9fSDhruva Gole {
550936afd9fSDhruva Gole 	int ret;
551936afd9fSDhruva Gole 	uint8_t p_state, c_state;
552936afd9fSDhruva Gole 
553936afd9fSDhruva Gole 	if (!r_state && !curr_state)
554936afd9fSDhruva Gole 		return -EINVAL;
555936afd9fSDhruva Gole 
556936afd9fSDhruva Gole 	ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
557936afd9fSDhruva Gole 	if (ret)
558936afd9fSDhruva Gole 		return ret;
559936afd9fSDhruva Gole 
560936afd9fSDhruva Gole 	if (r_state)
561936afd9fSDhruva Gole 		*r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
562936afd9fSDhruva Gole 	if (curr_state)
563936afd9fSDhruva Gole 		*curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
564936afd9fSDhruva Gole 
565936afd9fSDhruva Gole 	return 0;
566936afd9fSDhruva Gole }
567936afd9fSDhruva Gole 
568936afd9fSDhruva Gole /**
569936afd9fSDhruva Gole  * ti_sci_device_is_on() - Check if the device is requested to be ON
570936afd9fSDhruva Gole  *
571936afd9fSDhruva Gole  * @id:		Device Identifier
572936afd9fSDhruva Gole  * @r_state:	true if requested to be ON
573936afd9fSDhruva Gole  * @curr_state:	true if currently ON and active
574936afd9fSDhruva Gole  *
575936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
576936afd9fSDhruva Gole  */
577936afd9fSDhruva Gole int ti_sci_device_is_on(uint32_t id, bool *r_state,  bool *curr_state)
578936afd9fSDhruva Gole {
579936afd9fSDhruva Gole 	int ret;
580936afd9fSDhruva Gole 	uint8_t p_state, c_state;
581936afd9fSDhruva Gole 
582936afd9fSDhruva Gole 	if (!r_state && !curr_state)
583936afd9fSDhruva Gole 		return -EINVAL;
584936afd9fSDhruva Gole 
585936afd9fSDhruva Gole 	ret =
586936afd9fSDhruva Gole 	    ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
587936afd9fSDhruva Gole 	if (ret)
588936afd9fSDhruva Gole 		return ret;
589936afd9fSDhruva Gole 
590936afd9fSDhruva Gole 	if (r_state)
591936afd9fSDhruva Gole 		*r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
592936afd9fSDhruva Gole 	if (curr_state)
593936afd9fSDhruva Gole 		*curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
594936afd9fSDhruva Gole 
595936afd9fSDhruva Gole 	return 0;
596936afd9fSDhruva Gole }
597936afd9fSDhruva Gole 
598936afd9fSDhruva Gole /**
599936afd9fSDhruva Gole  * ti_sci_device_is_trans() - Check if the device is currently transitioning
600936afd9fSDhruva Gole  *
601936afd9fSDhruva Gole  * @id:		Device Identifier
602936afd9fSDhruva Gole  * @curr_state:	true if currently transitioning
603936afd9fSDhruva Gole  *
604936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
605936afd9fSDhruva Gole  */
606936afd9fSDhruva Gole int ti_sci_device_is_trans(uint32_t id, bool *curr_state)
607936afd9fSDhruva Gole {
608936afd9fSDhruva Gole 	int ret;
609936afd9fSDhruva Gole 	uint8_t state;
610936afd9fSDhruva Gole 
611936afd9fSDhruva Gole 	if (!curr_state)
612936afd9fSDhruva Gole 		return -EINVAL;
613936afd9fSDhruva Gole 
614936afd9fSDhruva Gole 	ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state);
615936afd9fSDhruva Gole 	if (ret)
616936afd9fSDhruva Gole 		return ret;
617936afd9fSDhruva Gole 
618936afd9fSDhruva Gole 	*curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
619936afd9fSDhruva Gole 
620936afd9fSDhruva Gole 	return 0;
621936afd9fSDhruva Gole }
622936afd9fSDhruva Gole 
623936afd9fSDhruva Gole /**
624936afd9fSDhruva Gole  * ti_sci_device_set_resets() - Set resets for device managed by TISCI
625936afd9fSDhruva Gole  *
626936afd9fSDhruva Gole  * @id:			Device Identifier
627936afd9fSDhruva Gole  * @reset_state:	Device specific reset bit field
628936afd9fSDhruva Gole  *
629936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
630936afd9fSDhruva Gole  */
631936afd9fSDhruva Gole int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state)
632936afd9fSDhruva Gole {
633936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_device_resets req;
634936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
635936afd9fSDhruva Gole 
636936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
637936afd9fSDhruva Gole 	int ret;
638936afd9fSDhruva Gole 
639936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS, 0,
640936afd9fSDhruva Gole 				    &req, sizeof(req),
641936afd9fSDhruva Gole 				    &resp, sizeof(resp),
642936afd9fSDhruva Gole 				    &xfer);
643936afd9fSDhruva Gole 	if (ret) {
644936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
645936afd9fSDhruva Gole 		return ret;
646936afd9fSDhruva Gole 	}
647936afd9fSDhruva Gole 
648936afd9fSDhruva Gole 	req.id = id;
649936afd9fSDhruva Gole 	req.resets = reset_state;
650936afd9fSDhruva Gole 
651936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
652936afd9fSDhruva Gole 	if (ret) {
653936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
654936afd9fSDhruva Gole 		return ret;
655936afd9fSDhruva Gole 	}
656936afd9fSDhruva Gole 
657936afd9fSDhruva Gole 	return 0;
658936afd9fSDhruva Gole }
659936afd9fSDhruva Gole 
660936afd9fSDhruva Gole /**
661936afd9fSDhruva Gole  * ti_sci_device_get_resets() - Get reset state for device managed by TISCI
662936afd9fSDhruva Gole  *
663936afd9fSDhruva Gole  * @id:			Device Identifier
664936afd9fSDhruva Gole  * @reset_state:	Pointer to reset state to populate
665936afd9fSDhruva Gole  *
666936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
667936afd9fSDhruva Gole  */
668936afd9fSDhruva Gole int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state)
669936afd9fSDhruva Gole {
670936afd9fSDhruva Gole 	return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL);
671936afd9fSDhruva Gole }
672936afd9fSDhruva Gole 
673936afd9fSDhruva Gole /**
674936afd9fSDhruva Gole  * ti_sci_clock_set_state() - Set clock state helper
675936afd9fSDhruva Gole  *
676936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
677936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request,
678936afd9fSDhruva Gole  *		Each device has its own set of clock inputs, This indexes
679936afd9fSDhruva Gole  *		which clock input to modify
680936afd9fSDhruva Gole  * @flags:	Header flags as needed
681936afd9fSDhruva Gole  * @state:	State to request for the clock
682936afd9fSDhruva Gole  *
683936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
684936afd9fSDhruva Gole  */
685936afd9fSDhruva Gole int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id,
686936afd9fSDhruva Gole 			   uint32_t flags, uint8_t state)
687936afd9fSDhruva Gole {
688936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_clock_state req;
689936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
690936afd9fSDhruva Gole 
691936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
692936afd9fSDhruva Gole 	int ret;
693936afd9fSDhruva Gole 
694936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_STATE, flags,
695936afd9fSDhruva Gole 				    &req, sizeof(req),
696936afd9fSDhruva Gole 				    &resp, sizeof(resp),
697936afd9fSDhruva Gole 				    &xfer);
698936afd9fSDhruva Gole 	if (ret) {
699936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
700936afd9fSDhruva Gole 		return ret;
701936afd9fSDhruva Gole 	}
702936afd9fSDhruva Gole 
703936afd9fSDhruva Gole 	req.dev_id = dev_id;
704936afd9fSDhruva Gole 	req.clk_id = clk_id;
705936afd9fSDhruva Gole 	req.request_state = state;
706936afd9fSDhruva Gole 
707936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
708936afd9fSDhruva Gole 	if (ret) {
709936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
710936afd9fSDhruva Gole 		return ret;
711936afd9fSDhruva Gole 	}
712936afd9fSDhruva Gole 
713936afd9fSDhruva Gole 	return 0;
714936afd9fSDhruva Gole }
715936afd9fSDhruva Gole 
716936afd9fSDhruva Gole /**
717936afd9fSDhruva Gole  * ti_sci_clock_get_state() - Get clock state helper
718936afd9fSDhruva Gole  *
719936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
720936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
721936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
722936afd9fSDhruva Gole  *		which clock input to modify.
723936afd9fSDhruva Gole  * @programmed_state:	State requested for clock to move to
724936afd9fSDhruva Gole  * @current_state:	State that the clock is currently in
725936afd9fSDhruva Gole  *
726936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
727936afd9fSDhruva Gole  */
728936afd9fSDhruva Gole int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id,
729936afd9fSDhruva Gole 			   uint8_t *programmed_state,
730936afd9fSDhruva Gole 			   uint8_t *current_state)
731936afd9fSDhruva Gole {
732936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_clock_state req;
733936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_clock_state resp;
734936afd9fSDhruva Gole 
735936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
736936afd9fSDhruva Gole 	int ret;
737936afd9fSDhruva Gole 
738936afd9fSDhruva Gole 	if (!programmed_state && !current_state)
739936afd9fSDhruva Gole 		return -EINVAL;
740936afd9fSDhruva Gole 
741936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_STATE, 0,
742936afd9fSDhruva Gole 				    &req, sizeof(req),
743936afd9fSDhruva Gole 				    &resp, sizeof(resp),
744936afd9fSDhruva Gole 				    &xfer);
745936afd9fSDhruva Gole 	if (ret) {
746936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
747936afd9fSDhruva Gole 		return ret;
748936afd9fSDhruva Gole 	}
749936afd9fSDhruva Gole 
750936afd9fSDhruva Gole 	req.dev_id = dev_id;
751936afd9fSDhruva Gole 	req.clk_id = clk_id;
752936afd9fSDhruva Gole 
753936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
754936afd9fSDhruva Gole 	if (ret) {
755936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
756936afd9fSDhruva Gole 		return ret;
757936afd9fSDhruva Gole 	}
758936afd9fSDhruva Gole 
759936afd9fSDhruva Gole 	if (programmed_state)
760936afd9fSDhruva Gole 		*programmed_state = resp.programmed_state;
761936afd9fSDhruva Gole 	if (current_state)
762936afd9fSDhruva Gole 		*current_state = resp.current_state;
763936afd9fSDhruva Gole 
764936afd9fSDhruva Gole 	return 0;
765936afd9fSDhruva Gole }
766936afd9fSDhruva Gole 
767936afd9fSDhruva Gole /**
768936afd9fSDhruva Gole  * ti_sci_clock_get() - Get control of a clock from TI SCI
769936afd9fSDhruva Gole 
770936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
771936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
772936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
773936afd9fSDhruva Gole  *		which clock input to modify.
774936afd9fSDhruva Gole  * @needs_ssc: 'true' iff Spread Spectrum clock is desired
775936afd9fSDhruva Gole  * @can_change_freq: 'true' iff frequency change is desired
776936afd9fSDhruva Gole  * @enable_input_term: 'true' iff input termination is desired
777936afd9fSDhruva Gole  *
778936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
779936afd9fSDhruva Gole  */
780936afd9fSDhruva Gole int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id,
781936afd9fSDhruva Gole 		     bool needs_ssc, bool can_change_freq,
782936afd9fSDhruva Gole 		     bool enable_input_term)
783936afd9fSDhruva Gole {
784936afd9fSDhruva Gole 	uint32_t flags = 0;
785936afd9fSDhruva Gole 
786936afd9fSDhruva Gole 	flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
787936afd9fSDhruva Gole 	flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
788936afd9fSDhruva Gole 	flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
789936afd9fSDhruva Gole 
790936afd9fSDhruva Gole 	return ti_sci_clock_set_state(dev_id, clk_id, flags,
791936afd9fSDhruva Gole 				      MSG_CLOCK_SW_STATE_REQ);
792936afd9fSDhruva Gole }
793936afd9fSDhruva Gole 
794936afd9fSDhruva Gole /**
795936afd9fSDhruva Gole  * ti_sci_clock_idle() - Idle a clock which is in our control
796936afd9fSDhruva Gole 
797936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
798936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
799936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
800936afd9fSDhruva Gole  *		which clock input to modify.
801936afd9fSDhruva Gole  *
802936afd9fSDhruva Gole  * NOTE: This clock must have been requested by get_clock previously.
803936afd9fSDhruva Gole  *
804936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
805936afd9fSDhruva Gole  */
806936afd9fSDhruva Gole int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id)
807936afd9fSDhruva Gole {
808936afd9fSDhruva Gole 	return ti_sci_clock_set_state(dev_id, clk_id, 0,
809936afd9fSDhruva Gole 				      MSG_CLOCK_SW_STATE_UNREQ);
810936afd9fSDhruva Gole }
811936afd9fSDhruva Gole 
812936afd9fSDhruva Gole /**
813936afd9fSDhruva Gole  * ti_sci_clock_put() - Release a clock from our control
814936afd9fSDhruva Gole  *
815936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
816936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
817936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
818936afd9fSDhruva Gole  *		which clock input to modify.
819936afd9fSDhruva Gole  *
820936afd9fSDhruva Gole  * NOTE: This clock must have been requested by get_clock previously.
821936afd9fSDhruva Gole  *
822936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
823936afd9fSDhruva Gole  */
824936afd9fSDhruva Gole int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id)
825936afd9fSDhruva Gole {
826936afd9fSDhruva Gole 	return ti_sci_clock_set_state(dev_id, clk_id, 0,
827936afd9fSDhruva Gole 				      MSG_CLOCK_SW_STATE_AUTO);
828936afd9fSDhruva Gole }
829936afd9fSDhruva Gole 
830936afd9fSDhruva Gole /**
831936afd9fSDhruva Gole  * ti_sci_clock_is_auto() - Is the clock being auto managed
832936afd9fSDhruva Gole  *
833936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
834936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
835936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
836936afd9fSDhruva Gole  *		which clock input to modify.
837936afd9fSDhruva Gole  * @req_state: state indicating if the clock is auto managed
838936afd9fSDhruva Gole  *
839936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
840936afd9fSDhruva Gole  */
841936afd9fSDhruva Gole int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, bool *req_state)
842936afd9fSDhruva Gole {
843936afd9fSDhruva Gole 	uint8_t state = 0;
844936afd9fSDhruva Gole 	int ret;
845936afd9fSDhruva Gole 
846936afd9fSDhruva Gole 	if (!req_state)
847936afd9fSDhruva Gole 		return -EINVAL;
848936afd9fSDhruva Gole 
849936afd9fSDhruva Gole 	ret = ti_sci_clock_get_state(dev_id, clk_id, &state, NULL);
850936afd9fSDhruva Gole 	if (ret)
851936afd9fSDhruva Gole 		return ret;
852936afd9fSDhruva Gole 
853936afd9fSDhruva Gole 	*req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
854936afd9fSDhruva Gole 
855936afd9fSDhruva Gole 	return 0;
856936afd9fSDhruva Gole }
857936afd9fSDhruva Gole 
858936afd9fSDhruva Gole /**
859936afd9fSDhruva Gole  * ti_sci_clock_is_on() - Is the clock ON
860936afd9fSDhruva Gole  *
861936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
862936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
863936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
864936afd9fSDhruva Gole  *		which clock input to modify.
865936afd9fSDhruva Gole  * @req_state: state indicating if the clock is managed by us and enabled
866936afd9fSDhruva Gole  * @curr_state: state indicating if the clock is ready for operation
867936afd9fSDhruva Gole  *
868936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
869936afd9fSDhruva Gole  */
870936afd9fSDhruva Gole int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id,
871936afd9fSDhruva Gole 		       bool *req_state, bool *curr_state)
872936afd9fSDhruva Gole {
873936afd9fSDhruva Gole 	uint8_t c_state = 0, r_state = 0;
874936afd9fSDhruva Gole 	int ret;
875936afd9fSDhruva Gole 
876936afd9fSDhruva Gole 	if (!req_state && !curr_state)
877936afd9fSDhruva Gole 		return -EINVAL;
878936afd9fSDhruva Gole 
879936afd9fSDhruva Gole 	ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
880936afd9fSDhruva Gole 	if (ret)
881936afd9fSDhruva Gole 		return ret;
882936afd9fSDhruva Gole 
883936afd9fSDhruva Gole 	if (req_state)
884936afd9fSDhruva Gole 		*req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
885936afd9fSDhruva Gole 	if (curr_state)
886936afd9fSDhruva Gole 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
887936afd9fSDhruva Gole 
888936afd9fSDhruva Gole 	return 0;
889936afd9fSDhruva Gole }
890936afd9fSDhruva Gole 
891936afd9fSDhruva Gole /**
892936afd9fSDhruva Gole  * ti_sci_clock_is_off() - Is the clock OFF
893936afd9fSDhruva Gole  *
894936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
895936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
896936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
897936afd9fSDhruva Gole  *		which clock input to modify.
898936afd9fSDhruva Gole  * @req_state: state indicating if the clock is managed by us and disabled
899936afd9fSDhruva Gole  * @curr_state: state indicating if the clock is NOT ready for operation
900936afd9fSDhruva Gole  *
901936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
902936afd9fSDhruva Gole  */
903936afd9fSDhruva Gole int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id,
904936afd9fSDhruva Gole 			bool *req_state, bool *curr_state)
905936afd9fSDhruva Gole {
906936afd9fSDhruva Gole 	uint8_t c_state = 0, r_state = 0;
907936afd9fSDhruva Gole 	int ret;
908936afd9fSDhruva Gole 
909936afd9fSDhruva Gole 	if (!req_state && !curr_state)
910936afd9fSDhruva Gole 		return -EINVAL;
911936afd9fSDhruva Gole 
912936afd9fSDhruva Gole 	ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
913936afd9fSDhruva Gole 	if (ret)
914936afd9fSDhruva Gole 		return ret;
915936afd9fSDhruva Gole 
916936afd9fSDhruva Gole 	if (req_state)
917936afd9fSDhruva Gole 		*req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
918936afd9fSDhruva Gole 	if (curr_state)
919936afd9fSDhruva Gole 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
920936afd9fSDhruva Gole 
921936afd9fSDhruva Gole 	return 0;
922936afd9fSDhruva Gole }
923936afd9fSDhruva Gole 
924936afd9fSDhruva Gole /**
925936afd9fSDhruva Gole  * ti_sci_clock_set_parent() - Set the clock source of a specific device clock
926936afd9fSDhruva Gole  *
927936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
928936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
929936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
930936afd9fSDhruva Gole  *		which clock input to modify.
931936afd9fSDhruva Gole  * @parent_id:	Parent clock identifier to set
932936afd9fSDhruva Gole  *
933936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
934936afd9fSDhruva Gole  */
935936afd9fSDhruva Gole int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, uint8_t parent_id)
936936afd9fSDhruva Gole {
937936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_clock_parent req;
938936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
939936afd9fSDhruva Gole 
940936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
941936afd9fSDhruva Gole 	int ret;
942936afd9fSDhruva Gole 
943936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_PARENT, 0,
944936afd9fSDhruva Gole 				    &req, sizeof(req),
945936afd9fSDhruva Gole 				    &resp, sizeof(resp),
946936afd9fSDhruva Gole 				    &xfer);
947936afd9fSDhruva Gole 	if (ret) {
948936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
949936afd9fSDhruva Gole 		return ret;
950936afd9fSDhruva Gole 	}
951936afd9fSDhruva Gole 
952936afd9fSDhruva Gole 	req.dev_id = dev_id;
953936afd9fSDhruva Gole 	req.clk_id = clk_id;
954936afd9fSDhruva Gole 	req.parent_id = parent_id;
955936afd9fSDhruva Gole 
956936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
957936afd9fSDhruva Gole 	if (ret) {
958936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
959936afd9fSDhruva Gole 		return ret;
960936afd9fSDhruva Gole 	}
961936afd9fSDhruva Gole 
962936afd9fSDhruva Gole 	return 0;
963936afd9fSDhruva Gole }
964936afd9fSDhruva Gole 
965936afd9fSDhruva Gole /**
966936afd9fSDhruva Gole  * ti_sci_clock_get_parent() - Get current parent clock source
967936afd9fSDhruva Gole  *
968936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
969936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
970936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
971936afd9fSDhruva Gole  *		which clock input to modify.
972936afd9fSDhruva Gole  * @parent_id:	Current clock parent
973936afd9fSDhruva Gole  *
974936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
975936afd9fSDhruva Gole  */
976936afd9fSDhruva Gole int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, uint8_t *parent_id)
977936afd9fSDhruva Gole {
978936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_clock_parent req;
979936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_clock_parent resp;
980936afd9fSDhruva Gole 
981936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
982936afd9fSDhruva Gole 	int ret;
983936afd9fSDhruva Gole 
984936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_PARENT, 0,
985936afd9fSDhruva Gole 				    &req, sizeof(req),
986936afd9fSDhruva Gole 				    &resp, sizeof(resp),
987936afd9fSDhruva Gole 				    &xfer);
988936afd9fSDhruva Gole 	if (ret) {
989936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
990936afd9fSDhruva Gole 		return ret;
991936afd9fSDhruva Gole 	}
992936afd9fSDhruva Gole 
993936afd9fSDhruva Gole 	req.dev_id = dev_id;
994936afd9fSDhruva Gole 	req.clk_id = clk_id;
995936afd9fSDhruva Gole 
996936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
997936afd9fSDhruva Gole 	if (ret) {
998936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
999936afd9fSDhruva Gole 		return ret;
1000936afd9fSDhruva Gole 	}
1001936afd9fSDhruva Gole 
1002936afd9fSDhruva Gole 	*parent_id = resp.parent_id;
1003936afd9fSDhruva Gole 
1004936afd9fSDhruva Gole 	return 0;
1005936afd9fSDhruva Gole }
1006936afd9fSDhruva Gole 
1007936afd9fSDhruva Gole /**
1008936afd9fSDhruva Gole  * ti_sci_clock_get_num_parents() - Get num parents of the current clk source
1009936afd9fSDhruva Gole  *
1010936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
1011936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
1012936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
1013936afd9fSDhruva Gole  *		which clock input to modify.
1014936afd9fSDhruva Gole  * @num_parents: Returns he number of parents to the current clock.
1015936afd9fSDhruva Gole  *
1016936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1017936afd9fSDhruva Gole  */
1018936afd9fSDhruva Gole int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id,
1019936afd9fSDhruva Gole 				 uint8_t *num_parents)
1020936afd9fSDhruva Gole {
1021936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_clock_num_parents req;
1022936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_clock_num_parents resp;
1023936afd9fSDhruva Gole 
1024936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1025936afd9fSDhruva Gole 	int ret;
1026936afd9fSDhruva Gole 
1027936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, 0,
1028936afd9fSDhruva Gole 				    &req, sizeof(req),
1029936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1030936afd9fSDhruva Gole 				    &xfer);
1031936afd9fSDhruva Gole 	if (ret) {
1032936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1033936afd9fSDhruva Gole 		return ret;
1034936afd9fSDhruva Gole 	}
1035936afd9fSDhruva Gole 
1036936afd9fSDhruva Gole 	req.dev_id = dev_id;
1037936afd9fSDhruva Gole 	req.clk_id = clk_id;
1038936afd9fSDhruva Gole 
1039936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1040936afd9fSDhruva Gole 	if (ret) {
1041936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1042936afd9fSDhruva Gole 		return ret;
1043936afd9fSDhruva Gole 	}
1044936afd9fSDhruva Gole 
1045936afd9fSDhruva Gole 	*num_parents = resp.num_parents;
1046936afd9fSDhruva Gole 
1047936afd9fSDhruva Gole 	return 0;
1048936afd9fSDhruva Gole }
1049936afd9fSDhruva Gole 
1050936afd9fSDhruva Gole /**
1051936afd9fSDhruva Gole  * ti_sci_clock_get_match_freq() - Find a good match for frequency
1052936afd9fSDhruva Gole  *
1053936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
1054936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
1055936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
1056936afd9fSDhruva Gole  *		which clock input to modify.
1057936afd9fSDhruva Gole  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
1058936afd9fSDhruva Gole  *		allowable programmed frequency and does not account for clock
1059936afd9fSDhruva Gole  *		tolerances and jitter.
1060936afd9fSDhruva Gole  * @target_freq: The target clock frequency in Hz. A frequency will be
1061936afd9fSDhruva Gole  *		processed as close to this target frequency as possible.
1062936afd9fSDhruva Gole  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
1063936afd9fSDhruva Gole  *		allowable programmed frequency and does not account for clock
1064936afd9fSDhruva Gole  *		tolerances and jitter.
1065936afd9fSDhruva Gole  * @match_freq:	Frequency match in Hz response.
1066936afd9fSDhruva Gole  *
1067936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1068936afd9fSDhruva Gole  */
1069936afd9fSDhruva Gole int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id,
1070936afd9fSDhruva Gole 				uint64_t min_freq, uint64_t target_freq,
1071936afd9fSDhruva Gole 				uint64_t max_freq, uint64_t *match_freq)
1072936afd9fSDhruva Gole {
1073936afd9fSDhruva Gole 	struct ti_sci_msg_req_query_clock_freq req;
1074936afd9fSDhruva Gole 	struct ti_sci_msg_resp_query_clock_freq resp;
1075936afd9fSDhruva Gole 
1076936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1077936afd9fSDhruva Gole 	int ret;
1078936afd9fSDhruva Gole 
1079936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_CLOCK_FREQ, 0,
1080936afd9fSDhruva Gole 				    &req, sizeof(req),
1081936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1082936afd9fSDhruva Gole 				    &xfer);
1083936afd9fSDhruva Gole 	if (ret) {
1084936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1085936afd9fSDhruva Gole 		return ret;
1086936afd9fSDhruva Gole 	}
1087936afd9fSDhruva Gole 
1088936afd9fSDhruva Gole 	req.dev_id = dev_id;
1089936afd9fSDhruva Gole 	req.clk_id = clk_id;
1090936afd9fSDhruva Gole 	req.min_freq_hz = min_freq;
1091936afd9fSDhruva Gole 	req.target_freq_hz = target_freq;
1092936afd9fSDhruva Gole 	req.max_freq_hz = max_freq;
1093936afd9fSDhruva Gole 
1094936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1095936afd9fSDhruva Gole 	if (ret) {
1096936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1097936afd9fSDhruva Gole 		return ret;
1098936afd9fSDhruva Gole 	}
1099936afd9fSDhruva Gole 
1100936afd9fSDhruva Gole 	*match_freq = resp.freq_hz;
1101936afd9fSDhruva Gole 
1102936afd9fSDhruva Gole 	return 0;
1103936afd9fSDhruva Gole }
1104936afd9fSDhruva Gole 
1105936afd9fSDhruva Gole /**
1106936afd9fSDhruva Gole  * ti_sci_clock_set_freq() - Set a frequency for clock
1107936afd9fSDhruva Gole  *
1108936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
1109936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
1110936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
1111936afd9fSDhruva Gole  *		which clock input to modify.
1112936afd9fSDhruva Gole  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
1113936afd9fSDhruva Gole  *		allowable programmed frequency and does not account for clock
1114936afd9fSDhruva Gole  *		tolerances and jitter.
1115936afd9fSDhruva Gole  * @target_freq: The target clock frequency in Hz. A frequency will be
1116936afd9fSDhruva Gole  *		processed as close to this target frequency as possible.
1117936afd9fSDhruva Gole  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
1118936afd9fSDhruva Gole  *		allowable programmed frequency and does not account for clock
1119936afd9fSDhruva Gole  *		tolerances and jitter.
1120936afd9fSDhruva Gole  *
1121936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1122936afd9fSDhruva Gole  */
1123936afd9fSDhruva Gole int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, uint64_t min_freq,
1124936afd9fSDhruva Gole 			  uint64_t target_freq, uint64_t max_freq)
1125936afd9fSDhruva Gole {
1126936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_clock_freq req;
1127936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1128936afd9fSDhruva Gole 
1129936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1130936afd9fSDhruva Gole 	int ret;
1131936afd9fSDhruva Gole 
1132936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_FREQ, 0,
1133936afd9fSDhruva Gole 				    &req, sizeof(req),
1134936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1135936afd9fSDhruva Gole 				    &xfer);
1136936afd9fSDhruva Gole 	if (ret) {
1137936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1138936afd9fSDhruva Gole 		return ret;
1139936afd9fSDhruva Gole 	}
1140936afd9fSDhruva Gole 	req.dev_id = dev_id;
1141936afd9fSDhruva Gole 	req.clk_id = clk_id;
1142936afd9fSDhruva Gole 	req.min_freq_hz = min_freq;
1143936afd9fSDhruva Gole 	req.target_freq_hz = target_freq;
1144936afd9fSDhruva Gole 	req.max_freq_hz = max_freq;
1145936afd9fSDhruva Gole 
1146936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1147936afd9fSDhruva Gole 	if (ret) {
1148936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1149936afd9fSDhruva Gole 		return ret;
1150936afd9fSDhruva Gole 	}
1151936afd9fSDhruva Gole 
1152936afd9fSDhruva Gole 	return 0;
1153936afd9fSDhruva Gole }
1154936afd9fSDhruva Gole 
1155936afd9fSDhruva Gole /**
1156936afd9fSDhruva Gole  * ti_sci_clock_get_freq() - Get current frequency
1157936afd9fSDhruva Gole  *
1158936afd9fSDhruva Gole  * @dev_id:	Device identifier this request is for
1159936afd9fSDhruva Gole  * @clk_id:	Clock identifier for the device for this request.
1160936afd9fSDhruva Gole  *		Each device has its own set of clock inputs. This indexes
1161936afd9fSDhruva Gole  *		which clock input to modify.
1162936afd9fSDhruva Gole  * @freq:	Currently frequency in Hz
1163936afd9fSDhruva Gole  *
1164936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1165936afd9fSDhruva Gole  */
1166936afd9fSDhruva Gole int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq)
1167936afd9fSDhruva Gole {
1168936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_clock_freq req;
1169936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_clock_freq resp;
1170936afd9fSDhruva Gole 
1171936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1172936afd9fSDhruva Gole 	int ret;
1173936afd9fSDhruva Gole 
1174936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_FREQ, 0,
1175936afd9fSDhruva Gole 				    &req, sizeof(req),
1176936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1177936afd9fSDhruva Gole 				    &xfer);
1178936afd9fSDhruva Gole 	if (ret) {
1179936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1180936afd9fSDhruva Gole 		return ret;
1181936afd9fSDhruva Gole 	}
1182936afd9fSDhruva Gole 
1183936afd9fSDhruva Gole 	req.dev_id = dev_id;
1184936afd9fSDhruva Gole 	req.clk_id = clk_id;
1185936afd9fSDhruva Gole 
1186936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1187936afd9fSDhruva Gole 	if (ret) {
1188936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1189936afd9fSDhruva Gole 		return ret;
1190936afd9fSDhruva Gole 	}
1191936afd9fSDhruva Gole 
1192936afd9fSDhruva Gole 	*freq = resp.freq_hz;
1193936afd9fSDhruva Gole 
1194936afd9fSDhruva Gole 	return 0;
1195936afd9fSDhruva Gole }
1196936afd9fSDhruva Gole 
1197936afd9fSDhruva Gole /**
1198936afd9fSDhruva Gole  * ti_sci_core_reboot() - Command to request system reset
1199936afd9fSDhruva Gole  *
1200936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1201936afd9fSDhruva Gole  */
1202936afd9fSDhruva Gole int ti_sci_core_reboot(void)
1203936afd9fSDhruva Gole {
1204936afd9fSDhruva Gole 	struct ti_sci_msg_req_reboot req;
1205936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1206936afd9fSDhruva Gole 
1207936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1208936afd9fSDhruva Gole 	int ret;
1209936afd9fSDhruva Gole 
1210936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SYS_RESET, 0,
1211936afd9fSDhruva Gole 				    &req, sizeof(req),
1212936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1213936afd9fSDhruva Gole 				    &xfer);
1214936afd9fSDhruva Gole 	if (ret) {
1215936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1216936afd9fSDhruva Gole 		return ret;
1217936afd9fSDhruva Gole 	}
1218936afd9fSDhruva Gole 	req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET;
1219936afd9fSDhruva Gole 
1220936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1221936afd9fSDhruva Gole 	if (ret) {
1222936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1223936afd9fSDhruva Gole 		return ret;
1224936afd9fSDhruva Gole 	}
1225936afd9fSDhruva Gole 
1226936afd9fSDhruva Gole 	return 0;
1227936afd9fSDhruva Gole }
1228936afd9fSDhruva Gole 
1229936afd9fSDhruva Gole /**
1230936afd9fSDhruva Gole  * ti_sci_proc_request() - Request a physical processor control
1231936afd9fSDhruva Gole  *
1232936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1233936afd9fSDhruva Gole  *
1234936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1235936afd9fSDhruva Gole  */
1236936afd9fSDhruva Gole int ti_sci_proc_request(uint8_t proc_id)
1237936afd9fSDhruva Gole {
1238936afd9fSDhruva Gole 	struct ti_sci_msg_req_proc_request req;
1239936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1240936afd9fSDhruva Gole 
1241936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1242936afd9fSDhruva Gole 	int ret;
1243936afd9fSDhruva Gole 
1244936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST, 0,
1245936afd9fSDhruva Gole 				    &req, sizeof(req),
1246936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1247936afd9fSDhruva Gole 				    &xfer);
1248936afd9fSDhruva Gole 	if (ret) {
1249936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1250936afd9fSDhruva Gole 		return ret;
1251936afd9fSDhruva Gole 	}
1252936afd9fSDhruva Gole 
1253936afd9fSDhruva Gole 	req.processor_id = proc_id;
1254936afd9fSDhruva Gole 
1255936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1256936afd9fSDhruva Gole 	if (ret) {
1257936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1258936afd9fSDhruva Gole 		return ret;
1259936afd9fSDhruva Gole 	}
1260936afd9fSDhruva Gole 
1261936afd9fSDhruva Gole 	return 0;
1262936afd9fSDhruva Gole }
1263936afd9fSDhruva Gole 
1264936afd9fSDhruva Gole /**
1265936afd9fSDhruva Gole  * ti_sci_proc_release() - Release a physical processor control
1266936afd9fSDhruva Gole  *
1267936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1268936afd9fSDhruva Gole  *
1269936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1270936afd9fSDhruva Gole  */
1271936afd9fSDhruva Gole int ti_sci_proc_release(uint8_t proc_id)
1272936afd9fSDhruva Gole {
1273936afd9fSDhruva Gole 	struct ti_sci_msg_req_proc_release req;
1274936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1275936afd9fSDhruva Gole 
1276936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1277936afd9fSDhruva Gole 	int ret;
1278936afd9fSDhruva Gole 
1279936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE, 0,
1280936afd9fSDhruva Gole 				    &req, sizeof(req),
1281936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1282936afd9fSDhruva Gole 				    &xfer);
1283936afd9fSDhruva Gole 	if (ret) {
1284936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1285936afd9fSDhruva Gole 		return ret;
1286936afd9fSDhruva Gole 	}
1287936afd9fSDhruva Gole 
1288936afd9fSDhruva Gole 	req.processor_id = proc_id;
1289936afd9fSDhruva Gole 
1290936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1291936afd9fSDhruva Gole 	if (ret) {
1292936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1293936afd9fSDhruva Gole 		return ret;
1294936afd9fSDhruva Gole 	}
1295936afd9fSDhruva Gole 
1296936afd9fSDhruva Gole 	return 0;
1297936afd9fSDhruva Gole }
1298936afd9fSDhruva Gole 
1299936afd9fSDhruva Gole /**
1300936afd9fSDhruva Gole  * ti_sci_proc_handover() - Handover a physical processor control to a host in
1301936afd9fSDhruva Gole  *                          the processor's access control list.
1302936afd9fSDhruva Gole  *
1303936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1304936afd9fSDhruva Gole  * @host_id:	Host ID to get the control of the processor
1305936afd9fSDhruva Gole  *
1306936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1307936afd9fSDhruva Gole  */
1308936afd9fSDhruva Gole int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id)
1309936afd9fSDhruva Gole {
1310936afd9fSDhruva Gole 	struct ti_sci_msg_req_proc_handover req;
1311936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1312936afd9fSDhruva Gole 
1313936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1314936afd9fSDhruva Gole 	int ret;
1315936afd9fSDhruva Gole 
1316936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER, 0,
1317936afd9fSDhruva Gole 				    &req, sizeof(req),
1318936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1319936afd9fSDhruva Gole 				    &xfer);
1320936afd9fSDhruva Gole 	if (ret) {
1321936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1322936afd9fSDhruva Gole 		return ret;
1323936afd9fSDhruva Gole 	}
1324936afd9fSDhruva Gole 
1325936afd9fSDhruva Gole 	req.processor_id = proc_id;
1326936afd9fSDhruva Gole 	req.host_id = host_id;
1327936afd9fSDhruva Gole 
1328936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1329936afd9fSDhruva Gole 	if (ret) {
1330936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1331936afd9fSDhruva Gole 		return ret;
1332936afd9fSDhruva Gole 	}
1333936afd9fSDhruva Gole 
1334936afd9fSDhruva Gole 	return 0;
1335936afd9fSDhruva Gole }
1336936afd9fSDhruva Gole 
1337936afd9fSDhruva Gole /**
1338936afd9fSDhruva Gole  * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags
1339936afd9fSDhruva Gole  *
1340936afd9fSDhruva Gole  * @proc_id:		Processor ID this request is for
1341936afd9fSDhruva Gole  * @config_flags_set:	Configuration flags to be set
1342936afd9fSDhruva Gole  * @config_flags_clear:	Configuration flags to be cleared
1343936afd9fSDhruva Gole  *
1344936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1345936afd9fSDhruva Gole  */
1346936afd9fSDhruva Gole int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector,
1347936afd9fSDhruva Gole 			     uint32_t config_flags_set,
1348936afd9fSDhruva Gole 			     uint32_t config_flags_clear)
1349936afd9fSDhruva Gole {
1350936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_proc_boot_config req;
1351936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1352936afd9fSDhruva Gole 
1353936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1354936afd9fSDhruva Gole 	int ret;
1355936afd9fSDhruva Gole 
1356936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG, 0,
1357936afd9fSDhruva Gole 				    &req, sizeof(req),
1358936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1359936afd9fSDhruva Gole 				    &xfer);
1360936afd9fSDhruva Gole 	if (ret) {
1361936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1362936afd9fSDhruva Gole 		return ret;
1363936afd9fSDhruva Gole 	}
1364936afd9fSDhruva Gole 
1365936afd9fSDhruva Gole 	req.processor_id = proc_id;
1366936afd9fSDhruva Gole 	req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
1367936afd9fSDhruva Gole 	req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
1368936afd9fSDhruva Gole 				TISCI_ADDR_HIGH_SHIFT;
1369936afd9fSDhruva Gole 	req.config_flags_set = config_flags_set;
1370936afd9fSDhruva Gole 	req.config_flags_clear = config_flags_clear;
1371936afd9fSDhruva Gole 
1372936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1373936afd9fSDhruva Gole 	if (ret) {
1374936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1375936afd9fSDhruva Gole 		return ret;
1376936afd9fSDhruva Gole 	}
1377936afd9fSDhruva Gole 
1378936afd9fSDhruva Gole 	return 0;
1379936afd9fSDhruva Gole }
1380936afd9fSDhruva Gole 
1381936afd9fSDhruva Gole /**
1382936afd9fSDhruva Gole  * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags
1383936afd9fSDhruva Gole  *
1384936afd9fSDhruva Gole  * @proc_id:			Processor ID this request is for
1385936afd9fSDhruva Gole  * @control_flags_set:		Control flags to be set
1386936afd9fSDhruva Gole  * @control_flags_clear:	Control flags to be cleared
1387936afd9fSDhruva Gole  *
1388936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1389936afd9fSDhruva Gole  */
1390936afd9fSDhruva Gole int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set,
1391936afd9fSDhruva Gole 			      uint32_t control_flags_clear)
1392936afd9fSDhruva Gole {
1393936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_proc_boot_ctrl req;
1394936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1395936afd9fSDhruva Gole 
1396936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1397936afd9fSDhruva Gole 	int ret;
1398936afd9fSDhruva Gole 
1399936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0,
1400936afd9fSDhruva Gole 				    &req, sizeof(req),
1401936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1402936afd9fSDhruva Gole 				    &xfer);
1403936afd9fSDhruva Gole 	if (ret) {
1404936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1405936afd9fSDhruva Gole 		return ret;
1406936afd9fSDhruva Gole 	}
1407936afd9fSDhruva Gole 
1408936afd9fSDhruva Gole 	req.processor_id = proc_id;
1409936afd9fSDhruva Gole 	req.control_flags_set = control_flags_set;
1410936afd9fSDhruva Gole 	req.control_flags_clear = control_flags_clear;
1411936afd9fSDhruva Gole 
1412936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1413936afd9fSDhruva Gole 	if (ret) {
1414936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1415936afd9fSDhruva Gole 		return ret;
1416936afd9fSDhruva Gole 	}
1417936afd9fSDhruva Gole 
1418936afd9fSDhruva Gole 	return 0;
1419936afd9fSDhruva Gole }
1420936afd9fSDhruva Gole 
1421936afd9fSDhruva Gole /**
1422936afd9fSDhruva Gole  * ti_sci_proc_set_boot_ctrl_no_wait() - Set the processor boot control flags
1423936afd9fSDhruva Gole  *					 without requesting or waiting for a
1424936afd9fSDhruva Gole  *					 response.
1425936afd9fSDhruva Gole  *
1426936afd9fSDhruva Gole  * @proc_id:			Processor ID this request is for
1427936afd9fSDhruva Gole  * @control_flags_set:		Control flags to be set
1428936afd9fSDhruva Gole  * @control_flags_clear:	Control flags to be cleared
1429936afd9fSDhruva Gole  *
1430936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1431936afd9fSDhruva Gole  */
1432936afd9fSDhruva Gole int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id,
1433936afd9fSDhruva Gole 				      uint32_t control_flags_set,
1434936afd9fSDhruva Gole 				      uint32_t control_flags_clear)
1435936afd9fSDhruva Gole {
1436936afd9fSDhruva Gole 	struct ti_sci_msg_req_set_proc_boot_ctrl req;
1437936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1438936afd9fSDhruva Gole 	int ret;
1439936afd9fSDhruva Gole 
1440936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0,
1441936afd9fSDhruva Gole 				    &req, sizeof(req),
1442936afd9fSDhruva Gole 				    NULL, 0,
1443936afd9fSDhruva Gole 				    &xfer);
1444936afd9fSDhruva Gole 	if (ret != 0U) {
1445936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1446936afd9fSDhruva Gole 		return ret;
1447936afd9fSDhruva Gole 	}
1448936afd9fSDhruva Gole 
1449936afd9fSDhruva Gole 	req.processor_id = proc_id;
1450936afd9fSDhruva Gole 	req.control_flags_set = control_flags_set;
1451936afd9fSDhruva Gole 	req.control_flags_clear = control_flags_clear;
1452936afd9fSDhruva Gole 
1453936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1454936afd9fSDhruva Gole 	if (ret != 0U) {
1455936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1456936afd9fSDhruva Gole 		return ret;
1457936afd9fSDhruva Gole 	}
1458936afd9fSDhruva Gole 
1459936afd9fSDhruva Gole 	return 0;
1460936afd9fSDhruva Gole }
1461936afd9fSDhruva Gole 
1462936afd9fSDhruva Gole /**
1463936afd9fSDhruva Gole  * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the
1464936afd9fSDhruva Gole  *                                 processor configuration flags
1465936afd9fSDhruva Gole  *
1466936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1467936afd9fSDhruva Gole  * @cert_addr:	Memory address at which payload image certificate is located
1468936afd9fSDhruva Gole  *
1469936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1470936afd9fSDhruva Gole  */
1471936afd9fSDhruva Gole int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr)
1472936afd9fSDhruva Gole {
1473936afd9fSDhruva Gole 	struct ti_sci_msg_req_proc_auth_boot_image req;
1474936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1475936afd9fSDhruva Gole 
1476936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1477936afd9fSDhruva Gole 	int ret;
1478936afd9fSDhruva Gole 
1479936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMAGE, 0,
1480936afd9fSDhruva Gole 				    &req, sizeof(req),
1481936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1482936afd9fSDhruva Gole 				    &xfer);
1483936afd9fSDhruva Gole 	if (ret) {
1484936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1485936afd9fSDhruva Gole 		return ret;
1486936afd9fSDhruva Gole 	}
1487936afd9fSDhruva Gole 
1488936afd9fSDhruva Gole 	req.processor_id = proc_id;
1489936afd9fSDhruva Gole 	req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
1490936afd9fSDhruva Gole 	req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
1491936afd9fSDhruva Gole 				TISCI_ADDR_HIGH_SHIFT;
1492936afd9fSDhruva Gole 
1493936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1494936afd9fSDhruva Gole 	if (ret) {
1495936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1496936afd9fSDhruva Gole 		return ret;
1497936afd9fSDhruva Gole 	}
1498936afd9fSDhruva Gole 
1499936afd9fSDhruva Gole 	return 0;
1500936afd9fSDhruva Gole }
1501936afd9fSDhruva Gole 
1502936afd9fSDhruva Gole /**
1503936afd9fSDhruva Gole  * ti_sci_proc_get_boot_status() - Get the processor boot status
1504936afd9fSDhruva Gole  *
1505936afd9fSDhruva Gole  * @proc_id:	Processor ID this request is for
1506936afd9fSDhruva Gole  *
1507936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1508936afd9fSDhruva Gole  */
1509936afd9fSDhruva Gole int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv,
1510936afd9fSDhruva Gole 				uint32_t *cfg_flags,
1511936afd9fSDhruva Gole 				uint32_t *ctrl_flags,
1512936afd9fSDhruva Gole 				uint32_t *sts_flags)
1513936afd9fSDhruva Gole {
1514936afd9fSDhruva Gole 	struct ti_sci_msg_req_get_proc_boot_status req;
1515936afd9fSDhruva Gole 	struct ti_sci_msg_resp_get_proc_boot_status resp;
1516936afd9fSDhruva Gole 
1517936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1518936afd9fSDhruva Gole 	int ret;
1519936afd9fSDhruva Gole 
1520936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS, 0,
1521936afd9fSDhruva Gole 				    &req, sizeof(req),
1522936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1523936afd9fSDhruva Gole 				    &xfer);
1524936afd9fSDhruva Gole 	if (ret) {
1525936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1526936afd9fSDhruva Gole 		return ret;
1527936afd9fSDhruva Gole 	}
1528936afd9fSDhruva Gole 
1529936afd9fSDhruva Gole 	req.processor_id = proc_id;
1530936afd9fSDhruva Gole 
1531936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1532936afd9fSDhruva Gole 	if (ret) {
1533936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1534936afd9fSDhruva Gole 		return ret;
1535936afd9fSDhruva Gole 	}
1536936afd9fSDhruva Gole 
1537936afd9fSDhruva Gole 	*bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) |
1538936afd9fSDhruva Gole 	      (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) &
1539936afd9fSDhruva Gole 	       TISCI_ADDR_HIGH_MASK);
1540936afd9fSDhruva Gole 	*cfg_flags = resp.config_flags;
1541936afd9fSDhruva Gole 	*ctrl_flags = resp.control_flags;
1542936afd9fSDhruva Gole 	*sts_flags = resp.status_flags;
1543936afd9fSDhruva Gole 
1544936afd9fSDhruva Gole 	return 0;
1545936afd9fSDhruva Gole }
1546936afd9fSDhruva Gole 
1547936afd9fSDhruva Gole /**
1548936afd9fSDhruva Gole  * ti_sci_proc_wait_boot_status() - Wait for a processor boot status
1549936afd9fSDhruva Gole  *
1550936afd9fSDhruva Gole  * @proc_id:			Processor ID this request is for
1551936afd9fSDhruva Gole  * @num_wait_iterations		Total number of iterations we will check before
1552936afd9fSDhruva Gole  *				we will timeout and give up
1553936afd9fSDhruva Gole  * @num_match_iterations	How many iterations should we have continued
1554936afd9fSDhruva Gole  *				status to account for status bits glitching.
1555936afd9fSDhruva Gole  *				This is to make sure that match occurs for
1556936afd9fSDhruva Gole  *				consecutive checks. This implies that the
1557936afd9fSDhruva Gole  *				worst case should consider that the stable
1558936afd9fSDhruva Gole  *				time should at the worst be num_wait_iterations
1559936afd9fSDhruva Gole  *				num_match_iterations to prevent timeout.
1560936afd9fSDhruva Gole  * @delay_per_iteration_us	Specifies how long to wait (in micro seconds)
1561936afd9fSDhruva Gole  *				between each status checks. This is the minimum
1562936afd9fSDhruva Gole  *				duration, and overhead of register reads and
1563936afd9fSDhruva Gole  *				checks are on top of this and can vary based on
1564936afd9fSDhruva Gole  *				varied conditions.
1565936afd9fSDhruva Gole  * @delay_before_iterations_us	Specifies how long to wait (in micro seconds)
1566936afd9fSDhruva Gole  *				before the very first check in the first
1567936afd9fSDhruva Gole  *				iteration of status check loop. This is the
1568936afd9fSDhruva Gole  *				minimum duration, and overhead of register
1569936afd9fSDhruva Gole  *				reads and checks are.
1570936afd9fSDhruva Gole  * @status_flags_1_set_all_wait	If non-zero, Specifies that all bits of the
1571936afd9fSDhruva Gole  *				status matching this field requested MUST be 1.
1572936afd9fSDhruva Gole  * @status_flags_1_set_any_wait	If non-zero, Specifies that at least one of the
1573936afd9fSDhruva Gole  *				bits matching this field requested MUST be 1.
1574936afd9fSDhruva Gole  * @status_flags_1_clr_all_wait	If non-zero, Specifies that all bits of the
1575936afd9fSDhruva Gole  *				status matching this field requested MUST be 0.
1576936afd9fSDhruva Gole  * @status_flags_1_clr_any_wait	If non-zero, Specifies that at least one of the
1577936afd9fSDhruva Gole  *				bits matching this field requested MUST be 0.
1578936afd9fSDhruva Gole  *
1579936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1580936afd9fSDhruva Gole  */
1581936afd9fSDhruva Gole int ti_sci_proc_wait_boot_status(uint8_t proc_id, uint8_t num_wait_iterations,
1582936afd9fSDhruva Gole 				 uint8_t num_match_iterations,
1583936afd9fSDhruva Gole 				 uint8_t delay_per_iteration_us,
1584936afd9fSDhruva Gole 				 uint8_t delay_before_iterations_us,
1585936afd9fSDhruva Gole 				 uint32_t status_flags_1_set_all_wait,
1586936afd9fSDhruva Gole 				 uint32_t status_flags_1_set_any_wait,
1587936afd9fSDhruva Gole 				 uint32_t status_flags_1_clr_all_wait,
1588936afd9fSDhruva Gole 				 uint32_t status_flags_1_clr_any_wait)
1589936afd9fSDhruva Gole {
1590936afd9fSDhruva Gole 	struct ti_sci_msg_req_wait_proc_boot_status req;
1591936afd9fSDhruva Gole 	struct ti_sci_msg_hdr resp;
1592936afd9fSDhruva Gole 
1593936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1594936afd9fSDhruva Gole 	int ret;
1595936afd9fSDhruva Gole 
1596936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0,
1597936afd9fSDhruva Gole 				    &req, sizeof(req),
1598936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1599936afd9fSDhruva Gole 				    &xfer);
1600936afd9fSDhruva Gole 	if (ret) {
1601936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1602936afd9fSDhruva Gole 		return ret;
1603936afd9fSDhruva Gole 	}
1604936afd9fSDhruva Gole 
1605936afd9fSDhruva Gole 	req.processor_id = proc_id;
1606936afd9fSDhruva Gole 	req.num_wait_iterations = num_wait_iterations;
1607936afd9fSDhruva Gole 	req.num_match_iterations = num_match_iterations;
1608936afd9fSDhruva Gole 	req.delay_per_iteration_us = delay_per_iteration_us;
1609936afd9fSDhruva Gole 	req.delay_before_iterations_us = delay_before_iterations_us;
1610936afd9fSDhruva Gole 	req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
1611936afd9fSDhruva Gole 	req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
1612936afd9fSDhruva Gole 	req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
1613936afd9fSDhruva Gole 	req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
1614936afd9fSDhruva Gole 
1615936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1616936afd9fSDhruva Gole 	if (ret) {
1617936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1618936afd9fSDhruva Gole 		return ret;
1619936afd9fSDhruva Gole 	}
1620936afd9fSDhruva Gole 
1621936afd9fSDhruva Gole 	return 0;
1622936afd9fSDhruva Gole }
1623936afd9fSDhruva Gole 
1624936afd9fSDhruva Gole /**
1625936afd9fSDhruva Gole  * ti_sci_proc_wait_boot_status_no_wait() - Wait for a processor boot status
1626936afd9fSDhruva Gole  *					    without requesting or waiting for
1627936afd9fSDhruva Gole  *					    a response.
1628936afd9fSDhruva Gole  *
1629936afd9fSDhruva Gole  * @proc_id:			Processor ID this request is for
1630936afd9fSDhruva Gole  * @num_wait_iterations		Total number of iterations we will check before
1631936afd9fSDhruva Gole  *				we will timeout and give up
1632936afd9fSDhruva Gole  * @num_match_iterations	How many iterations should we have continued
1633936afd9fSDhruva Gole  *				status to account for status bits glitching.
1634936afd9fSDhruva Gole  *				This is to make sure that match occurs for
1635936afd9fSDhruva Gole  *				consecutive checks. This implies that the
1636936afd9fSDhruva Gole  *				worst case should consider that the stable
1637936afd9fSDhruva Gole  *				time should at the worst be num_wait_iterations
1638936afd9fSDhruva Gole  *				num_match_iterations to prevent timeout.
1639936afd9fSDhruva Gole  * @delay_per_iteration_us	Specifies how long to wait (in micro seconds)
1640936afd9fSDhruva Gole  *				between each status checks. This is the minimum
1641936afd9fSDhruva Gole  *				duration, and overhead of register reads and
1642936afd9fSDhruva Gole  *				checks are on top of this and can vary based on
1643936afd9fSDhruva Gole  *				varied conditions.
1644936afd9fSDhruva Gole  * @delay_before_iterations_us	Specifies how long to wait (in micro seconds)
1645936afd9fSDhruva Gole  *				before the very first check in the first
1646936afd9fSDhruva Gole  *				iteration of status check loop. This is the
1647936afd9fSDhruva Gole  *				minimum duration, and overhead of register
1648936afd9fSDhruva Gole  *				reads and checks are.
1649936afd9fSDhruva Gole  * @status_flags_1_set_all_wait	If non-zero, Specifies that all bits of the
1650936afd9fSDhruva Gole  *				status matching this field requested MUST be 1.
1651936afd9fSDhruva Gole  * @status_flags_1_set_any_wait	If non-zero, Specifies that at least one of the
1652936afd9fSDhruva Gole  *				bits matching this field requested MUST be 1.
1653936afd9fSDhruva Gole  * @status_flags_1_clr_all_wait	If non-zero, Specifies that all bits of the
1654936afd9fSDhruva Gole  *				status matching this field requested MUST be 0.
1655936afd9fSDhruva Gole  * @status_flags_1_clr_any_wait	If non-zero, Specifies that at least one of the
1656936afd9fSDhruva Gole  *				bits matching this field requested MUST be 0.
1657936afd9fSDhruva Gole  *
1658936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1659936afd9fSDhruva Gole  */
1660936afd9fSDhruva Gole int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id,
1661936afd9fSDhruva Gole 					 uint8_t num_wait_iterations,
1662936afd9fSDhruva Gole 					 uint8_t num_match_iterations,
1663936afd9fSDhruva Gole 					 uint8_t delay_per_iteration_us,
1664936afd9fSDhruva Gole 					 uint8_t delay_before_iterations_us,
1665936afd9fSDhruva Gole 					 uint32_t status_flags_1_set_all_wait,
1666936afd9fSDhruva Gole 					 uint32_t status_flags_1_set_any_wait,
1667936afd9fSDhruva Gole 					 uint32_t status_flags_1_clr_all_wait,
1668936afd9fSDhruva Gole 					 uint32_t status_flags_1_clr_any_wait)
1669936afd9fSDhruva Gole {
1670936afd9fSDhruva Gole 	struct ti_sci_msg_req_wait_proc_boot_status req;
1671936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1672936afd9fSDhruva Gole 	int ret;
1673936afd9fSDhruva Gole 
1674936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0,
1675936afd9fSDhruva Gole 				    &req, sizeof(req),
1676936afd9fSDhruva Gole 				    NULL, 0,
1677936afd9fSDhruva Gole 				    &xfer);
1678936afd9fSDhruva Gole 	if (ret != 0U) {
1679936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1680936afd9fSDhruva Gole 		return ret;
1681936afd9fSDhruva Gole 	}
1682936afd9fSDhruva Gole 
1683936afd9fSDhruva Gole 	req.processor_id = proc_id;
1684936afd9fSDhruva Gole 	req.num_wait_iterations = num_wait_iterations;
1685936afd9fSDhruva Gole 	req.num_match_iterations = num_match_iterations;
1686936afd9fSDhruva Gole 	req.delay_per_iteration_us = delay_per_iteration_us;
1687936afd9fSDhruva Gole 	req.delay_before_iterations_us = delay_before_iterations_us;
1688936afd9fSDhruva Gole 	req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
1689936afd9fSDhruva Gole 	req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
1690936afd9fSDhruva Gole 	req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
1691936afd9fSDhruva Gole 	req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
1692936afd9fSDhruva Gole 
1693936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1694936afd9fSDhruva Gole 	if (ret != 0U) {
1695936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1696936afd9fSDhruva Gole 		return ret;
1697936afd9fSDhruva Gole 	}
1698936afd9fSDhruva Gole 
1699936afd9fSDhruva Gole 	return 0;
1700936afd9fSDhruva Gole }
1701936afd9fSDhruva Gole 
1702936afd9fSDhruva Gole /**
1703936afd9fSDhruva Gole  * ti_sci_enter_sleep - Command to initiate system transition into suspend.
1704936afd9fSDhruva Gole  *
1705936afd9fSDhruva Gole  * @proc_id: Processor ID.
1706936afd9fSDhruva Gole  * @mode: Low power mode to enter.
1707936afd9fSDhruva Gole  * @core_resume_addr: Address that core should be
1708936afd9fSDhruva Gole  *		      resumed from after low power transition.
1709936afd9fSDhruva Gole  *
1710936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1711936afd9fSDhruva Gole  */
1712936afd9fSDhruva Gole int ti_sci_enter_sleep(uint8_t proc_id,
1713936afd9fSDhruva Gole 		       uint8_t mode,
1714936afd9fSDhruva Gole 		       uint64_t core_resume_addr)
1715936afd9fSDhruva Gole {
1716936afd9fSDhruva Gole 	struct ti_sci_msg_req_enter_sleep req;
1717936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1718936afd9fSDhruva Gole 	int ret;
1719936afd9fSDhruva Gole 
1720936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_ENTER_SLEEP, 0,
1721936afd9fSDhruva Gole 				    &req, sizeof(req),
1722936afd9fSDhruva Gole 				    NULL, 0,
1723936afd9fSDhruva Gole 				    &xfer);
1724936afd9fSDhruva Gole 	if (ret != 0U) {
1725936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1726936afd9fSDhruva Gole 		return ret;
1727936afd9fSDhruva Gole 	}
1728936afd9fSDhruva Gole 
1729936afd9fSDhruva Gole 	req.processor_id = proc_id;
1730936afd9fSDhruva Gole 	req.mode = mode;
1731936afd9fSDhruva Gole 	req.core_resume_lo = core_resume_addr & TISCI_ADDR_LOW_MASK;
1732936afd9fSDhruva Gole 	req.core_resume_hi = (core_resume_addr & TISCI_ADDR_HIGH_MASK) >>
1733936afd9fSDhruva Gole 			     TISCI_ADDR_HIGH_SHIFT;
1734936afd9fSDhruva Gole 
1735936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1736936afd9fSDhruva Gole 	if (ret != 0U) {
1737936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1738936afd9fSDhruva Gole 		return ret;
1739936afd9fSDhruva Gole 	}
1740936afd9fSDhruva Gole 
1741936afd9fSDhruva Gole 	return 0;
1742936afd9fSDhruva Gole }
1743936afd9fSDhruva Gole 
1744936afd9fSDhruva Gole /**
1745936afd9fSDhruva Gole  * ti_sci_lpm_get_next_sys_mode() - Get next LPM system mode
1746936afd9fSDhruva Gole  *
1747936afd9fSDhruva Gole  * @next_mode:	pointer to a variable that will store the next mode
1748936afd9fSDhruva Gole  *
1749936afd9fSDhruva Gole  * Return: 0 if all goes well, else appropriate error message
1750936afd9fSDhruva Gole  */
1751936afd9fSDhruva Gole int ti_sci_lpm_get_next_sys_mode(uint8_t *next_mode)
1752936afd9fSDhruva Gole {
1753936afd9fSDhruva Gole 	struct ti_sci_msg_req_lpm_get_next_sys_mode req;
1754936afd9fSDhruva Gole 	struct ti_sci_msg_resp_lpm_get_next_sys_mode resp;
1755936afd9fSDhruva Gole 	struct ti_sci_xfer xfer;
1756936afd9fSDhruva Gole 	int ret;
1757936afd9fSDhruva Gole 
1758936afd9fSDhruva Gole 	if (next_mode == NULL) {
1759936afd9fSDhruva Gole 		return -EINVAL;
1760936afd9fSDhruva Gole 	}
1761936afd9fSDhruva Gole 
1762936afd9fSDhruva Gole 	ret = ti_sci_setup_one_xfer(TI_SCI_MSG_LPM_GET_NEXT_SYS_MODE, 0,
1763936afd9fSDhruva Gole 				    &req, sizeof(req),
1764936afd9fSDhruva Gole 				    &resp, sizeof(resp),
1765936afd9fSDhruva Gole 				    &xfer);
1766936afd9fSDhruva Gole 	if (ret != 0) {
1767936afd9fSDhruva Gole 		ERROR("Message alloc failed (%d)\n", ret);
1768936afd9fSDhruva Gole 		return ret;
1769936afd9fSDhruva Gole 	}
1770936afd9fSDhruva Gole 
1771936afd9fSDhruva Gole 	ret = ti_sci_do_xfer(&xfer);
1772936afd9fSDhruva Gole 	if (ret != 0) {
1773936afd9fSDhruva Gole 		ERROR("Transfer send failed (%d)\n", ret);
1774936afd9fSDhruva Gole 		return ret;
1775936afd9fSDhruva Gole 	}
1776936afd9fSDhruva Gole 
1777936afd9fSDhruva Gole 	*next_mode = resp.mode;
1778936afd9fSDhruva Gole 
1779936afd9fSDhruva Gole 	return 0;
1780936afd9fSDhruva Gole }
1781