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