xref: /openbmc/u-boot/drivers/firmware/ti_sci.c (revision 9b87181fd297f38bd52b597a31dc64ba959afdfd)
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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
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
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
777*9b87181fSLokesh Vutla /**
778*9b87181fSLokesh Vutla  * ti_sci_set_clock_state() - Set clock state helper
779*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
780*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
781*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
782*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
783*9b87181fSLokesh Vutla  *		which clock input to modify.
784*9b87181fSLokesh Vutla  * @flags:	Header flags as needed
785*9b87181fSLokesh Vutla  * @state:	State to request for the clock.
786*9b87181fSLokesh Vutla  *
787*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
788*9b87181fSLokesh Vutla  */
789*9b87181fSLokesh Vutla static int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
790*9b87181fSLokesh Vutla 				  u32 dev_id, u8 clk_id,
791*9b87181fSLokesh Vutla 				  u32 flags, u8 state)
792*9b87181fSLokesh Vutla {
793*9b87181fSLokesh Vutla 	struct ti_sci_msg_req_set_clock_state req;
794*9b87181fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
795*9b87181fSLokesh Vutla 	struct ti_sci_info *info;
796*9b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
797*9b87181fSLokesh Vutla 	int ret = 0;
798*9b87181fSLokesh Vutla 
799*9b87181fSLokesh Vutla 	if (IS_ERR(handle))
800*9b87181fSLokesh Vutla 		return PTR_ERR(handle);
801*9b87181fSLokesh Vutla 	if (!handle)
802*9b87181fSLokesh Vutla 		return -EINVAL;
803*9b87181fSLokesh Vutla 
804*9b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
805*9b87181fSLokesh Vutla 
806*9b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
807*9b87181fSLokesh Vutla 				     flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
808*9b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
809*9b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
810*9b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
811*9b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
812*9b87181fSLokesh Vutla 		return ret;
813*9b87181fSLokesh Vutla 	}
814*9b87181fSLokesh Vutla 	req.dev_id = dev_id;
815*9b87181fSLokesh Vutla 	req.clk_id = clk_id;
816*9b87181fSLokesh Vutla 	req.request_state = state;
817*9b87181fSLokesh Vutla 
818*9b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
819*9b87181fSLokesh Vutla 	if (ret) {
820*9b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
821*9b87181fSLokesh Vutla 		return ret;
822*9b87181fSLokesh Vutla 	}
823*9b87181fSLokesh Vutla 
824*9b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
825*9b87181fSLokesh Vutla 
826*9b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
827*9b87181fSLokesh Vutla 		return -ENODEV;
828*9b87181fSLokesh Vutla 
829*9b87181fSLokesh Vutla 	return ret;
830*9b87181fSLokesh Vutla }
831*9b87181fSLokesh Vutla 
832*9b87181fSLokesh Vutla /**
833*9b87181fSLokesh Vutla  * ti_sci_cmd_get_clock_state() - Get clock state helper
834*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
835*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
836*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
837*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
838*9b87181fSLokesh Vutla  *		which clock input to modify.
839*9b87181fSLokesh Vutla  * @programmed_state:	State requested for clock to move to
840*9b87181fSLokesh Vutla  * @current_state:	State that the clock is currently in
841*9b87181fSLokesh Vutla  *
842*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
843*9b87181fSLokesh Vutla  */
844*9b87181fSLokesh Vutla static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
845*9b87181fSLokesh Vutla 				      u32 dev_id, u8 clk_id,
846*9b87181fSLokesh Vutla 				      u8 *programmed_state, u8 *current_state)
847*9b87181fSLokesh Vutla {
848*9b87181fSLokesh Vutla 	struct ti_sci_msg_resp_get_clock_state *resp;
849*9b87181fSLokesh Vutla 	struct ti_sci_msg_req_get_clock_state req;
850*9b87181fSLokesh Vutla 	struct ti_sci_info *info;
851*9b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
852*9b87181fSLokesh Vutla 	int ret = 0;
853*9b87181fSLokesh Vutla 
854*9b87181fSLokesh Vutla 	if (IS_ERR(handle))
855*9b87181fSLokesh Vutla 		return PTR_ERR(handle);
856*9b87181fSLokesh Vutla 	if (!handle)
857*9b87181fSLokesh Vutla 		return -EINVAL;
858*9b87181fSLokesh Vutla 
859*9b87181fSLokesh Vutla 	if (!programmed_state && !current_state)
860*9b87181fSLokesh Vutla 		return -EINVAL;
861*9b87181fSLokesh Vutla 
862*9b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
863*9b87181fSLokesh Vutla 
864*9b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
865*9b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
866*9b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
867*9b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
868*9b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
869*9b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
870*9b87181fSLokesh Vutla 		return ret;
871*9b87181fSLokesh Vutla 	}
872*9b87181fSLokesh Vutla 	req.dev_id = dev_id;
873*9b87181fSLokesh Vutla 	req.clk_id = clk_id;
874*9b87181fSLokesh Vutla 
875*9b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
876*9b87181fSLokesh Vutla 	if (ret) {
877*9b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
878*9b87181fSLokesh Vutla 		return ret;
879*9b87181fSLokesh Vutla 	}
880*9b87181fSLokesh Vutla 
881*9b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->tx_message.buf;
882*9b87181fSLokesh Vutla 
883*9b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
884*9b87181fSLokesh Vutla 		return -ENODEV;
885*9b87181fSLokesh Vutla 
886*9b87181fSLokesh Vutla 	if (programmed_state)
887*9b87181fSLokesh Vutla 		*programmed_state = resp->programmed_state;
888*9b87181fSLokesh Vutla 	if (current_state)
889*9b87181fSLokesh Vutla 		*current_state = resp->current_state;
890*9b87181fSLokesh Vutla 
891*9b87181fSLokesh Vutla 	return ret;
892*9b87181fSLokesh Vutla }
893*9b87181fSLokesh Vutla 
894*9b87181fSLokesh Vutla /**
895*9b87181fSLokesh Vutla  * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
896*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
897*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
898*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
899*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
900*9b87181fSLokesh Vutla  *		which clock input to modify.
901*9b87181fSLokesh Vutla  * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
902*9b87181fSLokesh Vutla  * @can_change_freq: 'true' if frequency change is desired, else 'false'
903*9b87181fSLokesh Vutla  * @enable_input_term: 'true' if input termination is desired, else 'false'
904*9b87181fSLokesh Vutla  *
905*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
906*9b87181fSLokesh Vutla  */
907*9b87181fSLokesh Vutla static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
908*9b87181fSLokesh Vutla 				u8 clk_id, bool needs_ssc, bool can_change_freq,
909*9b87181fSLokesh Vutla 				bool enable_input_term)
910*9b87181fSLokesh Vutla {
911*9b87181fSLokesh Vutla 	u32 flags = 0;
912*9b87181fSLokesh Vutla 
913*9b87181fSLokesh Vutla 	flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
914*9b87181fSLokesh Vutla 	flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
915*9b87181fSLokesh Vutla 	flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
916*9b87181fSLokesh Vutla 
917*9b87181fSLokesh Vutla 	return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
918*9b87181fSLokesh Vutla 				      MSG_CLOCK_SW_STATE_REQ);
919*9b87181fSLokesh Vutla }
920*9b87181fSLokesh Vutla 
921*9b87181fSLokesh Vutla /**
922*9b87181fSLokesh Vutla  * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
923*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
924*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
925*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
926*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
927*9b87181fSLokesh Vutla  *		which clock input to modify.
928*9b87181fSLokesh Vutla  *
929*9b87181fSLokesh Vutla  * NOTE: This clock must have been requested by get_clock previously.
930*9b87181fSLokesh Vutla  *
931*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
932*9b87181fSLokesh Vutla  */
933*9b87181fSLokesh Vutla static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
934*9b87181fSLokesh Vutla 				 u32 dev_id, u8 clk_id)
935*9b87181fSLokesh Vutla {
936*9b87181fSLokesh Vutla 	return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
937*9b87181fSLokesh Vutla 				      MSG_CLOCK_SW_STATE_UNREQ);
938*9b87181fSLokesh Vutla }
939*9b87181fSLokesh Vutla 
940*9b87181fSLokesh Vutla /**
941*9b87181fSLokesh Vutla  * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
942*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
943*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
944*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
945*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
946*9b87181fSLokesh Vutla  *		which clock input to modify.
947*9b87181fSLokesh Vutla  *
948*9b87181fSLokesh Vutla  * NOTE: This clock must have been requested by get_clock previously.
949*9b87181fSLokesh Vutla  *
950*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
951*9b87181fSLokesh Vutla  */
952*9b87181fSLokesh Vutla static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
953*9b87181fSLokesh Vutla 				u32 dev_id, u8 clk_id)
954*9b87181fSLokesh Vutla {
955*9b87181fSLokesh Vutla 	return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
956*9b87181fSLokesh Vutla 				      MSG_CLOCK_SW_STATE_AUTO);
957*9b87181fSLokesh Vutla }
958*9b87181fSLokesh Vutla 
959*9b87181fSLokesh Vutla /**
960*9b87181fSLokesh Vutla  * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
961*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
962*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
963*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
964*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
965*9b87181fSLokesh Vutla  *		which clock input to modify.
966*9b87181fSLokesh Vutla  * @req_state: state indicating if the clock is auto managed
967*9b87181fSLokesh Vutla  *
968*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
969*9b87181fSLokesh Vutla  */
970*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
971*9b87181fSLokesh Vutla 				  u32 dev_id, u8 clk_id, bool *req_state)
972*9b87181fSLokesh Vutla {
973*9b87181fSLokesh Vutla 	u8 state = 0;
974*9b87181fSLokesh Vutla 	int ret;
975*9b87181fSLokesh Vutla 
976*9b87181fSLokesh Vutla 	if (!req_state)
977*9b87181fSLokesh Vutla 		return -EINVAL;
978*9b87181fSLokesh Vutla 
979*9b87181fSLokesh Vutla 	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
980*9b87181fSLokesh Vutla 	if (ret)
981*9b87181fSLokesh Vutla 		return ret;
982*9b87181fSLokesh Vutla 
983*9b87181fSLokesh Vutla 	*req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
984*9b87181fSLokesh Vutla 	return 0;
985*9b87181fSLokesh Vutla }
986*9b87181fSLokesh Vutla 
987*9b87181fSLokesh Vutla /**
988*9b87181fSLokesh Vutla  * ti_sci_cmd_clk_is_on() - Is the clock ON
989*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
990*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
991*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
992*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
993*9b87181fSLokesh Vutla  *		which clock input to modify.
994*9b87181fSLokesh Vutla  * @req_state: state indicating if the clock is managed by us and enabled
995*9b87181fSLokesh Vutla  * @curr_state: state indicating if the clock is ready for operation
996*9b87181fSLokesh Vutla  *
997*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
998*9b87181fSLokesh Vutla  */
999*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
1000*9b87181fSLokesh Vutla 				u8 clk_id, bool *req_state, bool *curr_state)
1001*9b87181fSLokesh Vutla {
1002*9b87181fSLokesh Vutla 	u8 c_state = 0, r_state = 0;
1003*9b87181fSLokesh Vutla 	int ret;
1004*9b87181fSLokesh Vutla 
1005*9b87181fSLokesh Vutla 	if (!req_state && !curr_state)
1006*9b87181fSLokesh Vutla 		return -EINVAL;
1007*9b87181fSLokesh Vutla 
1008*9b87181fSLokesh Vutla 	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1009*9b87181fSLokesh Vutla 					 &r_state, &c_state);
1010*9b87181fSLokesh Vutla 	if (ret)
1011*9b87181fSLokesh Vutla 		return ret;
1012*9b87181fSLokesh Vutla 
1013*9b87181fSLokesh Vutla 	if (req_state)
1014*9b87181fSLokesh Vutla 		*req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
1015*9b87181fSLokesh Vutla 	if (curr_state)
1016*9b87181fSLokesh Vutla 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
1017*9b87181fSLokesh Vutla 	return 0;
1018*9b87181fSLokesh Vutla }
1019*9b87181fSLokesh Vutla 
1020*9b87181fSLokesh Vutla /**
1021*9b87181fSLokesh Vutla  * ti_sci_cmd_clk_is_off() - Is the clock OFF
1022*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
1023*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
1024*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
1025*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
1026*9b87181fSLokesh Vutla  *		which clock input to modify.
1027*9b87181fSLokesh Vutla  * @req_state: state indicating if the clock is managed by us and disabled
1028*9b87181fSLokesh Vutla  * @curr_state: state indicating if the clock is NOT ready for operation
1029*9b87181fSLokesh Vutla  *
1030*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1031*9b87181fSLokesh Vutla  */
1032*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
1033*9b87181fSLokesh Vutla 				 u8 clk_id, bool *req_state, bool *curr_state)
1034*9b87181fSLokesh Vutla {
1035*9b87181fSLokesh Vutla 	u8 c_state = 0, r_state = 0;
1036*9b87181fSLokesh Vutla 	int ret;
1037*9b87181fSLokesh Vutla 
1038*9b87181fSLokesh Vutla 	if (!req_state && !curr_state)
1039*9b87181fSLokesh Vutla 		return -EINVAL;
1040*9b87181fSLokesh Vutla 
1041*9b87181fSLokesh Vutla 	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1042*9b87181fSLokesh Vutla 					 &r_state, &c_state);
1043*9b87181fSLokesh Vutla 	if (ret)
1044*9b87181fSLokesh Vutla 		return ret;
1045*9b87181fSLokesh Vutla 
1046*9b87181fSLokesh Vutla 	if (req_state)
1047*9b87181fSLokesh Vutla 		*req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
1048*9b87181fSLokesh Vutla 	if (curr_state)
1049*9b87181fSLokesh Vutla 		*curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
1050*9b87181fSLokesh Vutla 	return 0;
1051*9b87181fSLokesh Vutla }
1052*9b87181fSLokesh Vutla 
1053*9b87181fSLokesh Vutla /**
1054*9b87181fSLokesh Vutla  * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
1055*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
1056*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
1057*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
1058*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
1059*9b87181fSLokesh Vutla  *		which clock input to modify.
1060*9b87181fSLokesh Vutla  * @parent_id:	Parent clock identifier to set
1061*9b87181fSLokesh Vutla  *
1062*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1063*9b87181fSLokesh Vutla  */
1064*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
1065*9b87181fSLokesh Vutla 				     u32 dev_id, u8 clk_id, u8 parent_id)
1066*9b87181fSLokesh Vutla {
1067*9b87181fSLokesh Vutla 	struct ti_sci_msg_req_set_clock_parent req;
1068*9b87181fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
1069*9b87181fSLokesh Vutla 	struct ti_sci_info *info;
1070*9b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1071*9b87181fSLokesh Vutla 	int ret = 0;
1072*9b87181fSLokesh Vutla 
1073*9b87181fSLokesh Vutla 	if (IS_ERR(handle))
1074*9b87181fSLokesh Vutla 		return PTR_ERR(handle);
1075*9b87181fSLokesh Vutla 	if (!handle)
1076*9b87181fSLokesh Vutla 		return -EINVAL;
1077*9b87181fSLokesh Vutla 
1078*9b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1079*9b87181fSLokesh Vutla 
1080*9b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
1081*9b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1082*9b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1083*9b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
1084*9b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
1085*9b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1086*9b87181fSLokesh Vutla 		return ret;
1087*9b87181fSLokesh Vutla 	}
1088*9b87181fSLokesh Vutla 	req.dev_id = dev_id;
1089*9b87181fSLokesh Vutla 	req.clk_id = clk_id;
1090*9b87181fSLokesh Vutla 	req.parent_id = parent_id;
1091*9b87181fSLokesh Vutla 
1092*9b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1093*9b87181fSLokesh Vutla 	if (ret) {
1094*9b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1095*9b87181fSLokesh Vutla 		return ret;
1096*9b87181fSLokesh Vutla 	}
1097*9b87181fSLokesh Vutla 
1098*9b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1099*9b87181fSLokesh Vutla 
1100*9b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1101*9b87181fSLokesh Vutla 		return -ENODEV;
1102*9b87181fSLokesh Vutla 
1103*9b87181fSLokesh Vutla 	return ret;
1104*9b87181fSLokesh Vutla }
1105*9b87181fSLokesh Vutla 
1106*9b87181fSLokesh Vutla /**
1107*9b87181fSLokesh Vutla  * ti_sci_cmd_clk_get_parent() - Get current parent clock source
1108*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
1109*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
1110*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
1111*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
1112*9b87181fSLokesh Vutla  *		which clock input to modify.
1113*9b87181fSLokesh Vutla  * @parent_id:	Current clock parent
1114*9b87181fSLokesh Vutla  *
1115*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1116*9b87181fSLokesh Vutla  */
1117*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
1118*9b87181fSLokesh Vutla 				     u32 dev_id, u8 clk_id, u8 *parent_id)
1119*9b87181fSLokesh Vutla {
1120*9b87181fSLokesh Vutla 	struct ti_sci_msg_resp_get_clock_parent *resp;
1121*9b87181fSLokesh Vutla 	struct ti_sci_msg_req_get_clock_parent req;
1122*9b87181fSLokesh Vutla 	struct ti_sci_info *info;
1123*9b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1124*9b87181fSLokesh Vutla 	int ret = 0;
1125*9b87181fSLokesh Vutla 
1126*9b87181fSLokesh Vutla 	if (IS_ERR(handle))
1127*9b87181fSLokesh Vutla 		return PTR_ERR(handle);
1128*9b87181fSLokesh Vutla 	if (!handle || !parent_id)
1129*9b87181fSLokesh Vutla 		return -EINVAL;
1130*9b87181fSLokesh Vutla 
1131*9b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1132*9b87181fSLokesh Vutla 
1133*9b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
1134*9b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1135*9b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1136*9b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
1137*9b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
1138*9b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1139*9b87181fSLokesh Vutla 		return ret;
1140*9b87181fSLokesh Vutla 	}
1141*9b87181fSLokesh Vutla 	req.dev_id = dev_id;
1142*9b87181fSLokesh Vutla 	req.clk_id = clk_id;
1143*9b87181fSLokesh Vutla 
1144*9b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1145*9b87181fSLokesh Vutla 	if (ret) {
1146*9b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1147*9b87181fSLokesh Vutla 		return ret;
1148*9b87181fSLokesh Vutla 	}
1149*9b87181fSLokesh Vutla 
1150*9b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->tx_message.buf;
1151*9b87181fSLokesh Vutla 
1152*9b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1153*9b87181fSLokesh Vutla 		ret = -ENODEV;
1154*9b87181fSLokesh Vutla 	else
1155*9b87181fSLokesh Vutla 		*parent_id = resp->parent_id;
1156*9b87181fSLokesh Vutla 
1157*9b87181fSLokesh Vutla 	return ret;
1158*9b87181fSLokesh Vutla }
1159*9b87181fSLokesh Vutla 
1160*9b87181fSLokesh Vutla /**
1161*9b87181fSLokesh Vutla  * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source
1162*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
1163*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
1164*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
1165*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
1166*9b87181fSLokesh Vutla  *		which clock input to modify.
1167*9b87181fSLokesh Vutla  * @num_parents: Returns he number of parents to the current clock.
1168*9b87181fSLokesh Vutla  *
1169*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1170*9b87181fSLokesh Vutla  */
1171*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
1172*9b87181fSLokesh Vutla 					  u32 dev_id, u8 clk_id,
1173*9b87181fSLokesh Vutla 					  u8 *num_parents)
1174*9b87181fSLokesh Vutla {
1175*9b87181fSLokesh Vutla 	struct ti_sci_msg_resp_get_clock_num_parents *resp;
1176*9b87181fSLokesh Vutla 	struct ti_sci_msg_req_get_clock_num_parents req;
1177*9b87181fSLokesh Vutla 	struct ti_sci_info *info;
1178*9b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1179*9b87181fSLokesh Vutla 	int ret = 0;
1180*9b87181fSLokesh Vutla 
1181*9b87181fSLokesh Vutla 	if (IS_ERR(handle))
1182*9b87181fSLokesh Vutla 		return PTR_ERR(handle);
1183*9b87181fSLokesh Vutla 	if (!handle || !num_parents)
1184*9b87181fSLokesh Vutla 		return -EINVAL;
1185*9b87181fSLokesh Vutla 
1186*9b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1187*9b87181fSLokesh Vutla 
1188*9b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
1189*9b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1190*9b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1191*9b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
1192*9b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
1193*9b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1194*9b87181fSLokesh Vutla 		return ret;
1195*9b87181fSLokesh Vutla 	}
1196*9b87181fSLokesh Vutla 	req.dev_id = dev_id;
1197*9b87181fSLokesh Vutla 	req.clk_id = clk_id;
1198*9b87181fSLokesh Vutla 
1199*9b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1200*9b87181fSLokesh Vutla 	if (ret) {
1201*9b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1202*9b87181fSLokesh Vutla 		return ret;
1203*9b87181fSLokesh Vutla 	}
1204*9b87181fSLokesh Vutla 
1205*9b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_get_clock_num_parents *)
1206*9b87181fSLokesh Vutla 							xfer->tx_message.buf;
1207*9b87181fSLokesh Vutla 
1208*9b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1209*9b87181fSLokesh Vutla 		ret = -ENODEV;
1210*9b87181fSLokesh Vutla 	else
1211*9b87181fSLokesh Vutla 		*num_parents = resp->num_parents;
1212*9b87181fSLokesh Vutla 
1213*9b87181fSLokesh Vutla 	return ret;
1214*9b87181fSLokesh Vutla }
1215*9b87181fSLokesh Vutla 
1216*9b87181fSLokesh Vutla /**
1217*9b87181fSLokesh Vutla  * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
1218*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
1219*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
1220*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
1221*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
1222*9b87181fSLokesh Vutla  *		which clock input to modify.
1223*9b87181fSLokesh Vutla  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
1224*9b87181fSLokesh Vutla  *		allowable programmed frequency and does not account for clock
1225*9b87181fSLokesh Vutla  *		tolerances and jitter.
1226*9b87181fSLokesh Vutla  * @target_freq: The target clock frequency in Hz. A frequency will be
1227*9b87181fSLokesh Vutla  *		processed as close to this target frequency as possible.
1228*9b87181fSLokesh Vutla  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
1229*9b87181fSLokesh Vutla  *		allowable programmed frequency and does not account for clock
1230*9b87181fSLokesh Vutla  *		tolerances and jitter.
1231*9b87181fSLokesh Vutla  * @match_freq:	Frequency match in Hz response.
1232*9b87181fSLokesh Vutla  *
1233*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1234*9b87181fSLokesh Vutla  */
1235*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
1236*9b87181fSLokesh Vutla 					 u32 dev_id, u8 clk_id, u64 min_freq,
1237*9b87181fSLokesh Vutla 					 u64 target_freq, u64 max_freq,
1238*9b87181fSLokesh Vutla 					 u64 *match_freq)
1239*9b87181fSLokesh Vutla {
1240*9b87181fSLokesh Vutla 	struct ti_sci_msg_resp_query_clock_freq *resp;
1241*9b87181fSLokesh Vutla 	struct ti_sci_msg_req_query_clock_freq req;
1242*9b87181fSLokesh Vutla 	struct ti_sci_info *info;
1243*9b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1244*9b87181fSLokesh Vutla 	int ret = 0;
1245*9b87181fSLokesh Vutla 
1246*9b87181fSLokesh Vutla 	if (IS_ERR(handle))
1247*9b87181fSLokesh Vutla 		return PTR_ERR(handle);
1248*9b87181fSLokesh Vutla 	if (!handle || !match_freq)
1249*9b87181fSLokesh Vutla 		return -EINVAL;
1250*9b87181fSLokesh Vutla 
1251*9b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1252*9b87181fSLokesh Vutla 
1253*9b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
1254*9b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1255*9b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1256*9b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
1257*9b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
1258*9b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1259*9b87181fSLokesh Vutla 		return ret;
1260*9b87181fSLokesh Vutla 	}
1261*9b87181fSLokesh Vutla 	req.dev_id = dev_id;
1262*9b87181fSLokesh Vutla 	req.clk_id = clk_id;
1263*9b87181fSLokesh Vutla 	req.min_freq_hz = min_freq;
1264*9b87181fSLokesh Vutla 	req.target_freq_hz = target_freq;
1265*9b87181fSLokesh Vutla 	req.max_freq_hz = max_freq;
1266*9b87181fSLokesh Vutla 
1267*9b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1268*9b87181fSLokesh Vutla 	if (ret) {
1269*9b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1270*9b87181fSLokesh Vutla 		return ret;
1271*9b87181fSLokesh Vutla 	}
1272*9b87181fSLokesh Vutla 
1273*9b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->tx_message.buf;
1274*9b87181fSLokesh Vutla 
1275*9b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1276*9b87181fSLokesh Vutla 		ret = -ENODEV;
1277*9b87181fSLokesh Vutla 	else
1278*9b87181fSLokesh Vutla 		*match_freq = resp->freq_hz;
1279*9b87181fSLokesh Vutla 
1280*9b87181fSLokesh Vutla 	return ret;
1281*9b87181fSLokesh Vutla }
1282*9b87181fSLokesh Vutla 
1283*9b87181fSLokesh Vutla /**
1284*9b87181fSLokesh Vutla  * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
1285*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
1286*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
1287*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
1288*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
1289*9b87181fSLokesh Vutla  *		which clock input to modify.
1290*9b87181fSLokesh Vutla  * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
1291*9b87181fSLokesh Vutla  *		allowable programmed frequency and does not account for clock
1292*9b87181fSLokesh Vutla  *		tolerances and jitter.
1293*9b87181fSLokesh Vutla  * @target_freq: The target clock frequency in Hz. A frequency will be
1294*9b87181fSLokesh Vutla  *		processed as close to this target frequency as possible.
1295*9b87181fSLokesh Vutla  * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
1296*9b87181fSLokesh Vutla  *		allowable programmed frequency and does not account for clock
1297*9b87181fSLokesh Vutla  *		tolerances and jitter.
1298*9b87181fSLokesh Vutla  *
1299*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1300*9b87181fSLokesh Vutla  */
1301*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
1302*9b87181fSLokesh Vutla 				   u32 dev_id, u8 clk_id, u64 min_freq,
1303*9b87181fSLokesh Vutla 				   u64 target_freq, u64 max_freq)
1304*9b87181fSLokesh Vutla {
1305*9b87181fSLokesh Vutla 	struct ti_sci_msg_req_set_clock_freq req;
1306*9b87181fSLokesh Vutla 	struct ti_sci_msg_hdr *resp;
1307*9b87181fSLokesh Vutla 	struct ti_sci_info *info;
1308*9b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1309*9b87181fSLokesh Vutla 	int ret = 0;
1310*9b87181fSLokesh Vutla 
1311*9b87181fSLokesh Vutla 	if (IS_ERR(handle))
1312*9b87181fSLokesh Vutla 		return PTR_ERR(handle);
1313*9b87181fSLokesh Vutla 	if (!handle)
1314*9b87181fSLokesh Vutla 		return -EINVAL;
1315*9b87181fSLokesh Vutla 
1316*9b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1317*9b87181fSLokesh Vutla 
1318*9b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
1319*9b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1320*9b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1321*9b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
1322*9b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
1323*9b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1324*9b87181fSLokesh Vutla 		return ret;
1325*9b87181fSLokesh Vutla 	}
1326*9b87181fSLokesh Vutla 	req.dev_id = dev_id;
1327*9b87181fSLokesh Vutla 	req.clk_id = clk_id;
1328*9b87181fSLokesh Vutla 	req.min_freq_hz = min_freq;
1329*9b87181fSLokesh Vutla 	req.target_freq_hz = target_freq;
1330*9b87181fSLokesh Vutla 	req.max_freq_hz = max_freq;
1331*9b87181fSLokesh Vutla 
1332*9b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1333*9b87181fSLokesh Vutla 	if (ret) {
1334*9b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1335*9b87181fSLokesh Vutla 		return ret;
1336*9b87181fSLokesh Vutla 	}
1337*9b87181fSLokesh Vutla 
1338*9b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1339*9b87181fSLokesh Vutla 
1340*9b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1341*9b87181fSLokesh Vutla 		return -ENODEV;
1342*9b87181fSLokesh Vutla 
1343*9b87181fSLokesh Vutla 	return ret;
1344*9b87181fSLokesh Vutla }
1345*9b87181fSLokesh Vutla 
1346*9b87181fSLokesh Vutla /**
1347*9b87181fSLokesh Vutla  * ti_sci_cmd_clk_get_freq() - Get current frequency
1348*9b87181fSLokesh Vutla  * @handle:	pointer to TI SCI handle
1349*9b87181fSLokesh Vutla  * @dev_id:	Device identifier this request is for
1350*9b87181fSLokesh Vutla  * @clk_id:	Clock identifier for the device for this request.
1351*9b87181fSLokesh Vutla  *		Each device has it's own set of clock inputs. This indexes
1352*9b87181fSLokesh Vutla  *		which clock input to modify.
1353*9b87181fSLokesh Vutla  * @freq:	Currently frequency in Hz
1354*9b87181fSLokesh Vutla  *
1355*9b87181fSLokesh Vutla  * Return: 0 if all went well, else returns appropriate error value.
1356*9b87181fSLokesh Vutla  */
1357*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
1358*9b87181fSLokesh Vutla 				   u32 dev_id, u8 clk_id, u64 *freq)
1359*9b87181fSLokesh Vutla {
1360*9b87181fSLokesh Vutla 	struct ti_sci_msg_resp_get_clock_freq *resp;
1361*9b87181fSLokesh Vutla 	struct ti_sci_msg_req_get_clock_freq req;
1362*9b87181fSLokesh Vutla 	struct ti_sci_info *info;
1363*9b87181fSLokesh Vutla 	struct ti_sci_xfer *xfer;
1364*9b87181fSLokesh Vutla 	int ret = 0;
1365*9b87181fSLokesh Vutla 
1366*9b87181fSLokesh Vutla 	if (IS_ERR(handle))
1367*9b87181fSLokesh Vutla 		return PTR_ERR(handle);
1368*9b87181fSLokesh Vutla 	if (!handle || !freq)
1369*9b87181fSLokesh Vutla 		return -EINVAL;
1370*9b87181fSLokesh Vutla 
1371*9b87181fSLokesh Vutla 	info = handle_to_ti_sci_info(handle);
1372*9b87181fSLokesh Vutla 
1373*9b87181fSLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
1374*9b87181fSLokesh Vutla 				     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1375*9b87181fSLokesh Vutla 				     (u32 *)&req, sizeof(req), sizeof(*resp));
1376*9b87181fSLokesh Vutla 	if (IS_ERR(xfer)) {
1377*9b87181fSLokesh Vutla 		ret = PTR_ERR(xfer);
1378*9b87181fSLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1379*9b87181fSLokesh Vutla 		return ret;
1380*9b87181fSLokesh Vutla 	}
1381*9b87181fSLokesh Vutla 	req.dev_id = dev_id;
1382*9b87181fSLokesh Vutla 	req.clk_id = clk_id;
1383*9b87181fSLokesh Vutla 
1384*9b87181fSLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
1385*9b87181fSLokesh Vutla 	if (ret) {
1386*9b87181fSLokesh Vutla 		dev_err(info->dev, "Mbox send fail %d\n", ret);
1387*9b87181fSLokesh Vutla 		return ret;
1388*9b87181fSLokesh Vutla 	}
1389*9b87181fSLokesh Vutla 
1390*9b87181fSLokesh Vutla 	resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->tx_message.buf;
1391*9b87181fSLokesh Vutla 
1392*9b87181fSLokesh Vutla 	if (!ti_sci_is_response_ack(resp))
1393*9b87181fSLokesh Vutla 		ret = -ENODEV;
1394*9b87181fSLokesh Vutla 	else
1395*9b87181fSLokesh Vutla 		*freq = resp->freq_hz;
1396*9b87181fSLokesh Vutla 
1397*9b87181fSLokesh Vutla 	return ret;
1398*9b87181fSLokesh Vutla }
1399*9b87181fSLokesh Vutla 
1400dcfc52adSAndreas Dannenberg /*
1401dcfc52adSAndreas Dannenberg  * ti_sci_setup_ops() - Setup the operations structures
1402dcfc52adSAndreas Dannenberg  * @info:	pointer to TISCI pointer
1403dcfc52adSAndreas Dannenberg  */
1404dcfc52adSAndreas Dannenberg static void ti_sci_setup_ops(struct ti_sci_info *info)
1405dcfc52adSAndreas Dannenberg {
1406dcfc52adSAndreas Dannenberg 	struct ti_sci_ops *ops = &info->handle.ops;
1407dcfc52adSAndreas Dannenberg 	struct ti_sci_board_ops *bops = &ops->board_ops;
14087bc33045SAndreas Dannenberg 	struct ti_sci_dev_ops *dops = &ops->dev_ops;
1409*9b87181fSLokesh Vutla 	struct ti_sci_clk_ops *cops = &ops->clk_ops;
1410dcfc52adSAndreas Dannenberg 
1411dcfc52adSAndreas Dannenberg 	bops->board_config = ti_sci_cmd_set_board_config;
1412dcfc52adSAndreas Dannenberg 	bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
1413dcfc52adSAndreas Dannenberg 	bops->board_config_security = ti_sci_cmd_set_board_config_security;
1414dcfc52adSAndreas Dannenberg 	bops->board_config_pm = ti_sci_cmd_set_board_config_pm;
14157bc33045SAndreas Dannenberg 
14167bc33045SAndreas Dannenberg 	dops->get_device = ti_sci_cmd_get_device;
14177bc33045SAndreas Dannenberg 	dops->idle_device = ti_sci_cmd_idle_device;
14187bc33045SAndreas Dannenberg 	dops->put_device = ti_sci_cmd_put_device;
14197bc33045SAndreas Dannenberg 	dops->is_valid = ti_sci_cmd_dev_is_valid;
14207bc33045SAndreas Dannenberg 	dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
14217bc33045SAndreas Dannenberg 	dops->is_idle = ti_sci_cmd_dev_is_idle;
14227bc33045SAndreas Dannenberg 	dops->is_stop = ti_sci_cmd_dev_is_stop;
14237bc33045SAndreas Dannenberg 	dops->is_on = ti_sci_cmd_dev_is_on;
14247bc33045SAndreas Dannenberg 	dops->is_transitioning = ti_sci_cmd_dev_is_trans;
14257bc33045SAndreas Dannenberg 	dops->set_device_resets = ti_sci_cmd_set_device_resets;
14267bc33045SAndreas Dannenberg 	dops->get_device_resets = ti_sci_cmd_get_device_resets;
1427*9b87181fSLokesh Vutla 
1428*9b87181fSLokesh Vutla 	cops->get_clock = ti_sci_cmd_get_clock;
1429*9b87181fSLokesh Vutla 	cops->idle_clock = ti_sci_cmd_idle_clock;
1430*9b87181fSLokesh Vutla 	cops->put_clock = ti_sci_cmd_put_clock;
1431*9b87181fSLokesh Vutla 	cops->is_auto = ti_sci_cmd_clk_is_auto;
1432*9b87181fSLokesh Vutla 	cops->is_on = ti_sci_cmd_clk_is_on;
1433*9b87181fSLokesh Vutla 	cops->is_off = ti_sci_cmd_clk_is_off;
1434*9b87181fSLokesh Vutla 
1435*9b87181fSLokesh Vutla 	cops->set_parent = ti_sci_cmd_clk_set_parent;
1436*9b87181fSLokesh Vutla 	cops->get_parent = ti_sci_cmd_clk_get_parent;
1437*9b87181fSLokesh Vutla 	cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
1438*9b87181fSLokesh Vutla 
1439*9b87181fSLokesh Vutla 	cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
1440*9b87181fSLokesh Vutla 	cops->set_freq = ti_sci_cmd_clk_set_freq;
1441*9b87181fSLokesh Vutla 	cops->get_freq = ti_sci_cmd_clk_get_freq;
1442dcfc52adSAndreas Dannenberg }
1443dcfc52adSAndreas Dannenberg 
1444dcfc52adSAndreas Dannenberg /**
144532cd2512SLokesh Vutla  * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW
144632cd2512SLokesh Vutla  * @dev:	Pointer to the SYSFW device
144732cd2512SLokesh Vutla  *
144832cd2512SLokesh Vutla  * Return: pointer to handle if successful, else EINVAL if invalid conditions
144932cd2512SLokesh Vutla  *         are encountered.
145032cd2512SLokesh Vutla  */
145132cd2512SLokesh Vutla const
145232cd2512SLokesh Vutla struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev)
145332cd2512SLokesh Vutla {
145432cd2512SLokesh Vutla 	if (!sci_dev)
145532cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
145632cd2512SLokesh Vutla 
145732cd2512SLokesh Vutla 	struct ti_sci_info *info = dev_get_priv(sci_dev);
145832cd2512SLokesh Vutla 
145932cd2512SLokesh Vutla 	if (!info)
146032cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
146132cd2512SLokesh Vutla 
146232cd2512SLokesh Vutla 	struct ti_sci_handle *handle = &info->handle;
146332cd2512SLokesh Vutla 
146432cd2512SLokesh Vutla 	if (!handle)
146532cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
146632cd2512SLokesh Vutla 
146732cd2512SLokesh Vutla 	return handle;
146832cd2512SLokesh Vutla }
146932cd2512SLokesh Vutla 
147032cd2512SLokesh Vutla /**
147132cd2512SLokesh Vutla  * ti_sci_get_handle() - Get the TI SCI handle for a device
147232cd2512SLokesh Vutla  * @dev:	Pointer to device for which we want SCI handle
147332cd2512SLokesh Vutla  *
147432cd2512SLokesh Vutla  * Return: pointer to handle if successful, else EINVAL if invalid conditions
147532cd2512SLokesh Vutla  *         are encountered.
147632cd2512SLokesh Vutla  */
147732cd2512SLokesh Vutla const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev)
147832cd2512SLokesh Vutla {
147932cd2512SLokesh Vutla 	if (!dev)
148032cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
148132cd2512SLokesh Vutla 
148232cd2512SLokesh Vutla 	struct udevice *sci_dev = dev_get_parent(dev);
148332cd2512SLokesh Vutla 
148432cd2512SLokesh Vutla 	return ti_sci_get_handle_from_sysfw(sci_dev);
148532cd2512SLokesh Vutla }
148632cd2512SLokesh Vutla 
148732cd2512SLokesh Vutla /**
148832cd2512SLokesh Vutla  * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
148932cd2512SLokesh Vutla  * @dev:	device node
149032cd2512SLokesh Vutla  * @propname:	property name containing phandle on TISCI node
149132cd2512SLokesh Vutla  *
149232cd2512SLokesh Vutla  * Return: pointer to handle if successful, else appropriate error value.
149332cd2512SLokesh Vutla  */
149432cd2512SLokesh Vutla const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev,
149532cd2512SLokesh Vutla 						  const char *property)
149632cd2512SLokesh Vutla {
149732cd2512SLokesh Vutla 	struct ti_sci_info *entry, *info = NULL;
149832cd2512SLokesh Vutla 	u32 phandle, err;
149932cd2512SLokesh Vutla 	ofnode node;
150032cd2512SLokesh Vutla 
150132cd2512SLokesh Vutla 	err = ofnode_read_u32(dev_ofnode(dev), property, &phandle);
150232cd2512SLokesh Vutla 	if (err)
150332cd2512SLokesh Vutla 		return ERR_PTR(err);
150432cd2512SLokesh Vutla 
150532cd2512SLokesh Vutla 	node = ofnode_get_by_phandle(phandle);
150632cd2512SLokesh Vutla 	if (!ofnode_valid(node))
150732cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
150832cd2512SLokesh Vutla 
150932cd2512SLokesh Vutla 	list_for_each_entry(entry, &ti_sci_list, list)
151032cd2512SLokesh Vutla 		if (ofnode_equal(dev_ofnode(entry->dev), node)) {
151132cd2512SLokesh Vutla 			info = entry;
151232cd2512SLokesh Vutla 			break;
151332cd2512SLokesh Vutla 		}
151432cd2512SLokesh Vutla 
151532cd2512SLokesh Vutla 	if (!info)
151632cd2512SLokesh Vutla 		return ERR_PTR(-ENODEV);
151732cd2512SLokesh Vutla 
151832cd2512SLokesh Vutla 	return &info->handle;
151932cd2512SLokesh Vutla }
152032cd2512SLokesh Vutla 
152132cd2512SLokesh Vutla /**
152232cd2512SLokesh Vutla  * ti_sci_of_to_info() - generate private data from device tree
152332cd2512SLokesh Vutla  * @dev:	corresponding system controller interface device
152432cd2512SLokesh Vutla  * @info:	pointer to driver specific private data
152532cd2512SLokesh Vutla  *
152632cd2512SLokesh Vutla  * Return: 0 if all goes good, else appropriate error message.
152732cd2512SLokesh Vutla  */
152832cd2512SLokesh Vutla static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info)
152932cd2512SLokesh Vutla {
153032cd2512SLokesh Vutla 	int ret;
153132cd2512SLokesh Vutla 
153232cd2512SLokesh Vutla 	ret = mbox_get_by_name(dev, "tx", &info->chan_tx);
153332cd2512SLokesh Vutla 	if (ret) {
153432cd2512SLokesh Vutla 		dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n",
153532cd2512SLokesh Vutla 			__func__, ret);
153632cd2512SLokesh Vutla 		return ret;
153732cd2512SLokesh Vutla 	}
153832cd2512SLokesh Vutla 
153932cd2512SLokesh Vutla 	ret = mbox_get_by_name(dev, "rx", &info->chan_rx);
154032cd2512SLokesh Vutla 	if (ret) {
154132cd2512SLokesh Vutla 		dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n",
154232cd2512SLokesh Vutla 			__func__, ret);
154332cd2512SLokesh Vutla 		return ret;
154432cd2512SLokesh Vutla 	}
154532cd2512SLokesh Vutla 
154632cd2512SLokesh Vutla 	/* Notify channel is optional. Enable only if populated */
154732cd2512SLokesh Vutla 	ret = mbox_get_by_name(dev, "notify", &info->chan_notify);
154832cd2512SLokesh Vutla 	if (ret) {
154932cd2512SLokesh Vutla 		dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n",
155032cd2512SLokesh Vutla 			__func__, ret);
155132cd2512SLokesh Vutla 	}
155232cd2512SLokesh Vutla 
155332cd2512SLokesh Vutla 	info->host_id = dev_read_u32_default(dev, "ti,host-id",
155432cd2512SLokesh Vutla 					     info->desc->host_id);
155532cd2512SLokesh Vutla 
155632cd2512SLokesh Vutla 	info->is_secure = dev_read_bool(dev, "ti,secure-host");
155732cd2512SLokesh Vutla 
155832cd2512SLokesh Vutla 	return 0;
155932cd2512SLokesh Vutla }
156032cd2512SLokesh Vutla 
156132cd2512SLokesh Vutla /**
156232cd2512SLokesh Vutla  * ti_sci_probe() - Basic probe
156332cd2512SLokesh Vutla  * @dev:	corresponding system controller interface device
156432cd2512SLokesh Vutla  *
156532cd2512SLokesh Vutla  * Return: 0 if all goes good, else appropriate error message.
156632cd2512SLokesh Vutla  */
156732cd2512SLokesh Vutla static int ti_sci_probe(struct udevice *dev)
156832cd2512SLokesh Vutla {
156932cd2512SLokesh Vutla 	struct ti_sci_info *info;
157032cd2512SLokesh Vutla 	int ret;
157132cd2512SLokesh Vutla 
157232cd2512SLokesh Vutla 	debug("%s(dev=%p)\n", __func__, dev);
157332cd2512SLokesh Vutla 
157432cd2512SLokesh Vutla 	info = dev_get_priv(dev);
157532cd2512SLokesh Vutla 	info->desc = (void *)dev_get_driver_data(dev);
157632cd2512SLokesh Vutla 
157732cd2512SLokesh Vutla 	ret = ti_sci_of_to_info(dev, info);
157832cd2512SLokesh Vutla 	if (ret) {
157932cd2512SLokesh Vutla 		dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
158032cd2512SLokesh Vutla 		return ret;
158132cd2512SLokesh Vutla 	}
158232cd2512SLokesh Vutla 
158332cd2512SLokesh Vutla 	info->dev = dev;
158432cd2512SLokesh Vutla 	info->seq = 0xA;
158532cd2512SLokesh Vutla 
158632cd2512SLokesh Vutla 	list_add_tail(&info->list, &ti_sci_list);
1587dcfc52adSAndreas Dannenberg 	ti_sci_setup_ops(info);
158832cd2512SLokesh Vutla 
158932cd2512SLokesh Vutla 	ret = ti_sci_cmd_get_revision(&info->handle);
159032cd2512SLokesh Vutla 
159132cd2512SLokesh Vutla 	return ret;
159232cd2512SLokesh Vutla }
159332cd2512SLokesh Vutla 
159432cd2512SLokesh Vutla /* Description for AM654 */
159532cd2512SLokesh Vutla static const struct ti_sci_desc ti_sci_sysfw_am654_desc = {
159632cd2512SLokesh Vutla 	.host_id = 4,
159732cd2512SLokesh Vutla 	.max_rx_timeout_us = 1000000,
159832cd2512SLokesh Vutla 	.max_msg_size = 60,
159932cd2512SLokesh Vutla };
160032cd2512SLokesh Vutla 
160132cd2512SLokesh Vutla static const struct udevice_id ti_sci_ids[] = {
160232cd2512SLokesh Vutla 	{
160332cd2512SLokesh Vutla 		.compatible = "ti,k2g-sci",
160432cd2512SLokesh Vutla 		.data = (ulong)&ti_sci_sysfw_am654_desc
160532cd2512SLokesh Vutla 	},
160632cd2512SLokesh Vutla 	{ /* Sentinel */ },
160732cd2512SLokesh Vutla };
160832cd2512SLokesh Vutla 
160932cd2512SLokesh Vutla U_BOOT_DRIVER(ti_sci) = {
161032cd2512SLokesh Vutla 	.name = "ti_sci",
161132cd2512SLokesh Vutla 	.id = UCLASS_FIRMWARE,
161232cd2512SLokesh Vutla 	.of_match = ti_sci_ids,
161332cd2512SLokesh Vutla 	.probe = ti_sci_probe,
161432cd2512SLokesh Vutla 	.priv_auto_alloc_size = sizeof(struct ti_sci_info),
161532cd2512SLokesh Vutla };
1616