xref: /openbmc/u-boot/drivers/firmware/ti_sci.c (revision d1e15041)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Texas Instruments System Control Interface Protocol Driver
4  * Based on drivers/firmware/ti_sci.c from Linux.
5  *
6  * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
7  *	Lokesh Vutla <lokeshvutla@ti.com>
8  */
9 
10 #include <common.h>
11 #include <dm.h>
12 #include <errno.h>
13 #include <mailbox.h>
14 #include <dm/device.h>
15 #include <linux/err.h>
16 #include <linux/soc/ti/k3-sec-proxy.h>
17 #include <linux/soc/ti/ti_sci_protocol.h>
18 
19 #include "ti_sci.h"
20 
21 /* List of all TI SCI devices active in system */
22 static LIST_HEAD(ti_sci_list);
23 
24 /**
25  * struct ti_sci_xfer - Structure representing a message flow
26  * @tx_message:	Transmit message
27  * @rx_len:	Receive message length
28  */
29 struct ti_sci_xfer {
30 	struct k3_sec_proxy_msg tx_message;
31 	u8 rx_len;
32 };
33 
34 /**
35  * struct ti_sci_desc - Description of SoC integration
36  * @host_id:		Host identifier representing the compute entity
37  * @max_rx_timeout_us:	Timeout for communication with SoC (in Microseconds)
38  * @max_msg_size:	Maximum size of data per message that can be handled.
39  */
40 struct ti_sci_desc {
41 	u8 host_id;
42 	int max_rx_timeout_us;
43 	int max_msg_size;
44 };
45 
46 /**
47  * struct ti_sci_info - Structure representing a TI SCI instance
48  * @dev:	Device pointer
49  * @desc:	SoC description for this instance
50  * @handle:	Instance of TI SCI handle to send to clients.
51  * @chan_tx:	Transmit mailbox channel
52  * @chan_rx:	Receive mailbox channel
53  * @xfer:	xfer info
54  * @list:	list head
55  * @is_secure:	Determines if the communication is through secure threads.
56  * @host_id:	Host identifier representing the compute entity
57  * @seq:	Seq id used for verification for tx and rx message.
58  */
59 struct ti_sci_info {
60 	struct udevice *dev;
61 	const struct ti_sci_desc *desc;
62 	struct ti_sci_handle handle;
63 	struct mbox_chan chan_tx;
64 	struct mbox_chan chan_rx;
65 	struct mbox_chan chan_notify;
66 	struct ti_sci_xfer xfer;
67 	struct list_head list;
68 	bool is_secure;
69 	u8 host_id;
70 	u8 seq;
71 };
72 
73 #define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
74 
75 /**
76  * ti_sci_setup_one_xfer() - Setup one message type
77  * @info:	Pointer to SCI entity information
78  * @msg_type:	Message type
79  * @msg_flags:	Flag to set for the message
80  * @buf:	Buffer to be send to mailbox channel
81  * @tx_message_size: transmit message size
82  * @rx_message_size: receive message size
83  *
84  * Helper function which is used by various command functions that are
85  * exposed to clients of this driver for allocating a message traffic event.
86  *
87  * Return: Corresponding ti_sci_xfer pointer if all went fine,
88  *	   else appropriate error pointer.
89  */
ti_sci_setup_one_xfer(struct ti_sci_info * info,u16 msg_type,u32 msg_flags,u32 * buf,size_t tx_message_size,size_t rx_message_size)90 static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info,
91 						 u16 msg_type, u32 msg_flags,
92 						 u32 *buf,
93 						 size_t tx_message_size,
94 						 size_t rx_message_size)
95 {
96 	struct ti_sci_xfer *xfer = &info->xfer;
97 	struct ti_sci_msg_hdr *hdr;
98 
99 	/* Ensure we have sane transfer sizes */
100 	if (rx_message_size > info->desc->max_msg_size ||
101 	    tx_message_size > info->desc->max_msg_size ||
102 	    rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr))
103 		return ERR_PTR(-ERANGE);
104 
105 	info->seq = ~info->seq;
106 	xfer->tx_message.buf = buf;
107 	xfer->tx_message.len = tx_message_size;
108 	xfer->rx_len = (u8)rx_message_size;
109 
110 	hdr = (struct ti_sci_msg_hdr *)buf;
111 	hdr->seq = info->seq;
112 	hdr->type = msg_type;
113 	hdr->host = info->host_id;
114 	hdr->flags = msg_flags;
115 
116 	return xfer;
117 }
118 
119 /**
120  * ti_sci_get_response() - Receive response from mailbox channel
121  * @info:	Pointer to SCI entity information
122  * @xfer:	Transfer to initiate and wait for response
123  * @chan:	Channel to receive the response
124  *
125  * Return: -ETIMEDOUT in case of no response, if transmit error,
126  *	   return corresponding error, else if all goes well,
127  *	   return 0.
128  */
ti_sci_get_response(struct ti_sci_info * info,struct ti_sci_xfer * xfer,struct mbox_chan * chan)129 static inline int ti_sci_get_response(struct ti_sci_info *info,
130 				      struct ti_sci_xfer *xfer,
131 				      struct mbox_chan *chan)
132 {
133 	struct k3_sec_proxy_msg *msg = &xfer->tx_message;
134 	struct ti_sci_secure_msg_hdr *secure_hdr;
135 	struct ti_sci_msg_hdr *hdr;
136 	int ret;
137 
138 	/* Receive the response */
139 	ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_us);
140 	if (ret) {
141 		dev_err(info->dev, "%s: Message receive failed. ret = %d\n",
142 			__func__, ret);
143 		return ret;
144 	}
145 
146 	/* ToDo: Verify checksum */
147 	if (info->is_secure) {
148 		secure_hdr = (struct ti_sci_secure_msg_hdr *)msg->buf;
149 		msg->buf = (u32 *)((void *)msg->buf + sizeof(*secure_hdr));
150 	}
151 
152 	/* msg is updated by mailbox driver */
153 	hdr = (struct ti_sci_msg_hdr *)msg->buf;
154 
155 	/* Sanity check for message response */
156 	if (hdr->seq != info->seq) {
157 		dev_dbg(info->dev, "%s: Message for %d is not expected\n",
158 			__func__, hdr->seq);
159 		return ret;
160 	}
161 
162 	if (msg->len > info->desc->max_msg_size) {
163 		dev_err(info->dev, "%s: Unable to handle %zu xfer (max %d)\n",
164 			__func__, msg->len, info->desc->max_msg_size);
165 		return -EINVAL;
166 	}
167 
168 	if (msg->len < xfer->rx_len) {
169 		dev_err(info->dev, "%s: Recv xfer %zu < expected %d length\n",
170 			__func__, msg->len, xfer->rx_len);
171 	}
172 
173 	return ret;
174 }
175 
176 /**
177  * ti_sci_do_xfer() - Do one transfer
178  * @info:	Pointer to SCI entity information
179  * @xfer:	Transfer to initiate and wait for response
180  *
181  * Return: 0 if all went fine, else return appropriate error.
182  */
ti_sci_do_xfer(struct ti_sci_info * info,struct ti_sci_xfer * xfer)183 static inline int ti_sci_do_xfer(struct ti_sci_info *info,
184 				 struct ti_sci_xfer *xfer)
185 {
186 	struct k3_sec_proxy_msg *msg = &xfer->tx_message;
187 	u8 secure_buf[info->desc->max_msg_size];
188 	struct ti_sci_secure_msg_hdr secure_hdr;
189 	int ret;
190 
191 	if (info->is_secure) {
192 		/* ToDo: get checksum of the entire message */
193 		secure_hdr.checksum = 0;
194 		secure_hdr.reserved = 0;
195 		memcpy(&secure_buf[sizeof(secure_hdr)], xfer->tx_message.buf,
196 		       xfer->tx_message.len);
197 
198 		xfer->tx_message.buf = (u32 *)secure_buf;
199 		xfer->tx_message.len += sizeof(secure_hdr);
200 		xfer->rx_len += sizeof(secure_hdr);
201 	}
202 
203 	/* Send the message */
204 	ret = mbox_send(&info->chan_tx, msg);
205 	if (ret) {
206 		dev_err(info->dev, "%s: Message sending failed. ret = %d\n",
207 			__func__, ret);
208 		return ret;
209 	}
210 
211 	return ti_sci_get_response(info, xfer, &info->chan_rx);
212 }
213 
214 /**
215  * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
216  * @handle:	pointer to TI SCI handle
217  *
218  * Updates the SCI information in the internal data structure.
219  *
220  * Return: 0 if all went fine, else return appropriate error.
221  */
ti_sci_cmd_get_revision(struct ti_sci_handle * handle)222 static int ti_sci_cmd_get_revision(struct ti_sci_handle *handle)
223 {
224 	struct ti_sci_msg_resp_version *rev_info;
225 	struct ti_sci_version_info *ver;
226 	struct ti_sci_msg_hdr hdr;
227 	struct ti_sci_info *info;
228 	struct ti_sci_xfer *xfer;
229 	int ret;
230 
231 	if (IS_ERR(handle))
232 		return PTR_ERR(handle);
233 	if (!handle)
234 		return -EINVAL;
235 
236 	info = handle_to_ti_sci_info(handle);
237 
238 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION, 0x0,
239 				     (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr),
240 				     sizeof(*rev_info));
241 	if (IS_ERR(xfer)) {
242 		ret = PTR_ERR(xfer);
243 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
244 		return ret;
245 	}
246 
247 	ret = ti_sci_do_xfer(info, xfer);
248 	if (ret) {
249 		dev_err(info->dev, "Mbox communication fail %d\n", ret);
250 		return ret;
251 	}
252 
253 	rev_info = (struct ti_sci_msg_resp_version *)xfer->tx_message.buf;
254 
255 	ver = &handle->version;
256 	ver->abi_major = rev_info->abi_major;
257 	ver->abi_minor = rev_info->abi_minor;
258 	ver->firmware_revision = rev_info->firmware_revision;
259 	strncpy(ver->firmware_description, rev_info->firmware_description,
260 		sizeof(ver->firmware_description));
261 
262 	return 0;
263 }
264 
265 /**
266  * ti_sci_is_response_ack() - Generic ACK/NACK message checkup
267  * @r:	pointer to response buffer
268  *
269  * Return: true if the response was an ACK, else returns false.
270  */
ti_sci_is_response_ack(void * r)271 static inline bool ti_sci_is_response_ack(void *r)
272 {
273 	struct ti_sci_msg_hdr *hdr = r;
274 
275 	return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
276 }
277 
278 /**
279  * cmd_set_board_config_using_msg() - Common command to send board configuration
280  *                                    message
281  * @handle:	pointer to TI SCI handle
282  * @msg_type:	One of the TISCI message types to set board configuration
283  * @addr:	Address where the board config structure is located
284  * @size:	Size of the board config structure
285  *
286  * Return: 0 if all went well, else returns appropriate error value.
287  */
cmd_set_board_config_using_msg(const struct ti_sci_handle * handle,u16 msg_type,u64 addr,u32 size)288 static int cmd_set_board_config_using_msg(const struct ti_sci_handle *handle,
289 					  u16 msg_type, u64 addr, u32 size)
290 {
291 	struct ti_sci_msg_board_config req;
292 	struct ti_sci_msg_hdr *resp;
293 	struct ti_sci_info *info;
294 	struct ti_sci_xfer *xfer;
295 	int ret = 0;
296 
297 	if (IS_ERR(handle))
298 		return PTR_ERR(handle);
299 	if (!handle)
300 		return -EINVAL;
301 
302 	info = handle_to_ti_sci_info(handle);
303 
304 	xfer = ti_sci_setup_one_xfer(info, msg_type,
305 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
306 				     (u32 *)&req, sizeof(req), sizeof(*resp));
307 	if (IS_ERR(xfer)) {
308 		ret = PTR_ERR(xfer);
309 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
310 		return ret;
311 	}
312 	req.boardcfgp_high = (addr >> 32) & 0xffffffff;
313 	req.boardcfgp_low = addr & 0xffffffff;
314 	req.boardcfg_size = size;
315 
316 	ret = ti_sci_do_xfer(info, xfer);
317 	if (ret) {
318 		dev_err(info->dev, "Mbox send fail %d\n", ret);
319 		return ret;
320 	}
321 
322 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
323 
324 	if (!ti_sci_is_response_ack(resp))
325 		return -ENODEV;
326 
327 	return ret;
328 }
329 
330 /**
331  * ti_sci_cmd_set_board_config() - Command to send board configuration message
332  * @handle:	pointer to TI SCI handle
333  * @addr:	Address where the board config structure is located
334  * @size:	Size of the board config structure
335  *
336  * Return: 0 if all went well, else returns appropriate error value.
337  */
ti_sci_cmd_set_board_config(const struct ti_sci_handle * handle,u64 addr,u32 size)338 static int ti_sci_cmd_set_board_config(const struct ti_sci_handle *handle,
339 				       u64 addr, u32 size)
340 {
341 	return cmd_set_board_config_using_msg(handle,
342 					      TI_SCI_MSG_BOARD_CONFIG,
343 					      addr, size);
344 }
345 
346 /**
347  * ti_sci_cmd_set_board_config_rm() - Command to send board resource
348  *				      management configuration
349  * @handle:	pointer to TI SCI handle
350  * @addr:	Address where the board RM config structure is located
351  * @size:	Size of the RM config structure
352  *
353  * Return: 0 if all went well, else returns appropriate error value.
354  */
355 static
ti_sci_cmd_set_board_config_rm(const struct ti_sci_handle * handle,u64 addr,u32 size)356 int ti_sci_cmd_set_board_config_rm(const struct ti_sci_handle *handle,
357 				   u64 addr, u32 size)
358 {
359 	return cmd_set_board_config_using_msg(handle,
360 					      TI_SCI_MSG_BOARD_CONFIG_RM,
361 					      addr, size);
362 }
363 
364 /**
365  * ti_sci_cmd_set_board_config_security() - Command to send board security
366  *					    configuration message
367  * @handle:	pointer to TI SCI handle
368  * @addr:	Address where the board security config structure is located
369  * @size:	Size of the security config structure
370  *
371  * Return: 0 if all went well, else returns appropriate error value.
372  */
373 static
ti_sci_cmd_set_board_config_security(const struct ti_sci_handle * handle,u64 addr,u32 size)374 int ti_sci_cmd_set_board_config_security(const struct ti_sci_handle *handle,
375 					 u64 addr, u32 size)
376 {
377 	return cmd_set_board_config_using_msg(handle,
378 					      TI_SCI_MSG_BOARD_CONFIG_SECURITY,
379 					      addr, size);
380 }
381 
382 /**
383  * ti_sci_cmd_set_board_config_pm() - Command to send board power and clock
384  *				      configuration message
385  * @handle:	pointer to TI SCI handle
386  * @addr:	Address where the board PM config structure is located
387  * @size:	Size of the PM config structure
388  *
389  * Return: 0 if all went well, else returns appropriate error value.
390  */
ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle * handle,u64 addr,u32 size)391 static int ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle *handle,
392 					  u64 addr, u32 size)
393 {
394 	return cmd_set_board_config_using_msg(handle,
395 					      TI_SCI_MSG_BOARD_CONFIG_PM,
396 					      addr, size);
397 }
398 
399 /**
400  * ti_sci_set_device_state() - Set device state helper
401  * @handle:	pointer to TI SCI handle
402  * @id:		Device identifier
403  * @flags:	flags to setup for the device
404  * @state:	State to move the device to
405  *
406  * Return: 0 if all went well, else returns appropriate error value.
407  */
ti_sci_set_device_state(const struct ti_sci_handle * handle,u32 id,u32 flags,u8 state)408 static int ti_sci_set_device_state(const struct ti_sci_handle *handle,
409 				   u32 id, u32 flags, u8 state)
410 {
411 	struct ti_sci_msg_req_set_device_state req;
412 	struct ti_sci_msg_hdr *resp;
413 	struct ti_sci_info *info;
414 	struct ti_sci_xfer *xfer;
415 	int ret = 0;
416 
417 	if (IS_ERR(handle))
418 		return PTR_ERR(handle);
419 	if (!handle)
420 		return -EINVAL;
421 
422 	info = handle_to_ti_sci_info(handle);
423 
424 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
425 				     flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
426 				     (u32 *)&req, sizeof(req), sizeof(*resp));
427 	if (IS_ERR(xfer)) {
428 		ret = PTR_ERR(xfer);
429 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
430 		return ret;
431 	}
432 	req.id = id;
433 	req.state = state;
434 
435 	ret = ti_sci_do_xfer(info, xfer);
436 	if (ret) {
437 		dev_err(info->dev, "Mbox send fail %d\n", ret);
438 		return ret;
439 	}
440 
441 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
442 
443 	if (!ti_sci_is_response_ack(resp))
444 		return -ENODEV;
445 
446 	return ret;
447 }
448 
449 /**
450  * ti_sci_get_device_state() - Get device state helper
451  * @handle:	Handle to the device
452  * @id:		Device Identifier
453  * @clcnt:	Pointer to Context Loss Count
454  * @resets:	pointer to resets
455  * @p_state:	pointer to p_state
456  * @c_state:	pointer to c_state
457  *
458  * Return: 0 if all went fine, else return appropriate error.
459  */
ti_sci_get_device_state(const struct ti_sci_handle * handle,u32 id,u32 * clcnt,u32 * resets,u8 * p_state,u8 * c_state)460 static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
461 				   u32 id,  u32 *clcnt,  u32 *resets,
462 				   u8 *p_state,  u8 *c_state)
463 {
464 	struct ti_sci_msg_resp_get_device_state *resp;
465 	struct ti_sci_msg_req_get_device_state req;
466 	struct ti_sci_info *info;
467 	struct ti_sci_xfer *xfer;
468 	int ret = 0;
469 
470 	if (IS_ERR(handle))
471 		return PTR_ERR(handle);
472 	if (!handle)
473 		return -EINVAL;
474 
475 	if (!clcnt && !resets && !p_state && !c_state)
476 		return -EINVAL;
477 
478 	info = handle_to_ti_sci_info(handle);
479 
480 	/* Response is expected, so need of any flags */
481 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE, 0,
482 				     (u32 *)&req, sizeof(req), sizeof(*resp));
483 	if (IS_ERR(xfer)) {
484 		ret = PTR_ERR(xfer);
485 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
486 		return ret;
487 	}
488 	req.id = id;
489 
490 	ret = ti_sci_do_xfer(info, xfer);
491 	if (ret) {
492 		dev_err(dev, "Mbox send fail %d\n", ret);
493 		return ret;
494 	}
495 
496 	resp = (struct ti_sci_msg_resp_get_device_state *)xfer->tx_message.buf;
497 	if (!ti_sci_is_response_ack(resp))
498 		return -ENODEV;
499 
500 	if (clcnt)
501 		*clcnt = resp->context_loss_count;
502 	if (resets)
503 		*resets = resp->resets;
504 	if (p_state)
505 		*p_state = resp->programmed_state;
506 	if (c_state)
507 		*c_state = resp->current_state;
508 
509 	return ret;
510 }
511 
512 /**
513  * ti_sci_cmd_get_device() - command to request for device managed by TISCI
514  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
515  * @id:		Device Identifier
516  *
517  * Request for the device - NOTE: the client MUST maintain integrity of
518  * usage count by balancing get_device with put_device. No refcounting is
519  * managed by driver for that purpose.
520  *
521  * NOTE: The request is for exclusive access for the processor.
522  *
523  * Return: 0 if all went fine, else return appropriate error.
524  */
ti_sci_cmd_get_device(const struct ti_sci_handle * handle,u32 id)525 static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
526 {
527 	return ti_sci_set_device_state(handle, id,
528 				       MSG_FLAG_DEVICE_EXCLUSIVE,
529 				       MSG_DEVICE_SW_STATE_ON);
530 }
531 
532 /**
533  * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI
534  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
535  * @id:		Device Identifier
536  *
537  * Request for the device - NOTE: the client MUST maintain integrity of
538  * usage count by balancing get_device with put_device. No refcounting is
539  * managed by driver for that purpose.
540  *
541  * Return: 0 if all went fine, else return appropriate error.
542  */
ti_sci_cmd_idle_device(const struct ti_sci_handle * handle,u32 id)543 static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
544 {
545 	return ti_sci_set_device_state(handle, id,
546 				       MSG_FLAG_DEVICE_EXCLUSIVE,
547 				       MSG_DEVICE_SW_STATE_RETENTION);
548 }
549 
550 /**
551  * ti_sci_cmd_put_device() - command to release a device managed by TISCI
552  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
553  * @id:		Device Identifier
554  *
555  * Request for the device - NOTE: the client MUST maintain integrity of
556  * usage count by balancing get_device with put_device. No refcounting is
557  * managed by driver for that purpose.
558  *
559  * Return: 0 if all went fine, else return appropriate error.
560  */
ti_sci_cmd_put_device(const struct ti_sci_handle * handle,u32 id)561 static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id)
562 {
563 	return ti_sci_set_device_state(handle, id,
564 				       0, MSG_DEVICE_SW_STATE_AUTO_OFF);
565 }
566 
567 /**
568  * ti_sci_cmd_dev_is_valid() - Is the device valid
569  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
570  * @id:		Device Identifier
571  *
572  * Return: 0 if all went fine and the device ID is valid, else return
573  * appropriate error.
574  */
ti_sci_cmd_dev_is_valid(const struct ti_sci_handle * handle,u32 id)575 static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id)
576 {
577 	u8 unused;
578 
579 	/* check the device state which will also tell us if the ID is valid */
580 	return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused);
581 }
582 
583 /**
584  * ti_sci_cmd_dev_get_clcnt() - Get context loss counter
585  * @handle:	Pointer to TISCI handle
586  * @id:		Device Identifier
587  * @count:	Pointer to Context Loss counter to populate
588  *
589  * Return: 0 if all went fine, else return appropriate error.
590  */
ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle * handle,u32 id,u32 * count)591 static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id,
592 				    u32 *count)
593 {
594 	return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL);
595 }
596 
597 /**
598  * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle
599  * @handle:	Pointer to TISCI handle
600  * @id:		Device Identifier
601  * @r_state:	true if requested to be idle
602  *
603  * Return: 0 if all went fine, else return appropriate error.
604  */
ti_sci_cmd_dev_is_idle(const struct ti_sci_handle * handle,u32 id,bool * r_state)605 static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id,
606 				  bool *r_state)
607 {
608 	int ret;
609 	u8 state;
610 
611 	if (!r_state)
612 		return -EINVAL;
613 
614 	ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL);
615 	if (ret)
616 		return ret;
617 
618 	*r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
619 
620 	return 0;
621 }
622 
623 /**
624  * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped
625  * @handle:	Pointer to TISCI handle
626  * @id:		Device Identifier
627  * @r_state:	true if requested to be stopped
628  * @curr_state:	true if currently stopped.
629  *
630  * Return: 0 if all went fine, else return appropriate error.
631  */
ti_sci_cmd_dev_is_stop(const struct ti_sci_handle * handle,u32 id,bool * r_state,bool * curr_state)632 static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id,
633 				  bool *r_state,  bool *curr_state)
634 {
635 	int ret;
636 	u8 p_state, c_state;
637 
638 	if (!r_state && !curr_state)
639 		return -EINVAL;
640 
641 	ret =
642 	    ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
643 	if (ret)
644 		return ret;
645 
646 	if (r_state)
647 		*r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
648 	if (curr_state)
649 		*curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
650 
651 	return 0;
652 }
653 
654 /**
655  * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON
656  * @handle:	Pointer to TISCI handle
657  * @id:		Device Identifier
658  * @r_state:	true if requested to be ON
659  * @curr_state:	true if currently ON and active
660  *
661  * Return: 0 if all went fine, else return appropriate error.
662  */
ti_sci_cmd_dev_is_on(const struct ti_sci_handle * handle,u32 id,bool * r_state,bool * curr_state)663 static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id,
664 				bool *r_state,  bool *curr_state)
665 {
666 	int ret;
667 	u8 p_state, c_state;
668 
669 	if (!r_state && !curr_state)
670 		return -EINVAL;
671 
672 	ret =
673 	    ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
674 	if (ret)
675 		return ret;
676 
677 	if (r_state)
678 		*r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
679 	if (curr_state)
680 		*curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
681 
682 	return 0;
683 }
684 
685 /**
686  * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning
687  * @handle:	Pointer to TISCI handle
688  * @id:		Device Identifier
689  * @curr_state:	true if currently transitioning.
690  *
691  * Return: 0 if all went fine, else return appropriate error.
692  */
ti_sci_cmd_dev_is_trans(const struct ti_sci_handle * handle,u32 id,bool * curr_state)693 static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id,
694 				   bool *curr_state)
695 {
696 	int ret;
697 	u8 state;
698 
699 	if (!curr_state)
700 		return -EINVAL;
701 
702 	ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state);
703 	if (ret)
704 		return ret;
705 
706 	*curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
707 
708 	return 0;
709 }
710 
711 /**
712  * ti_sci_cmd_set_device_resets() - command to set resets for device managed
713  *				    by TISCI
714  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
715  * @id:		Device Identifier
716  * @reset_state: Device specific reset bit field
717  *
718  * Return: 0 if all went fine, else return appropriate error.
719  */
ti_sci_cmd_set_device_resets(const struct ti_sci_handle * handle,u32 id,u32 reset_state)720 static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle,
721 					u32 id, u32 reset_state)
722 {
723 	struct ti_sci_msg_req_set_device_resets req;
724 	struct ti_sci_msg_hdr *resp;
725 	struct ti_sci_info *info;
726 	struct ti_sci_xfer *xfer;
727 	int ret = 0;
728 
729 	if (IS_ERR(handle))
730 		return PTR_ERR(handle);
731 	if (!handle)
732 		return -EINVAL;
733 
734 	info = handle_to_ti_sci_info(handle);
735 
736 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS,
737 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
738 				     (u32 *)&req, sizeof(req), sizeof(*resp));
739 	if (IS_ERR(xfer)) {
740 		ret = PTR_ERR(xfer);
741 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
742 		return ret;
743 	}
744 	req.id = id;
745 	req.resets = reset_state;
746 
747 	ret = ti_sci_do_xfer(info, xfer);
748 	if (ret) {
749 		dev_err(info->dev, "Mbox send fail %d\n", ret);
750 		return ret;
751 	}
752 
753 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
754 
755 	if (!ti_sci_is_response_ack(resp))
756 		return -ENODEV;
757 
758 	return ret;
759 }
760 
761 /**
762  * ti_sci_cmd_get_device_resets() - Get reset state for device managed
763  *				    by TISCI
764  * @handle:		Pointer to TISCI handle
765  * @id:			Device Identifier
766  * @reset_state:	Pointer to reset state to populate
767  *
768  * Return: 0 if all went fine, else return appropriate error.
769  */
ti_sci_cmd_get_device_resets(const struct ti_sci_handle * handle,u32 id,u32 * reset_state)770 static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle,
771 					u32 id, u32 *reset_state)
772 {
773 	return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL,
774 				       NULL);
775 }
776 
777 /**
778  * ti_sci_set_clock_state() - Set clock state helper
779  * @handle:	pointer to TI SCI handle
780  * @dev_id:	Device identifier this request is for
781  * @clk_id:	Clock identifier for the device for this request.
782  *		Each device has it's own set of clock inputs. This indexes
783  *		which clock input to modify.
784  * @flags:	Header flags as needed
785  * @state:	State to request for the clock.
786  *
787  * Return: 0 if all went well, else returns appropriate error value.
788  */
ti_sci_set_clock_state(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u32 flags,u8 state)789 static int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
790 				  u32 dev_id, u8 clk_id,
791 				  u32 flags, u8 state)
792 {
793 	struct ti_sci_msg_req_set_clock_state req;
794 	struct ti_sci_msg_hdr *resp;
795 	struct ti_sci_info *info;
796 	struct ti_sci_xfer *xfer;
797 	int ret = 0;
798 
799 	if (IS_ERR(handle))
800 		return PTR_ERR(handle);
801 	if (!handle)
802 		return -EINVAL;
803 
804 	info = handle_to_ti_sci_info(handle);
805 
806 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
807 				     flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
808 				     (u32 *)&req, sizeof(req), sizeof(*resp));
809 	if (IS_ERR(xfer)) {
810 		ret = PTR_ERR(xfer);
811 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
812 		return ret;
813 	}
814 	req.dev_id = dev_id;
815 	req.clk_id = clk_id;
816 	req.request_state = state;
817 
818 	ret = ti_sci_do_xfer(info, xfer);
819 	if (ret) {
820 		dev_err(info->dev, "Mbox send fail %d\n", ret);
821 		return ret;
822 	}
823 
824 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
825 
826 	if (!ti_sci_is_response_ack(resp))
827 		return -ENODEV;
828 
829 	return ret;
830 }
831 
832 /**
833  * ti_sci_cmd_get_clock_state() - Get clock state helper
834  * @handle:	pointer to TI SCI handle
835  * @dev_id:	Device identifier this request is for
836  * @clk_id:	Clock identifier for the device for this request.
837  *		Each device has it's own set of clock inputs. This indexes
838  *		which clock input to modify.
839  * @programmed_state:	State requested for clock to move to
840  * @current_state:	State that the clock is currently in
841  *
842  * Return: 0 if all went well, else returns appropriate error value.
843  */
ti_sci_cmd_get_clock_state(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u8 * programmed_state,u8 * current_state)844 static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
845 				      u32 dev_id, u8 clk_id,
846 				      u8 *programmed_state, u8 *current_state)
847 {
848 	struct ti_sci_msg_resp_get_clock_state *resp;
849 	struct ti_sci_msg_req_get_clock_state req;
850 	struct ti_sci_info *info;
851 	struct ti_sci_xfer *xfer;
852 	int ret = 0;
853 
854 	if (IS_ERR(handle))
855 		return PTR_ERR(handle);
856 	if (!handle)
857 		return -EINVAL;
858 
859 	if (!programmed_state && !current_state)
860 		return -EINVAL;
861 
862 	info = handle_to_ti_sci_info(handle);
863 
864 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
865 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
866 				     (u32 *)&req, sizeof(req), sizeof(*resp));
867 	if (IS_ERR(xfer)) {
868 		ret = PTR_ERR(xfer);
869 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
870 		return ret;
871 	}
872 	req.dev_id = dev_id;
873 	req.clk_id = clk_id;
874 
875 	ret = ti_sci_do_xfer(info, xfer);
876 	if (ret) {
877 		dev_err(info->dev, "Mbox send fail %d\n", ret);
878 		return ret;
879 	}
880 
881 	resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->tx_message.buf;
882 
883 	if (!ti_sci_is_response_ack(resp))
884 		return -ENODEV;
885 
886 	if (programmed_state)
887 		*programmed_state = resp->programmed_state;
888 	if (current_state)
889 		*current_state = resp->current_state;
890 
891 	return ret;
892 }
893 
894 /**
895  * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
896  * @handle:	pointer to TI SCI handle
897  * @dev_id:	Device identifier this request is for
898  * @clk_id:	Clock identifier for the device for this request.
899  *		Each device has it's own set of clock inputs. This indexes
900  *		which clock input to modify.
901  * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
902  * @can_change_freq: 'true' if frequency change is desired, else 'false'
903  * @enable_input_term: 'true' if input termination is desired, else 'false'
904  *
905  * Return: 0 if all went well, else returns appropriate error value.
906  */
ti_sci_cmd_get_clock(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,bool needs_ssc,bool can_change_freq,bool enable_input_term)907 static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
908 				u8 clk_id, bool needs_ssc, bool can_change_freq,
909 				bool enable_input_term)
910 {
911 	u32 flags = 0;
912 
913 	flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
914 	flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
915 	flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
916 
917 	return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
918 				      MSG_CLOCK_SW_STATE_REQ);
919 }
920 
921 /**
922  * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
923  * @handle:	pointer to TI SCI handle
924  * @dev_id:	Device identifier this request is for
925  * @clk_id:	Clock identifier for the device for this request.
926  *		Each device has it's own set of clock inputs. This indexes
927  *		which clock input to modify.
928  *
929  * NOTE: This clock must have been requested by get_clock previously.
930  *
931  * Return: 0 if all went well, else returns appropriate error value.
932  */
ti_sci_cmd_idle_clock(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id)933 static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
934 				 u32 dev_id, u8 clk_id)
935 {
936 	return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
937 				      MSG_CLOCK_SW_STATE_UNREQ);
938 }
939 
940 /**
941  * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
942  * @handle:	pointer to TI SCI handle
943  * @dev_id:	Device identifier this request is for
944  * @clk_id:	Clock identifier for the device for this request.
945  *		Each device has it's own set of clock inputs. This indexes
946  *		which clock input to modify.
947  *
948  * NOTE: This clock must have been requested by get_clock previously.
949  *
950  * Return: 0 if all went well, else returns appropriate error value.
951  */
ti_sci_cmd_put_clock(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id)952 static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
953 				u32 dev_id, u8 clk_id)
954 {
955 	return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
956 				      MSG_CLOCK_SW_STATE_AUTO);
957 }
958 
959 /**
960  * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
961  * @handle:	pointer to TI SCI handle
962  * @dev_id:	Device identifier this request is for
963  * @clk_id:	Clock identifier for the device for this request.
964  *		Each device has it's own set of clock inputs. This indexes
965  *		which clock input to modify.
966  * @req_state: state indicating if the clock is auto managed
967  *
968  * Return: 0 if all went well, else returns appropriate error value.
969  */
ti_sci_cmd_clk_is_auto(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,bool * req_state)970 static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
971 				  u32 dev_id, u8 clk_id, bool *req_state)
972 {
973 	u8 state = 0;
974 	int ret;
975 
976 	if (!req_state)
977 		return -EINVAL;
978 
979 	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
980 	if (ret)
981 		return ret;
982 
983 	*req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
984 	return 0;
985 }
986 
987 /**
988  * ti_sci_cmd_clk_is_on() - Is the clock ON
989  * @handle:	pointer to TI SCI handle
990  * @dev_id:	Device identifier this request is for
991  * @clk_id:	Clock identifier for the device for this request.
992  *		Each device has it's own set of clock inputs. This indexes
993  *		which clock input to modify.
994  * @req_state: state indicating if the clock is managed by us and enabled
995  * @curr_state: state indicating if the clock is ready for operation
996  *
997  * Return: 0 if all went well, else returns appropriate error value.
998  */
ti_sci_cmd_clk_is_on(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,bool * req_state,bool * curr_state)999 static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
1000 				u8 clk_id, bool *req_state, bool *curr_state)
1001 {
1002 	u8 c_state = 0, r_state = 0;
1003 	int ret;
1004 
1005 	if (!req_state && !curr_state)
1006 		return -EINVAL;
1007 
1008 	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1009 					 &r_state, &c_state);
1010 	if (ret)
1011 		return ret;
1012 
1013 	if (req_state)
1014 		*req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
1015 	if (curr_state)
1016 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
1017 	return 0;
1018 }
1019 
1020 /**
1021  * ti_sci_cmd_clk_is_off() - Is the clock OFF
1022  * @handle:	pointer to TI SCI handle
1023  * @dev_id:	Device identifier this request is for
1024  * @clk_id:	Clock identifier for the device for this request.
1025  *		Each device has it's own set of clock inputs. This indexes
1026  *		which clock input to modify.
1027  * @req_state: state indicating if the clock is managed by us and disabled
1028  * @curr_state: state indicating if the clock is NOT ready for operation
1029  *
1030  * Return: 0 if all went well, else returns appropriate error value.
1031  */
ti_sci_cmd_clk_is_off(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,bool * req_state,bool * curr_state)1032 static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
1033 				 u8 clk_id, bool *req_state, bool *curr_state)
1034 {
1035 	u8 c_state = 0, r_state = 0;
1036 	int ret;
1037 
1038 	if (!req_state && !curr_state)
1039 		return -EINVAL;
1040 
1041 	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1042 					 &r_state, &c_state);
1043 	if (ret)
1044 		return ret;
1045 
1046 	if (req_state)
1047 		*req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
1048 	if (curr_state)
1049 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
1050 	return 0;
1051 }
1052 
1053 /**
1054  * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
1055  * @handle:	pointer to TI SCI handle
1056  * @dev_id:	Device identifier this request is for
1057  * @clk_id:	Clock identifier for the device for this request.
1058  *		Each device has it's own set of clock inputs. This indexes
1059  *		which clock input to modify.
1060  * @parent_id:	Parent clock identifier to set
1061  *
1062  * Return: 0 if all went well, else returns appropriate error value.
1063  */
ti_sci_cmd_clk_set_parent(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u8 parent_id)1064 static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
1065 				     u32 dev_id, u8 clk_id, u8 parent_id)
1066 {
1067 	struct ti_sci_msg_req_set_clock_parent req;
1068 	struct ti_sci_msg_hdr *resp;
1069 	struct ti_sci_info *info;
1070 	struct ti_sci_xfer *xfer;
1071 	int ret = 0;
1072 
1073 	if (IS_ERR(handle))
1074 		return PTR_ERR(handle);
1075 	if (!handle)
1076 		return -EINVAL;
1077 
1078 	info = handle_to_ti_sci_info(handle);
1079 
1080 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
1081 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1082 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1083 	if (IS_ERR(xfer)) {
1084 		ret = PTR_ERR(xfer);
1085 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1086 		return ret;
1087 	}
1088 	req.dev_id = dev_id;
1089 	req.clk_id = clk_id;
1090 	req.parent_id = parent_id;
1091 
1092 	ret = ti_sci_do_xfer(info, xfer);
1093 	if (ret) {
1094 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1095 		return ret;
1096 	}
1097 
1098 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1099 
1100 	if (!ti_sci_is_response_ack(resp))
1101 		return -ENODEV;
1102 
1103 	return ret;
1104 }
1105 
1106 /**
1107  * ti_sci_cmd_clk_get_parent() - Get current parent clock source
1108  * @handle:	pointer to TI SCI handle
1109  * @dev_id:	Device identifier this request is for
1110  * @clk_id:	Clock identifier for the device for this request.
1111  *		Each device has it's own set of clock inputs. This indexes
1112  *		which clock input to modify.
1113  * @parent_id:	Current clock parent
1114  *
1115  * Return: 0 if all went well, else returns appropriate error value.
1116  */
ti_sci_cmd_clk_get_parent(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u8 * parent_id)1117 static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
1118 				     u32 dev_id, u8 clk_id, u8 *parent_id)
1119 {
1120 	struct ti_sci_msg_resp_get_clock_parent *resp;
1121 	struct ti_sci_msg_req_get_clock_parent req;
1122 	struct ti_sci_info *info;
1123 	struct ti_sci_xfer *xfer;
1124 	int ret = 0;
1125 
1126 	if (IS_ERR(handle))
1127 		return PTR_ERR(handle);
1128 	if (!handle || !parent_id)
1129 		return -EINVAL;
1130 
1131 	info = handle_to_ti_sci_info(handle);
1132 
1133 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
1134 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1135 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1136 	if (IS_ERR(xfer)) {
1137 		ret = PTR_ERR(xfer);
1138 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1139 		return ret;
1140 	}
1141 	req.dev_id = dev_id;
1142 	req.clk_id = clk_id;
1143 
1144 	ret = ti_sci_do_xfer(info, xfer);
1145 	if (ret) {
1146 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1147 		return ret;
1148 	}
1149 
1150 	resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->tx_message.buf;
1151 
1152 	if (!ti_sci_is_response_ack(resp))
1153 		ret = -ENODEV;
1154 	else
1155 		*parent_id = resp->parent_id;
1156 
1157 	return ret;
1158 }
1159 
1160 /**
1161  * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source
1162  * @handle:	pointer to TI SCI handle
1163  * @dev_id:	Device identifier this request is for
1164  * @clk_id:	Clock identifier for the device for this request.
1165  *		Each device has it's own set of clock inputs. This indexes
1166  *		which clock input to modify.
1167  * @num_parents: Returns he number of parents to the current clock.
1168  *
1169  * Return: 0 if all went well, else returns appropriate error value.
1170  */
ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u8 * num_parents)1171 static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
1172 					  u32 dev_id, u8 clk_id,
1173 					  u8 *num_parents)
1174 {
1175 	struct ti_sci_msg_resp_get_clock_num_parents *resp;
1176 	struct ti_sci_msg_req_get_clock_num_parents req;
1177 	struct ti_sci_info *info;
1178 	struct ti_sci_xfer *xfer;
1179 	int ret = 0;
1180 
1181 	if (IS_ERR(handle))
1182 		return PTR_ERR(handle);
1183 	if (!handle || !num_parents)
1184 		return -EINVAL;
1185 
1186 	info = handle_to_ti_sci_info(handle);
1187 
1188 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
1189 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1190 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1191 	if (IS_ERR(xfer)) {
1192 		ret = PTR_ERR(xfer);
1193 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1194 		return ret;
1195 	}
1196 	req.dev_id = dev_id;
1197 	req.clk_id = clk_id;
1198 
1199 	ret = ti_sci_do_xfer(info, xfer);
1200 	if (ret) {
1201 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1202 		return ret;
1203 	}
1204 
1205 	resp = (struct ti_sci_msg_resp_get_clock_num_parents *)
1206 							xfer->tx_message.buf;
1207 
1208 	if (!ti_sci_is_response_ack(resp))
1209 		ret = -ENODEV;
1210 	else
1211 		*num_parents = resp->num_parents;
1212 
1213 	return ret;
1214 }
1215 
1216 /**
1217  * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
1218  * @handle:	pointer to TI SCI handle
1219  * @dev_id:	Device identifier this request is for
1220  * @clk_id:	Clock identifier for the device for this request.
1221  *		Each device has it's own set of clock inputs. This indexes
1222  *		which clock input to modify.
1223  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
1224  *		allowable programmed frequency and does not account for clock
1225  *		tolerances and jitter.
1226  * @target_freq: The target clock frequency in Hz. A frequency will be
1227  *		processed as close to this target frequency as possible.
1228  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
1229  *		allowable programmed frequency and does not account for clock
1230  *		tolerances and jitter.
1231  * @match_freq:	Frequency match in Hz response.
1232  *
1233  * Return: 0 if all went well, else returns appropriate error value.
1234  */
ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u64 min_freq,u64 target_freq,u64 max_freq,u64 * match_freq)1235 static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
1236 					 u32 dev_id, u8 clk_id, u64 min_freq,
1237 					 u64 target_freq, u64 max_freq,
1238 					 u64 *match_freq)
1239 {
1240 	struct ti_sci_msg_resp_query_clock_freq *resp;
1241 	struct ti_sci_msg_req_query_clock_freq req;
1242 	struct ti_sci_info *info;
1243 	struct ti_sci_xfer *xfer;
1244 	int ret = 0;
1245 
1246 	if (IS_ERR(handle))
1247 		return PTR_ERR(handle);
1248 	if (!handle || !match_freq)
1249 		return -EINVAL;
1250 
1251 	info = handle_to_ti_sci_info(handle);
1252 
1253 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
1254 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1255 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1256 	if (IS_ERR(xfer)) {
1257 		ret = PTR_ERR(xfer);
1258 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1259 		return ret;
1260 	}
1261 	req.dev_id = dev_id;
1262 	req.clk_id = clk_id;
1263 	req.min_freq_hz = min_freq;
1264 	req.target_freq_hz = target_freq;
1265 	req.max_freq_hz = max_freq;
1266 
1267 	ret = ti_sci_do_xfer(info, xfer);
1268 	if (ret) {
1269 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1270 		return ret;
1271 	}
1272 
1273 	resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->tx_message.buf;
1274 
1275 	if (!ti_sci_is_response_ack(resp))
1276 		ret = -ENODEV;
1277 	else
1278 		*match_freq = resp->freq_hz;
1279 
1280 	return ret;
1281 }
1282 
1283 /**
1284  * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
1285  * @handle:	pointer to TI SCI handle
1286  * @dev_id:	Device identifier this request is for
1287  * @clk_id:	Clock identifier for the device for this request.
1288  *		Each device has it's own set of clock inputs. This indexes
1289  *		which clock input to modify.
1290  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
1291  *		allowable programmed frequency and does not account for clock
1292  *		tolerances and jitter.
1293  * @target_freq: The target clock frequency in Hz. A frequency will be
1294  *		processed as close to this target frequency as possible.
1295  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
1296  *		allowable programmed frequency and does not account for clock
1297  *		tolerances and jitter.
1298  *
1299  * Return: 0 if all went well, else returns appropriate error value.
1300  */
ti_sci_cmd_clk_set_freq(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u64 min_freq,u64 target_freq,u64 max_freq)1301 static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
1302 				   u32 dev_id, u8 clk_id, u64 min_freq,
1303 				   u64 target_freq, u64 max_freq)
1304 {
1305 	struct ti_sci_msg_req_set_clock_freq req;
1306 	struct ti_sci_msg_hdr *resp;
1307 	struct ti_sci_info *info;
1308 	struct ti_sci_xfer *xfer;
1309 	int ret = 0;
1310 
1311 	if (IS_ERR(handle))
1312 		return PTR_ERR(handle);
1313 	if (!handle)
1314 		return -EINVAL;
1315 
1316 	info = handle_to_ti_sci_info(handle);
1317 
1318 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
1319 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1320 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1321 	if (IS_ERR(xfer)) {
1322 		ret = PTR_ERR(xfer);
1323 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1324 		return ret;
1325 	}
1326 	req.dev_id = dev_id;
1327 	req.clk_id = clk_id;
1328 	req.min_freq_hz = min_freq;
1329 	req.target_freq_hz = target_freq;
1330 	req.max_freq_hz = max_freq;
1331 
1332 	ret = ti_sci_do_xfer(info, xfer);
1333 	if (ret) {
1334 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1335 		return ret;
1336 	}
1337 
1338 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1339 
1340 	if (!ti_sci_is_response_ack(resp))
1341 		return -ENODEV;
1342 
1343 	return ret;
1344 }
1345 
1346 /**
1347  * ti_sci_cmd_clk_get_freq() - Get current frequency
1348  * @handle:	pointer to TI SCI handle
1349  * @dev_id:	Device identifier this request is for
1350  * @clk_id:	Clock identifier for the device for this request.
1351  *		Each device has it's own set of clock inputs. This indexes
1352  *		which clock input to modify.
1353  * @freq:	Currently frequency in Hz
1354  *
1355  * Return: 0 if all went well, else returns appropriate error value.
1356  */
ti_sci_cmd_clk_get_freq(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u64 * freq)1357 static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
1358 				   u32 dev_id, u8 clk_id, u64 *freq)
1359 {
1360 	struct ti_sci_msg_resp_get_clock_freq *resp;
1361 	struct ti_sci_msg_req_get_clock_freq req;
1362 	struct ti_sci_info *info;
1363 	struct ti_sci_xfer *xfer;
1364 	int ret = 0;
1365 
1366 	if (IS_ERR(handle))
1367 		return PTR_ERR(handle);
1368 	if (!handle || !freq)
1369 		return -EINVAL;
1370 
1371 	info = handle_to_ti_sci_info(handle);
1372 
1373 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
1374 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1375 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1376 	if (IS_ERR(xfer)) {
1377 		ret = PTR_ERR(xfer);
1378 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1379 		return ret;
1380 	}
1381 	req.dev_id = dev_id;
1382 	req.clk_id = clk_id;
1383 
1384 	ret = ti_sci_do_xfer(info, xfer);
1385 	if (ret) {
1386 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1387 		return ret;
1388 	}
1389 
1390 	resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->tx_message.buf;
1391 
1392 	if (!ti_sci_is_response_ack(resp))
1393 		ret = -ENODEV;
1394 	else
1395 		*freq = resp->freq_hz;
1396 
1397 	return ret;
1398 }
1399 
1400 /**
1401  * ti_sci_cmd_core_reboot() - Command to request system reset
1402  * @handle:	pointer to TI SCI handle
1403  *
1404  * Return: 0 if all went well, else returns appropriate error value.
1405  */
ti_sci_cmd_core_reboot(const struct ti_sci_handle * handle)1406 static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
1407 {
1408 	struct ti_sci_msg_req_reboot req;
1409 	struct ti_sci_msg_hdr *resp;
1410 	struct ti_sci_info *info;
1411 	struct ti_sci_xfer *xfer;
1412 	int ret = 0;
1413 
1414 	if (IS_ERR(handle))
1415 		return PTR_ERR(handle);
1416 	if (!handle)
1417 		return -EINVAL;
1418 
1419 	info = handle_to_ti_sci_info(handle);
1420 
1421 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SYS_RESET,
1422 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1423 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1424 	if (IS_ERR(xfer)) {
1425 		ret = PTR_ERR(xfer);
1426 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1427 		return ret;
1428 	}
1429 
1430 	ret = ti_sci_do_xfer(info, xfer);
1431 	if (ret) {
1432 		dev_err(dev, "Mbox send fail %d\n", ret);
1433 		return ret;
1434 	}
1435 
1436 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1437 
1438 	if (!ti_sci_is_response_ack(resp))
1439 		return -ENODEV;
1440 
1441 	return ret;
1442 }
1443 
1444 /**
1445  * ti_sci_cmd_proc_request() - Command to request a physical processor control
1446  * @handle:	Pointer to TI SCI handle
1447  * @proc_id:	Processor ID this request is for
1448  *
1449  * Return: 0 if all went well, else returns appropriate error value.
1450  */
ti_sci_cmd_proc_request(const struct ti_sci_handle * handle,u8 proc_id)1451 static int ti_sci_cmd_proc_request(const struct ti_sci_handle *handle,
1452 				   u8 proc_id)
1453 {
1454 	struct ti_sci_msg_req_proc_request req;
1455 	struct ti_sci_msg_hdr *resp;
1456 	struct ti_sci_info *info;
1457 	struct ti_sci_xfer *xfer;
1458 	int ret = 0;
1459 
1460 	if (IS_ERR(handle))
1461 		return PTR_ERR(handle);
1462 	if (!handle)
1463 		return -EINVAL;
1464 
1465 	info = handle_to_ti_sci_info(handle);
1466 
1467 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_REQUEST,
1468 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1469 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1470 	if (IS_ERR(xfer)) {
1471 		ret = PTR_ERR(xfer);
1472 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1473 		return ret;
1474 	}
1475 	req.processor_id = proc_id;
1476 
1477 	ret = ti_sci_do_xfer(info, xfer);
1478 	if (ret) {
1479 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1480 		return ret;
1481 	}
1482 
1483 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1484 
1485 	if (!ti_sci_is_response_ack(resp))
1486 		ret = -ENODEV;
1487 
1488 	return ret;
1489 }
1490 
1491 /**
1492  * ti_sci_cmd_proc_release() - Command to release a physical processor control
1493  * @handle:	Pointer to TI SCI handle
1494  * @proc_id:	Processor ID this request is for
1495  *
1496  * Return: 0 if all went well, else returns appropriate error value.
1497  */
ti_sci_cmd_proc_release(const struct ti_sci_handle * handle,u8 proc_id)1498 static int ti_sci_cmd_proc_release(const struct ti_sci_handle *handle,
1499 				   u8 proc_id)
1500 {
1501 	struct ti_sci_msg_req_proc_release req;
1502 	struct ti_sci_msg_hdr *resp;
1503 	struct ti_sci_info *info;
1504 	struct ti_sci_xfer *xfer;
1505 	int ret = 0;
1506 
1507 	if (IS_ERR(handle))
1508 		return PTR_ERR(handle);
1509 	if (!handle)
1510 		return -EINVAL;
1511 
1512 	info = handle_to_ti_sci_info(handle);
1513 
1514 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_RELEASE,
1515 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1516 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1517 	if (IS_ERR(xfer)) {
1518 		ret = PTR_ERR(xfer);
1519 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1520 		return ret;
1521 	}
1522 	req.processor_id = proc_id;
1523 
1524 	ret = ti_sci_do_xfer(info, xfer);
1525 	if (ret) {
1526 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1527 		return ret;
1528 	}
1529 
1530 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1531 
1532 	if (!ti_sci_is_response_ack(resp))
1533 		ret = -ENODEV;
1534 
1535 	return ret;
1536 }
1537 
1538 /**
1539  * ti_sci_cmd_proc_handover() - Command to handover a physical processor
1540  *				control to a host in the processor's access
1541  *				control list.
1542  * @handle:	Pointer to TI SCI handle
1543  * @proc_id:	Processor ID this request is for
1544  * @host_id:	Host ID to get the control of the processor
1545  *
1546  * Return: 0 if all went well, else returns appropriate error value.
1547  */
ti_sci_cmd_proc_handover(const struct ti_sci_handle * handle,u8 proc_id,u8 host_id)1548 static int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle,
1549 				    u8 proc_id, u8 host_id)
1550 {
1551 	struct ti_sci_msg_req_proc_handover req;
1552 	struct ti_sci_msg_hdr *resp;
1553 	struct ti_sci_info *info;
1554 	struct ti_sci_xfer *xfer;
1555 	int ret = 0;
1556 
1557 	if (IS_ERR(handle))
1558 		return PTR_ERR(handle);
1559 	if (!handle)
1560 		return -EINVAL;
1561 
1562 	info = handle_to_ti_sci_info(handle);
1563 
1564 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_HANDOVER,
1565 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1566 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1567 	if (IS_ERR(xfer)) {
1568 		ret = PTR_ERR(xfer);
1569 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1570 		return ret;
1571 	}
1572 	req.processor_id = proc_id;
1573 	req.host_id = host_id;
1574 
1575 	ret = ti_sci_do_xfer(info, xfer);
1576 	if (ret) {
1577 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1578 		return ret;
1579 	}
1580 
1581 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1582 
1583 	if (!ti_sci_is_response_ack(resp))
1584 		ret = -ENODEV;
1585 
1586 	return ret;
1587 }
1588 
1589 /**
1590  * ti_sci_cmd_set_proc_boot_cfg() - Command to set the processor boot
1591  *				    configuration flags
1592  * @handle:		Pointer to TI SCI handle
1593  * @proc_id:		Processor ID this request is for
1594  * @config_flags_set:	Configuration flags to be set
1595  * @config_flags_clear:	Configuration flags to be cleared.
1596  *
1597  * Return: 0 if all went well, else returns appropriate error value.
1598  */
ti_sci_cmd_set_proc_boot_cfg(const struct ti_sci_handle * handle,u8 proc_id,u64 bootvector,u32 config_flags_set,u32 config_flags_clear)1599 static int ti_sci_cmd_set_proc_boot_cfg(const struct ti_sci_handle *handle,
1600 					u8 proc_id, u64 bootvector,
1601 					u32 config_flags_set,
1602 					u32 config_flags_clear)
1603 {
1604 	struct ti_sci_msg_req_set_proc_boot_config req;
1605 	struct ti_sci_msg_hdr *resp;
1606 	struct ti_sci_info *info;
1607 	struct ti_sci_xfer *xfer;
1608 	int ret = 0;
1609 
1610 	if (IS_ERR(handle))
1611 		return PTR_ERR(handle);
1612 	if (!handle)
1613 		return -EINVAL;
1614 
1615 	info = handle_to_ti_sci_info(handle);
1616 
1617 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CONFIG,
1618 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1619 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1620 	if (IS_ERR(xfer)) {
1621 		ret = PTR_ERR(xfer);
1622 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1623 		return ret;
1624 	}
1625 	req.processor_id = proc_id;
1626 	req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
1627 	req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
1628 				TISCI_ADDR_HIGH_SHIFT;
1629 	req.config_flags_set = config_flags_set;
1630 	req.config_flags_clear = config_flags_clear;
1631 
1632 	ret = ti_sci_do_xfer(info, xfer);
1633 	if (ret) {
1634 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1635 		return ret;
1636 	}
1637 
1638 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1639 
1640 	if (!ti_sci_is_response_ack(resp))
1641 		ret = -ENODEV;
1642 
1643 	return ret;
1644 }
1645 
1646 /**
1647  * ti_sci_cmd_set_proc_boot_ctrl() - Command to set the processor boot
1648  *				     control flags
1649  * @handle:			Pointer to TI SCI handle
1650  * @proc_id:			Processor ID this request is for
1651  * @control_flags_set:		Control flags to be set
1652  * @control_flags_clear:	Control flags to be cleared
1653  *
1654  * Return: 0 if all went well, else returns appropriate error value.
1655  */
ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle * handle,u8 proc_id,u32 control_flags_set,u32 control_flags_clear)1656 static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle,
1657 					 u8 proc_id, u32 control_flags_set,
1658 					 u32 control_flags_clear)
1659 {
1660 	struct ti_sci_msg_req_set_proc_boot_ctrl req;
1661 	struct ti_sci_msg_hdr *resp;
1662 	struct ti_sci_info *info;
1663 	struct ti_sci_xfer *xfer;
1664 	int ret = 0;
1665 
1666 	if (IS_ERR(handle))
1667 		return PTR_ERR(handle);
1668 	if (!handle)
1669 		return -EINVAL;
1670 
1671 	info = handle_to_ti_sci_info(handle);
1672 
1673 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CTRL,
1674 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1675 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1676 	if (IS_ERR(xfer)) {
1677 		ret = PTR_ERR(xfer);
1678 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1679 		return ret;
1680 	}
1681 	req.processor_id = proc_id;
1682 	req.control_flags_set = control_flags_set;
1683 	req.control_flags_clear = control_flags_clear;
1684 
1685 	ret = ti_sci_do_xfer(info, xfer);
1686 	if (ret) {
1687 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1688 		return ret;
1689 	}
1690 
1691 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1692 
1693 	if (!ti_sci_is_response_ack(resp))
1694 		ret = -ENODEV;
1695 
1696 	return ret;
1697 }
1698 
1699 /**
1700  * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the
1701  *			image and then set the processor configuration flags.
1702  * @handle:	Pointer to TI SCI handle
1703  * @proc_id:	Processor ID this request is for
1704  * @cert_addr:	Memory address at which payload image certificate is located.
1705  *
1706  * Return: 0 if all went well, else returns appropriate error value.
1707  */
ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle * handle,u8 proc_id,u64 cert_addr)1708 static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle,
1709 					   u8 proc_id, u64 cert_addr)
1710 {
1711 	struct ti_sci_msg_req_proc_auth_boot_image req;
1712 	struct ti_sci_msg_hdr *resp;
1713 	struct ti_sci_info *info;
1714 	struct ti_sci_xfer *xfer;
1715 	int ret = 0;
1716 
1717 	if (IS_ERR(handle))
1718 		return PTR_ERR(handle);
1719 	if (!handle)
1720 		return -EINVAL;
1721 
1722 	info = handle_to_ti_sci_info(handle);
1723 
1724 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_BOOT_IMIAGE,
1725 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1726 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1727 	if (IS_ERR(xfer)) {
1728 		ret = PTR_ERR(xfer);
1729 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1730 		return ret;
1731 	}
1732 	req.processor_id = proc_id;
1733 	req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
1734 	req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
1735 				TISCI_ADDR_HIGH_SHIFT;
1736 
1737 	ret = ti_sci_do_xfer(info, xfer);
1738 	if (ret) {
1739 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1740 		return ret;
1741 	}
1742 
1743 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1744 
1745 	if (!ti_sci_is_response_ack(resp))
1746 		ret = -ENODEV;
1747 
1748 	return ret;
1749 }
1750 
1751 /**
1752  * ti_sci_cmd_get_proc_boot_status() - Command to get the processor boot status
1753  * @handle:	Pointer to TI SCI handle
1754  * @proc_id:	Processor ID this request is for
1755  *
1756  * Return: 0 if all went well, else returns appropriate error value.
1757  */
ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle * handle,u8 proc_id,u64 * bv,u32 * cfg_flags,u32 * ctrl_flags,u32 * sts_flags)1758 static int ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle *handle,
1759 					   u8 proc_id, u64 *bv, u32 *cfg_flags,
1760 					   u32 *ctrl_flags, u32 *sts_flags)
1761 {
1762 	struct ti_sci_msg_resp_get_proc_boot_status *resp;
1763 	struct ti_sci_msg_req_get_proc_boot_status req;
1764 	struct ti_sci_info *info;
1765 	struct ti_sci_xfer *xfer;
1766 	int ret = 0;
1767 
1768 	if (IS_ERR(handle))
1769 		return PTR_ERR(handle);
1770 	if (!handle)
1771 		return -EINVAL;
1772 
1773 	info = handle_to_ti_sci_info(handle);
1774 
1775 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_GET_PROC_BOOT_STATUS,
1776 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1777 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1778 	if (IS_ERR(xfer)) {
1779 		ret = PTR_ERR(xfer);
1780 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1781 		return ret;
1782 	}
1783 	req.processor_id = proc_id;
1784 
1785 	ret = ti_sci_do_xfer(info, xfer);
1786 	if (ret) {
1787 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1788 		return ret;
1789 	}
1790 
1791 	resp = (struct ti_sci_msg_resp_get_proc_boot_status *)
1792 							xfer->tx_message.buf;
1793 
1794 	if (!ti_sci_is_response_ack(resp))
1795 		return -ENODEV;
1796 	*bv = (resp->bootvector_low & TISCI_ADDR_LOW_MASK) |
1797 			(((u64)resp->bootvector_high  <<
1798 			  TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
1799 	*cfg_flags = resp->config_flags;
1800 	*ctrl_flags = resp->control_flags;
1801 	*sts_flags = resp->status_flags;
1802 
1803 	return ret;
1804 }
1805 
1806 /*
1807  * ti_sci_setup_ops() - Setup the operations structures
1808  * @info:	pointer to TISCI pointer
1809  */
ti_sci_setup_ops(struct ti_sci_info * info)1810 static void ti_sci_setup_ops(struct ti_sci_info *info)
1811 {
1812 	struct ti_sci_ops *ops = &info->handle.ops;
1813 	struct ti_sci_board_ops *bops = &ops->board_ops;
1814 	struct ti_sci_dev_ops *dops = &ops->dev_ops;
1815 	struct ti_sci_clk_ops *cops = &ops->clk_ops;
1816 	struct ti_sci_core_ops *core_ops = &ops->core_ops;
1817 	struct ti_sci_proc_ops *pops = &ops->proc_ops;
1818 
1819 	bops->board_config = ti_sci_cmd_set_board_config;
1820 	bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
1821 	bops->board_config_security = ti_sci_cmd_set_board_config_security;
1822 	bops->board_config_pm = ti_sci_cmd_set_board_config_pm;
1823 
1824 	dops->get_device = ti_sci_cmd_get_device;
1825 	dops->idle_device = ti_sci_cmd_idle_device;
1826 	dops->put_device = ti_sci_cmd_put_device;
1827 	dops->is_valid = ti_sci_cmd_dev_is_valid;
1828 	dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
1829 	dops->is_idle = ti_sci_cmd_dev_is_idle;
1830 	dops->is_stop = ti_sci_cmd_dev_is_stop;
1831 	dops->is_on = ti_sci_cmd_dev_is_on;
1832 	dops->is_transitioning = ti_sci_cmd_dev_is_trans;
1833 	dops->set_device_resets = ti_sci_cmd_set_device_resets;
1834 	dops->get_device_resets = ti_sci_cmd_get_device_resets;
1835 
1836 	cops->get_clock = ti_sci_cmd_get_clock;
1837 	cops->idle_clock = ti_sci_cmd_idle_clock;
1838 	cops->put_clock = ti_sci_cmd_put_clock;
1839 	cops->is_auto = ti_sci_cmd_clk_is_auto;
1840 	cops->is_on = ti_sci_cmd_clk_is_on;
1841 	cops->is_off = ti_sci_cmd_clk_is_off;
1842 
1843 	cops->set_parent = ti_sci_cmd_clk_set_parent;
1844 	cops->get_parent = ti_sci_cmd_clk_get_parent;
1845 	cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
1846 
1847 	cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
1848 	cops->set_freq = ti_sci_cmd_clk_set_freq;
1849 	cops->get_freq = ti_sci_cmd_clk_get_freq;
1850 
1851 	core_ops->reboot_device = ti_sci_cmd_core_reboot;
1852 
1853 	pops->proc_request = ti_sci_cmd_proc_request;
1854 	pops->proc_release = ti_sci_cmd_proc_release;
1855 	pops->proc_handover = ti_sci_cmd_proc_handover;
1856 	pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg;
1857 	pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl;
1858 	pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image;
1859 	pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status;
1860 }
1861 
1862 /**
1863  * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW
1864  * @dev:	Pointer to the SYSFW device
1865  *
1866  * Return: pointer to handle if successful, else EINVAL if invalid conditions
1867  *         are encountered.
1868  */
1869 const
ti_sci_get_handle_from_sysfw(struct udevice * sci_dev)1870 struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev)
1871 {
1872 	if (!sci_dev)
1873 		return ERR_PTR(-EINVAL);
1874 
1875 	struct ti_sci_info *info = dev_get_priv(sci_dev);
1876 
1877 	if (!info)
1878 		return ERR_PTR(-EINVAL);
1879 
1880 	struct ti_sci_handle *handle = &info->handle;
1881 
1882 	if (!handle)
1883 		return ERR_PTR(-EINVAL);
1884 
1885 	return handle;
1886 }
1887 
1888 /**
1889  * ti_sci_get_handle() - Get the TI SCI handle for a device
1890  * @dev:	Pointer to device for which we want SCI handle
1891  *
1892  * Return: pointer to handle if successful, else EINVAL if invalid conditions
1893  *         are encountered.
1894  */
ti_sci_get_handle(struct udevice * dev)1895 const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev)
1896 {
1897 	if (!dev)
1898 		return ERR_PTR(-EINVAL);
1899 
1900 	struct udevice *sci_dev = dev_get_parent(dev);
1901 
1902 	return ti_sci_get_handle_from_sysfw(sci_dev);
1903 }
1904 
1905 /**
1906  * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
1907  * @dev:	device node
1908  * @propname:	property name containing phandle on TISCI node
1909  *
1910  * Return: pointer to handle if successful, else appropriate error value.
1911  */
ti_sci_get_by_phandle(struct udevice * dev,const char * property)1912 const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev,
1913 						  const char *property)
1914 {
1915 	struct ti_sci_info *entry, *info = NULL;
1916 	u32 phandle, err;
1917 	ofnode node;
1918 
1919 	err = ofnode_read_u32(dev_ofnode(dev), property, &phandle);
1920 	if (err)
1921 		return ERR_PTR(err);
1922 
1923 	node = ofnode_get_by_phandle(phandle);
1924 	if (!ofnode_valid(node))
1925 		return ERR_PTR(-EINVAL);
1926 
1927 	list_for_each_entry(entry, &ti_sci_list, list)
1928 		if (ofnode_equal(dev_ofnode(entry->dev), node)) {
1929 			info = entry;
1930 			break;
1931 		}
1932 
1933 	if (!info)
1934 		return ERR_PTR(-ENODEV);
1935 
1936 	return &info->handle;
1937 }
1938 
1939 /**
1940  * ti_sci_of_to_info() - generate private data from device tree
1941  * @dev:	corresponding system controller interface device
1942  * @info:	pointer to driver specific private data
1943  *
1944  * Return: 0 if all goes good, else appropriate error message.
1945  */
ti_sci_of_to_info(struct udevice * dev,struct ti_sci_info * info)1946 static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info)
1947 {
1948 	int ret;
1949 
1950 	ret = mbox_get_by_name(dev, "tx", &info->chan_tx);
1951 	if (ret) {
1952 		dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n",
1953 			__func__, ret);
1954 		return ret;
1955 	}
1956 
1957 	ret = mbox_get_by_name(dev, "rx", &info->chan_rx);
1958 	if (ret) {
1959 		dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n",
1960 			__func__, ret);
1961 		return ret;
1962 	}
1963 
1964 	/* Notify channel is optional. Enable only if populated */
1965 	ret = mbox_get_by_name(dev, "notify", &info->chan_notify);
1966 	if (ret) {
1967 		dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n",
1968 			__func__, ret);
1969 	}
1970 
1971 	info->host_id = dev_read_u32_default(dev, "ti,host-id",
1972 					     info->desc->host_id);
1973 
1974 	info->is_secure = dev_read_bool(dev, "ti,secure-host");
1975 
1976 	return 0;
1977 }
1978 
1979 /**
1980  * ti_sci_probe() - Basic probe
1981  * @dev:	corresponding system controller interface device
1982  *
1983  * Return: 0 if all goes good, else appropriate error message.
1984  */
ti_sci_probe(struct udevice * dev)1985 static int ti_sci_probe(struct udevice *dev)
1986 {
1987 	struct ti_sci_info *info;
1988 	int ret;
1989 
1990 	debug("%s(dev=%p)\n", __func__, dev);
1991 
1992 	info = dev_get_priv(dev);
1993 	info->desc = (void *)dev_get_driver_data(dev);
1994 
1995 	ret = ti_sci_of_to_info(dev, info);
1996 	if (ret) {
1997 		dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
1998 		return ret;
1999 	}
2000 
2001 	info->dev = dev;
2002 	info->seq = 0xA;
2003 
2004 	list_add_tail(&info->list, &ti_sci_list);
2005 	ti_sci_setup_ops(info);
2006 
2007 	ret = ti_sci_cmd_get_revision(&info->handle);
2008 
2009 	return ret;
2010 }
2011 
2012 /* Description for AM654 */
2013 static const struct ti_sci_desc ti_sci_sysfw_am654_desc = {
2014 	.host_id = 4,
2015 	.max_rx_timeout_us = 1000000,
2016 	.max_msg_size = 60,
2017 };
2018 
2019 static const struct udevice_id ti_sci_ids[] = {
2020 	{
2021 		.compatible = "ti,k2g-sci",
2022 		.data = (ulong)&ti_sci_sysfw_am654_desc
2023 	},
2024 	{ /* Sentinel */ },
2025 };
2026 
2027 U_BOOT_DRIVER(ti_sci) = {
2028 	.name = "ti_sci",
2029 	.id = UCLASS_FIRMWARE,
2030 	.of_match = ti_sci_ids,
2031 	.probe = ti_sci_probe,
2032 	.priv_auto_alloc_size = sizeof(struct ti_sci_info),
2033 };
2034