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