xref: /openbmc/u-boot/drivers/firmware/ti_sci.c (revision d1e15041)
132cd2512SLokesh Vutla // SPDX-License-Identifier: GPL-2.0+
232cd2512SLokesh Vutla /*
332cd2512SLokesh Vutla  * Texas Instruments System Control Interface Protocol Driver
432cd2512SLokesh Vutla  * Based on drivers/firmware/ti_sci.c from Linux.
532cd2512SLokesh Vutla  *
632cd2512SLokesh Vutla  * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
732cd2512SLokesh Vutla  *	Lokesh Vutla <lokeshvutla@ti.com>
832cd2512SLokesh Vutla  */
932cd2512SLokesh Vutla 
1032cd2512SLokesh Vutla #include <common.h>
1132cd2512SLokesh Vutla #include <dm.h>
1232cd2512SLokesh Vutla #include <errno.h>
1332cd2512SLokesh Vutla #include <mailbox.h>
1432cd2512SLokesh Vutla #include <dm/device.h>
1532cd2512SLokesh Vutla #include <linux/err.h>
1632cd2512SLokesh Vutla #include <linux/soc/ti/k3-sec-proxy.h>
1732cd2512SLokesh Vutla #include <linux/soc/ti/ti_sci_protocol.h>
1832cd2512SLokesh Vutla 
1932cd2512SLokesh Vutla #include "ti_sci.h"
2032cd2512SLokesh Vutla 
2132cd2512SLokesh Vutla /* List of all TI SCI devices active in system */
2232cd2512SLokesh Vutla static LIST_HEAD(ti_sci_list);
2332cd2512SLokesh Vutla 
2432cd2512SLokesh Vutla /**
2532cd2512SLokesh Vutla  * struct ti_sci_xfer - Structure representing a message flow
2632cd2512SLokesh Vutla  * @tx_message:	Transmit message
2732cd2512SLokesh Vutla  * @rx_len:	Receive message length
2832cd2512SLokesh Vutla  */
2932cd2512SLokesh Vutla struct ti_sci_xfer {
3032cd2512SLokesh Vutla 	struct k3_sec_proxy_msg tx_message;
3132cd2512SLokesh Vutla 	u8 rx_len;
3232cd2512SLokesh Vutla };
3332cd2512SLokesh Vutla 
3432cd2512SLokesh Vutla /**
3532cd2512SLokesh Vutla  * struct ti_sci_desc - Description of SoC integration
3632cd2512SLokesh Vutla  * @host_id:		Host identifier representing the compute entity
3732cd2512SLokesh Vutla  * @max_rx_timeout_us:	Timeout for communication with SoC (in Microseconds)
3832cd2512SLokesh Vutla  * @max_msg_size:	Maximum size of data per message that can be handled.
3932cd2512SLokesh Vutla  */
4032cd2512SLokesh Vutla struct ti_sci_desc {
4132cd2512SLokesh Vutla 	u8 host_id;
4232cd2512SLokesh Vutla 	int max_rx_timeout_us;
4332cd2512SLokesh Vutla 	int max_msg_size;
4432cd2512SLokesh Vutla };
4532cd2512SLokesh Vutla 
4632cd2512SLokesh Vutla /**
4732cd2512SLokesh Vutla  * struct ti_sci_info - Structure representing a TI SCI instance
4832cd2512SLokesh Vutla  * @dev:	Device pointer
4932cd2512SLokesh Vutla  * @desc:	SoC description for this instance
5032cd2512SLokesh Vutla  * @handle:	Instance of TI SCI handle to send to clients.
5132cd2512SLokesh Vutla  * @chan_tx:	Transmit mailbox channel
5232cd2512SLokesh Vutla  * @chan_rx:	Receive mailbox channel
5332cd2512SLokesh Vutla  * @xfer:	xfer info
5432cd2512SLokesh Vutla  * @list:	list head
5532cd2512SLokesh Vutla  * @is_secure:	Determines if the communication is through secure threads.
5632cd2512SLokesh Vutla  * @host_id:	Host identifier representing the compute entity
5732cd2512SLokesh Vutla  * @seq:	Seq id used for verification for tx and rx message.
5832cd2512SLokesh Vutla  */
5932cd2512SLokesh Vutla struct ti_sci_info {
6032cd2512SLokesh Vutla 	struct udevice *dev;
6132cd2512SLokesh Vutla 	const struct ti_sci_desc *desc;
6232cd2512SLokesh Vutla 	struct ti_sci_handle handle;
6332cd2512SLokesh Vutla 	struct mbox_chan chan_tx;
6432cd2512SLokesh Vutla 	struct mbox_chan chan_rx;
6532cd2512SLokesh Vutla 	struct mbox_chan chan_notify;
6632cd2512SLokesh Vutla 	struct ti_sci_xfer xfer;
6732cd2512SLokesh Vutla 	struct list_head list;
6832cd2512SLokesh Vutla 	bool is_secure;
6932cd2512SLokesh Vutla 	u8 host_id;
7032cd2512SLokesh Vutla 	u8 seq;
7132cd2512SLokesh Vutla };
7232cd2512SLokesh Vutla 
7332cd2512SLokesh Vutla #define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
7432cd2512SLokesh Vutla 
7532cd2512SLokesh Vutla /**
7632cd2512SLokesh Vutla  * ti_sci_setup_one_xfer() - Setup one message type
7732cd2512SLokesh Vutla  * @info:	Pointer to SCI entity information
7832cd2512SLokesh Vutla  * @msg_type:	Message type
7932cd2512SLokesh Vutla  * @msg_flags:	Flag to set for the message
8032cd2512SLokesh Vutla  * @buf:	Buffer to be send to mailbox channel
8132cd2512SLokesh Vutla  * @tx_message_size: transmit message size
8232cd2512SLokesh Vutla  * @rx_message_size: receive message size
8332cd2512SLokesh Vutla  *
8432cd2512SLokesh Vutla  * Helper function which is used by various command functions that are
8532cd2512SLokesh Vutla  * exposed to clients of this driver for allocating a message traffic event.
8632cd2512SLokesh Vutla  *
8732cd2512SLokesh Vutla  * Return: Corresponding ti_sci_xfer pointer if all went fine,
8832cd2512SLokesh Vutla  *	   else appropriate error pointer.
8932cd2512SLokesh Vutla  */
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)9032cd2512SLokesh Vutla static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info,
9132cd2512SLokesh Vutla 						 u16 msg_type, u32 msg_flags,
9232cd2512SLokesh Vutla 						 u32 *buf,
9332cd2512SLokesh Vutla 						 size_t tx_message_size,
9432cd2512SLokesh Vutla 						 size_t rx_message_size)
9532cd2512SLokesh Vutla {
9632cd2512SLokesh Vutla 	struct ti_sci_xfer *xfer = &info->xfer;
9732cd2512SLokesh Vutla 	struct ti_sci_msg_hdr *hdr;
9832cd2512SLokesh Vutla 
9932cd2512SLokesh Vutla 	/* Ensure we have sane transfer sizes */
10032cd2512SLokesh Vutla 	if (rx_message_size > info->desc->max_msg_size ||
10132cd2512SLokesh Vutla 	    tx_message_size > info->desc->max_msg_size ||
10232cd2512SLokesh Vutla 	    rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr))
10332cd2512SLokesh Vutla 		return ERR_PTR(-ERANGE);
10432cd2512SLokesh Vutla 
10532cd2512SLokesh Vutla 	info->seq = ~info->seq;
10632cd2512SLokesh Vutla 	xfer->tx_message.buf = buf;
10732cd2512SLokesh Vutla 	xfer->tx_message.len = tx_message_size;
10832cd2512SLokesh Vutla 	xfer->rx_len = (u8)rx_message_size;
10932cd2512SLokesh Vutla 
11032cd2512SLokesh Vutla 	hdr = (struct ti_sci_msg_hdr *)buf;
11132cd2512SLokesh Vutla 	hdr->seq = info->seq;
11232cd2512SLokesh Vutla 	hdr->type = msg_type;
11332cd2512SLokesh Vutla 	hdr->host = info->host_id;
11432cd2512SLokesh Vutla 	hdr->flags = msg_flags;
11532cd2512SLokesh Vutla 
11632cd2512SLokesh Vutla 	return xfer;
11732cd2512SLokesh Vutla }
11832cd2512SLokesh Vutla 
11932cd2512SLokesh Vutla /**
12032cd2512SLokesh Vutla  * ti_sci_get_response() - Receive response from mailbox channel
12132cd2512SLokesh Vutla  * @info:	Pointer to SCI entity information
12232cd2512SLokesh Vutla  * @xfer:	Transfer to initiate and wait for response
12332cd2512SLokesh Vutla  * @chan:	Channel to receive the response
12432cd2512SLokesh Vutla  *
12532cd2512SLokesh Vutla  * Return: -ETIMEDOUT in case of no response, if transmit error,
12632cd2512SLokesh Vutla  *	   return corresponding error, else if all goes well,
12732cd2512SLokesh Vutla  *	   return 0.
12832cd2512SLokesh Vutla  */
ti_sci_get_response(struct ti_sci_info * info,struct ti_sci_xfer * xfer,struct mbox_chan * chan)12932cd2512SLokesh Vutla static inline int ti_sci_get_response(struct ti_sci_info *info,
13032cd2512SLokesh Vutla 				      struct ti_sci_xfer *xfer,
13132cd2512SLokesh Vutla 				      struct mbox_chan *chan)
13232cd2512SLokesh Vutla {
13332cd2512SLokesh Vutla 	struct k3_sec_proxy_msg *msg = &xfer->tx_message;
13432cd2512SLokesh Vutla 	struct ti_sci_secure_msg_hdr *secure_hdr;
13532cd2512SLokesh Vutla 	struct ti_sci_msg_hdr *hdr;
13632cd2512SLokesh Vutla 	int ret;
13732cd2512SLokesh Vutla 
13832cd2512SLokesh Vutla 	/* Receive the response */
13932cd2512SLokesh Vutla 	ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_us);
14032cd2512SLokesh Vutla 	if (ret) {
14132cd2512SLokesh Vutla 		dev_err(info->dev, "%s: Message receive failed. ret = %d\n",
14232cd2512SLokesh Vutla 			__func__, ret);
14332cd2512SLokesh Vutla 		return ret;
14432cd2512SLokesh Vutla 	}
14532cd2512SLokesh Vutla 
14632cd2512SLokesh Vutla 	/* ToDo: Verify checksum */
14732cd2512SLokesh Vutla 	if (info->is_secure) {
14832cd2512SLokesh Vutla 		secure_hdr = (struct ti_sci_secure_msg_hdr *)msg->buf;
14932cd2512SLokesh Vutla 		msg->buf = (u32 *)((void *)msg->buf + sizeof(*secure_hdr));
15032cd2512SLokesh Vutla 	}
15132cd2512SLokesh Vutla 
15232cd2512SLokesh Vutla 	/* msg is updated by mailbox driver */
15332cd2512SLokesh Vutla 	hdr = (struct ti_sci_msg_hdr *)msg->buf;
15432cd2512SLokesh Vutla 
15532cd2512SLokesh Vutla 	/* Sanity check for message response */
15632cd2512SLokesh Vutla 	if (hdr->seq != info->seq) {
15732cd2512SLokesh Vutla 		dev_dbg(info->dev, "%s: Message for %d is not expected\n",
15832cd2512SLokesh Vutla 			__func__, hdr->seq);
15932cd2512SLokesh Vutla 		return ret;
16032cd2512SLokesh Vutla 	}
16132cd2512SLokesh Vutla 
16232cd2512SLokesh Vutla 	if (msg->len > info->desc->max_msg_size) {
16332cd2512SLokesh Vutla 		dev_err(info->dev, "%s: Unable to handle %zu xfer (max %d)\n",
16432cd2512SLokesh Vutla 			__func__, msg->len, info->desc->max_msg_size);
16532cd2512SLokesh Vutla 		return -EINVAL;
16632cd2512SLokesh Vutla 	}
16732cd2512SLokesh Vutla 
16832cd2512SLokesh Vutla 	if (msg->len < xfer->rx_len) {
16932cd2512SLokesh Vutla 		dev_err(info->dev, "%s: Recv xfer %zu < expected %d length\n",
17032cd2512SLokesh Vutla 			__func__, msg->len, xfer->rx_len);
17132cd2512SLokesh Vutla 	}
17232cd2512SLokesh Vutla 
17332cd2512SLokesh Vutla 	return ret;
17432cd2512SLokesh Vutla }
17532cd2512SLokesh Vutla 
17632cd2512SLokesh Vutla /**
17732cd2512SLokesh Vutla  * ti_sci_do_xfer() - Do one transfer
17832cd2512SLokesh Vutla  * @info:	Pointer to SCI entity information
17932cd2512SLokesh Vutla  * @xfer:	Transfer to initiate and wait for response
18032cd2512SLokesh Vutla  *
18132cd2512SLokesh Vutla  * Return: 0 if all went fine, else return appropriate error.
18232cd2512SLokesh Vutla  */
ti_sci_do_xfer(struct ti_sci_info * info,struct ti_sci_xfer * xfer)18332cd2512SLokesh Vutla static inline int ti_sci_do_xfer(struct ti_sci_info *info,
18432cd2512SLokesh Vutla 				 struct ti_sci_xfer *xfer)
18532cd2512SLokesh Vutla {
18632cd2512SLokesh Vutla 	struct k3_sec_proxy_msg *msg = &xfer->tx_message;
18732cd2512SLokesh Vutla 	u8 secure_buf[info->desc->max_msg_size];
18832cd2512SLokesh Vutla 	struct ti_sci_secure_msg_hdr secure_hdr;
18932cd2512SLokesh Vutla 	int ret;
19032cd2512SLokesh Vutla 
19132cd2512SLokesh Vutla 	if (info->is_secure) {
19232cd2512SLokesh Vutla 		/* ToDo: get checksum of the entire message */
19332cd2512SLokesh Vutla 		secure_hdr.checksum = 0;
19432cd2512SLokesh Vutla 		secure_hdr.reserved = 0;
19532cd2512SLokesh Vutla 		memcpy(&secure_buf[sizeof(secure_hdr)], xfer->tx_message.buf,
19632cd2512SLokesh Vutla 		       xfer->tx_message.len);
19732cd2512SLokesh Vutla 
19832cd2512SLokesh Vutla 		xfer->tx_message.buf = (u32 *)secure_buf;
19932cd2512SLokesh Vutla 		xfer->tx_message.len += sizeof(secure_hdr);
20032cd2512SLokesh Vutla 		xfer->rx_len += sizeof(secure_hdr);
20132cd2512SLokesh Vutla 	}
20232cd2512SLokesh Vutla 
20332cd2512SLokesh Vutla 	/* Send the message */
20432cd2512SLokesh Vutla 	ret = mbox_send(&info->chan_tx, msg);
20532cd2512SLokesh Vutla 	if (ret) {
20632cd2512SLokesh Vutla 		dev_err(info->dev, "%s: Message sending failed. ret = %d\n",
20732cd2512SLokesh Vutla 			__func__, ret);
20832cd2512SLokesh Vutla 		return ret;
20932cd2512SLokesh Vutla 	}
21032cd2512SLokesh Vutla 
21132cd2512SLokesh Vutla 	return ti_sci_get_response(info, xfer, &info->chan_rx);
21232cd2512SLokesh Vutla }
21332cd2512SLokesh Vutla 
21432cd2512SLokesh Vutla /**
21532cd2512SLokesh Vutla  * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
21632cd2512SLokesh Vutla  * @handle:	pointer to TI SCI handle
21732cd2512SLokesh Vutla  *
21832cd2512SLokesh Vutla  * Updates the SCI information in the internal data structure.
21932cd2512SLokesh Vutla  *
22032cd2512SLokesh Vutla  * Return: 0 if all went fine, else return appropriate error.
22132cd2512SLokesh Vutla  */
ti_sci_cmd_get_revision(struct ti_sci_handle * handle)22232cd2512SLokesh Vutla static int ti_sci_cmd_get_revision(struct ti_sci_handle *handle)
22332cd2512SLokesh Vutla {
22432cd2512SLokesh Vutla 	struct ti_sci_msg_resp_version *rev_info;
22532cd2512SLokesh Vutla 	struct ti_sci_version_info *ver;
22632cd2512SLokesh Vutla 	struct ti_sci_msg_hdr hdr;
22732cd2512SLokesh Vutla 	struct ti_sci_info *info;
22832cd2512SLokesh Vutla 	struct ti_sci_xfer *xfer;
22932cd2512SLokesh Vutla 	int ret;
23032cd2512SLokesh Vutla 
23132cd2512SLokesh Vutla 	if (IS_ERR(handle))
23232cd2512SLokesh Vutla 		return PTR_ERR(handle);
23332cd2512SLokesh Vutla 	if (!handle)
23432cd2512SLokesh Vutla 		return -EINVAL;
23532cd2512SLokesh Vutla 
23632cd2512SLokesh Vutla 	info = handle_to_ti_sci_info(handle);
23732cd2512SLokesh Vutla 
23832cd2512SLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION, 0x0,
23932cd2512SLokesh Vutla 				     (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr),
24032cd2512SLokesh Vutla 				     sizeof(*rev_info));
24132cd2512SLokesh Vutla 	if (IS_ERR(xfer)) {
24232cd2512SLokesh Vutla 		ret = PTR_ERR(xfer);
24332cd2512SLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
24432cd2512SLokesh Vutla 		return ret;
24532cd2512SLokesh Vutla 	}
24632cd2512SLokesh Vutla 
24732cd2512SLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
24832cd2512SLokesh Vutla 	if (ret) {
24932cd2512SLokesh Vutla 		dev_err(info->dev, "Mbox communication fail %d\n", ret);
25032cd2512SLokesh Vutla 		return ret;
25132cd2512SLokesh Vutla 	}
25232cd2512SLokesh Vutla 
25332cd2512SLokesh Vutla 	rev_info = (struct ti_sci_msg_resp_version *)xfer->tx_message.buf;
25432cd2512SLokesh Vutla 
25532cd2512SLokesh Vutla 	ver = &handle->version;
25632cd2512SLokesh Vutla 	ver->abi_major = rev_info->abi_major;
25732cd2512SLokesh Vutla 	ver->abi_minor = rev_info->abi_minor;
25832cd2512SLokesh Vutla 	ver->firmware_revision = rev_info->firmware_revision;
25932cd2512SLokesh Vutla 	strncpy(ver->firmware_description, rev_info->firmware_description,
26032cd2512SLokesh Vutla 		sizeof(ver->firmware_description));
26132cd2512SLokesh Vutla 
26232cd2512SLokesh Vutla 	return 0;
26332cd2512SLokesh Vutla }
26432cd2512SLokesh Vutla 
26532cd2512SLokesh Vutla /**
26632cd2512SLokesh Vutla  * ti_sci_is_response_ack() - Generic ACK/NACK message checkup
26732cd2512SLokesh Vutla  * @r:	pointer to response buffer
26832cd2512SLokesh Vutla  *
26932cd2512SLokesh Vutla  * Return: true if the response was an ACK, else returns false.
27032cd2512SLokesh Vutla  */
ti_sci_is_response_ack(void * r)27132cd2512SLokesh Vutla static inline bool ti_sci_is_response_ack(void *r)
27232cd2512SLokesh Vutla {
27332cd2512SLokesh Vutla 	struct ti_sci_msg_hdr *hdr = r;
27432cd2512SLokesh Vutla 
27532cd2512SLokesh Vutla 	return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
27632cd2512SLokesh Vutla }
27732cd2512SLokesh Vutla 
27832cd2512SLokesh Vutla /**
279dcfc52adSAndreas Dannenberg  * cmd_set_board_config_using_msg() - Common command to send board configuration
280dcfc52adSAndreas Dannenberg  *                                    message
281dcfc52adSAndreas Dannenberg  * @handle:	pointer to TI SCI handle
282dcfc52adSAndreas Dannenberg  * @msg_type:	One of the TISCI message types to set board configuration
283dcfc52adSAndreas Dannenberg  * @addr:	Address where the board config structure is located
284dcfc52adSAndreas Dannenberg  * @size:	Size of the board config structure
285dcfc52adSAndreas Dannenberg  *
286dcfc52adSAndreas Dannenberg  * Return: 0 if all went well, else returns appropriate error value.
287dcfc52adSAndreas Dannenberg  */
cmd_set_board_config_using_msg(const struct ti_sci_handle * handle,u16 msg_type,u64 addr,u32 size)288dcfc52adSAndreas Dannenberg static int cmd_set_board_config_using_msg(const struct ti_sci_handle *handle,
289dcfc52adSAndreas Dannenberg 					  u16 msg_type, u64 addr, u32 size)
290dcfc52adSAndreas Dannenberg {
291dcfc52adSAndreas Dannenberg 	struct ti_sci_msg_board_config req;
292dcfc52adSAndreas Dannenberg 	struct ti_sci_msg_hdr *resp;
293dcfc52adSAndreas Dannenberg 	struct ti_sci_info *info;
294dcfc52adSAndreas Dannenberg 	struct ti_sci_xfer *xfer;
295dcfc52adSAndreas Dannenberg 	int ret = 0;
296dcfc52adSAndreas Dannenberg 
297dcfc52adSAndreas Dannenberg 	if (IS_ERR(handle))
298dcfc52adSAndreas Dannenberg 		return PTR_ERR(handle);
299dcfc52adSAndreas Dannenberg 	if (!handle)
300dcfc52adSAndreas Dannenberg 		return -EINVAL;
301dcfc52adSAndreas Dannenberg 
302dcfc52adSAndreas Dannenberg 	info = handle_to_ti_sci_info(handle);
303dcfc52adSAndreas Dannenberg 
304dcfc52adSAndreas Dannenberg 	xfer = ti_sci_setup_one_xfer(info, msg_type,
305dcfc52adSAndreas Dannenberg 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
306dcfc52adSAndreas Dannenberg 				     (u32 *)&req, sizeof(req), sizeof(*resp));
307dcfc52adSAndreas Dannenberg 	if (IS_ERR(xfer)) {
308dcfc52adSAndreas Dannenberg 		ret = PTR_ERR(xfer);
309dcfc52adSAndreas Dannenberg 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
310dcfc52adSAndreas Dannenberg 		return ret;
311dcfc52adSAndreas Dannenberg 	}
312dcfc52adSAndreas Dannenberg 	req.boardcfgp_high = (addr >> 32) & 0xffffffff;
313dcfc52adSAndreas Dannenberg 	req.boardcfgp_low = addr & 0xffffffff;
314dcfc52adSAndreas Dannenberg 	req.boardcfg_size = size;
315dcfc52adSAndreas Dannenberg 
316dcfc52adSAndreas Dannenberg 	ret = ti_sci_do_xfer(info, xfer);
317dcfc52adSAndreas Dannenberg 	if (ret) {
318dcfc52adSAndreas Dannenberg 		dev_err(info->dev, "Mbox send fail %d\n", ret);
319dcfc52adSAndreas Dannenberg 		return ret;
320dcfc52adSAndreas Dannenberg 	}
321dcfc52adSAndreas Dannenberg 
322dcfc52adSAndreas Dannenberg 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
323dcfc52adSAndreas Dannenberg 
324dcfc52adSAndreas Dannenberg 	if (!ti_sci_is_response_ack(resp))
325dcfc52adSAndreas Dannenberg 		return -ENODEV;
326dcfc52adSAndreas Dannenberg 
327dcfc52adSAndreas Dannenberg 	return ret;
328dcfc52adSAndreas Dannenberg }
329dcfc52adSAndreas Dannenberg 
330dcfc52adSAndreas Dannenberg /**
331dcfc52adSAndreas Dannenberg  * ti_sci_cmd_set_board_config() - Command to send board configuration message
332dcfc52adSAndreas Dannenberg  * @handle:	pointer to TI SCI handle
333dcfc52adSAndreas Dannenberg  * @addr:	Address where the board config structure is located
334dcfc52adSAndreas Dannenberg  * @size:	Size of the board config structure
335dcfc52adSAndreas Dannenberg  *
336dcfc52adSAndreas Dannenberg  * Return: 0 if all went well, else returns appropriate error value.
337dcfc52adSAndreas Dannenberg  */
ti_sci_cmd_set_board_config(const struct ti_sci_handle * handle,u64 addr,u32 size)338dcfc52adSAndreas Dannenberg static int ti_sci_cmd_set_board_config(const struct ti_sci_handle *handle,
339dcfc52adSAndreas Dannenberg 				       u64 addr, u32 size)
340dcfc52adSAndreas Dannenberg {
341dcfc52adSAndreas Dannenberg 	return cmd_set_board_config_using_msg(handle,
342dcfc52adSAndreas Dannenberg 					      TI_SCI_MSG_BOARD_CONFIG,
343dcfc52adSAndreas Dannenberg 					      addr, size);
344dcfc52adSAndreas Dannenberg }
345dcfc52adSAndreas Dannenberg 
346dcfc52adSAndreas Dannenberg /**
347dcfc52adSAndreas Dannenberg  * ti_sci_cmd_set_board_config_rm() - Command to send board resource
348dcfc52adSAndreas Dannenberg  *				      management configuration
349dcfc52adSAndreas Dannenberg  * @handle:	pointer to TI SCI handle
350dcfc52adSAndreas Dannenberg  * @addr:	Address where the board RM config structure is located
351dcfc52adSAndreas Dannenberg  * @size:	Size of the RM config structure
352dcfc52adSAndreas Dannenberg  *
353dcfc52adSAndreas Dannenberg  * Return: 0 if all went well, else returns appropriate error value.
354dcfc52adSAndreas Dannenberg  */
355dcfc52adSAndreas Dannenberg static
ti_sci_cmd_set_board_config_rm(const struct ti_sci_handle * handle,u64 addr,u32 size)356dcfc52adSAndreas Dannenberg int ti_sci_cmd_set_board_config_rm(const struct ti_sci_handle *handle,
357dcfc52adSAndreas Dannenberg 				   u64 addr, u32 size)
358dcfc52adSAndreas Dannenberg {
359dcfc52adSAndreas Dannenberg 	return cmd_set_board_config_using_msg(handle,
360dcfc52adSAndreas Dannenberg 					      TI_SCI_MSG_BOARD_CONFIG_RM,
361dcfc52adSAndreas Dannenberg 					      addr, size);
362dcfc52adSAndreas Dannenberg }
363dcfc52adSAndreas Dannenberg 
364dcfc52adSAndreas Dannenberg /**
365dcfc52adSAndreas Dannenberg  * ti_sci_cmd_set_board_config_security() - Command to send board security
366dcfc52adSAndreas Dannenberg  *					    configuration message
367dcfc52adSAndreas Dannenberg  * @handle:	pointer to TI SCI handle
368dcfc52adSAndreas Dannenberg  * @addr:	Address where the board security config structure is located
369dcfc52adSAndreas Dannenberg  * @size:	Size of the security config structure
370dcfc52adSAndreas Dannenberg  *
371dcfc52adSAndreas Dannenberg  * Return: 0 if all went well, else returns appropriate error value.
372dcfc52adSAndreas Dannenberg  */
373dcfc52adSAndreas Dannenberg static
ti_sci_cmd_set_board_config_security(const struct ti_sci_handle * handle,u64 addr,u32 size)374dcfc52adSAndreas Dannenberg int ti_sci_cmd_set_board_config_security(const struct ti_sci_handle *handle,
375dcfc52adSAndreas Dannenberg 					 u64 addr, u32 size)
376dcfc52adSAndreas Dannenberg {
377dcfc52adSAndreas Dannenberg 	return cmd_set_board_config_using_msg(handle,
378dcfc52adSAndreas Dannenberg 					      TI_SCI_MSG_BOARD_CONFIG_SECURITY,
379dcfc52adSAndreas Dannenberg 					      addr, size);
380dcfc52adSAndreas Dannenberg }
381dcfc52adSAndreas Dannenberg 
382dcfc52adSAndreas Dannenberg /**
383dcfc52adSAndreas Dannenberg  * ti_sci_cmd_set_board_config_pm() - Command to send board power and clock
384dcfc52adSAndreas Dannenberg  *				      configuration message
385dcfc52adSAndreas Dannenberg  * @handle:	pointer to TI SCI handle
386dcfc52adSAndreas Dannenberg  * @addr:	Address where the board PM config structure is located
387dcfc52adSAndreas Dannenberg  * @size:	Size of the PM config structure
388dcfc52adSAndreas Dannenberg  *
389dcfc52adSAndreas Dannenberg  * Return: 0 if all went well, else returns appropriate error value.
390dcfc52adSAndreas Dannenberg  */
ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle * handle,u64 addr,u32 size)391dcfc52adSAndreas Dannenberg static int ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle *handle,
392dcfc52adSAndreas Dannenberg 					  u64 addr, u32 size)
393dcfc52adSAndreas Dannenberg {
394dcfc52adSAndreas Dannenberg 	return cmd_set_board_config_using_msg(handle,
395dcfc52adSAndreas Dannenberg 					      TI_SCI_MSG_BOARD_CONFIG_PM,
396dcfc52adSAndreas Dannenberg 					      addr, size);
397dcfc52adSAndreas Dannenberg }
398dcfc52adSAndreas Dannenberg 
3997bc33045SAndreas Dannenberg /**
4007bc33045SAndreas Dannenberg  * ti_sci_set_device_state() - Set device state helper
4017bc33045SAndreas Dannenberg  * @handle:	pointer to TI SCI handle
4027bc33045SAndreas Dannenberg  * @id:		Device identifier
4037bc33045SAndreas Dannenberg  * @flags:	flags to setup for the device
4047bc33045SAndreas Dannenberg  * @state:	State to move the device to
4057bc33045SAndreas Dannenberg  *
4067bc33045SAndreas Dannenberg  * Return: 0 if all went well, else returns appropriate error value.
4077bc33045SAndreas Dannenberg  */
ti_sci_set_device_state(const struct ti_sci_handle * handle,u32 id,u32 flags,u8 state)4087bc33045SAndreas Dannenberg static int ti_sci_set_device_state(const struct ti_sci_handle *handle,
4097bc33045SAndreas Dannenberg 				   u32 id, u32 flags, u8 state)
4107bc33045SAndreas Dannenberg {
4117bc33045SAndreas Dannenberg 	struct ti_sci_msg_req_set_device_state req;
4127bc33045SAndreas Dannenberg 	struct ti_sci_msg_hdr *resp;
4137bc33045SAndreas Dannenberg 	struct ti_sci_info *info;
4147bc33045SAndreas Dannenberg 	struct ti_sci_xfer *xfer;
4157bc33045SAndreas Dannenberg 	int ret = 0;
4167bc33045SAndreas Dannenberg 
4177bc33045SAndreas Dannenberg 	if (IS_ERR(handle))
4187bc33045SAndreas Dannenberg 		return PTR_ERR(handle);
4197bc33045SAndreas Dannenberg 	if (!handle)
4207bc33045SAndreas Dannenberg 		return -EINVAL;
4217bc33045SAndreas Dannenberg 
4227bc33045SAndreas Dannenberg 	info = handle_to_ti_sci_info(handle);
4237bc33045SAndreas Dannenberg 
4247bc33045SAndreas Dannenberg 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
4257bc33045SAndreas Dannenberg 				     flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
4267bc33045SAndreas Dannenberg 				     (u32 *)&req, sizeof(req), sizeof(*resp));
4277bc33045SAndreas Dannenberg 	if (IS_ERR(xfer)) {
4287bc33045SAndreas Dannenberg 		ret = PTR_ERR(xfer);
4297bc33045SAndreas Dannenberg 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
4307bc33045SAndreas Dannenberg 		return ret;
4317bc33045SAndreas Dannenberg 	}
4327bc33045SAndreas Dannenberg 	req.id = id;
4337bc33045SAndreas Dannenberg 	req.state = state;
4347bc33045SAndreas Dannenberg 
4357bc33045SAndreas Dannenberg 	ret = ti_sci_do_xfer(info, xfer);
4367bc33045SAndreas Dannenberg 	if (ret) {
4377bc33045SAndreas Dannenberg 		dev_err(info->dev, "Mbox send fail %d\n", ret);
4387bc33045SAndreas Dannenberg 		return ret;
4397bc33045SAndreas Dannenberg 	}
4407bc33045SAndreas Dannenberg 
4417bc33045SAndreas Dannenberg 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
4427bc33045SAndreas Dannenberg 
4437bc33045SAndreas Dannenberg 	if (!ti_sci_is_response_ack(resp))
4447bc33045SAndreas Dannenberg 		return -ENODEV;
4457bc33045SAndreas Dannenberg 
4467bc33045SAndreas Dannenberg 	return ret;
4477bc33045SAndreas Dannenberg }
4487bc33045SAndreas Dannenberg 
4497bc33045SAndreas Dannenberg /**
4507bc33045SAndreas Dannenberg  * ti_sci_get_device_state() - Get device state helper
4517bc33045SAndreas Dannenberg  * @handle:	Handle to the device
4527bc33045SAndreas Dannenberg  * @id:		Device Identifier
4537bc33045SAndreas Dannenberg  * @clcnt:	Pointer to Context Loss Count
4547bc33045SAndreas Dannenberg  * @resets:	pointer to resets
4557bc33045SAndreas Dannenberg  * @p_state:	pointer to p_state
4567bc33045SAndreas Dannenberg  * @c_state:	pointer to c_state
4577bc33045SAndreas Dannenberg  *
4587bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
4597bc33045SAndreas Dannenberg  */
ti_sci_get_device_state(const struct ti_sci_handle * handle,u32 id,u32 * clcnt,u32 * resets,u8 * p_state,u8 * c_state)4607bc33045SAndreas Dannenberg static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
4617bc33045SAndreas Dannenberg 				   u32 id,  u32 *clcnt,  u32 *resets,
4627bc33045SAndreas Dannenberg 				   u8 *p_state,  u8 *c_state)
4637bc33045SAndreas Dannenberg {
4647bc33045SAndreas Dannenberg 	struct ti_sci_msg_resp_get_device_state *resp;
4657bc33045SAndreas Dannenberg 	struct ti_sci_msg_req_get_device_state req;
4667bc33045SAndreas Dannenberg 	struct ti_sci_info *info;
4677bc33045SAndreas Dannenberg 	struct ti_sci_xfer *xfer;
4687bc33045SAndreas Dannenberg 	int ret = 0;
4697bc33045SAndreas Dannenberg 
4707bc33045SAndreas Dannenberg 	if (IS_ERR(handle))
4717bc33045SAndreas Dannenberg 		return PTR_ERR(handle);
4727bc33045SAndreas Dannenberg 	if (!handle)
4737bc33045SAndreas Dannenberg 		return -EINVAL;
4747bc33045SAndreas Dannenberg 
4757bc33045SAndreas Dannenberg 	if (!clcnt && !resets && !p_state && !c_state)
4767bc33045SAndreas Dannenberg 		return -EINVAL;
4777bc33045SAndreas Dannenberg 
4787bc33045SAndreas Dannenberg 	info = handle_to_ti_sci_info(handle);
4797bc33045SAndreas Dannenberg 
4807bc33045SAndreas Dannenberg 	/* Response is expected, so need of any flags */
4817bc33045SAndreas Dannenberg 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE, 0,
4827bc33045SAndreas Dannenberg 				     (u32 *)&req, sizeof(req), sizeof(*resp));
4837bc33045SAndreas Dannenberg 	if (IS_ERR(xfer)) {
4847bc33045SAndreas Dannenberg 		ret = PTR_ERR(xfer);
4857bc33045SAndreas Dannenberg 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
4867bc33045SAndreas Dannenberg 		return ret;
4877bc33045SAndreas Dannenberg 	}
4887bc33045SAndreas Dannenberg 	req.id = id;
4897bc33045SAndreas Dannenberg 
4907bc33045SAndreas Dannenberg 	ret = ti_sci_do_xfer(info, xfer);
4917bc33045SAndreas Dannenberg 	if (ret) {
4927bc33045SAndreas Dannenberg 		dev_err(dev, "Mbox send fail %d\n", ret);
4937bc33045SAndreas Dannenberg 		return ret;
4947bc33045SAndreas Dannenberg 	}
4957bc33045SAndreas Dannenberg 
4967bc33045SAndreas Dannenberg 	resp = (struct ti_sci_msg_resp_get_device_state *)xfer->tx_message.buf;
4977bc33045SAndreas Dannenberg 	if (!ti_sci_is_response_ack(resp))
4987bc33045SAndreas Dannenberg 		return -ENODEV;
4997bc33045SAndreas Dannenberg 
5007bc33045SAndreas Dannenberg 	if (clcnt)
5017bc33045SAndreas Dannenberg 		*clcnt = resp->context_loss_count;
5027bc33045SAndreas Dannenberg 	if (resets)
5037bc33045SAndreas Dannenberg 		*resets = resp->resets;
5047bc33045SAndreas Dannenberg 	if (p_state)
5057bc33045SAndreas Dannenberg 		*p_state = resp->programmed_state;
5067bc33045SAndreas Dannenberg 	if (c_state)
5077bc33045SAndreas Dannenberg 		*c_state = resp->current_state;
5087bc33045SAndreas Dannenberg 
5097bc33045SAndreas Dannenberg 	return ret;
5107bc33045SAndreas Dannenberg }
5117bc33045SAndreas Dannenberg 
5127bc33045SAndreas Dannenberg /**
5137bc33045SAndreas Dannenberg  * ti_sci_cmd_get_device() - command to request for device managed by TISCI
5147bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
5157bc33045SAndreas Dannenberg  * @id:		Device Identifier
5167bc33045SAndreas Dannenberg  *
5177bc33045SAndreas Dannenberg  * Request for the device - NOTE: the client MUST maintain integrity of
5187bc33045SAndreas Dannenberg  * usage count by balancing get_device with put_device. No refcounting is
5197bc33045SAndreas Dannenberg  * managed by driver for that purpose.
5207bc33045SAndreas Dannenberg  *
5217bc33045SAndreas Dannenberg  * NOTE: The request is for exclusive access for the processor.
5227bc33045SAndreas Dannenberg  *
5237bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
5247bc33045SAndreas Dannenberg  */
ti_sci_cmd_get_device(const struct ti_sci_handle * handle,u32 id)5257bc33045SAndreas Dannenberg static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
5267bc33045SAndreas Dannenberg {
5277bc33045SAndreas Dannenberg 	return ti_sci_set_device_state(handle, id,
5287bc33045SAndreas Dannenberg 				       MSG_FLAG_DEVICE_EXCLUSIVE,
5297bc33045SAndreas Dannenberg 				       MSG_DEVICE_SW_STATE_ON);
5307bc33045SAndreas Dannenberg }
5317bc33045SAndreas Dannenberg 
5327bc33045SAndreas Dannenberg /**
5337bc33045SAndreas Dannenberg  * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI
5347bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
5357bc33045SAndreas Dannenberg  * @id:		Device Identifier
5367bc33045SAndreas Dannenberg  *
5377bc33045SAndreas Dannenberg  * Request for the device - NOTE: the client MUST maintain integrity of
5387bc33045SAndreas Dannenberg  * usage count by balancing get_device with put_device. No refcounting is
5397bc33045SAndreas Dannenberg  * managed by driver for that purpose.
5407bc33045SAndreas Dannenberg  *
5417bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
5427bc33045SAndreas Dannenberg  */
ti_sci_cmd_idle_device(const struct ti_sci_handle * handle,u32 id)5437bc33045SAndreas Dannenberg static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
5447bc33045SAndreas Dannenberg {
5457bc33045SAndreas Dannenberg 	return ti_sci_set_device_state(handle, id,
5467bc33045SAndreas Dannenberg 				       MSG_FLAG_DEVICE_EXCLUSIVE,
5477bc33045SAndreas Dannenberg 				       MSG_DEVICE_SW_STATE_RETENTION);
5487bc33045SAndreas Dannenberg }
5497bc33045SAndreas Dannenberg 
5507bc33045SAndreas Dannenberg /**
5517bc33045SAndreas Dannenberg  * ti_sci_cmd_put_device() - command to release a device managed by TISCI
5527bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
5537bc33045SAndreas Dannenberg  * @id:		Device Identifier
5547bc33045SAndreas Dannenberg  *
5557bc33045SAndreas Dannenberg  * Request for the device - NOTE: the client MUST maintain integrity of
5567bc33045SAndreas Dannenberg  * usage count by balancing get_device with put_device. No refcounting is
5577bc33045SAndreas Dannenberg  * managed by driver for that purpose.
5587bc33045SAndreas Dannenberg  *
5597bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
5607bc33045SAndreas Dannenberg  */
ti_sci_cmd_put_device(const struct ti_sci_handle * handle,u32 id)5617bc33045SAndreas Dannenberg static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id)
5627bc33045SAndreas Dannenberg {
5637bc33045SAndreas Dannenberg 	return ti_sci_set_device_state(handle, id,
5647bc33045SAndreas Dannenberg 				       0, MSG_DEVICE_SW_STATE_AUTO_OFF);
5657bc33045SAndreas Dannenberg }
5667bc33045SAndreas Dannenberg 
5677bc33045SAndreas Dannenberg /**
5687bc33045SAndreas Dannenberg  * ti_sci_cmd_dev_is_valid() - Is the device valid
5697bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
5707bc33045SAndreas Dannenberg  * @id:		Device Identifier
5717bc33045SAndreas Dannenberg  *
5727bc33045SAndreas Dannenberg  * Return: 0 if all went fine and the device ID is valid, else return
5737bc33045SAndreas Dannenberg  * appropriate error.
5747bc33045SAndreas Dannenberg  */
ti_sci_cmd_dev_is_valid(const struct ti_sci_handle * handle,u32 id)5757bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id)
5767bc33045SAndreas Dannenberg {
5777bc33045SAndreas Dannenberg 	u8 unused;
5787bc33045SAndreas Dannenberg 
5797bc33045SAndreas Dannenberg 	/* check the device state which will also tell us if the ID is valid */
5807bc33045SAndreas Dannenberg 	return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused);
5817bc33045SAndreas Dannenberg }
5827bc33045SAndreas Dannenberg 
5837bc33045SAndreas Dannenberg /**
5847bc33045SAndreas Dannenberg  * ti_sci_cmd_dev_get_clcnt() - Get context loss counter
5857bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle
5867bc33045SAndreas Dannenberg  * @id:		Device Identifier
5877bc33045SAndreas Dannenberg  * @count:	Pointer to Context Loss counter to populate
5887bc33045SAndreas Dannenberg  *
5897bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
5907bc33045SAndreas Dannenberg  */
ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle * handle,u32 id,u32 * count)5917bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id,
5927bc33045SAndreas Dannenberg 				    u32 *count)
5937bc33045SAndreas Dannenberg {
5947bc33045SAndreas Dannenberg 	return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL);
5957bc33045SAndreas Dannenberg }
5967bc33045SAndreas Dannenberg 
5977bc33045SAndreas Dannenberg /**
5987bc33045SAndreas Dannenberg  * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle
5997bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle
6007bc33045SAndreas Dannenberg  * @id:		Device Identifier
6017bc33045SAndreas Dannenberg  * @r_state:	true if requested to be idle
6027bc33045SAndreas Dannenberg  *
6037bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
6047bc33045SAndreas Dannenberg  */
ti_sci_cmd_dev_is_idle(const struct ti_sci_handle * handle,u32 id,bool * r_state)6057bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id,
6067bc33045SAndreas Dannenberg 				  bool *r_state)
6077bc33045SAndreas Dannenberg {
6087bc33045SAndreas Dannenberg 	int ret;
6097bc33045SAndreas Dannenberg 	u8 state;
6107bc33045SAndreas Dannenberg 
6117bc33045SAndreas Dannenberg 	if (!r_state)
6127bc33045SAndreas Dannenberg 		return -EINVAL;
6137bc33045SAndreas Dannenberg 
6147bc33045SAndreas Dannenberg 	ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL);
6157bc33045SAndreas Dannenberg 	if (ret)
6167bc33045SAndreas Dannenberg 		return ret;
6177bc33045SAndreas Dannenberg 
6187bc33045SAndreas Dannenberg 	*r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
6197bc33045SAndreas Dannenberg 
6207bc33045SAndreas Dannenberg 	return 0;
6217bc33045SAndreas Dannenberg }
6227bc33045SAndreas Dannenberg 
6237bc33045SAndreas Dannenberg /**
6247bc33045SAndreas Dannenberg  * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped
6257bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle
6267bc33045SAndreas Dannenberg  * @id:		Device Identifier
6277bc33045SAndreas Dannenberg  * @r_state:	true if requested to be stopped
6287bc33045SAndreas Dannenberg  * @curr_state:	true if currently stopped.
6297bc33045SAndreas Dannenberg  *
6307bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
6317bc33045SAndreas Dannenberg  */
ti_sci_cmd_dev_is_stop(const struct ti_sci_handle * handle,u32 id,bool * r_state,bool * curr_state)6327bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id,
6337bc33045SAndreas Dannenberg 				  bool *r_state,  bool *curr_state)
6347bc33045SAndreas Dannenberg {
6357bc33045SAndreas Dannenberg 	int ret;
6367bc33045SAndreas Dannenberg 	u8 p_state, c_state;
6377bc33045SAndreas Dannenberg 
6387bc33045SAndreas Dannenberg 	if (!r_state && !curr_state)
6397bc33045SAndreas Dannenberg 		return -EINVAL;
6407bc33045SAndreas Dannenberg 
6417bc33045SAndreas Dannenberg 	ret =
6427bc33045SAndreas Dannenberg 	    ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
6437bc33045SAndreas Dannenberg 	if (ret)
6447bc33045SAndreas Dannenberg 		return ret;
6457bc33045SAndreas Dannenberg 
6467bc33045SAndreas Dannenberg 	if (r_state)
6477bc33045SAndreas Dannenberg 		*r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
6487bc33045SAndreas Dannenberg 	if (curr_state)
6497bc33045SAndreas Dannenberg 		*curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
6507bc33045SAndreas Dannenberg 
6517bc33045SAndreas Dannenberg 	return 0;
6527bc33045SAndreas Dannenberg }
6537bc33045SAndreas Dannenberg 
6547bc33045SAndreas Dannenberg /**
6557bc33045SAndreas Dannenberg  * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON
6567bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle
6577bc33045SAndreas Dannenberg  * @id:		Device Identifier
6587bc33045SAndreas Dannenberg  * @r_state:	true if requested to be ON
6597bc33045SAndreas Dannenberg  * @curr_state:	true if currently ON and active
6607bc33045SAndreas Dannenberg  *
6617bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
6627bc33045SAndreas Dannenberg  */
ti_sci_cmd_dev_is_on(const struct ti_sci_handle * handle,u32 id,bool * r_state,bool * curr_state)6637bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id,
6647bc33045SAndreas Dannenberg 				bool *r_state,  bool *curr_state)
6657bc33045SAndreas Dannenberg {
6667bc33045SAndreas Dannenberg 	int ret;
6677bc33045SAndreas Dannenberg 	u8 p_state, c_state;
6687bc33045SAndreas Dannenberg 
6697bc33045SAndreas Dannenberg 	if (!r_state && !curr_state)
6707bc33045SAndreas Dannenberg 		return -EINVAL;
6717bc33045SAndreas Dannenberg 
6727bc33045SAndreas Dannenberg 	ret =
6737bc33045SAndreas Dannenberg 	    ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
6747bc33045SAndreas Dannenberg 	if (ret)
6757bc33045SAndreas Dannenberg 		return ret;
6767bc33045SAndreas Dannenberg 
6777bc33045SAndreas Dannenberg 	if (r_state)
6787bc33045SAndreas Dannenberg 		*r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
6797bc33045SAndreas Dannenberg 	if (curr_state)
6807bc33045SAndreas Dannenberg 		*curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
6817bc33045SAndreas Dannenberg 
6827bc33045SAndreas Dannenberg 	return 0;
6837bc33045SAndreas Dannenberg }
6847bc33045SAndreas Dannenberg 
6857bc33045SAndreas Dannenberg /**
6867bc33045SAndreas Dannenberg  * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning
6877bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle
6887bc33045SAndreas Dannenberg  * @id:		Device Identifier
6897bc33045SAndreas Dannenberg  * @curr_state:	true if currently transitioning.
6907bc33045SAndreas Dannenberg  *
6917bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
6927bc33045SAndreas Dannenberg  */
ti_sci_cmd_dev_is_trans(const struct ti_sci_handle * handle,u32 id,bool * curr_state)6937bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id,
6947bc33045SAndreas Dannenberg 				   bool *curr_state)
6957bc33045SAndreas Dannenberg {
6967bc33045SAndreas Dannenberg 	int ret;
6977bc33045SAndreas Dannenberg 	u8 state;
6987bc33045SAndreas Dannenberg 
6997bc33045SAndreas Dannenberg 	if (!curr_state)
7007bc33045SAndreas Dannenberg 		return -EINVAL;
7017bc33045SAndreas Dannenberg 
7027bc33045SAndreas Dannenberg 	ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state);
7037bc33045SAndreas Dannenberg 	if (ret)
7047bc33045SAndreas Dannenberg 		return ret;
7057bc33045SAndreas Dannenberg 
7067bc33045SAndreas Dannenberg 	*curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
7077bc33045SAndreas Dannenberg 
7087bc33045SAndreas Dannenberg 	return 0;
7097bc33045SAndreas Dannenberg }
7107bc33045SAndreas Dannenberg 
7117bc33045SAndreas Dannenberg /**
7127bc33045SAndreas Dannenberg  * ti_sci_cmd_set_device_resets() - command to set resets for device managed
7137bc33045SAndreas Dannenberg  *				    by TISCI
7147bc33045SAndreas Dannenberg  * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
7157bc33045SAndreas Dannenberg  * @id:		Device Identifier
7167bc33045SAndreas Dannenberg  * @reset_state: Device specific reset bit field
7177bc33045SAndreas Dannenberg  *
7187bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
7197bc33045SAndreas Dannenberg  */
ti_sci_cmd_set_device_resets(const struct ti_sci_handle * handle,u32 id,u32 reset_state)7207bc33045SAndreas Dannenberg static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle,
7217bc33045SAndreas Dannenberg 					u32 id, u32 reset_state)
7227bc33045SAndreas Dannenberg {
7237bc33045SAndreas Dannenberg 	struct ti_sci_msg_req_set_device_resets req;
7247bc33045SAndreas Dannenberg 	struct ti_sci_msg_hdr *resp;
7257bc33045SAndreas Dannenberg 	struct ti_sci_info *info;
7267bc33045SAndreas Dannenberg 	struct ti_sci_xfer *xfer;
7277bc33045SAndreas Dannenberg 	int ret = 0;
7287bc33045SAndreas Dannenberg 
7297bc33045SAndreas Dannenberg 	if (IS_ERR(handle))
7307bc33045SAndreas Dannenberg 		return PTR_ERR(handle);
7317bc33045SAndreas Dannenberg 	if (!handle)
7327bc33045SAndreas Dannenberg 		return -EINVAL;
7337bc33045SAndreas Dannenberg 
7347bc33045SAndreas Dannenberg 	info = handle_to_ti_sci_info(handle);
7357bc33045SAndreas Dannenberg 
7367bc33045SAndreas Dannenberg 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS,
7377bc33045SAndreas Dannenberg 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
7387bc33045SAndreas Dannenberg 				     (u32 *)&req, sizeof(req), sizeof(*resp));
7397bc33045SAndreas Dannenberg 	if (IS_ERR(xfer)) {
7407bc33045SAndreas Dannenberg 		ret = PTR_ERR(xfer);
7417bc33045SAndreas Dannenberg 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
7427bc33045SAndreas Dannenberg 		return ret;
7437bc33045SAndreas Dannenberg 	}
7447bc33045SAndreas Dannenberg 	req.id = id;
7457bc33045SAndreas Dannenberg 	req.resets = reset_state;
7467bc33045SAndreas Dannenberg 
7477bc33045SAndreas Dannenberg 	ret = ti_sci_do_xfer(info, xfer);
7487bc33045SAndreas Dannenberg 	if (ret) {
7497bc33045SAndreas Dannenberg 		dev_err(info->dev, "Mbox send fail %d\n", ret);
7507bc33045SAndreas Dannenberg 		return ret;
7517bc33045SAndreas Dannenberg 	}
7527bc33045SAndreas Dannenberg 
7537bc33045SAndreas Dannenberg 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
7547bc33045SAndreas Dannenberg 
7557bc33045SAndreas Dannenberg 	if (!ti_sci_is_response_ack(resp))
7567bc33045SAndreas Dannenberg 		return -ENODEV;
7577bc33045SAndreas Dannenberg 
7587bc33045SAndreas Dannenberg 	return ret;
7597bc33045SAndreas Dannenberg }
7607bc33045SAndreas Dannenberg 
7617bc33045SAndreas Dannenberg /**
7627bc33045SAndreas Dannenberg  * ti_sci_cmd_get_device_resets() - Get reset state for device managed
7637bc33045SAndreas Dannenberg  *				    by TISCI
7647bc33045SAndreas Dannenberg  * @handle:		Pointer to TISCI handle
7657bc33045SAndreas Dannenberg  * @id:			Device Identifier
7667bc33045SAndreas Dannenberg  * @reset_state:	Pointer to reset state to populate
7677bc33045SAndreas Dannenberg  *
7687bc33045SAndreas Dannenberg  * Return: 0 if all went fine, else return appropriate error.
7697bc33045SAndreas Dannenberg  */
ti_sci_cmd_get_device_resets(const struct ti_sci_handle * handle,u32 id,u32 * reset_state)7707bc33045SAndreas Dannenberg static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle,
7717bc33045SAndreas Dannenberg 					u32 id, u32 *reset_state)
7727bc33045SAndreas Dannenberg {
7737bc33045SAndreas Dannenberg 	return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL,
7747bc33045SAndreas Dannenberg 				       NULL);
7757bc33045SAndreas Dannenberg }
7767bc33045SAndreas Dannenberg 
7779b87181fSLokesh Vutla /**
7789b87181fSLokesh Vutla  * ti_sci_set_clock_state() - Set clock state helper
7799b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
7809b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
7819b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
7829b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
7839b87181fSLokesh Vutla  *		which clock input to modify.
7849b87181fSLokesh Vutla  * @flags:	Header flags as needed
7859b87181fSLokesh Vutla  * @state:	State to request for the clock.
7869b87181fSLokesh Vutla  *
7879b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
7889b87181fSLokesh Vutla  */
ti_sci_set_clock_state(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u32 flags,u8 state)7899b87181fSLokesh Vutla static int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
7909b87181fSLokesh Vutla 				  u32 dev_id, u8 clk_id,
7919b87181fSLokesh Vutla 				  u32 flags, u8 state)
7929b87181fSLokesh Vutla {
7939b87181fSLokesh Vutla 	struct ti_sci_msg_req_set_clock_state req;
7949b87181fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
7959b87181fSLokesh Vutla 	struct ti_sci_info *info;
7969b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
7979b87181fSLokesh Vutla 	int ret = 0;
7989b87181fSLokesh Vutla 
7999b87181fSLokesh Vutla 	if (IS_ERR(handle))
8009b87181fSLokesh Vutla 		return PTR_ERR(handle);
8019b87181fSLokesh Vutla 	if (!handle)
8029b87181fSLokesh Vutla 		return -EINVAL;
8039b87181fSLokesh Vutla 
8049b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
8059b87181fSLokesh Vutla 
8069b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
8079b87181fSLokesh Vutla 				     flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
8089b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
8099b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
8109b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
8119b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
8129b87181fSLokesh Vutla 		return ret;
8139b87181fSLokesh Vutla 	}
8149b87181fSLokesh Vutla 	req.dev_id = dev_id;
8159b87181fSLokesh Vutla 	req.clk_id = clk_id;
8169b87181fSLokesh Vutla 	req.request_state = state;
8179b87181fSLokesh Vutla 
8189b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
8199b87181fSLokesh Vutla 	if (ret) {
8209b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
8219b87181fSLokesh Vutla 		return ret;
8229b87181fSLokesh Vutla 	}
8239b87181fSLokesh Vutla 
8249b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
8259b87181fSLokesh Vutla 
8269b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
8279b87181fSLokesh Vutla 		return -ENODEV;
8289b87181fSLokesh Vutla 
8299b87181fSLokesh Vutla 	return ret;
8309b87181fSLokesh Vutla }
8319b87181fSLokesh Vutla 
8329b87181fSLokesh Vutla /**
8339b87181fSLokesh Vutla  * ti_sci_cmd_get_clock_state() - Get clock state helper
8349b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
8359b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
8369b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
8379b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
8389b87181fSLokesh Vutla  *		which clock input to modify.
8399b87181fSLokesh Vutla  * @programmed_state:	State requested for clock to move to
8409b87181fSLokesh Vutla  * @current_state:	State that the clock is currently in
8419b87181fSLokesh Vutla  *
8429b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
8439b87181fSLokesh Vutla  */
ti_sci_cmd_get_clock_state(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u8 * programmed_state,u8 * current_state)8449b87181fSLokesh Vutla static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
8459b87181fSLokesh Vutla 				      u32 dev_id, u8 clk_id,
8469b87181fSLokesh Vutla 				      u8 *programmed_state, u8 *current_state)
8479b87181fSLokesh Vutla {
8489b87181fSLokesh Vutla 	struct ti_sci_msg_resp_get_clock_state *resp;
8499b87181fSLokesh Vutla 	struct ti_sci_msg_req_get_clock_state req;
8509b87181fSLokesh Vutla 	struct ti_sci_info *info;
8519b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
8529b87181fSLokesh Vutla 	int ret = 0;
8539b87181fSLokesh Vutla 
8549b87181fSLokesh Vutla 	if (IS_ERR(handle))
8559b87181fSLokesh Vutla 		return PTR_ERR(handle);
8569b87181fSLokesh Vutla 	if (!handle)
8579b87181fSLokesh Vutla 		return -EINVAL;
8589b87181fSLokesh Vutla 
8599b87181fSLokesh Vutla 	if (!programmed_state && !current_state)
8609b87181fSLokesh Vutla 		return -EINVAL;
8619b87181fSLokesh Vutla 
8629b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
8639b87181fSLokesh Vutla 
8649b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
8659b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
8669b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
8679b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
8689b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
8699b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
8709b87181fSLokesh Vutla 		return ret;
8719b87181fSLokesh Vutla 	}
8729b87181fSLokesh Vutla 	req.dev_id = dev_id;
8739b87181fSLokesh Vutla 	req.clk_id = clk_id;
8749b87181fSLokesh Vutla 
8759b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
8769b87181fSLokesh Vutla 	if (ret) {
8779b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
8789b87181fSLokesh Vutla 		return ret;
8799b87181fSLokesh Vutla 	}
8809b87181fSLokesh Vutla 
8819b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->tx_message.buf;
8829b87181fSLokesh Vutla 
8839b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
8849b87181fSLokesh Vutla 		return -ENODEV;
8859b87181fSLokesh Vutla 
8869b87181fSLokesh Vutla 	if (programmed_state)
8879b87181fSLokesh Vutla 		*programmed_state = resp->programmed_state;
8889b87181fSLokesh Vutla 	if (current_state)
8899b87181fSLokesh Vutla 		*current_state = resp->current_state;
8909b87181fSLokesh Vutla 
8919b87181fSLokesh Vutla 	return ret;
8929b87181fSLokesh Vutla }
8939b87181fSLokesh Vutla 
8949b87181fSLokesh Vutla /**
8959b87181fSLokesh Vutla  * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
8969b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
8979b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
8989b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
8999b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
9009b87181fSLokesh Vutla  *		which clock input to modify.
9019b87181fSLokesh Vutla  * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
9029b87181fSLokesh Vutla  * @can_change_freq: 'true' if frequency change is desired, else 'false'
9039b87181fSLokesh Vutla  * @enable_input_term: 'true' if input termination is desired, else 'false'
9049b87181fSLokesh Vutla  *
9059b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
9069b87181fSLokesh Vutla  */
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)9079b87181fSLokesh Vutla static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
9089b87181fSLokesh Vutla 				u8 clk_id, bool needs_ssc, bool can_change_freq,
9099b87181fSLokesh Vutla 				bool enable_input_term)
9109b87181fSLokesh Vutla {
9119b87181fSLokesh Vutla 	u32 flags = 0;
9129b87181fSLokesh Vutla 
9139b87181fSLokesh Vutla 	flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
9149b87181fSLokesh Vutla 	flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
9159b87181fSLokesh Vutla 	flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
9169b87181fSLokesh Vutla 
9179b87181fSLokesh Vutla 	return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
9189b87181fSLokesh Vutla 				      MSG_CLOCK_SW_STATE_REQ);
9199b87181fSLokesh Vutla }
9209b87181fSLokesh Vutla 
9219b87181fSLokesh Vutla /**
9229b87181fSLokesh Vutla  * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
9239b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
9249b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
9259b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
9269b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
9279b87181fSLokesh Vutla  *		which clock input to modify.
9289b87181fSLokesh Vutla  *
9299b87181fSLokesh Vutla  * NOTE: This clock must have been requested by get_clock previously.
9309b87181fSLokesh Vutla  *
9319b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
9329b87181fSLokesh Vutla  */
ti_sci_cmd_idle_clock(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id)9339b87181fSLokesh Vutla static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
9349b87181fSLokesh Vutla 				 u32 dev_id, u8 clk_id)
9359b87181fSLokesh Vutla {
9369b87181fSLokesh Vutla 	return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
9379b87181fSLokesh Vutla 				      MSG_CLOCK_SW_STATE_UNREQ);
9389b87181fSLokesh Vutla }
9399b87181fSLokesh Vutla 
9409b87181fSLokesh Vutla /**
9419b87181fSLokesh Vutla  * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
9429b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
9439b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
9449b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
9459b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
9469b87181fSLokesh Vutla  *		which clock input to modify.
9479b87181fSLokesh Vutla  *
9489b87181fSLokesh Vutla  * NOTE: This clock must have been requested by get_clock previously.
9499b87181fSLokesh Vutla  *
9509b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
9519b87181fSLokesh Vutla  */
ti_sci_cmd_put_clock(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id)9529b87181fSLokesh Vutla static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
9539b87181fSLokesh Vutla 				u32 dev_id, u8 clk_id)
9549b87181fSLokesh Vutla {
9559b87181fSLokesh Vutla 	return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
9569b87181fSLokesh Vutla 				      MSG_CLOCK_SW_STATE_AUTO);
9579b87181fSLokesh Vutla }
9589b87181fSLokesh Vutla 
9599b87181fSLokesh Vutla /**
9609b87181fSLokesh Vutla  * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
9619b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
9629b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
9639b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
9649b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
9659b87181fSLokesh Vutla  *		which clock input to modify.
9669b87181fSLokesh Vutla  * @req_state: state indicating if the clock is auto managed
9679b87181fSLokesh Vutla  *
9689b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
9699b87181fSLokesh Vutla  */
ti_sci_cmd_clk_is_auto(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,bool * req_state)9709b87181fSLokesh Vutla static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
9719b87181fSLokesh Vutla 				  u32 dev_id, u8 clk_id, bool *req_state)
9729b87181fSLokesh Vutla {
9739b87181fSLokesh Vutla 	u8 state = 0;
9749b87181fSLokesh Vutla 	int ret;
9759b87181fSLokesh Vutla 
9769b87181fSLokesh Vutla 	if (!req_state)
9779b87181fSLokesh Vutla 		return -EINVAL;
9789b87181fSLokesh Vutla 
9799b87181fSLokesh Vutla 	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
9809b87181fSLokesh Vutla 	if (ret)
9819b87181fSLokesh Vutla 		return ret;
9829b87181fSLokesh Vutla 
9839b87181fSLokesh Vutla 	*req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
9849b87181fSLokesh Vutla 	return 0;
9859b87181fSLokesh Vutla }
9869b87181fSLokesh Vutla 
9879b87181fSLokesh Vutla /**
9889b87181fSLokesh Vutla  * ti_sci_cmd_clk_is_on() - Is the clock ON
9899b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
9909b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
9919b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
9929b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
9939b87181fSLokesh Vutla  *		which clock input to modify.
9949b87181fSLokesh Vutla  * @req_state: state indicating if the clock is managed by us and enabled
9959b87181fSLokesh Vutla  * @curr_state: state indicating if the clock is ready for operation
9969b87181fSLokesh Vutla  *
9979b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
9989b87181fSLokesh Vutla  */
ti_sci_cmd_clk_is_on(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,bool * req_state,bool * curr_state)9999b87181fSLokesh Vutla static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
10009b87181fSLokesh Vutla 				u8 clk_id, bool *req_state, bool *curr_state)
10019b87181fSLokesh Vutla {
10029b87181fSLokesh Vutla 	u8 c_state = 0, r_state = 0;
10039b87181fSLokesh Vutla 	int ret;
10049b87181fSLokesh Vutla 
10059b87181fSLokesh Vutla 	if (!req_state && !curr_state)
10069b87181fSLokesh Vutla 		return -EINVAL;
10079b87181fSLokesh Vutla 
10089b87181fSLokesh Vutla 	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
10099b87181fSLokesh Vutla 					 &r_state, &c_state);
10109b87181fSLokesh Vutla 	if (ret)
10119b87181fSLokesh Vutla 		return ret;
10129b87181fSLokesh Vutla 
10139b87181fSLokesh Vutla 	if (req_state)
10149b87181fSLokesh Vutla 		*req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
10159b87181fSLokesh Vutla 	if (curr_state)
10169b87181fSLokesh Vutla 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
10179b87181fSLokesh Vutla 	return 0;
10189b87181fSLokesh Vutla }
10199b87181fSLokesh Vutla 
10209b87181fSLokesh Vutla /**
10219b87181fSLokesh Vutla  * ti_sci_cmd_clk_is_off() - Is the clock OFF
10229b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
10239b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
10249b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
10259b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
10269b87181fSLokesh Vutla  *		which clock input to modify.
10279b87181fSLokesh Vutla  * @req_state: state indicating if the clock is managed by us and disabled
10289b87181fSLokesh Vutla  * @curr_state: state indicating if the clock is NOT ready for operation
10299b87181fSLokesh Vutla  *
10309b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
10319b87181fSLokesh Vutla  */
ti_sci_cmd_clk_is_off(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,bool * req_state,bool * curr_state)10329b87181fSLokesh Vutla static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
10339b87181fSLokesh Vutla 				 u8 clk_id, bool *req_state, bool *curr_state)
10349b87181fSLokesh Vutla {
10359b87181fSLokesh Vutla 	u8 c_state = 0, r_state = 0;
10369b87181fSLokesh Vutla 	int ret;
10379b87181fSLokesh Vutla 
10389b87181fSLokesh Vutla 	if (!req_state && !curr_state)
10399b87181fSLokesh Vutla 		return -EINVAL;
10409b87181fSLokesh Vutla 
10419b87181fSLokesh Vutla 	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
10429b87181fSLokesh Vutla 					 &r_state, &c_state);
10439b87181fSLokesh Vutla 	if (ret)
10449b87181fSLokesh Vutla 		return ret;
10459b87181fSLokesh Vutla 
10469b87181fSLokesh Vutla 	if (req_state)
10479b87181fSLokesh Vutla 		*req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
10489b87181fSLokesh Vutla 	if (curr_state)
10499b87181fSLokesh Vutla 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
10509b87181fSLokesh Vutla 	return 0;
10519b87181fSLokesh Vutla }
10529b87181fSLokesh Vutla 
10539b87181fSLokesh Vutla /**
10549b87181fSLokesh Vutla  * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
10559b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
10569b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
10579b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
10589b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
10599b87181fSLokesh Vutla  *		which clock input to modify.
10609b87181fSLokesh Vutla  * @parent_id:	Parent clock identifier to set
10619b87181fSLokesh Vutla  *
10629b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
10639b87181fSLokesh Vutla  */
ti_sci_cmd_clk_set_parent(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u8 parent_id)10649b87181fSLokesh Vutla static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
10659b87181fSLokesh Vutla 				     u32 dev_id, u8 clk_id, u8 parent_id)
10669b87181fSLokesh Vutla {
10679b87181fSLokesh Vutla 	struct ti_sci_msg_req_set_clock_parent req;
10689b87181fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
10699b87181fSLokesh Vutla 	struct ti_sci_info *info;
10709b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
10719b87181fSLokesh Vutla 	int ret = 0;
10729b87181fSLokesh Vutla 
10739b87181fSLokesh Vutla 	if (IS_ERR(handle))
10749b87181fSLokesh Vutla 		return PTR_ERR(handle);
10759b87181fSLokesh Vutla 	if (!handle)
10769b87181fSLokesh Vutla 		return -EINVAL;
10779b87181fSLokesh Vutla 
10789b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
10799b87181fSLokesh Vutla 
10809b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
10819b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
10829b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
10839b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
10849b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
10859b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
10869b87181fSLokesh Vutla 		return ret;
10879b87181fSLokesh Vutla 	}
10889b87181fSLokesh Vutla 	req.dev_id = dev_id;
10899b87181fSLokesh Vutla 	req.clk_id = clk_id;
10909b87181fSLokesh Vutla 	req.parent_id = parent_id;
10919b87181fSLokesh Vutla 
10929b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
10939b87181fSLokesh Vutla 	if (ret) {
10949b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
10959b87181fSLokesh Vutla 		return ret;
10969b87181fSLokesh Vutla 	}
10979b87181fSLokesh Vutla 
10989b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
10999b87181fSLokesh Vutla 
11009b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
11019b87181fSLokesh Vutla 		return -ENODEV;
11029b87181fSLokesh Vutla 
11039b87181fSLokesh Vutla 	return ret;
11049b87181fSLokesh Vutla }
11059b87181fSLokesh Vutla 
11069b87181fSLokesh Vutla /**
11079b87181fSLokesh Vutla  * ti_sci_cmd_clk_get_parent() - Get current parent clock source
11089b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
11099b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
11109b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
11119b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
11129b87181fSLokesh Vutla  *		which clock input to modify.
11139b87181fSLokesh Vutla  * @parent_id:	Current clock parent
11149b87181fSLokesh Vutla  *
11159b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
11169b87181fSLokesh Vutla  */
ti_sci_cmd_clk_get_parent(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u8 * parent_id)11179b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
11189b87181fSLokesh Vutla 				     u32 dev_id, u8 clk_id, u8 *parent_id)
11199b87181fSLokesh Vutla {
11209b87181fSLokesh Vutla 	struct ti_sci_msg_resp_get_clock_parent *resp;
11219b87181fSLokesh Vutla 	struct ti_sci_msg_req_get_clock_parent req;
11229b87181fSLokesh Vutla 	struct ti_sci_info *info;
11239b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
11249b87181fSLokesh Vutla 	int ret = 0;
11259b87181fSLokesh Vutla 
11269b87181fSLokesh Vutla 	if (IS_ERR(handle))
11279b87181fSLokesh Vutla 		return PTR_ERR(handle);
11289b87181fSLokesh Vutla 	if (!handle || !parent_id)
11299b87181fSLokesh Vutla 		return -EINVAL;
11309b87181fSLokesh Vutla 
11319b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
11329b87181fSLokesh Vutla 
11339b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
11349b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
11359b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
11369b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
11379b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
11389b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
11399b87181fSLokesh Vutla 		return ret;
11409b87181fSLokesh Vutla 	}
11419b87181fSLokesh Vutla 	req.dev_id = dev_id;
11429b87181fSLokesh Vutla 	req.clk_id = clk_id;
11439b87181fSLokesh Vutla 
11449b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
11459b87181fSLokesh Vutla 	if (ret) {
11469b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
11479b87181fSLokesh Vutla 		return ret;
11489b87181fSLokesh Vutla 	}
11499b87181fSLokesh Vutla 
11509b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->tx_message.buf;
11519b87181fSLokesh Vutla 
11529b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
11539b87181fSLokesh Vutla 		ret = -ENODEV;
11549b87181fSLokesh Vutla 	else
11559b87181fSLokesh Vutla 		*parent_id = resp->parent_id;
11569b87181fSLokesh Vutla 
11579b87181fSLokesh Vutla 	return ret;
11589b87181fSLokesh Vutla }
11599b87181fSLokesh Vutla 
11609b87181fSLokesh Vutla /**
11619b87181fSLokesh Vutla  * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source
11629b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
11639b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
11649b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
11659b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
11669b87181fSLokesh Vutla  *		which clock input to modify.
11679b87181fSLokesh Vutla  * @num_parents: Returns he number of parents to the current clock.
11689b87181fSLokesh Vutla  *
11699b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
11709b87181fSLokesh Vutla  */
ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u8 * num_parents)11719b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
11729b87181fSLokesh Vutla 					  u32 dev_id, u8 clk_id,
11739b87181fSLokesh Vutla 					  u8 *num_parents)
11749b87181fSLokesh Vutla {
11759b87181fSLokesh Vutla 	struct ti_sci_msg_resp_get_clock_num_parents *resp;
11769b87181fSLokesh Vutla 	struct ti_sci_msg_req_get_clock_num_parents req;
11779b87181fSLokesh Vutla 	struct ti_sci_info *info;
11789b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
11799b87181fSLokesh Vutla 	int ret = 0;
11809b87181fSLokesh Vutla 
11819b87181fSLokesh Vutla 	if (IS_ERR(handle))
11829b87181fSLokesh Vutla 		return PTR_ERR(handle);
11839b87181fSLokesh Vutla 	if (!handle || !num_parents)
11849b87181fSLokesh Vutla 		return -EINVAL;
11859b87181fSLokesh Vutla 
11869b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
11879b87181fSLokesh Vutla 
11889b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
11899b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
11909b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
11919b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
11929b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
11939b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
11949b87181fSLokesh Vutla 		return ret;
11959b87181fSLokesh Vutla 	}
11969b87181fSLokesh Vutla 	req.dev_id = dev_id;
11979b87181fSLokesh Vutla 	req.clk_id = clk_id;
11989b87181fSLokesh Vutla 
11999b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
12009b87181fSLokesh Vutla 	if (ret) {
12019b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
12029b87181fSLokesh Vutla 		return ret;
12039b87181fSLokesh Vutla 	}
12049b87181fSLokesh Vutla 
12059b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_get_clock_num_parents *)
12069b87181fSLokesh Vutla 							xfer->tx_message.buf;
12079b87181fSLokesh Vutla 
12089b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
12099b87181fSLokesh Vutla 		ret = -ENODEV;
12109b87181fSLokesh Vutla 	else
12119b87181fSLokesh Vutla 		*num_parents = resp->num_parents;
12129b87181fSLokesh Vutla 
12139b87181fSLokesh Vutla 	return ret;
12149b87181fSLokesh Vutla }
12159b87181fSLokesh Vutla 
12169b87181fSLokesh Vutla /**
12179b87181fSLokesh Vutla  * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
12189b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
12199b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
12209b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
12219b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
12229b87181fSLokesh Vutla  *		which clock input to modify.
12239b87181fSLokesh Vutla  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
12249b87181fSLokesh Vutla  *		allowable programmed frequency and does not account for clock
12259b87181fSLokesh Vutla  *		tolerances and jitter.
12269b87181fSLokesh Vutla  * @target_freq: The target clock frequency in Hz. A frequency will be
12279b87181fSLokesh Vutla  *		processed as close to this target frequency as possible.
12289b87181fSLokesh Vutla  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
12299b87181fSLokesh Vutla  *		allowable programmed frequency and does not account for clock
12309b87181fSLokesh Vutla  *		tolerances and jitter.
12319b87181fSLokesh Vutla  * @match_freq:	Frequency match in Hz response.
12329b87181fSLokesh Vutla  *
12339b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
12349b87181fSLokesh Vutla  */
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)12359b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
12369b87181fSLokesh Vutla 					 u32 dev_id, u8 clk_id, u64 min_freq,
12379b87181fSLokesh Vutla 					 u64 target_freq, u64 max_freq,
12389b87181fSLokesh Vutla 					 u64 *match_freq)
12399b87181fSLokesh Vutla {
12409b87181fSLokesh Vutla 	struct ti_sci_msg_resp_query_clock_freq *resp;
12419b87181fSLokesh Vutla 	struct ti_sci_msg_req_query_clock_freq req;
12429b87181fSLokesh Vutla 	struct ti_sci_info *info;
12439b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
12449b87181fSLokesh Vutla 	int ret = 0;
12459b87181fSLokesh Vutla 
12469b87181fSLokesh Vutla 	if (IS_ERR(handle))
12479b87181fSLokesh Vutla 		return PTR_ERR(handle);
12489b87181fSLokesh Vutla 	if (!handle || !match_freq)
12499b87181fSLokesh Vutla 		return -EINVAL;
12509b87181fSLokesh Vutla 
12519b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
12529b87181fSLokesh Vutla 
12539b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
12549b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
12559b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
12569b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
12579b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
12589b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
12599b87181fSLokesh Vutla 		return ret;
12609b87181fSLokesh Vutla 	}
12619b87181fSLokesh Vutla 	req.dev_id = dev_id;
12629b87181fSLokesh Vutla 	req.clk_id = clk_id;
12639b87181fSLokesh Vutla 	req.min_freq_hz = min_freq;
12649b87181fSLokesh Vutla 	req.target_freq_hz = target_freq;
12659b87181fSLokesh Vutla 	req.max_freq_hz = max_freq;
12669b87181fSLokesh Vutla 
12679b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
12689b87181fSLokesh Vutla 	if (ret) {
12699b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
12709b87181fSLokesh Vutla 		return ret;
12719b87181fSLokesh Vutla 	}
12729b87181fSLokesh Vutla 
12739b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->tx_message.buf;
12749b87181fSLokesh Vutla 
12759b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
12769b87181fSLokesh Vutla 		ret = -ENODEV;
12779b87181fSLokesh Vutla 	else
12789b87181fSLokesh Vutla 		*match_freq = resp->freq_hz;
12799b87181fSLokesh Vutla 
12809b87181fSLokesh Vutla 	return ret;
12819b87181fSLokesh Vutla }
12829b87181fSLokesh Vutla 
12839b87181fSLokesh Vutla /**
12849b87181fSLokesh Vutla  * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
12859b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
12869b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
12879b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
12889b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
12899b87181fSLokesh Vutla  *		which clock input to modify.
12909b87181fSLokesh Vutla  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
12919b87181fSLokesh Vutla  *		allowable programmed frequency and does not account for clock
12929b87181fSLokesh Vutla  *		tolerances and jitter.
12939b87181fSLokesh Vutla  * @target_freq: The target clock frequency in Hz. A frequency will be
12949b87181fSLokesh Vutla  *		processed as close to this target frequency as possible.
12959b87181fSLokesh Vutla  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
12969b87181fSLokesh Vutla  *		allowable programmed frequency and does not account for clock
12979b87181fSLokesh Vutla  *		tolerances and jitter.
12989b87181fSLokesh Vutla  *
12999b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
13009b87181fSLokesh Vutla  */
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)13019b87181fSLokesh Vutla static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
13029b87181fSLokesh Vutla 				   u32 dev_id, u8 clk_id, u64 min_freq,
13039b87181fSLokesh Vutla 				   u64 target_freq, u64 max_freq)
13049b87181fSLokesh Vutla {
13059b87181fSLokesh Vutla 	struct ti_sci_msg_req_set_clock_freq req;
13069b87181fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
13079b87181fSLokesh Vutla 	struct ti_sci_info *info;
13089b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
13099b87181fSLokesh Vutla 	int ret = 0;
13109b87181fSLokesh Vutla 
13119b87181fSLokesh Vutla 	if (IS_ERR(handle))
13129b87181fSLokesh Vutla 		return PTR_ERR(handle);
13139b87181fSLokesh Vutla 	if (!handle)
13149b87181fSLokesh Vutla 		return -EINVAL;
13159b87181fSLokesh Vutla 
13169b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
13179b87181fSLokesh Vutla 
13189b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
13199b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
13209b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
13219b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
13229b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
13239b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
13249b87181fSLokesh Vutla 		return ret;
13259b87181fSLokesh Vutla 	}
13269b87181fSLokesh Vutla 	req.dev_id = dev_id;
13279b87181fSLokesh Vutla 	req.clk_id = clk_id;
13289b87181fSLokesh Vutla 	req.min_freq_hz = min_freq;
13299b87181fSLokesh Vutla 	req.target_freq_hz = target_freq;
13309b87181fSLokesh Vutla 	req.max_freq_hz = max_freq;
13319b87181fSLokesh Vutla 
13329b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
13339b87181fSLokesh Vutla 	if (ret) {
13349b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
13359b87181fSLokesh Vutla 		return ret;
13369b87181fSLokesh Vutla 	}
13379b87181fSLokesh Vutla 
13389b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
13399b87181fSLokesh Vutla 
13409b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
13419b87181fSLokesh Vutla 		return -ENODEV;
13429b87181fSLokesh Vutla 
13439b87181fSLokesh Vutla 	return ret;
13449b87181fSLokesh Vutla }
13459b87181fSLokesh Vutla 
13469b87181fSLokesh Vutla /**
13479b87181fSLokesh Vutla  * ti_sci_cmd_clk_get_freq() - Get current frequency
13489b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
13499b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
13509b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
13519b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
13529b87181fSLokesh Vutla  *		which clock input to modify.
13539b87181fSLokesh Vutla  * @freq:	Currently frequency in Hz
13549b87181fSLokesh Vutla  *
13559b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
13569b87181fSLokesh Vutla  */
ti_sci_cmd_clk_get_freq(const struct ti_sci_handle * handle,u32 dev_id,u8 clk_id,u64 * freq)13579b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
13589b87181fSLokesh Vutla 				   u32 dev_id, u8 clk_id, u64 *freq)
13599b87181fSLokesh Vutla {
13609b87181fSLokesh Vutla 	struct ti_sci_msg_resp_get_clock_freq *resp;
13619b87181fSLokesh Vutla 	struct ti_sci_msg_req_get_clock_freq req;
13629b87181fSLokesh Vutla 	struct ti_sci_info *info;
13639b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
13649b87181fSLokesh Vutla 	int ret = 0;
13659b87181fSLokesh Vutla 
13669b87181fSLokesh Vutla 	if (IS_ERR(handle))
13679b87181fSLokesh Vutla 		return PTR_ERR(handle);
13689b87181fSLokesh Vutla 	if (!handle || !freq)
13699b87181fSLokesh Vutla 		return -EINVAL;
13709b87181fSLokesh Vutla 
13719b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
13729b87181fSLokesh Vutla 
13739b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
13749b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
13759b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
13769b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
13779b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
13789b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
13799b87181fSLokesh Vutla 		return ret;
13809b87181fSLokesh Vutla 	}
13819b87181fSLokesh Vutla 	req.dev_id = dev_id;
13829b87181fSLokesh Vutla 	req.clk_id = clk_id;
13839b87181fSLokesh Vutla 
13849b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
13859b87181fSLokesh Vutla 	if (ret) {
13869b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
13879b87181fSLokesh Vutla 		return ret;
13889b87181fSLokesh Vutla 	}
13899b87181fSLokesh Vutla 
13909b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->tx_message.buf;
13919b87181fSLokesh Vutla 
13929b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
13939b87181fSLokesh Vutla 		ret = -ENODEV;
13949b87181fSLokesh Vutla 	else
13959b87181fSLokesh Vutla 		*freq = resp->freq_hz;
13969b87181fSLokesh Vutla 
13979b87181fSLokesh Vutla 	return ret;
13989b87181fSLokesh Vutla }
13999b87181fSLokesh Vutla 
1400f369b0f2SAndreas Dannenberg /**
1401f369b0f2SAndreas Dannenberg  * ti_sci_cmd_core_reboot() - Command to request system reset
1402f369b0f2SAndreas Dannenberg  * @handle:	pointer to TI SCI handle
1403f369b0f2SAndreas Dannenberg  *
1404f369b0f2SAndreas Dannenberg  * Return: 0 if all went well, else returns appropriate error value.
1405f369b0f2SAndreas Dannenberg  */
ti_sci_cmd_core_reboot(const struct ti_sci_handle * handle)1406f369b0f2SAndreas Dannenberg static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
1407f369b0f2SAndreas Dannenberg {
1408f369b0f2SAndreas Dannenberg 	struct ti_sci_msg_req_reboot req;
1409f369b0f2SAndreas Dannenberg 	struct ti_sci_msg_hdr *resp;
1410f369b0f2SAndreas Dannenberg 	struct ti_sci_info *info;
1411f369b0f2SAndreas Dannenberg 	struct ti_sci_xfer *xfer;
1412f369b0f2SAndreas Dannenberg 	int ret = 0;
1413f369b0f2SAndreas Dannenberg 
1414f369b0f2SAndreas Dannenberg 	if (IS_ERR(handle))
1415f369b0f2SAndreas Dannenberg 		return PTR_ERR(handle);
1416f369b0f2SAndreas Dannenberg 	if (!handle)
1417f369b0f2SAndreas Dannenberg 		return -EINVAL;
1418f369b0f2SAndreas Dannenberg 
1419f369b0f2SAndreas Dannenberg 	info = handle_to_ti_sci_info(handle);
1420f369b0f2SAndreas Dannenberg 
1421f369b0f2SAndreas Dannenberg 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SYS_RESET,
1422f369b0f2SAndreas Dannenberg 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1423f369b0f2SAndreas Dannenberg 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1424f369b0f2SAndreas Dannenberg 	if (IS_ERR(xfer)) {
1425f369b0f2SAndreas Dannenberg 		ret = PTR_ERR(xfer);
1426f369b0f2SAndreas Dannenberg 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1427f369b0f2SAndreas Dannenberg 		return ret;
1428f369b0f2SAndreas Dannenberg 	}
1429f369b0f2SAndreas Dannenberg 
1430f369b0f2SAndreas Dannenberg 	ret = ti_sci_do_xfer(info, xfer);
1431f369b0f2SAndreas Dannenberg 	if (ret) {
1432f369b0f2SAndreas Dannenberg 		dev_err(dev, "Mbox send fail %d\n", ret);
1433f369b0f2SAndreas Dannenberg 		return ret;
1434f369b0f2SAndreas Dannenberg 	}
1435f369b0f2SAndreas Dannenberg 
1436f369b0f2SAndreas Dannenberg 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1437f369b0f2SAndreas Dannenberg 
1438f369b0f2SAndreas Dannenberg 	if (!ti_sci_is_response_ack(resp))
1439f369b0f2SAndreas Dannenberg 		return -ENODEV;
1440f369b0f2SAndreas Dannenberg 
1441f369b0f2SAndreas Dannenberg 	return ret;
1442f369b0f2SAndreas Dannenberg }
1443f369b0f2SAndreas Dannenberg 
1444*ccbc8b2fSLokesh Vutla /**
1445*ccbc8b2fSLokesh Vutla  * ti_sci_cmd_proc_request() - Command to request a physical processor control
1446*ccbc8b2fSLokesh Vutla  * @handle:	Pointer to TI SCI handle
1447*ccbc8b2fSLokesh Vutla  * @proc_id:	Processor ID this request is for
1448*ccbc8b2fSLokesh Vutla  *
1449*ccbc8b2fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1450*ccbc8b2fSLokesh Vutla  */
ti_sci_cmd_proc_request(const struct ti_sci_handle * handle,u8 proc_id)1451*ccbc8b2fSLokesh Vutla static int ti_sci_cmd_proc_request(const struct ti_sci_handle *handle,
1452*ccbc8b2fSLokesh Vutla 				   u8 proc_id)
1453*ccbc8b2fSLokesh Vutla {
1454*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_req_proc_request req;
1455*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
1456*ccbc8b2fSLokesh Vutla 	struct ti_sci_info *info;
1457*ccbc8b2fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1458*ccbc8b2fSLokesh Vutla 	int ret = 0;
1459*ccbc8b2fSLokesh Vutla 
1460*ccbc8b2fSLokesh Vutla 	if (IS_ERR(handle))
1461*ccbc8b2fSLokesh Vutla 		return PTR_ERR(handle);
1462*ccbc8b2fSLokesh Vutla 	if (!handle)
1463*ccbc8b2fSLokesh Vutla 		return -EINVAL;
1464*ccbc8b2fSLokesh Vutla 
1465*ccbc8b2fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1466*ccbc8b2fSLokesh Vutla 
1467*ccbc8b2fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_REQUEST,
1468*ccbc8b2fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1469*ccbc8b2fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1470*ccbc8b2fSLokesh Vutla 	if (IS_ERR(xfer)) {
1471*ccbc8b2fSLokesh Vutla 		ret = PTR_ERR(xfer);
1472*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1473*ccbc8b2fSLokesh Vutla 		return ret;
1474*ccbc8b2fSLokesh Vutla 	}
1475*ccbc8b2fSLokesh Vutla 	req.processor_id = proc_id;
1476*ccbc8b2fSLokesh Vutla 
1477*ccbc8b2fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1478*ccbc8b2fSLokesh Vutla 	if (ret) {
1479*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1480*ccbc8b2fSLokesh Vutla 		return ret;
1481*ccbc8b2fSLokesh Vutla 	}
1482*ccbc8b2fSLokesh Vutla 
1483*ccbc8b2fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1484*ccbc8b2fSLokesh Vutla 
1485*ccbc8b2fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1486*ccbc8b2fSLokesh Vutla 		ret = -ENODEV;
1487*ccbc8b2fSLokesh Vutla 
1488*ccbc8b2fSLokesh Vutla 	return ret;
1489*ccbc8b2fSLokesh Vutla }
1490*ccbc8b2fSLokesh Vutla 
1491*ccbc8b2fSLokesh Vutla /**
1492*ccbc8b2fSLokesh Vutla  * ti_sci_cmd_proc_release() - Command to release a physical processor control
1493*ccbc8b2fSLokesh Vutla  * @handle:	Pointer to TI SCI handle
1494*ccbc8b2fSLokesh Vutla  * @proc_id:	Processor ID this request is for
1495*ccbc8b2fSLokesh Vutla  *
1496*ccbc8b2fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1497*ccbc8b2fSLokesh Vutla  */
ti_sci_cmd_proc_release(const struct ti_sci_handle * handle,u8 proc_id)1498*ccbc8b2fSLokesh Vutla static int ti_sci_cmd_proc_release(const struct ti_sci_handle *handle,
1499*ccbc8b2fSLokesh Vutla 				   u8 proc_id)
1500*ccbc8b2fSLokesh Vutla {
1501*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_req_proc_release req;
1502*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
1503*ccbc8b2fSLokesh Vutla 	struct ti_sci_info *info;
1504*ccbc8b2fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1505*ccbc8b2fSLokesh Vutla 	int ret = 0;
1506*ccbc8b2fSLokesh Vutla 
1507*ccbc8b2fSLokesh Vutla 	if (IS_ERR(handle))
1508*ccbc8b2fSLokesh Vutla 		return PTR_ERR(handle);
1509*ccbc8b2fSLokesh Vutla 	if (!handle)
1510*ccbc8b2fSLokesh Vutla 		return -EINVAL;
1511*ccbc8b2fSLokesh Vutla 
1512*ccbc8b2fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1513*ccbc8b2fSLokesh Vutla 
1514*ccbc8b2fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_RELEASE,
1515*ccbc8b2fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1516*ccbc8b2fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1517*ccbc8b2fSLokesh Vutla 	if (IS_ERR(xfer)) {
1518*ccbc8b2fSLokesh Vutla 		ret = PTR_ERR(xfer);
1519*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1520*ccbc8b2fSLokesh Vutla 		return ret;
1521*ccbc8b2fSLokesh Vutla 	}
1522*ccbc8b2fSLokesh Vutla 	req.processor_id = proc_id;
1523*ccbc8b2fSLokesh Vutla 
1524*ccbc8b2fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1525*ccbc8b2fSLokesh Vutla 	if (ret) {
1526*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1527*ccbc8b2fSLokesh Vutla 		return ret;
1528*ccbc8b2fSLokesh Vutla 	}
1529*ccbc8b2fSLokesh Vutla 
1530*ccbc8b2fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1531*ccbc8b2fSLokesh Vutla 
1532*ccbc8b2fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1533*ccbc8b2fSLokesh Vutla 		ret = -ENODEV;
1534*ccbc8b2fSLokesh Vutla 
1535*ccbc8b2fSLokesh Vutla 	return ret;
1536*ccbc8b2fSLokesh Vutla }
1537*ccbc8b2fSLokesh Vutla 
1538*ccbc8b2fSLokesh Vutla /**
1539*ccbc8b2fSLokesh Vutla  * ti_sci_cmd_proc_handover() - Command to handover a physical processor
1540*ccbc8b2fSLokesh Vutla  *				control to a host in the processor's access
1541*ccbc8b2fSLokesh Vutla  *				control list.
1542*ccbc8b2fSLokesh Vutla  * @handle:	Pointer to TI SCI handle
1543*ccbc8b2fSLokesh Vutla  * @proc_id:	Processor ID this request is for
1544*ccbc8b2fSLokesh Vutla  * @host_id:	Host ID to get the control of the processor
1545*ccbc8b2fSLokesh Vutla  *
1546*ccbc8b2fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1547*ccbc8b2fSLokesh Vutla  */
ti_sci_cmd_proc_handover(const struct ti_sci_handle * handle,u8 proc_id,u8 host_id)1548*ccbc8b2fSLokesh Vutla static int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle,
1549*ccbc8b2fSLokesh Vutla 				    u8 proc_id, u8 host_id)
1550*ccbc8b2fSLokesh Vutla {
1551*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_req_proc_handover req;
1552*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
1553*ccbc8b2fSLokesh Vutla 	struct ti_sci_info *info;
1554*ccbc8b2fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1555*ccbc8b2fSLokesh Vutla 	int ret = 0;
1556*ccbc8b2fSLokesh Vutla 
1557*ccbc8b2fSLokesh Vutla 	if (IS_ERR(handle))
1558*ccbc8b2fSLokesh Vutla 		return PTR_ERR(handle);
1559*ccbc8b2fSLokesh Vutla 	if (!handle)
1560*ccbc8b2fSLokesh Vutla 		return -EINVAL;
1561*ccbc8b2fSLokesh Vutla 
1562*ccbc8b2fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1563*ccbc8b2fSLokesh Vutla 
1564*ccbc8b2fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_HANDOVER,
1565*ccbc8b2fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1566*ccbc8b2fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1567*ccbc8b2fSLokesh Vutla 	if (IS_ERR(xfer)) {
1568*ccbc8b2fSLokesh Vutla 		ret = PTR_ERR(xfer);
1569*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1570*ccbc8b2fSLokesh Vutla 		return ret;
1571*ccbc8b2fSLokesh Vutla 	}
1572*ccbc8b2fSLokesh Vutla 	req.processor_id = proc_id;
1573*ccbc8b2fSLokesh Vutla 	req.host_id = host_id;
1574*ccbc8b2fSLokesh Vutla 
1575*ccbc8b2fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1576*ccbc8b2fSLokesh Vutla 	if (ret) {
1577*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1578*ccbc8b2fSLokesh Vutla 		return ret;
1579*ccbc8b2fSLokesh Vutla 	}
1580*ccbc8b2fSLokesh Vutla 
1581*ccbc8b2fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1582*ccbc8b2fSLokesh Vutla 
1583*ccbc8b2fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1584*ccbc8b2fSLokesh Vutla 		ret = -ENODEV;
1585*ccbc8b2fSLokesh Vutla 
1586*ccbc8b2fSLokesh Vutla 	return ret;
1587*ccbc8b2fSLokesh Vutla }
1588*ccbc8b2fSLokesh Vutla 
1589*ccbc8b2fSLokesh Vutla /**
1590*ccbc8b2fSLokesh Vutla  * ti_sci_cmd_set_proc_boot_cfg() - Command to set the processor boot
1591*ccbc8b2fSLokesh Vutla  *				    configuration flags
1592*ccbc8b2fSLokesh Vutla  * @handle:		Pointer to TI SCI handle
1593*ccbc8b2fSLokesh Vutla  * @proc_id:		Processor ID this request is for
1594*ccbc8b2fSLokesh Vutla  * @config_flags_set:	Configuration flags to be set
1595*ccbc8b2fSLokesh Vutla  * @config_flags_clear:	Configuration flags to be cleared.
1596*ccbc8b2fSLokesh Vutla  *
1597*ccbc8b2fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1598*ccbc8b2fSLokesh Vutla  */
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*ccbc8b2fSLokesh Vutla static int ti_sci_cmd_set_proc_boot_cfg(const struct ti_sci_handle *handle,
1600*ccbc8b2fSLokesh Vutla 					u8 proc_id, u64 bootvector,
1601*ccbc8b2fSLokesh Vutla 					u32 config_flags_set,
1602*ccbc8b2fSLokesh Vutla 					u32 config_flags_clear)
1603*ccbc8b2fSLokesh Vutla {
1604*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_req_set_proc_boot_config req;
1605*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
1606*ccbc8b2fSLokesh Vutla 	struct ti_sci_info *info;
1607*ccbc8b2fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1608*ccbc8b2fSLokesh Vutla 	int ret = 0;
1609*ccbc8b2fSLokesh Vutla 
1610*ccbc8b2fSLokesh Vutla 	if (IS_ERR(handle))
1611*ccbc8b2fSLokesh Vutla 		return PTR_ERR(handle);
1612*ccbc8b2fSLokesh Vutla 	if (!handle)
1613*ccbc8b2fSLokesh Vutla 		return -EINVAL;
1614*ccbc8b2fSLokesh Vutla 
1615*ccbc8b2fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1616*ccbc8b2fSLokesh Vutla 
1617*ccbc8b2fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CONFIG,
1618*ccbc8b2fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1619*ccbc8b2fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1620*ccbc8b2fSLokesh Vutla 	if (IS_ERR(xfer)) {
1621*ccbc8b2fSLokesh Vutla 		ret = PTR_ERR(xfer);
1622*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1623*ccbc8b2fSLokesh Vutla 		return ret;
1624*ccbc8b2fSLokesh Vutla 	}
1625*ccbc8b2fSLokesh Vutla 	req.processor_id = proc_id;
1626*ccbc8b2fSLokesh Vutla 	req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
1627*ccbc8b2fSLokesh Vutla 	req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
1628*ccbc8b2fSLokesh Vutla 				TISCI_ADDR_HIGH_SHIFT;
1629*ccbc8b2fSLokesh Vutla 	req.config_flags_set = config_flags_set;
1630*ccbc8b2fSLokesh Vutla 	req.config_flags_clear = config_flags_clear;
1631*ccbc8b2fSLokesh Vutla 
1632*ccbc8b2fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1633*ccbc8b2fSLokesh Vutla 	if (ret) {
1634*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1635*ccbc8b2fSLokesh Vutla 		return ret;
1636*ccbc8b2fSLokesh Vutla 	}
1637*ccbc8b2fSLokesh Vutla 
1638*ccbc8b2fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1639*ccbc8b2fSLokesh Vutla 
1640*ccbc8b2fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1641*ccbc8b2fSLokesh Vutla 		ret = -ENODEV;
1642*ccbc8b2fSLokesh Vutla 
1643*ccbc8b2fSLokesh Vutla 	return ret;
1644*ccbc8b2fSLokesh Vutla }
1645*ccbc8b2fSLokesh Vutla 
1646*ccbc8b2fSLokesh Vutla /**
1647*ccbc8b2fSLokesh Vutla  * ti_sci_cmd_set_proc_boot_ctrl() - Command to set the processor boot
1648*ccbc8b2fSLokesh Vutla  *				     control flags
1649*ccbc8b2fSLokesh Vutla  * @handle:			Pointer to TI SCI handle
1650*ccbc8b2fSLokesh Vutla  * @proc_id:			Processor ID this request is for
1651*ccbc8b2fSLokesh Vutla  * @control_flags_set:		Control flags to be set
1652*ccbc8b2fSLokesh Vutla  * @control_flags_clear:	Control flags to be cleared
1653*ccbc8b2fSLokesh Vutla  *
1654*ccbc8b2fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1655*ccbc8b2fSLokesh Vutla  */
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*ccbc8b2fSLokesh Vutla static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle,
1657*ccbc8b2fSLokesh Vutla 					 u8 proc_id, u32 control_flags_set,
1658*ccbc8b2fSLokesh Vutla 					 u32 control_flags_clear)
1659*ccbc8b2fSLokesh Vutla {
1660*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_req_set_proc_boot_ctrl req;
1661*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
1662*ccbc8b2fSLokesh Vutla 	struct ti_sci_info *info;
1663*ccbc8b2fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1664*ccbc8b2fSLokesh Vutla 	int ret = 0;
1665*ccbc8b2fSLokesh Vutla 
1666*ccbc8b2fSLokesh Vutla 	if (IS_ERR(handle))
1667*ccbc8b2fSLokesh Vutla 		return PTR_ERR(handle);
1668*ccbc8b2fSLokesh Vutla 	if (!handle)
1669*ccbc8b2fSLokesh Vutla 		return -EINVAL;
1670*ccbc8b2fSLokesh Vutla 
1671*ccbc8b2fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1672*ccbc8b2fSLokesh Vutla 
1673*ccbc8b2fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CTRL,
1674*ccbc8b2fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1675*ccbc8b2fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1676*ccbc8b2fSLokesh Vutla 	if (IS_ERR(xfer)) {
1677*ccbc8b2fSLokesh Vutla 		ret = PTR_ERR(xfer);
1678*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1679*ccbc8b2fSLokesh Vutla 		return ret;
1680*ccbc8b2fSLokesh Vutla 	}
1681*ccbc8b2fSLokesh Vutla 	req.processor_id = proc_id;
1682*ccbc8b2fSLokesh Vutla 	req.control_flags_set = control_flags_set;
1683*ccbc8b2fSLokesh Vutla 	req.control_flags_clear = control_flags_clear;
1684*ccbc8b2fSLokesh Vutla 
1685*ccbc8b2fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1686*ccbc8b2fSLokesh Vutla 	if (ret) {
1687*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1688*ccbc8b2fSLokesh Vutla 		return ret;
1689*ccbc8b2fSLokesh Vutla 	}
1690*ccbc8b2fSLokesh Vutla 
1691*ccbc8b2fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1692*ccbc8b2fSLokesh Vutla 
1693*ccbc8b2fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1694*ccbc8b2fSLokesh Vutla 		ret = -ENODEV;
1695*ccbc8b2fSLokesh Vutla 
1696*ccbc8b2fSLokesh Vutla 	return ret;
1697*ccbc8b2fSLokesh Vutla }
1698*ccbc8b2fSLokesh Vutla 
1699*ccbc8b2fSLokesh Vutla /**
1700*ccbc8b2fSLokesh Vutla  * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the
1701*ccbc8b2fSLokesh Vutla  *			image and then set the processor configuration flags.
1702*ccbc8b2fSLokesh Vutla  * @handle:	Pointer to TI SCI handle
1703*ccbc8b2fSLokesh Vutla  * @proc_id:	Processor ID this request is for
1704*ccbc8b2fSLokesh Vutla  * @cert_addr:	Memory address at which payload image certificate is located.
1705*ccbc8b2fSLokesh Vutla  *
1706*ccbc8b2fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1707*ccbc8b2fSLokesh Vutla  */
ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle * handle,u8 proc_id,u64 cert_addr)1708*ccbc8b2fSLokesh Vutla static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle,
1709*ccbc8b2fSLokesh Vutla 					   u8 proc_id, u64 cert_addr)
1710*ccbc8b2fSLokesh Vutla {
1711*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_req_proc_auth_boot_image req;
1712*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
1713*ccbc8b2fSLokesh Vutla 	struct ti_sci_info *info;
1714*ccbc8b2fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1715*ccbc8b2fSLokesh Vutla 	int ret = 0;
1716*ccbc8b2fSLokesh Vutla 
1717*ccbc8b2fSLokesh Vutla 	if (IS_ERR(handle))
1718*ccbc8b2fSLokesh Vutla 		return PTR_ERR(handle);
1719*ccbc8b2fSLokesh Vutla 	if (!handle)
1720*ccbc8b2fSLokesh Vutla 		return -EINVAL;
1721*ccbc8b2fSLokesh Vutla 
1722*ccbc8b2fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1723*ccbc8b2fSLokesh Vutla 
1724*ccbc8b2fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_BOOT_IMIAGE,
1725*ccbc8b2fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1726*ccbc8b2fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1727*ccbc8b2fSLokesh Vutla 	if (IS_ERR(xfer)) {
1728*ccbc8b2fSLokesh Vutla 		ret = PTR_ERR(xfer);
1729*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1730*ccbc8b2fSLokesh Vutla 		return ret;
1731*ccbc8b2fSLokesh Vutla 	}
1732*ccbc8b2fSLokesh Vutla 	req.processor_id = proc_id;
1733*ccbc8b2fSLokesh Vutla 	req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
1734*ccbc8b2fSLokesh Vutla 	req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
1735*ccbc8b2fSLokesh Vutla 				TISCI_ADDR_HIGH_SHIFT;
1736*ccbc8b2fSLokesh Vutla 
1737*ccbc8b2fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1738*ccbc8b2fSLokesh Vutla 	if (ret) {
1739*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1740*ccbc8b2fSLokesh Vutla 		return ret;
1741*ccbc8b2fSLokesh Vutla 	}
1742*ccbc8b2fSLokesh Vutla 
1743*ccbc8b2fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1744*ccbc8b2fSLokesh Vutla 
1745*ccbc8b2fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1746*ccbc8b2fSLokesh Vutla 		ret = -ENODEV;
1747*ccbc8b2fSLokesh Vutla 
1748*ccbc8b2fSLokesh Vutla 	return ret;
1749*ccbc8b2fSLokesh Vutla }
1750*ccbc8b2fSLokesh Vutla 
1751*ccbc8b2fSLokesh Vutla /**
1752*ccbc8b2fSLokesh Vutla  * ti_sci_cmd_get_proc_boot_status() - Command to get the processor boot status
1753*ccbc8b2fSLokesh Vutla  * @handle:	Pointer to TI SCI handle
1754*ccbc8b2fSLokesh Vutla  * @proc_id:	Processor ID this request is for
1755*ccbc8b2fSLokesh Vutla  *
1756*ccbc8b2fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1757*ccbc8b2fSLokesh Vutla  */
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*ccbc8b2fSLokesh Vutla static int ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle *handle,
1759*ccbc8b2fSLokesh Vutla 					   u8 proc_id, u64 *bv, u32 *cfg_flags,
1760*ccbc8b2fSLokesh Vutla 					   u32 *ctrl_flags, u32 *sts_flags)
1761*ccbc8b2fSLokesh Vutla {
1762*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_resp_get_proc_boot_status *resp;
1763*ccbc8b2fSLokesh Vutla 	struct ti_sci_msg_req_get_proc_boot_status req;
1764*ccbc8b2fSLokesh Vutla 	struct ti_sci_info *info;
1765*ccbc8b2fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1766*ccbc8b2fSLokesh Vutla 	int ret = 0;
1767*ccbc8b2fSLokesh Vutla 
1768*ccbc8b2fSLokesh Vutla 	if (IS_ERR(handle))
1769*ccbc8b2fSLokesh Vutla 		return PTR_ERR(handle);
1770*ccbc8b2fSLokesh Vutla 	if (!handle)
1771*ccbc8b2fSLokesh Vutla 		return -EINVAL;
1772*ccbc8b2fSLokesh Vutla 
1773*ccbc8b2fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1774*ccbc8b2fSLokesh Vutla 
1775*ccbc8b2fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_GET_PROC_BOOT_STATUS,
1776*ccbc8b2fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1777*ccbc8b2fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1778*ccbc8b2fSLokesh Vutla 	if (IS_ERR(xfer)) {
1779*ccbc8b2fSLokesh Vutla 		ret = PTR_ERR(xfer);
1780*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1781*ccbc8b2fSLokesh Vutla 		return ret;
1782*ccbc8b2fSLokesh Vutla 	}
1783*ccbc8b2fSLokesh Vutla 	req.processor_id = proc_id;
1784*ccbc8b2fSLokesh Vutla 
1785*ccbc8b2fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1786*ccbc8b2fSLokesh Vutla 	if (ret) {
1787*ccbc8b2fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1788*ccbc8b2fSLokesh Vutla 		return ret;
1789*ccbc8b2fSLokesh Vutla 	}
1790*ccbc8b2fSLokesh Vutla 
1791*ccbc8b2fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_get_proc_boot_status *)
1792*ccbc8b2fSLokesh Vutla 							xfer->tx_message.buf;
1793*ccbc8b2fSLokesh Vutla 
1794*ccbc8b2fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1795*ccbc8b2fSLokesh Vutla 		return -ENODEV;
1796*ccbc8b2fSLokesh Vutla 	*bv = (resp->bootvector_low & TISCI_ADDR_LOW_MASK) |
1797*ccbc8b2fSLokesh Vutla 			(((u64)resp->bootvector_high  <<
1798*ccbc8b2fSLokesh Vutla 			  TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
1799*ccbc8b2fSLokesh Vutla 	*cfg_flags = resp->config_flags;
1800*ccbc8b2fSLokesh Vutla 	*ctrl_flags = resp->control_flags;
1801*ccbc8b2fSLokesh Vutla 	*sts_flags = resp->status_flags;
1802*ccbc8b2fSLokesh Vutla 
1803*ccbc8b2fSLokesh Vutla 	return ret;
1804*ccbc8b2fSLokesh Vutla }
1805*ccbc8b2fSLokesh Vutla 
1806dcfc52adSAndreas Dannenberg /*
1807dcfc52adSAndreas Dannenberg  * ti_sci_setup_ops() - Setup the operations structures
1808dcfc52adSAndreas Dannenberg  * @info:	pointer to TISCI pointer
1809dcfc52adSAndreas Dannenberg  */
ti_sci_setup_ops(struct ti_sci_info * info)1810dcfc52adSAndreas Dannenberg static void ti_sci_setup_ops(struct ti_sci_info *info)
1811dcfc52adSAndreas Dannenberg {
1812dcfc52adSAndreas Dannenberg 	struct ti_sci_ops *ops = &info->handle.ops;
1813dcfc52adSAndreas Dannenberg 	struct ti_sci_board_ops *bops = &ops->board_ops;
18147bc33045SAndreas Dannenberg 	struct ti_sci_dev_ops *dops = &ops->dev_ops;
18159b87181fSLokesh Vutla 	struct ti_sci_clk_ops *cops = &ops->clk_ops;
1816f369b0f2SAndreas Dannenberg 	struct ti_sci_core_ops *core_ops = &ops->core_ops;
1817*ccbc8b2fSLokesh Vutla 	struct ti_sci_proc_ops *pops = &ops->proc_ops;
1818dcfc52adSAndreas Dannenberg 
1819dcfc52adSAndreas Dannenberg 	bops->board_config = ti_sci_cmd_set_board_config;
1820dcfc52adSAndreas Dannenberg 	bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
1821dcfc52adSAndreas Dannenberg 	bops->board_config_security = ti_sci_cmd_set_board_config_security;
1822dcfc52adSAndreas Dannenberg 	bops->board_config_pm = ti_sci_cmd_set_board_config_pm;
18237bc33045SAndreas Dannenberg 
18247bc33045SAndreas Dannenberg 	dops->get_device = ti_sci_cmd_get_device;
18257bc33045SAndreas Dannenberg 	dops->idle_device = ti_sci_cmd_idle_device;
18267bc33045SAndreas Dannenberg 	dops->put_device = ti_sci_cmd_put_device;
18277bc33045SAndreas Dannenberg 	dops->is_valid = ti_sci_cmd_dev_is_valid;
18287bc33045SAndreas Dannenberg 	dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
18297bc33045SAndreas Dannenberg 	dops->is_idle = ti_sci_cmd_dev_is_idle;
18307bc33045SAndreas Dannenberg 	dops->is_stop = ti_sci_cmd_dev_is_stop;
18317bc33045SAndreas Dannenberg 	dops->is_on = ti_sci_cmd_dev_is_on;
18327bc33045SAndreas Dannenberg 	dops->is_transitioning = ti_sci_cmd_dev_is_trans;
18337bc33045SAndreas Dannenberg 	dops->set_device_resets = ti_sci_cmd_set_device_resets;
18347bc33045SAndreas Dannenberg 	dops->get_device_resets = ti_sci_cmd_get_device_resets;
18359b87181fSLokesh Vutla 
18369b87181fSLokesh Vutla 	cops->get_clock = ti_sci_cmd_get_clock;
18379b87181fSLokesh Vutla 	cops->idle_clock = ti_sci_cmd_idle_clock;
18389b87181fSLokesh Vutla 	cops->put_clock = ti_sci_cmd_put_clock;
18399b87181fSLokesh Vutla 	cops->is_auto = ti_sci_cmd_clk_is_auto;
18409b87181fSLokesh Vutla 	cops->is_on = ti_sci_cmd_clk_is_on;
18419b87181fSLokesh Vutla 	cops->is_off = ti_sci_cmd_clk_is_off;
18429b87181fSLokesh Vutla 
18439b87181fSLokesh Vutla 	cops->set_parent = ti_sci_cmd_clk_set_parent;
18449b87181fSLokesh Vutla 	cops->get_parent = ti_sci_cmd_clk_get_parent;
18459b87181fSLokesh Vutla 	cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
18469b87181fSLokesh Vutla 
18479b87181fSLokesh Vutla 	cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
18489b87181fSLokesh Vutla 	cops->set_freq = ti_sci_cmd_clk_set_freq;
18499b87181fSLokesh Vutla 	cops->get_freq = ti_sci_cmd_clk_get_freq;
1850f369b0f2SAndreas Dannenberg 
1851f369b0f2SAndreas Dannenberg 	core_ops->reboot_device = ti_sci_cmd_core_reboot;
1852*ccbc8b2fSLokesh Vutla 
1853*ccbc8b2fSLokesh Vutla 	pops->proc_request = ti_sci_cmd_proc_request;
1854*ccbc8b2fSLokesh Vutla 	pops->proc_release = ti_sci_cmd_proc_release;
1855*ccbc8b2fSLokesh Vutla 	pops->proc_handover = ti_sci_cmd_proc_handover;
1856*ccbc8b2fSLokesh Vutla 	pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg;
1857*ccbc8b2fSLokesh Vutla 	pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl;
1858*ccbc8b2fSLokesh Vutla 	pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image;
1859*ccbc8b2fSLokesh Vutla 	pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status;
1860dcfc52adSAndreas Dannenberg }
1861dcfc52adSAndreas Dannenberg 
1862dcfc52adSAndreas Dannenberg /**
186332cd2512SLokesh Vutla  * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW
186432cd2512SLokesh Vutla  * @dev:	Pointer to the SYSFW device
186532cd2512SLokesh Vutla  *
186632cd2512SLokesh Vutla  * Return: pointer to handle if successful, else EINVAL if invalid conditions
186732cd2512SLokesh Vutla  *         are encountered.
186832cd2512SLokesh Vutla  */
186932cd2512SLokesh Vutla const
ti_sci_get_handle_from_sysfw(struct udevice * sci_dev)187032cd2512SLokesh Vutla struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev)
187132cd2512SLokesh Vutla {
187232cd2512SLokesh Vutla 	if (!sci_dev)
187332cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
187432cd2512SLokesh Vutla 
187532cd2512SLokesh Vutla 	struct ti_sci_info *info = dev_get_priv(sci_dev);
187632cd2512SLokesh Vutla 
187732cd2512SLokesh Vutla 	if (!info)
187832cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
187932cd2512SLokesh Vutla 
188032cd2512SLokesh Vutla 	struct ti_sci_handle *handle = &info->handle;
188132cd2512SLokesh Vutla 
188232cd2512SLokesh Vutla 	if (!handle)
188332cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
188432cd2512SLokesh Vutla 
188532cd2512SLokesh Vutla 	return handle;
188632cd2512SLokesh Vutla }
188732cd2512SLokesh Vutla 
188832cd2512SLokesh Vutla /**
188932cd2512SLokesh Vutla  * ti_sci_get_handle() - Get the TI SCI handle for a device
189032cd2512SLokesh Vutla  * @dev:	Pointer to device for which we want SCI handle
189132cd2512SLokesh Vutla  *
189232cd2512SLokesh Vutla  * Return: pointer to handle if successful, else EINVAL if invalid conditions
189332cd2512SLokesh Vutla  *         are encountered.
189432cd2512SLokesh Vutla  */
ti_sci_get_handle(struct udevice * dev)189532cd2512SLokesh Vutla const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev)
189632cd2512SLokesh Vutla {
189732cd2512SLokesh Vutla 	if (!dev)
189832cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
189932cd2512SLokesh Vutla 
190032cd2512SLokesh Vutla 	struct udevice *sci_dev = dev_get_parent(dev);
190132cd2512SLokesh Vutla 
190232cd2512SLokesh Vutla 	return ti_sci_get_handle_from_sysfw(sci_dev);
190332cd2512SLokesh Vutla }
190432cd2512SLokesh Vutla 
190532cd2512SLokesh Vutla /**
190632cd2512SLokesh Vutla  * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
190732cd2512SLokesh Vutla  * @dev:	device node
190832cd2512SLokesh Vutla  * @propname:	property name containing phandle on TISCI node
190932cd2512SLokesh Vutla  *
191032cd2512SLokesh Vutla  * Return: pointer to handle if successful, else appropriate error value.
191132cd2512SLokesh Vutla  */
ti_sci_get_by_phandle(struct udevice * dev,const char * property)191232cd2512SLokesh Vutla const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev,
191332cd2512SLokesh Vutla 						  const char *property)
191432cd2512SLokesh Vutla {
191532cd2512SLokesh Vutla 	struct ti_sci_info *entry, *info = NULL;
191632cd2512SLokesh Vutla 	u32 phandle, err;
191732cd2512SLokesh Vutla 	ofnode node;
191832cd2512SLokesh Vutla 
191932cd2512SLokesh Vutla 	err = ofnode_read_u32(dev_ofnode(dev), property, &phandle);
192032cd2512SLokesh Vutla 	if (err)
192132cd2512SLokesh Vutla 		return ERR_PTR(err);
192232cd2512SLokesh Vutla 
192332cd2512SLokesh Vutla 	node = ofnode_get_by_phandle(phandle);
192432cd2512SLokesh Vutla 	if (!ofnode_valid(node))
192532cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
192632cd2512SLokesh Vutla 
192732cd2512SLokesh Vutla 	list_for_each_entry(entry, &ti_sci_list, list)
192832cd2512SLokesh Vutla 		if (ofnode_equal(dev_ofnode(entry->dev), node)) {
192932cd2512SLokesh Vutla 			info = entry;
193032cd2512SLokesh Vutla 			break;
193132cd2512SLokesh Vutla 		}
193232cd2512SLokesh Vutla 
193332cd2512SLokesh Vutla 	if (!info)
193432cd2512SLokesh Vutla 		return ERR_PTR(-ENODEV);
193532cd2512SLokesh Vutla 
193632cd2512SLokesh Vutla 	return &info->handle;
193732cd2512SLokesh Vutla }
193832cd2512SLokesh Vutla 
193932cd2512SLokesh Vutla /**
194032cd2512SLokesh Vutla  * ti_sci_of_to_info() - generate private data from device tree
194132cd2512SLokesh Vutla  * @dev:	corresponding system controller interface device
194232cd2512SLokesh Vutla  * @info:	pointer to driver specific private data
194332cd2512SLokesh Vutla  *
194432cd2512SLokesh Vutla  * Return: 0 if all goes good, else appropriate error message.
194532cd2512SLokesh Vutla  */
ti_sci_of_to_info(struct udevice * dev,struct ti_sci_info * info)194632cd2512SLokesh Vutla static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info)
194732cd2512SLokesh Vutla {
194832cd2512SLokesh Vutla 	int ret;
194932cd2512SLokesh Vutla 
195032cd2512SLokesh Vutla 	ret = mbox_get_by_name(dev, "tx", &info->chan_tx);
195132cd2512SLokesh Vutla 	if (ret) {
195232cd2512SLokesh Vutla 		dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n",
195332cd2512SLokesh Vutla 			__func__, ret);
195432cd2512SLokesh Vutla 		return ret;
195532cd2512SLokesh Vutla 	}
195632cd2512SLokesh Vutla 
195732cd2512SLokesh Vutla 	ret = mbox_get_by_name(dev, "rx", &info->chan_rx);
195832cd2512SLokesh Vutla 	if (ret) {
195932cd2512SLokesh Vutla 		dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n",
196032cd2512SLokesh Vutla 			__func__, ret);
196132cd2512SLokesh Vutla 		return ret;
196232cd2512SLokesh Vutla 	}
196332cd2512SLokesh Vutla 
196432cd2512SLokesh Vutla 	/* Notify channel is optional. Enable only if populated */
196532cd2512SLokesh Vutla 	ret = mbox_get_by_name(dev, "notify", &info->chan_notify);
196632cd2512SLokesh Vutla 	if (ret) {
196732cd2512SLokesh Vutla 		dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n",
196832cd2512SLokesh Vutla 			__func__, ret);
196932cd2512SLokesh Vutla 	}
197032cd2512SLokesh Vutla 
197132cd2512SLokesh Vutla 	info->host_id = dev_read_u32_default(dev, "ti,host-id",
197232cd2512SLokesh Vutla 					     info->desc->host_id);
197332cd2512SLokesh Vutla 
197432cd2512SLokesh Vutla 	info->is_secure = dev_read_bool(dev, "ti,secure-host");
197532cd2512SLokesh Vutla 
197632cd2512SLokesh Vutla 	return 0;
197732cd2512SLokesh Vutla }
197832cd2512SLokesh Vutla 
197932cd2512SLokesh Vutla /**
198032cd2512SLokesh Vutla  * ti_sci_probe() - Basic probe
198132cd2512SLokesh Vutla  * @dev:	corresponding system controller interface device
198232cd2512SLokesh Vutla  *
198332cd2512SLokesh Vutla  * Return: 0 if all goes good, else appropriate error message.
198432cd2512SLokesh Vutla  */
ti_sci_probe(struct udevice * dev)198532cd2512SLokesh Vutla static int ti_sci_probe(struct udevice *dev)
198632cd2512SLokesh Vutla {
198732cd2512SLokesh Vutla 	struct ti_sci_info *info;
198832cd2512SLokesh Vutla 	int ret;
198932cd2512SLokesh Vutla 
199032cd2512SLokesh Vutla 	debug("%s(dev=%p)\n", __func__, dev);
199132cd2512SLokesh Vutla 
199232cd2512SLokesh Vutla 	info = dev_get_priv(dev);
199332cd2512SLokesh Vutla 	info->desc = (void *)dev_get_driver_data(dev);
199432cd2512SLokesh Vutla 
199532cd2512SLokesh Vutla 	ret = ti_sci_of_to_info(dev, info);
199632cd2512SLokesh Vutla 	if (ret) {
199732cd2512SLokesh Vutla 		dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
199832cd2512SLokesh Vutla 		return ret;
199932cd2512SLokesh Vutla 	}
200032cd2512SLokesh Vutla 
200132cd2512SLokesh Vutla 	info->dev = dev;
200232cd2512SLokesh Vutla 	info->seq = 0xA;
200332cd2512SLokesh Vutla 
200432cd2512SLokesh Vutla 	list_add_tail(&info->list, &ti_sci_list);
2005dcfc52adSAndreas Dannenberg 	ti_sci_setup_ops(info);
200632cd2512SLokesh Vutla 
200732cd2512SLokesh Vutla 	ret = ti_sci_cmd_get_revision(&info->handle);
200832cd2512SLokesh Vutla 
200932cd2512SLokesh Vutla 	return ret;
201032cd2512SLokesh Vutla }
201132cd2512SLokesh Vutla 
201232cd2512SLokesh Vutla /* Description for AM654 */
201332cd2512SLokesh Vutla static const struct ti_sci_desc ti_sci_sysfw_am654_desc = {
201432cd2512SLokesh Vutla 	.host_id = 4,
201532cd2512SLokesh Vutla 	.max_rx_timeout_us = 1000000,
201632cd2512SLokesh Vutla 	.max_msg_size = 60,
201732cd2512SLokesh Vutla };
201832cd2512SLokesh Vutla 
201932cd2512SLokesh Vutla static const struct udevice_id ti_sci_ids[] = {
202032cd2512SLokesh Vutla 	{
202132cd2512SLokesh Vutla 		.compatible = "ti,k2g-sci",
202232cd2512SLokesh Vutla 		.data = (ulong)&ti_sci_sysfw_am654_desc
202332cd2512SLokesh Vutla 	},
202432cd2512SLokesh Vutla 	{ /* Sentinel */ },
202532cd2512SLokesh Vutla };
202632cd2512SLokesh Vutla 
202732cd2512SLokesh Vutla U_BOOT_DRIVER(ti_sci) = {
202832cd2512SLokesh Vutla 	.name = "ti_sci",
202932cd2512SLokesh Vutla 	.id = UCLASS_FIRMWARE,
203032cd2512SLokesh Vutla 	.of_match = ti_sci_ids,
203132cd2512SLokesh Vutla 	.probe = ti_sci_probe,
203232cd2512SLokesh Vutla 	.priv_auto_alloc_size = sizeof(struct ti_sci_info),
203332cd2512SLokesh Vutla };
2034