162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Texas Instruments System Control Interface Protocol Driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com/
662306a36Sopenharmony_ci *	Nishanth Menon
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define pr_fmt(fmt) "%s: " fmt, __func__
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/bitmap.h>
1262306a36Sopenharmony_ci#include <linux/debugfs.h>
1362306a36Sopenharmony_ci#include <linux/export.h>
1462306a36Sopenharmony_ci#include <linux/io.h>
1562306a36Sopenharmony_ci#include <linux/iopoll.h>
1662306a36Sopenharmony_ci#include <linux/kernel.h>
1762306a36Sopenharmony_ci#include <linux/mailbox_client.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/of_device.h>
2062306a36Sopenharmony_ci#include <linux/semaphore.h>
2162306a36Sopenharmony_ci#include <linux/slab.h>
2262306a36Sopenharmony_ci#include <linux/soc/ti/ti-msgmgr.h>
2362306a36Sopenharmony_ci#include <linux/soc/ti/ti_sci_protocol.h>
2462306a36Sopenharmony_ci#include <linux/reboot.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include "ti_sci.h"
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/* List of all TI SCI devices active in system */
2962306a36Sopenharmony_cistatic LIST_HEAD(ti_sci_list);
3062306a36Sopenharmony_ci/* Protection for the entire list */
3162306a36Sopenharmony_cistatic DEFINE_MUTEX(ti_sci_list_mutex);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/**
3462306a36Sopenharmony_ci * struct ti_sci_xfer - Structure representing a message flow
3562306a36Sopenharmony_ci * @tx_message:	Transmit message
3662306a36Sopenharmony_ci * @rx_len:	Receive message length
3762306a36Sopenharmony_ci * @xfer_buf:	Preallocated buffer to store receive message
3862306a36Sopenharmony_ci *		Since we work with request-ACK protocol, we can
3962306a36Sopenharmony_ci *		reuse the same buffer for the rx path as we
4062306a36Sopenharmony_ci *		use for the tx path.
4162306a36Sopenharmony_ci * @done:	completion event
4262306a36Sopenharmony_ci */
4362306a36Sopenharmony_cistruct ti_sci_xfer {
4462306a36Sopenharmony_ci	struct ti_msgmgr_message tx_message;
4562306a36Sopenharmony_ci	u8 rx_len;
4662306a36Sopenharmony_ci	u8 *xfer_buf;
4762306a36Sopenharmony_ci	struct completion done;
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci/**
5162306a36Sopenharmony_ci * struct ti_sci_xfers_info - Structure to manage transfer information
5262306a36Sopenharmony_ci * @sem_xfer_count:	Counting Semaphore for managing max simultaneous
5362306a36Sopenharmony_ci *			Messages.
5462306a36Sopenharmony_ci * @xfer_block:		Preallocated Message array
5562306a36Sopenharmony_ci * @xfer_alloc_table:	Bitmap table for allocated messages.
5662306a36Sopenharmony_ci *			Index of this bitmap table is also used for message
5762306a36Sopenharmony_ci *			sequence identifier.
5862306a36Sopenharmony_ci * @xfer_lock:		Protection for message allocation
5962306a36Sopenharmony_ci */
6062306a36Sopenharmony_cistruct ti_sci_xfers_info {
6162306a36Sopenharmony_ci	struct semaphore sem_xfer_count;
6262306a36Sopenharmony_ci	struct ti_sci_xfer *xfer_block;
6362306a36Sopenharmony_ci	unsigned long *xfer_alloc_table;
6462306a36Sopenharmony_ci	/* protect transfer allocation */
6562306a36Sopenharmony_ci	spinlock_t xfer_lock;
6662306a36Sopenharmony_ci};
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/**
6962306a36Sopenharmony_ci * struct ti_sci_desc - Description of SoC integration
7062306a36Sopenharmony_ci * @default_host_id:	Host identifier representing the compute entity
7162306a36Sopenharmony_ci * @max_rx_timeout_ms:	Timeout for communication with SoC (in Milliseconds)
7262306a36Sopenharmony_ci * @max_msgs: Maximum number of messages that can be pending
7362306a36Sopenharmony_ci *		  simultaneously in the system
7462306a36Sopenharmony_ci * @max_msg_size: Maximum size of data per message that can be handled.
7562306a36Sopenharmony_ci */
7662306a36Sopenharmony_cistruct ti_sci_desc {
7762306a36Sopenharmony_ci	u8 default_host_id;
7862306a36Sopenharmony_ci	int max_rx_timeout_ms;
7962306a36Sopenharmony_ci	int max_msgs;
8062306a36Sopenharmony_ci	int max_msg_size;
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/**
8462306a36Sopenharmony_ci * struct ti_sci_info - Structure representing a TI SCI instance
8562306a36Sopenharmony_ci * @dev:	Device pointer
8662306a36Sopenharmony_ci * @desc:	SoC description for this instance
8762306a36Sopenharmony_ci * @nb:	Reboot Notifier block
8862306a36Sopenharmony_ci * @d:		Debugfs file entry
8962306a36Sopenharmony_ci * @debug_region: Memory region where the debug message are available
9062306a36Sopenharmony_ci * @debug_region_size: Debug region size
9162306a36Sopenharmony_ci * @debug_buffer: Buffer allocated to copy debug messages.
9262306a36Sopenharmony_ci * @handle:	Instance of TI SCI handle to send to clients.
9362306a36Sopenharmony_ci * @cl:		Mailbox Client
9462306a36Sopenharmony_ci * @chan_tx:	Transmit mailbox channel
9562306a36Sopenharmony_ci * @chan_rx:	Receive mailbox channel
9662306a36Sopenharmony_ci * @minfo:	Message info
9762306a36Sopenharmony_ci * @node:	list head
9862306a36Sopenharmony_ci * @host_id:	Host ID
9962306a36Sopenharmony_ci * @users:	Number of users of this instance
10062306a36Sopenharmony_ci */
10162306a36Sopenharmony_cistruct ti_sci_info {
10262306a36Sopenharmony_ci	struct device *dev;
10362306a36Sopenharmony_ci	struct notifier_block nb;
10462306a36Sopenharmony_ci	const struct ti_sci_desc *desc;
10562306a36Sopenharmony_ci	struct dentry *d;
10662306a36Sopenharmony_ci	void __iomem *debug_region;
10762306a36Sopenharmony_ci	char *debug_buffer;
10862306a36Sopenharmony_ci	size_t debug_region_size;
10962306a36Sopenharmony_ci	struct ti_sci_handle handle;
11062306a36Sopenharmony_ci	struct mbox_client cl;
11162306a36Sopenharmony_ci	struct mbox_chan *chan_tx;
11262306a36Sopenharmony_ci	struct mbox_chan *chan_rx;
11362306a36Sopenharmony_ci	struct ti_sci_xfers_info minfo;
11462306a36Sopenharmony_ci	struct list_head node;
11562306a36Sopenharmony_ci	u8 host_id;
11662306a36Sopenharmony_ci	/* protected by ti_sci_list_mutex */
11762306a36Sopenharmony_ci	int users;
11862306a36Sopenharmony_ci};
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#define cl_to_ti_sci_info(c)	container_of(c, struct ti_sci_info, cl)
12162306a36Sopenharmony_ci#define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
12262306a36Sopenharmony_ci#define reboot_to_ti_sci_info(n) container_of(n, struct ti_sci_info, nb)
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/**
12762306a36Sopenharmony_ci * ti_sci_debug_show() - Helper to dump the debug log
12862306a36Sopenharmony_ci * @s:	sequence file pointer
12962306a36Sopenharmony_ci * @unused:	unused.
13062306a36Sopenharmony_ci *
13162306a36Sopenharmony_ci * Return: 0
13262306a36Sopenharmony_ci */
13362306a36Sopenharmony_cistatic int ti_sci_debug_show(struct seq_file *s, void *unused)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	struct ti_sci_info *info = s->private;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	memcpy_fromio(info->debug_buffer, info->debug_region,
13862306a36Sopenharmony_ci		      info->debug_region_size);
13962306a36Sopenharmony_ci	/*
14062306a36Sopenharmony_ci	 * We don't trust firmware to leave NULL terminated last byte (hence
14162306a36Sopenharmony_ci	 * we have allocated 1 extra 0 byte). Since we cannot guarantee any
14262306a36Sopenharmony_ci	 * specific data format for debug messages, We just present the data
14362306a36Sopenharmony_ci	 * in the buffer as is - we expect the messages to be self explanatory.
14462306a36Sopenharmony_ci	 */
14562306a36Sopenharmony_ci	seq_puts(s, info->debug_buffer);
14662306a36Sopenharmony_ci	return 0;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/* Provide the log file operations interface*/
15062306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(ti_sci_debug);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci/**
15362306a36Sopenharmony_ci * ti_sci_debugfs_create() - Create log debug file
15462306a36Sopenharmony_ci * @pdev:	platform device pointer
15562306a36Sopenharmony_ci * @info:	Pointer to SCI entity information
15662306a36Sopenharmony_ci *
15762306a36Sopenharmony_ci * Return: 0 if all went fine, else corresponding error.
15862306a36Sopenharmony_ci */
15962306a36Sopenharmony_cistatic int ti_sci_debugfs_create(struct platform_device *pdev,
16062306a36Sopenharmony_ci				 struct ti_sci_info *info)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
16362306a36Sopenharmony_ci	struct resource *res;
16462306a36Sopenharmony_ci	char debug_name[50];
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	/* Debug region is optional */
16762306a36Sopenharmony_ci	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
16862306a36Sopenharmony_ci					   "debug_messages");
16962306a36Sopenharmony_ci	info->debug_region = devm_ioremap_resource(dev, res);
17062306a36Sopenharmony_ci	if (IS_ERR(info->debug_region))
17162306a36Sopenharmony_ci		return 0;
17262306a36Sopenharmony_ci	info->debug_region_size = resource_size(res);
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	info->debug_buffer = devm_kcalloc(dev, info->debug_region_size + 1,
17562306a36Sopenharmony_ci					  sizeof(char), GFP_KERNEL);
17662306a36Sopenharmony_ci	if (!info->debug_buffer)
17762306a36Sopenharmony_ci		return -ENOMEM;
17862306a36Sopenharmony_ci	/* Setup NULL termination */
17962306a36Sopenharmony_ci	info->debug_buffer[info->debug_region_size] = 0;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	snprintf(debug_name, sizeof(debug_name), "ti_sci_debug@%s",
18262306a36Sopenharmony_ci		 dev_name(dev));
18362306a36Sopenharmony_ci	info->d = debugfs_create_file(debug_name, 0444, NULL, info,
18462306a36Sopenharmony_ci				      &ti_sci_debug_fops);
18562306a36Sopenharmony_ci	if (IS_ERR(info->d))
18662306a36Sopenharmony_ci		return PTR_ERR(info->d);
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	dev_dbg(dev, "Debug region => %p, size = %zu bytes, resource: %pr\n",
18962306a36Sopenharmony_ci		info->debug_region, info->debug_region_size, res);
19062306a36Sopenharmony_ci	return 0;
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci#else /* CONFIG_DEBUG_FS */
19462306a36Sopenharmony_cistatic inline int ti_sci_debugfs_create(struct platform_device *dev,
19562306a36Sopenharmony_ci					struct ti_sci_info *info)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	return 0;
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistatic inline void ti_sci_debugfs_destroy(struct platform_device *dev,
20162306a36Sopenharmony_ci					  struct ti_sci_info *info)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci/**
20762306a36Sopenharmony_ci * ti_sci_dump_header_dbg() - Helper to dump a message header.
20862306a36Sopenharmony_ci * @dev:	Device pointer corresponding to the SCI entity
20962306a36Sopenharmony_ci * @hdr:	pointer to header.
21062306a36Sopenharmony_ci */
21162306a36Sopenharmony_cistatic inline void ti_sci_dump_header_dbg(struct device *dev,
21262306a36Sopenharmony_ci					  struct ti_sci_msg_hdr *hdr)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	dev_dbg(dev, "MSGHDR:type=0x%04x host=0x%02x seq=0x%02x flags=0x%08x\n",
21562306a36Sopenharmony_ci		hdr->type, hdr->host, hdr->seq, hdr->flags);
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/**
21962306a36Sopenharmony_ci * ti_sci_rx_callback() - mailbox client callback for receive messages
22062306a36Sopenharmony_ci * @cl:	client pointer
22162306a36Sopenharmony_ci * @m:	mailbox message
22262306a36Sopenharmony_ci *
22362306a36Sopenharmony_ci * Processes one received message to appropriate transfer information and
22462306a36Sopenharmony_ci * signals completion of the transfer.
22562306a36Sopenharmony_ci *
22662306a36Sopenharmony_ci * NOTE: This function will be invoked in IRQ context, hence should be
22762306a36Sopenharmony_ci * as optimal as possible.
22862306a36Sopenharmony_ci */
22962306a36Sopenharmony_cistatic void ti_sci_rx_callback(struct mbox_client *cl, void *m)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	struct ti_sci_info *info = cl_to_ti_sci_info(cl);
23262306a36Sopenharmony_ci	struct device *dev = info->dev;
23362306a36Sopenharmony_ci	struct ti_sci_xfers_info *minfo = &info->minfo;
23462306a36Sopenharmony_ci	struct ti_msgmgr_message *mbox_msg = m;
23562306a36Sopenharmony_ci	struct ti_sci_msg_hdr *hdr = (struct ti_sci_msg_hdr *)mbox_msg->buf;
23662306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
23762306a36Sopenharmony_ci	u8 xfer_id;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	xfer_id = hdr->seq;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	/*
24262306a36Sopenharmony_ci	 * Are we even expecting this?
24362306a36Sopenharmony_ci	 * NOTE: barriers were implicit in locks used for modifying the bitmap
24462306a36Sopenharmony_ci	 */
24562306a36Sopenharmony_ci	if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
24662306a36Sopenharmony_ci		dev_err(dev, "Message for %d is not expected!\n", xfer_id);
24762306a36Sopenharmony_ci		return;
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	xfer = &minfo->xfer_block[xfer_id];
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	/* Is the message of valid length? */
25362306a36Sopenharmony_ci	if (mbox_msg->len > info->desc->max_msg_size) {
25462306a36Sopenharmony_ci		dev_err(dev, "Unable to handle %zu xfer(max %d)\n",
25562306a36Sopenharmony_ci			mbox_msg->len, info->desc->max_msg_size);
25662306a36Sopenharmony_ci		ti_sci_dump_header_dbg(dev, hdr);
25762306a36Sopenharmony_ci		return;
25862306a36Sopenharmony_ci	}
25962306a36Sopenharmony_ci	if (mbox_msg->len < xfer->rx_len) {
26062306a36Sopenharmony_ci		dev_err(dev, "Recv xfer %zu < expected %d length\n",
26162306a36Sopenharmony_ci			mbox_msg->len, xfer->rx_len);
26262306a36Sopenharmony_ci		ti_sci_dump_header_dbg(dev, hdr);
26362306a36Sopenharmony_ci		return;
26462306a36Sopenharmony_ci	}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	ti_sci_dump_header_dbg(dev, hdr);
26762306a36Sopenharmony_ci	/* Take a copy to the rx buffer.. */
26862306a36Sopenharmony_ci	memcpy(xfer->xfer_buf, mbox_msg->buf, xfer->rx_len);
26962306a36Sopenharmony_ci	complete(&xfer->done);
27062306a36Sopenharmony_ci}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci/**
27362306a36Sopenharmony_ci * ti_sci_get_one_xfer() - Allocate one message
27462306a36Sopenharmony_ci * @info:	Pointer to SCI entity information
27562306a36Sopenharmony_ci * @msg_type:	Message type
27662306a36Sopenharmony_ci * @msg_flags:	Flag to set for the message
27762306a36Sopenharmony_ci * @tx_message_size: transmit message size
27862306a36Sopenharmony_ci * @rx_message_size: receive message size
27962306a36Sopenharmony_ci *
28062306a36Sopenharmony_ci * Helper function which is used by various command functions that are
28162306a36Sopenharmony_ci * exposed to clients of this driver for allocating a message traffic event.
28262306a36Sopenharmony_ci *
28362306a36Sopenharmony_ci * This function can sleep depending on pending requests already in the system
28462306a36Sopenharmony_ci * for the SCI entity. Further, this also holds a spinlock to maintain integrity
28562306a36Sopenharmony_ci * of internal data structures.
28662306a36Sopenharmony_ci *
28762306a36Sopenharmony_ci * Return: 0 if all went fine, else corresponding error.
28862306a36Sopenharmony_ci */
28962306a36Sopenharmony_cistatic struct ti_sci_xfer *ti_sci_get_one_xfer(struct ti_sci_info *info,
29062306a36Sopenharmony_ci					       u16 msg_type, u32 msg_flags,
29162306a36Sopenharmony_ci					       size_t tx_message_size,
29262306a36Sopenharmony_ci					       size_t rx_message_size)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	struct ti_sci_xfers_info *minfo = &info->minfo;
29562306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
29662306a36Sopenharmony_ci	struct ti_sci_msg_hdr *hdr;
29762306a36Sopenharmony_ci	unsigned long flags;
29862306a36Sopenharmony_ci	unsigned long bit_pos;
29962306a36Sopenharmony_ci	u8 xfer_id;
30062306a36Sopenharmony_ci	int ret;
30162306a36Sopenharmony_ci	int timeout;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	/* Ensure we have sane transfer sizes */
30462306a36Sopenharmony_ci	if (rx_message_size > info->desc->max_msg_size ||
30562306a36Sopenharmony_ci	    tx_message_size > info->desc->max_msg_size ||
30662306a36Sopenharmony_ci	    rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr))
30762306a36Sopenharmony_ci		return ERR_PTR(-ERANGE);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	/*
31062306a36Sopenharmony_ci	 * Ensure we have only controlled number of pending messages.
31162306a36Sopenharmony_ci	 * Ideally, we might just have to wait a single message, be
31262306a36Sopenharmony_ci	 * conservative and wait 5 times that..
31362306a36Sopenharmony_ci	 */
31462306a36Sopenharmony_ci	timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms) * 5;
31562306a36Sopenharmony_ci	ret = down_timeout(&minfo->sem_xfer_count, timeout);
31662306a36Sopenharmony_ci	if (ret < 0)
31762306a36Sopenharmony_ci		return ERR_PTR(ret);
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	/* Keep the locked section as small as possible */
32062306a36Sopenharmony_ci	spin_lock_irqsave(&minfo->xfer_lock, flags);
32162306a36Sopenharmony_ci	bit_pos = find_first_zero_bit(minfo->xfer_alloc_table,
32262306a36Sopenharmony_ci				      info->desc->max_msgs);
32362306a36Sopenharmony_ci	set_bit(bit_pos, minfo->xfer_alloc_table);
32462306a36Sopenharmony_ci	spin_unlock_irqrestore(&minfo->xfer_lock, flags);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	/*
32762306a36Sopenharmony_ci	 * We already ensured in probe that we can have max messages that can
32862306a36Sopenharmony_ci	 * fit in  hdr.seq - NOTE: this improves access latencies
32962306a36Sopenharmony_ci	 * to predictable O(1) access, BUT, it opens us to risk if
33062306a36Sopenharmony_ci	 * remote misbehaves with corrupted message sequence responses.
33162306a36Sopenharmony_ci	 * If that happens, we are going to be messed up anyways..
33262306a36Sopenharmony_ci	 */
33362306a36Sopenharmony_ci	xfer_id = (u8)bit_pos;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	xfer = &minfo->xfer_block[xfer_id];
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
33862306a36Sopenharmony_ci	xfer->tx_message.len = tx_message_size;
33962306a36Sopenharmony_ci	xfer->tx_message.chan_rx = info->chan_rx;
34062306a36Sopenharmony_ci	xfer->tx_message.timeout_rx_ms = info->desc->max_rx_timeout_ms;
34162306a36Sopenharmony_ci	xfer->rx_len = (u8)rx_message_size;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	reinit_completion(&xfer->done);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	hdr->seq = xfer_id;
34662306a36Sopenharmony_ci	hdr->type = msg_type;
34762306a36Sopenharmony_ci	hdr->host = info->host_id;
34862306a36Sopenharmony_ci	hdr->flags = msg_flags;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	return xfer;
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci/**
35462306a36Sopenharmony_ci * ti_sci_put_one_xfer() - Release a message
35562306a36Sopenharmony_ci * @minfo:	transfer info pointer
35662306a36Sopenharmony_ci * @xfer:	message that was reserved by ti_sci_get_one_xfer
35762306a36Sopenharmony_ci *
35862306a36Sopenharmony_ci * This holds a spinlock to maintain integrity of internal data structures.
35962306a36Sopenharmony_ci */
36062306a36Sopenharmony_cistatic void ti_sci_put_one_xfer(struct ti_sci_xfers_info *minfo,
36162306a36Sopenharmony_ci				struct ti_sci_xfer *xfer)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	unsigned long flags;
36462306a36Sopenharmony_ci	struct ti_sci_msg_hdr *hdr;
36562306a36Sopenharmony_ci	u8 xfer_id;
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
36862306a36Sopenharmony_ci	xfer_id = hdr->seq;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	/*
37162306a36Sopenharmony_ci	 * Keep the locked section as small as possible
37262306a36Sopenharmony_ci	 * NOTE: we might escape with smp_mb and no lock here..
37362306a36Sopenharmony_ci	 * but just be conservative and symmetric.
37462306a36Sopenharmony_ci	 */
37562306a36Sopenharmony_ci	spin_lock_irqsave(&minfo->xfer_lock, flags);
37662306a36Sopenharmony_ci	clear_bit(xfer_id, minfo->xfer_alloc_table);
37762306a36Sopenharmony_ci	spin_unlock_irqrestore(&minfo->xfer_lock, flags);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	/* Increment the count for the next user to get through */
38062306a36Sopenharmony_ci	up(&minfo->sem_xfer_count);
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci/**
38462306a36Sopenharmony_ci * ti_sci_do_xfer() - Do one transfer
38562306a36Sopenharmony_ci * @info:	Pointer to SCI entity information
38662306a36Sopenharmony_ci * @xfer:	Transfer to initiate and wait for response
38762306a36Sopenharmony_ci *
38862306a36Sopenharmony_ci * Return: -ETIMEDOUT in case of no response, if transmit error,
38962306a36Sopenharmony_ci *	   return corresponding error, else if all goes well,
39062306a36Sopenharmony_ci *	   return 0.
39162306a36Sopenharmony_ci */
39262306a36Sopenharmony_cistatic inline int ti_sci_do_xfer(struct ti_sci_info *info,
39362306a36Sopenharmony_ci				 struct ti_sci_xfer *xfer)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	int ret;
39662306a36Sopenharmony_ci	int timeout;
39762306a36Sopenharmony_ci	struct device *dev = info->dev;
39862306a36Sopenharmony_ci	bool done_state = true;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	ret = mbox_send_message(info->chan_tx, &xfer->tx_message);
40162306a36Sopenharmony_ci	if (ret < 0)
40262306a36Sopenharmony_ci		return ret;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	ret = 0;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	if (system_state <= SYSTEM_RUNNING) {
40762306a36Sopenharmony_ci		/* And we wait for the response. */
40862306a36Sopenharmony_ci		timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
40962306a36Sopenharmony_ci		if (!wait_for_completion_timeout(&xfer->done, timeout))
41062306a36Sopenharmony_ci			ret = -ETIMEDOUT;
41162306a36Sopenharmony_ci	} else {
41262306a36Sopenharmony_ci		/*
41362306a36Sopenharmony_ci		 * If we are !running, we cannot use wait_for_completion_timeout
41462306a36Sopenharmony_ci		 * during noirq phase, so we must manually poll the completion.
41562306a36Sopenharmony_ci		 */
41662306a36Sopenharmony_ci		ret = read_poll_timeout_atomic(try_wait_for_completion, done_state,
41762306a36Sopenharmony_ci					       done_state, 1,
41862306a36Sopenharmony_ci					       info->desc->max_rx_timeout_ms * 1000,
41962306a36Sopenharmony_ci					       false, &xfer->done);
42062306a36Sopenharmony_ci	}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	if (ret == -ETIMEDOUT)
42362306a36Sopenharmony_ci		dev_err(dev, "Mbox timedout in resp(caller: %pS)\n",
42462306a36Sopenharmony_ci			(void *)_RET_IP_);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	/*
42762306a36Sopenharmony_ci	 * NOTE: we might prefer not to need the mailbox ticker to manage the
42862306a36Sopenharmony_ci	 * transfer queueing since the protocol layer queues things by itself.
42962306a36Sopenharmony_ci	 * Unfortunately, we have to kick the mailbox framework after we have
43062306a36Sopenharmony_ci	 * received our message.
43162306a36Sopenharmony_ci	 */
43262306a36Sopenharmony_ci	mbox_client_txdone(info->chan_tx, ret);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	return ret;
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci/**
43862306a36Sopenharmony_ci * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
43962306a36Sopenharmony_ci * @info:	Pointer to SCI entity information
44062306a36Sopenharmony_ci *
44162306a36Sopenharmony_ci * Updates the SCI information in the internal data structure.
44262306a36Sopenharmony_ci *
44362306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
44462306a36Sopenharmony_ci */
44562306a36Sopenharmony_cistatic int ti_sci_cmd_get_revision(struct ti_sci_info *info)
44662306a36Sopenharmony_ci{
44762306a36Sopenharmony_ci	struct device *dev = info->dev;
44862306a36Sopenharmony_ci	struct ti_sci_handle *handle = &info->handle;
44962306a36Sopenharmony_ci	struct ti_sci_version_info *ver = &handle->version;
45062306a36Sopenharmony_ci	struct ti_sci_msg_resp_version *rev_info;
45162306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
45262306a36Sopenharmony_ci	int ret;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_VERSION,
45562306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
45662306a36Sopenharmony_ci				   sizeof(struct ti_sci_msg_hdr),
45762306a36Sopenharmony_ci				   sizeof(*rev_info));
45862306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
45962306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
46062306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
46162306a36Sopenharmony_ci		return ret;
46262306a36Sopenharmony_ci	}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	rev_info = (struct ti_sci_msg_resp_version *)xfer->xfer_buf;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
46762306a36Sopenharmony_ci	if (ret) {
46862306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
46962306a36Sopenharmony_ci		goto fail;
47062306a36Sopenharmony_ci	}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	ver->abi_major = rev_info->abi_major;
47362306a36Sopenharmony_ci	ver->abi_minor = rev_info->abi_minor;
47462306a36Sopenharmony_ci	ver->firmware_revision = rev_info->firmware_revision;
47562306a36Sopenharmony_ci	strncpy(ver->firmware_description, rev_info->firmware_description,
47662306a36Sopenharmony_ci		sizeof(ver->firmware_description));
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_cifail:
47962306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
48062306a36Sopenharmony_ci	return ret;
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci/**
48462306a36Sopenharmony_ci * ti_sci_is_response_ack() - Generic ACK/NACK message checkup
48562306a36Sopenharmony_ci * @r:	pointer to response buffer
48662306a36Sopenharmony_ci *
48762306a36Sopenharmony_ci * Return: true if the response was an ACK, else returns false.
48862306a36Sopenharmony_ci */
48962306a36Sopenharmony_cistatic inline bool ti_sci_is_response_ack(void *r)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	struct ti_sci_msg_hdr *hdr = r;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci/**
49762306a36Sopenharmony_ci * ti_sci_set_device_state() - Set device state helper
49862306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
49962306a36Sopenharmony_ci * @id:		Device identifier
50062306a36Sopenharmony_ci * @flags:	flags to setup for the device
50162306a36Sopenharmony_ci * @state:	State to move the device to
50262306a36Sopenharmony_ci *
50362306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
50462306a36Sopenharmony_ci */
50562306a36Sopenharmony_cistatic int ti_sci_set_device_state(const struct ti_sci_handle *handle,
50662306a36Sopenharmony_ci				   u32 id, u32 flags, u8 state)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	struct ti_sci_info *info;
50962306a36Sopenharmony_ci	struct ti_sci_msg_req_set_device_state *req;
51062306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
51162306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
51262306a36Sopenharmony_ci	struct device *dev;
51362306a36Sopenharmony_ci	int ret = 0;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	if (IS_ERR(handle))
51662306a36Sopenharmony_ci		return PTR_ERR(handle);
51762306a36Sopenharmony_ci	if (!handle)
51862306a36Sopenharmony_ci		return -EINVAL;
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
52162306a36Sopenharmony_ci	dev = info->dev;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
52462306a36Sopenharmony_ci				   flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
52562306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
52662306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
52762306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
52862306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
52962306a36Sopenharmony_ci		return ret;
53062306a36Sopenharmony_ci	}
53162306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_set_device_state *)xfer->xfer_buf;
53262306a36Sopenharmony_ci	req->id = id;
53362306a36Sopenharmony_ci	req->state = state;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
53662306a36Sopenharmony_ci	if (ret) {
53762306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
53862306a36Sopenharmony_ci		goto fail;
53962306a36Sopenharmony_ci	}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_cifail:
54662306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	return ret;
54962306a36Sopenharmony_ci}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci/**
55262306a36Sopenharmony_ci * ti_sci_get_device_state() - Get device state helper
55362306a36Sopenharmony_ci * @handle:	Handle to the device
55462306a36Sopenharmony_ci * @id:		Device Identifier
55562306a36Sopenharmony_ci * @clcnt:	Pointer to Context Loss Count
55662306a36Sopenharmony_ci * @resets:	pointer to resets
55762306a36Sopenharmony_ci * @p_state:	pointer to p_state
55862306a36Sopenharmony_ci * @c_state:	pointer to c_state
55962306a36Sopenharmony_ci *
56062306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
56162306a36Sopenharmony_ci */
56262306a36Sopenharmony_cistatic int ti_sci_get_device_state(const struct ti_sci_handle *handle,
56362306a36Sopenharmony_ci				   u32 id,  u32 *clcnt,  u32 *resets,
56462306a36Sopenharmony_ci				    u8 *p_state,  u8 *c_state)
56562306a36Sopenharmony_ci{
56662306a36Sopenharmony_ci	struct ti_sci_info *info;
56762306a36Sopenharmony_ci	struct ti_sci_msg_req_get_device_state *req;
56862306a36Sopenharmony_ci	struct ti_sci_msg_resp_get_device_state *resp;
56962306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
57062306a36Sopenharmony_ci	struct device *dev;
57162306a36Sopenharmony_ci	int ret = 0;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	if (IS_ERR(handle))
57462306a36Sopenharmony_ci		return PTR_ERR(handle);
57562306a36Sopenharmony_ci	if (!handle)
57662306a36Sopenharmony_ci		return -EINVAL;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	if (!clcnt && !resets && !p_state && !c_state)
57962306a36Sopenharmony_ci		return -EINVAL;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
58262306a36Sopenharmony_ci	dev = info->dev;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE,
58562306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
58662306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
58762306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
58862306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
58962306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
59062306a36Sopenharmony_ci		return ret;
59162306a36Sopenharmony_ci	}
59262306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_get_device_state *)xfer->xfer_buf;
59362306a36Sopenharmony_ci	req->id = id;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
59662306a36Sopenharmony_ci	if (ret) {
59762306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
59862306a36Sopenharmony_ci		goto fail;
59962306a36Sopenharmony_ci	}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	resp = (struct ti_sci_msg_resp_get_device_state *)xfer->xfer_buf;
60262306a36Sopenharmony_ci	if (!ti_sci_is_response_ack(resp)) {
60362306a36Sopenharmony_ci		ret = -ENODEV;
60462306a36Sopenharmony_ci		goto fail;
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	if (clcnt)
60862306a36Sopenharmony_ci		*clcnt = resp->context_loss_count;
60962306a36Sopenharmony_ci	if (resets)
61062306a36Sopenharmony_ci		*resets = resp->resets;
61162306a36Sopenharmony_ci	if (p_state)
61262306a36Sopenharmony_ci		*p_state = resp->programmed_state;
61362306a36Sopenharmony_ci	if (c_state)
61462306a36Sopenharmony_ci		*c_state = resp->current_state;
61562306a36Sopenharmony_cifail:
61662306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	return ret;
61962306a36Sopenharmony_ci}
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci/**
62262306a36Sopenharmony_ci * ti_sci_cmd_get_device() - command to request for device managed by TISCI
62362306a36Sopenharmony_ci *			     that can be shared with other hosts.
62462306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
62562306a36Sopenharmony_ci * @id:		Device Identifier
62662306a36Sopenharmony_ci *
62762306a36Sopenharmony_ci * Request for the device - NOTE: the client MUST maintain integrity of
62862306a36Sopenharmony_ci * usage count by balancing get_device with put_device. No refcounting is
62962306a36Sopenharmony_ci * managed by driver for that purpose.
63062306a36Sopenharmony_ci *
63162306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
63262306a36Sopenharmony_ci */
63362306a36Sopenharmony_cistatic int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
63462306a36Sopenharmony_ci{
63562306a36Sopenharmony_ci	return ti_sci_set_device_state(handle, id, 0,
63662306a36Sopenharmony_ci				       MSG_DEVICE_SW_STATE_ON);
63762306a36Sopenharmony_ci}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci/**
64062306a36Sopenharmony_ci * ti_sci_cmd_get_device_exclusive() - command to request for device managed by
64162306a36Sopenharmony_ci *				       TISCI that is exclusively owned by the
64262306a36Sopenharmony_ci *				       requesting host.
64362306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
64462306a36Sopenharmony_ci * @id:		Device Identifier
64562306a36Sopenharmony_ci *
64662306a36Sopenharmony_ci * Request for the device - NOTE: the client MUST maintain integrity of
64762306a36Sopenharmony_ci * usage count by balancing get_device with put_device. No refcounting is
64862306a36Sopenharmony_ci * managed by driver for that purpose.
64962306a36Sopenharmony_ci *
65062306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
65162306a36Sopenharmony_ci */
65262306a36Sopenharmony_cistatic int ti_sci_cmd_get_device_exclusive(const struct ti_sci_handle *handle,
65362306a36Sopenharmony_ci					   u32 id)
65462306a36Sopenharmony_ci{
65562306a36Sopenharmony_ci	return ti_sci_set_device_state(handle, id,
65662306a36Sopenharmony_ci				       MSG_FLAG_DEVICE_EXCLUSIVE,
65762306a36Sopenharmony_ci				       MSG_DEVICE_SW_STATE_ON);
65862306a36Sopenharmony_ci}
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci/**
66162306a36Sopenharmony_ci * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI
66262306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
66362306a36Sopenharmony_ci * @id:		Device Identifier
66462306a36Sopenharmony_ci *
66562306a36Sopenharmony_ci * Request for the device - NOTE: the client MUST maintain integrity of
66662306a36Sopenharmony_ci * usage count by balancing get_device with put_device. No refcounting is
66762306a36Sopenharmony_ci * managed by driver for that purpose.
66862306a36Sopenharmony_ci *
66962306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
67062306a36Sopenharmony_ci */
67162306a36Sopenharmony_cistatic int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
67262306a36Sopenharmony_ci{
67362306a36Sopenharmony_ci	return ti_sci_set_device_state(handle, id, 0,
67462306a36Sopenharmony_ci				       MSG_DEVICE_SW_STATE_RETENTION);
67562306a36Sopenharmony_ci}
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci/**
67862306a36Sopenharmony_ci * ti_sci_cmd_idle_device_exclusive() - Command to idle a device managed by
67962306a36Sopenharmony_ci *					TISCI that is exclusively owned by
68062306a36Sopenharmony_ci *					requesting host.
68162306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
68262306a36Sopenharmony_ci * @id:		Device Identifier
68362306a36Sopenharmony_ci *
68462306a36Sopenharmony_ci * Request for the device - NOTE: the client MUST maintain integrity of
68562306a36Sopenharmony_ci * usage count by balancing get_device with put_device. No refcounting is
68662306a36Sopenharmony_ci * managed by driver for that purpose.
68762306a36Sopenharmony_ci *
68862306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
68962306a36Sopenharmony_ci */
69062306a36Sopenharmony_cistatic int ti_sci_cmd_idle_device_exclusive(const struct ti_sci_handle *handle,
69162306a36Sopenharmony_ci					    u32 id)
69262306a36Sopenharmony_ci{
69362306a36Sopenharmony_ci	return ti_sci_set_device_state(handle, id,
69462306a36Sopenharmony_ci				       MSG_FLAG_DEVICE_EXCLUSIVE,
69562306a36Sopenharmony_ci				       MSG_DEVICE_SW_STATE_RETENTION);
69662306a36Sopenharmony_ci}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci/**
69962306a36Sopenharmony_ci * ti_sci_cmd_put_device() - command to release a device managed by TISCI
70062306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
70162306a36Sopenharmony_ci * @id:		Device Identifier
70262306a36Sopenharmony_ci *
70362306a36Sopenharmony_ci * Request for the device - NOTE: the client MUST maintain integrity of
70462306a36Sopenharmony_ci * usage count by balancing get_device with put_device. No refcounting is
70562306a36Sopenharmony_ci * managed by driver for that purpose.
70662306a36Sopenharmony_ci *
70762306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
70862306a36Sopenharmony_ci */
70962306a36Sopenharmony_cistatic int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id)
71062306a36Sopenharmony_ci{
71162306a36Sopenharmony_ci	return ti_sci_set_device_state(handle, id,
71262306a36Sopenharmony_ci				       0, MSG_DEVICE_SW_STATE_AUTO_OFF);
71362306a36Sopenharmony_ci}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci/**
71662306a36Sopenharmony_ci * ti_sci_cmd_dev_is_valid() - Is the device valid
71762306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
71862306a36Sopenharmony_ci * @id:		Device Identifier
71962306a36Sopenharmony_ci *
72062306a36Sopenharmony_ci * Return: 0 if all went fine and the device ID is valid, else return
72162306a36Sopenharmony_ci * appropriate error.
72262306a36Sopenharmony_ci */
72362306a36Sopenharmony_cistatic int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id)
72462306a36Sopenharmony_ci{
72562306a36Sopenharmony_ci	u8 unused;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	/* check the device state which will also tell us if the ID is valid */
72862306a36Sopenharmony_ci	return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused);
72962306a36Sopenharmony_ci}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci/**
73262306a36Sopenharmony_ci * ti_sci_cmd_dev_get_clcnt() - Get context loss counter
73362306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle
73462306a36Sopenharmony_ci * @id:		Device Identifier
73562306a36Sopenharmony_ci * @count:	Pointer to Context Loss counter to populate
73662306a36Sopenharmony_ci *
73762306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
73862306a36Sopenharmony_ci */
73962306a36Sopenharmony_cistatic int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id,
74062306a36Sopenharmony_ci				    u32 *count)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL);
74362306a36Sopenharmony_ci}
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci/**
74662306a36Sopenharmony_ci * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle
74762306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle
74862306a36Sopenharmony_ci * @id:		Device Identifier
74962306a36Sopenharmony_ci * @r_state:	true if requested to be idle
75062306a36Sopenharmony_ci *
75162306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
75262306a36Sopenharmony_ci */
75362306a36Sopenharmony_cistatic int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id,
75462306a36Sopenharmony_ci				  bool *r_state)
75562306a36Sopenharmony_ci{
75662306a36Sopenharmony_ci	int ret;
75762306a36Sopenharmony_ci	u8 state;
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	if (!r_state)
76062306a36Sopenharmony_ci		return -EINVAL;
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL);
76362306a36Sopenharmony_ci	if (ret)
76462306a36Sopenharmony_ci		return ret;
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	*r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	return 0;
76962306a36Sopenharmony_ci}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci/**
77262306a36Sopenharmony_ci * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped
77362306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle
77462306a36Sopenharmony_ci * @id:		Device Identifier
77562306a36Sopenharmony_ci * @r_state:	true if requested to be stopped
77662306a36Sopenharmony_ci * @curr_state:	true if currently stopped.
77762306a36Sopenharmony_ci *
77862306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
77962306a36Sopenharmony_ci */
78062306a36Sopenharmony_cistatic int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id,
78162306a36Sopenharmony_ci				  bool *r_state,  bool *curr_state)
78262306a36Sopenharmony_ci{
78362306a36Sopenharmony_ci	int ret;
78462306a36Sopenharmony_ci	u8 p_state, c_state;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	if (!r_state && !curr_state)
78762306a36Sopenharmony_ci		return -EINVAL;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	ret =
79062306a36Sopenharmony_ci	    ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
79162306a36Sopenharmony_ci	if (ret)
79262306a36Sopenharmony_ci		return ret;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	if (r_state)
79562306a36Sopenharmony_ci		*r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
79662306a36Sopenharmony_ci	if (curr_state)
79762306a36Sopenharmony_ci		*curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	return 0;
80062306a36Sopenharmony_ci}
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci/**
80362306a36Sopenharmony_ci * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON
80462306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle
80562306a36Sopenharmony_ci * @id:		Device Identifier
80662306a36Sopenharmony_ci * @r_state:	true if requested to be ON
80762306a36Sopenharmony_ci * @curr_state:	true if currently ON and active
80862306a36Sopenharmony_ci *
80962306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
81062306a36Sopenharmony_ci */
81162306a36Sopenharmony_cistatic int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id,
81262306a36Sopenharmony_ci				bool *r_state,  bool *curr_state)
81362306a36Sopenharmony_ci{
81462306a36Sopenharmony_ci	int ret;
81562306a36Sopenharmony_ci	u8 p_state, c_state;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	if (!r_state && !curr_state)
81862306a36Sopenharmony_ci		return -EINVAL;
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	ret =
82162306a36Sopenharmony_ci	    ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
82262306a36Sopenharmony_ci	if (ret)
82362306a36Sopenharmony_ci		return ret;
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	if (r_state)
82662306a36Sopenharmony_ci		*r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
82762306a36Sopenharmony_ci	if (curr_state)
82862306a36Sopenharmony_ci		*curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	return 0;
83162306a36Sopenharmony_ci}
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci/**
83462306a36Sopenharmony_ci * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning
83562306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle
83662306a36Sopenharmony_ci * @id:		Device Identifier
83762306a36Sopenharmony_ci * @curr_state:	true if currently transitioning.
83862306a36Sopenharmony_ci *
83962306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
84062306a36Sopenharmony_ci */
84162306a36Sopenharmony_cistatic int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id,
84262306a36Sopenharmony_ci				   bool *curr_state)
84362306a36Sopenharmony_ci{
84462306a36Sopenharmony_ci	int ret;
84562306a36Sopenharmony_ci	u8 state;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	if (!curr_state)
84862306a36Sopenharmony_ci		return -EINVAL;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state);
85162306a36Sopenharmony_ci	if (ret)
85262306a36Sopenharmony_ci		return ret;
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	*curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	return 0;
85762306a36Sopenharmony_ci}
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci/**
86062306a36Sopenharmony_ci * ti_sci_cmd_set_device_resets() - command to set resets for device managed
86162306a36Sopenharmony_ci *				    by TISCI
86262306a36Sopenharmony_ci * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
86362306a36Sopenharmony_ci * @id:		Device Identifier
86462306a36Sopenharmony_ci * @reset_state: Device specific reset bit field
86562306a36Sopenharmony_ci *
86662306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
86762306a36Sopenharmony_ci */
86862306a36Sopenharmony_cistatic int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle,
86962306a36Sopenharmony_ci					u32 id, u32 reset_state)
87062306a36Sopenharmony_ci{
87162306a36Sopenharmony_ci	struct ti_sci_info *info;
87262306a36Sopenharmony_ci	struct ti_sci_msg_req_set_device_resets *req;
87362306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
87462306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
87562306a36Sopenharmony_ci	struct device *dev;
87662306a36Sopenharmony_ci	int ret = 0;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	if (IS_ERR(handle))
87962306a36Sopenharmony_ci		return PTR_ERR(handle);
88062306a36Sopenharmony_ci	if (!handle)
88162306a36Sopenharmony_ci		return -EINVAL;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
88462306a36Sopenharmony_ci	dev = info->dev;
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS,
88762306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
88862306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
88962306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
89062306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
89162306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
89262306a36Sopenharmony_ci		return ret;
89362306a36Sopenharmony_ci	}
89462306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_set_device_resets *)xfer->xfer_buf;
89562306a36Sopenharmony_ci	req->id = id;
89662306a36Sopenharmony_ci	req->resets = reset_state;
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
89962306a36Sopenharmony_ci	if (ret) {
90062306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
90162306a36Sopenharmony_ci		goto fail;
90262306a36Sopenharmony_ci	}
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_cifail:
90962306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	return ret;
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci/**
91562306a36Sopenharmony_ci * ti_sci_cmd_get_device_resets() - Get reset state for device managed
91662306a36Sopenharmony_ci *				    by TISCI
91762306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle
91862306a36Sopenharmony_ci * @id:			Device Identifier
91962306a36Sopenharmony_ci * @reset_state:	Pointer to reset state to populate
92062306a36Sopenharmony_ci *
92162306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
92262306a36Sopenharmony_ci */
92362306a36Sopenharmony_cistatic int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle,
92462306a36Sopenharmony_ci					u32 id, u32 *reset_state)
92562306a36Sopenharmony_ci{
92662306a36Sopenharmony_ci	return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL,
92762306a36Sopenharmony_ci				       NULL);
92862306a36Sopenharmony_ci}
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci/**
93162306a36Sopenharmony_ci * ti_sci_set_clock_state() - Set clock state helper
93262306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
93362306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
93462306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
93562306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
93662306a36Sopenharmony_ci *		which clock input to modify.
93762306a36Sopenharmony_ci * @flags:	Header flags as needed
93862306a36Sopenharmony_ci * @state:	State to request for the clock.
93962306a36Sopenharmony_ci *
94062306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
94162306a36Sopenharmony_ci */
94262306a36Sopenharmony_cistatic int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
94362306a36Sopenharmony_ci				  u32 dev_id, u32 clk_id,
94462306a36Sopenharmony_ci				  u32 flags, u8 state)
94562306a36Sopenharmony_ci{
94662306a36Sopenharmony_ci	struct ti_sci_info *info;
94762306a36Sopenharmony_ci	struct ti_sci_msg_req_set_clock_state *req;
94862306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
94962306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
95062306a36Sopenharmony_ci	struct device *dev;
95162306a36Sopenharmony_ci	int ret = 0;
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	if (IS_ERR(handle))
95462306a36Sopenharmony_ci		return PTR_ERR(handle);
95562306a36Sopenharmony_ci	if (!handle)
95662306a36Sopenharmony_ci		return -EINVAL;
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
95962306a36Sopenharmony_ci	dev = info->dev;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
96262306a36Sopenharmony_ci				   flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
96362306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
96462306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
96562306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
96662306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
96762306a36Sopenharmony_ci		return ret;
96862306a36Sopenharmony_ci	}
96962306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_set_clock_state *)xfer->xfer_buf;
97062306a36Sopenharmony_ci	req->dev_id = dev_id;
97162306a36Sopenharmony_ci	if (clk_id < 255) {
97262306a36Sopenharmony_ci		req->clk_id = clk_id;
97362306a36Sopenharmony_ci	} else {
97462306a36Sopenharmony_ci		req->clk_id = 255;
97562306a36Sopenharmony_ci		req->clk_id_32 = clk_id;
97662306a36Sopenharmony_ci	}
97762306a36Sopenharmony_ci	req->request_state = state;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
98062306a36Sopenharmony_ci	if (ret) {
98162306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
98262306a36Sopenharmony_ci		goto fail;
98362306a36Sopenharmony_ci	}
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_cifail:
99062306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	return ret;
99362306a36Sopenharmony_ci}
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci/**
99662306a36Sopenharmony_ci * ti_sci_cmd_get_clock_state() - Get clock state helper
99762306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
99862306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
99962306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
100062306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
100162306a36Sopenharmony_ci *		which clock input to modify.
100262306a36Sopenharmony_ci * @programmed_state:	State requested for clock to move to
100362306a36Sopenharmony_ci * @current_state:	State that the clock is currently in
100462306a36Sopenharmony_ci *
100562306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
100662306a36Sopenharmony_ci */
100762306a36Sopenharmony_cistatic int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
100862306a36Sopenharmony_ci				      u32 dev_id, u32 clk_id,
100962306a36Sopenharmony_ci				      u8 *programmed_state, u8 *current_state)
101062306a36Sopenharmony_ci{
101162306a36Sopenharmony_ci	struct ti_sci_info *info;
101262306a36Sopenharmony_ci	struct ti_sci_msg_req_get_clock_state *req;
101362306a36Sopenharmony_ci	struct ti_sci_msg_resp_get_clock_state *resp;
101462306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
101562306a36Sopenharmony_ci	struct device *dev;
101662306a36Sopenharmony_ci	int ret = 0;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	if (IS_ERR(handle))
101962306a36Sopenharmony_ci		return PTR_ERR(handle);
102062306a36Sopenharmony_ci	if (!handle)
102162306a36Sopenharmony_ci		return -EINVAL;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	if (!programmed_state && !current_state)
102462306a36Sopenharmony_ci		return -EINVAL;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
102762306a36Sopenharmony_ci	dev = info->dev;
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
103062306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
103162306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
103262306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
103362306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
103462306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
103562306a36Sopenharmony_ci		return ret;
103662306a36Sopenharmony_ci	}
103762306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_get_clock_state *)xfer->xfer_buf;
103862306a36Sopenharmony_ci	req->dev_id = dev_id;
103962306a36Sopenharmony_ci	if (clk_id < 255) {
104062306a36Sopenharmony_ci		req->clk_id = clk_id;
104162306a36Sopenharmony_ci	} else {
104262306a36Sopenharmony_ci		req->clk_id = 255;
104362306a36Sopenharmony_ci		req->clk_id_32 = clk_id;
104462306a36Sopenharmony_ci	}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
104762306a36Sopenharmony_ci	if (ret) {
104862306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
104962306a36Sopenharmony_ci		goto fail;
105062306a36Sopenharmony_ci	}
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->xfer_buf;
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	if (!ti_sci_is_response_ack(resp)) {
105562306a36Sopenharmony_ci		ret = -ENODEV;
105662306a36Sopenharmony_ci		goto fail;
105762306a36Sopenharmony_ci	}
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	if (programmed_state)
106062306a36Sopenharmony_ci		*programmed_state = resp->programmed_state;
106162306a36Sopenharmony_ci	if (current_state)
106262306a36Sopenharmony_ci		*current_state = resp->current_state;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_cifail:
106562306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	return ret;
106862306a36Sopenharmony_ci}
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci/**
107162306a36Sopenharmony_ci * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
107262306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
107362306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
107462306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
107562306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
107662306a36Sopenharmony_ci *		which clock input to modify.
107762306a36Sopenharmony_ci * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
107862306a36Sopenharmony_ci * @can_change_freq: 'true' if frequency change is desired, else 'false'
107962306a36Sopenharmony_ci * @enable_input_term: 'true' if input termination is desired, else 'false'
108062306a36Sopenharmony_ci *
108162306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
108262306a36Sopenharmony_ci */
108362306a36Sopenharmony_cistatic int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
108462306a36Sopenharmony_ci				u32 clk_id, bool needs_ssc,
108562306a36Sopenharmony_ci				bool can_change_freq, bool enable_input_term)
108662306a36Sopenharmony_ci{
108762306a36Sopenharmony_ci	u32 flags = 0;
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
109062306a36Sopenharmony_ci	flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
109162306a36Sopenharmony_ci	flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
109462306a36Sopenharmony_ci				      MSG_CLOCK_SW_STATE_REQ);
109562306a36Sopenharmony_ci}
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci/**
109862306a36Sopenharmony_ci * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
109962306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
110062306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
110162306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
110262306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
110362306a36Sopenharmony_ci *		which clock input to modify.
110462306a36Sopenharmony_ci *
110562306a36Sopenharmony_ci * NOTE: This clock must have been requested by get_clock previously.
110662306a36Sopenharmony_ci *
110762306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
110862306a36Sopenharmony_ci */
110962306a36Sopenharmony_cistatic int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
111062306a36Sopenharmony_ci				 u32 dev_id, u32 clk_id)
111162306a36Sopenharmony_ci{
111262306a36Sopenharmony_ci	return ti_sci_set_clock_state(handle, dev_id, clk_id,
111362306a36Sopenharmony_ci				      MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE,
111462306a36Sopenharmony_ci				      MSG_CLOCK_SW_STATE_UNREQ);
111562306a36Sopenharmony_ci}
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci/**
111862306a36Sopenharmony_ci * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
111962306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
112062306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
112162306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
112262306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
112362306a36Sopenharmony_ci *		which clock input to modify.
112462306a36Sopenharmony_ci *
112562306a36Sopenharmony_ci * NOTE: This clock must have been requested by get_clock previously.
112662306a36Sopenharmony_ci *
112762306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
112862306a36Sopenharmony_ci */
112962306a36Sopenharmony_cistatic int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
113062306a36Sopenharmony_ci				u32 dev_id, u32 clk_id)
113162306a36Sopenharmony_ci{
113262306a36Sopenharmony_ci	return ti_sci_set_clock_state(handle, dev_id, clk_id,
113362306a36Sopenharmony_ci				      MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE,
113462306a36Sopenharmony_ci				      MSG_CLOCK_SW_STATE_AUTO);
113562306a36Sopenharmony_ci}
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci/**
113862306a36Sopenharmony_ci * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
113962306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
114062306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
114162306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
114262306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
114362306a36Sopenharmony_ci *		which clock input to modify.
114462306a36Sopenharmony_ci * @req_state: state indicating if the clock is auto managed
114562306a36Sopenharmony_ci *
114662306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
114762306a36Sopenharmony_ci */
114862306a36Sopenharmony_cistatic int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
114962306a36Sopenharmony_ci				  u32 dev_id, u32 clk_id, bool *req_state)
115062306a36Sopenharmony_ci{
115162306a36Sopenharmony_ci	u8 state = 0;
115262306a36Sopenharmony_ci	int ret;
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	if (!req_state)
115562306a36Sopenharmony_ci		return -EINVAL;
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
115862306a36Sopenharmony_ci	if (ret)
115962306a36Sopenharmony_ci		return ret;
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	*req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
116262306a36Sopenharmony_ci	return 0;
116362306a36Sopenharmony_ci}
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci/**
116662306a36Sopenharmony_ci * ti_sci_cmd_clk_is_on() - Is the clock ON
116762306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
116862306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
116962306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
117062306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
117162306a36Sopenharmony_ci *		which clock input to modify.
117262306a36Sopenharmony_ci * @req_state: state indicating if the clock is managed by us and enabled
117362306a36Sopenharmony_ci * @curr_state: state indicating if the clock is ready for operation
117462306a36Sopenharmony_ci *
117562306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
117662306a36Sopenharmony_ci */
117762306a36Sopenharmony_cistatic int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
117862306a36Sopenharmony_ci				u32 clk_id, bool *req_state, bool *curr_state)
117962306a36Sopenharmony_ci{
118062306a36Sopenharmony_ci	u8 c_state = 0, r_state = 0;
118162306a36Sopenharmony_ci	int ret;
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	if (!req_state && !curr_state)
118462306a36Sopenharmony_ci		return -EINVAL;
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
118762306a36Sopenharmony_ci					 &r_state, &c_state);
118862306a36Sopenharmony_ci	if (ret)
118962306a36Sopenharmony_ci		return ret;
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	if (req_state)
119262306a36Sopenharmony_ci		*req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
119362306a36Sopenharmony_ci	if (curr_state)
119462306a36Sopenharmony_ci		*curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
119562306a36Sopenharmony_ci	return 0;
119662306a36Sopenharmony_ci}
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci/**
119962306a36Sopenharmony_ci * ti_sci_cmd_clk_is_off() - Is the clock OFF
120062306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
120162306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
120262306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
120362306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
120462306a36Sopenharmony_ci *		which clock input to modify.
120562306a36Sopenharmony_ci * @req_state: state indicating if the clock is managed by us and disabled
120662306a36Sopenharmony_ci * @curr_state: state indicating if the clock is NOT ready for operation
120762306a36Sopenharmony_ci *
120862306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
120962306a36Sopenharmony_ci */
121062306a36Sopenharmony_cistatic int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
121162306a36Sopenharmony_ci				 u32 clk_id, bool *req_state, bool *curr_state)
121262306a36Sopenharmony_ci{
121362306a36Sopenharmony_ci	u8 c_state = 0, r_state = 0;
121462306a36Sopenharmony_ci	int ret;
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	if (!req_state && !curr_state)
121762306a36Sopenharmony_ci		return -EINVAL;
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
122062306a36Sopenharmony_ci					 &r_state, &c_state);
122162306a36Sopenharmony_ci	if (ret)
122262306a36Sopenharmony_ci		return ret;
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	if (req_state)
122562306a36Sopenharmony_ci		*req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
122662306a36Sopenharmony_ci	if (curr_state)
122762306a36Sopenharmony_ci		*curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
122862306a36Sopenharmony_ci	return 0;
122962306a36Sopenharmony_ci}
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci/**
123262306a36Sopenharmony_ci * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
123362306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
123462306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
123562306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
123662306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
123762306a36Sopenharmony_ci *		which clock input to modify.
123862306a36Sopenharmony_ci * @parent_id:	Parent clock identifier to set
123962306a36Sopenharmony_ci *
124062306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
124162306a36Sopenharmony_ci */
124262306a36Sopenharmony_cistatic int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
124362306a36Sopenharmony_ci				     u32 dev_id, u32 clk_id, u32 parent_id)
124462306a36Sopenharmony_ci{
124562306a36Sopenharmony_ci	struct ti_sci_info *info;
124662306a36Sopenharmony_ci	struct ti_sci_msg_req_set_clock_parent *req;
124762306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
124862306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
124962306a36Sopenharmony_ci	struct device *dev;
125062306a36Sopenharmony_ci	int ret = 0;
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	if (IS_ERR(handle))
125362306a36Sopenharmony_ci		return PTR_ERR(handle);
125462306a36Sopenharmony_ci	if (!handle)
125562306a36Sopenharmony_ci		return -EINVAL;
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
125862306a36Sopenharmony_ci	dev = info->dev;
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
126162306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
126262306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
126362306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
126462306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
126562306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
126662306a36Sopenharmony_ci		return ret;
126762306a36Sopenharmony_ci	}
126862306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_set_clock_parent *)xfer->xfer_buf;
126962306a36Sopenharmony_ci	req->dev_id = dev_id;
127062306a36Sopenharmony_ci	if (clk_id < 255) {
127162306a36Sopenharmony_ci		req->clk_id = clk_id;
127262306a36Sopenharmony_ci	} else {
127362306a36Sopenharmony_ci		req->clk_id = 255;
127462306a36Sopenharmony_ci		req->clk_id_32 = clk_id;
127562306a36Sopenharmony_ci	}
127662306a36Sopenharmony_ci	if (parent_id < 255) {
127762306a36Sopenharmony_ci		req->parent_id = parent_id;
127862306a36Sopenharmony_ci	} else {
127962306a36Sopenharmony_ci		req->parent_id = 255;
128062306a36Sopenharmony_ci		req->parent_id_32 = parent_id;
128162306a36Sopenharmony_ci	}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
128462306a36Sopenharmony_ci	if (ret) {
128562306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
128662306a36Sopenharmony_ci		goto fail;
128762306a36Sopenharmony_ci	}
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_cifail:
129462306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	return ret;
129762306a36Sopenharmony_ci}
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci/**
130062306a36Sopenharmony_ci * ti_sci_cmd_clk_get_parent() - Get current parent clock source
130162306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
130262306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
130362306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
130462306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
130562306a36Sopenharmony_ci *		which clock input to modify.
130662306a36Sopenharmony_ci * @parent_id:	Current clock parent
130762306a36Sopenharmony_ci *
130862306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
130962306a36Sopenharmony_ci */
131062306a36Sopenharmony_cistatic int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
131162306a36Sopenharmony_ci				     u32 dev_id, u32 clk_id, u32 *parent_id)
131262306a36Sopenharmony_ci{
131362306a36Sopenharmony_ci	struct ti_sci_info *info;
131462306a36Sopenharmony_ci	struct ti_sci_msg_req_get_clock_parent *req;
131562306a36Sopenharmony_ci	struct ti_sci_msg_resp_get_clock_parent *resp;
131662306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
131762306a36Sopenharmony_ci	struct device *dev;
131862306a36Sopenharmony_ci	int ret = 0;
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	if (IS_ERR(handle))
132162306a36Sopenharmony_ci		return PTR_ERR(handle);
132262306a36Sopenharmony_ci	if (!handle || !parent_id)
132362306a36Sopenharmony_ci		return -EINVAL;
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
132662306a36Sopenharmony_ci	dev = info->dev;
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
132962306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
133062306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
133162306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
133262306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
133362306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
133462306a36Sopenharmony_ci		return ret;
133562306a36Sopenharmony_ci	}
133662306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_get_clock_parent *)xfer->xfer_buf;
133762306a36Sopenharmony_ci	req->dev_id = dev_id;
133862306a36Sopenharmony_ci	if (clk_id < 255) {
133962306a36Sopenharmony_ci		req->clk_id = clk_id;
134062306a36Sopenharmony_ci	} else {
134162306a36Sopenharmony_ci		req->clk_id = 255;
134262306a36Sopenharmony_ci		req->clk_id_32 = clk_id;
134362306a36Sopenharmony_ci	}
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
134662306a36Sopenharmony_ci	if (ret) {
134762306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
134862306a36Sopenharmony_ci		goto fail;
134962306a36Sopenharmony_ci	}
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->xfer_buf;
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	if (!ti_sci_is_response_ack(resp)) {
135462306a36Sopenharmony_ci		ret = -ENODEV;
135562306a36Sopenharmony_ci	} else {
135662306a36Sopenharmony_ci		if (resp->parent_id < 255)
135762306a36Sopenharmony_ci			*parent_id = resp->parent_id;
135862306a36Sopenharmony_ci		else
135962306a36Sopenharmony_ci			*parent_id = resp->parent_id_32;
136062306a36Sopenharmony_ci	}
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_cifail:
136362306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	return ret;
136662306a36Sopenharmony_ci}
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci/**
136962306a36Sopenharmony_ci * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source
137062306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
137162306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
137262306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
137362306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
137462306a36Sopenharmony_ci *		which clock input to modify.
137562306a36Sopenharmony_ci * @num_parents: Returns he number of parents to the current clock.
137662306a36Sopenharmony_ci *
137762306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
137862306a36Sopenharmony_ci */
137962306a36Sopenharmony_cistatic int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
138062306a36Sopenharmony_ci					  u32 dev_id, u32 clk_id,
138162306a36Sopenharmony_ci					  u32 *num_parents)
138262306a36Sopenharmony_ci{
138362306a36Sopenharmony_ci	struct ti_sci_info *info;
138462306a36Sopenharmony_ci	struct ti_sci_msg_req_get_clock_num_parents *req;
138562306a36Sopenharmony_ci	struct ti_sci_msg_resp_get_clock_num_parents *resp;
138662306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
138762306a36Sopenharmony_ci	struct device *dev;
138862306a36Sopenharmony_ci	int ret = 0;
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	if (IS_ERR(handle))
139162306a36Sopenharmony_ci		return PTR_ERR(handle);
139262306a36Sopenharmony_ci	if (!handle || !num_parents)
139362306a36Sopenharmony_ci		return -EINVAL;
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
139662306a36Sopenharmony_ci	dev = info->dev;
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
139962306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
140062306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
140162306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
140262306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
140362306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
140462306a36Sopenharmony_ci		return ret;
140562306a36Sopenharmony_ci	}
140662306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_get_clock_num_parents *)xfer->xfer_buf;
140762306a36Sopenharmony_ci	req->dev_id = dev_id;
140862306a36Sopenharmony_ci	if (clk_id < 255) {
140962306a36Sopenharmony_ci		req->clk_id = clk_id;
141062306a36Sopenharmony_ci	} else {
141162306a36Sopenharmony_ci		req->clk_id = 255;
141262306a36Sopenharmony_ci		req->clk_id_32 = clk_id;
141362306a36Sopenharmony_ci	}
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
141662306a36Sopenharmony_ci	if (ret) {
141762306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
141862306a36Sopenharmony_ci		goto fail;
141962306a36Sopenharmony_ci	}
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	resp = (struct ti_sci_msg_resp_get_clock_num_parents *)xfer->xfer_buf;
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	if (!ti_sci_is_response_ack(resp)) {
142462306a36Sopenharmony_ci		ret = -ENODEV;
142562306a36Sopenharmony_ci	} else {
142662306a36Sopenharmony_ci		if (resp->num_parents < 255)
142762306a36Sopenharmony_ci			*num_parents = resp->num_parents;
142862306a36Sopenharmony_ci		else
142962306a36Sopenharmony_ci			*num_parents = resp->num_parents_32;
143062306a36Sopenharmony_ci	}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_cifail:
143362306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ci	return ret;
143662306a36Sopenharmony_ci}
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci/**
143962306a36Sopenharmony_ci * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
144062306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
144162306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
144262306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
144362306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
144462306a36Sopenharmony_ci *		which clock input to modify.
144562306a36Sopenharmony_ci * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
144662306a36Sopenharmony_ci *		allowable programmed frequency and does not account for clock
144762306a36Sopenharmony_ci *		tolerances and jitter.
144862306a36Sopenharmony_ci * @target_freq: The target clock frequency in Hz. A frequency will be
144962306a36Sopenharmony_ci *		processed as close to this target frequency as possible.
145062306a36Sopenharmony_ci * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
145162306a36Sopenharmony_ci *		allowable programmed frequency and does not account for clock
145262306a36Sopenharmony_ci *		tolerances and jitter.
145362306a36Sopenharmony_ci * @match_freq:	Frequency match in Hz response.
145462306a36Sopenharmony_ci *
145562306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
145662306a36Sopenharmony_ci */
145762306a36Sopenharmony_cistatic int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
145862306a36Sopenharmony_ci					 u32 dev_id, u32 clk_id, u64 min_freq,
145962306a36Sopenharmony_ci					 u64 target_freq, u64 max_freq,
146062306a36Sopenharmony_ci					 u64 *match_freq)
146162306a36Sopenharmony_ci{
146262306a36Sopenharmony_ci	struct ti_sci_info *info;
146362306a36Sopenharmony_ci	struct ti_sci_msg_req_query_clock_freq *req;
146462306a36Sopenharmony_ci	struct ti_sci_msg_resp_query_clock_freq *resp;
146562306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
146662306a36Sopenharmony_ci	struct device *dev;
146762306a36Sopenharmony_ci	int ret = 0;
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	if (IS_ERR(handle))
147062306a36Sopenharmony_ci		return PTR_ERR(handle);
147162306a36Sopenharmony_ci	if (!handle || !match_freq)
147262306a36Sopenharmony_ci		return -EINVAL;
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
147562306a36Sopenharmony_ci	dev = info->dev;
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
147862306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
147962306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
148062306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
148162306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
148262306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
148362306a36Sopenharmony_ci		return ret;
148462306a36Sopenharmony_ci	}
148562306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_query_clock_freq *)xfer->xfer_buf;
148662306a36Sopenharmony_ci	req->dev_id = dev_id;
148762306a36Sopenharmony_ci	if (clk_id < 255) {
148862306a36Sopenharmony_ci		req->clk_id = clk_id;
148962306a36Sopenharmony_ci	} else {
149062306a36Sopenharmony_ci		req->clk_id = 255;
149162306a36Sopenharmony_ci		req->clk_id_32 = clk_id;
149262306a36Sopenharmony_ci	}
149362306a36Sopenharmony_ci	req->min_freq_hz = min_freq;
149462306a36Sopenharmony_ci	req->target_freq_hz = target_freq;
149562306a36Sopenharmony_ci	req->max_freq_hz = max_freq;
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
149862306a36Sopenharmony_ci	if (ret) {
149962306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
150062306a36Sopenharmony_ci		goto fail;
150162306a36Sopenharmony_ci	}
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->xfer_buf;
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	if (!ti_sci_is_response_ack(resp))
150662306a36Sopenharmony_ci		ret = -ENODEV;
150762306a36Sopenharmony_ci	else
150862306a36Sopenharmony_ci		*match_freq = resp->freq_hz;
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_cifail:
151162306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	return ret;
151462306a36Sopenharmony_ci}
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci/**
151762306a36Sopenharmony_ci * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
151862306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
151962306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
152062306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
152162306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
152262306a36Sopenharmony_ci *		which clock input to modify.
152362306a36Sopenharmony_ci * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
152462306a36Sopenharmony_ci *		allowable programmed frequency and does not account for clock
152562306a36Sopenharmony_ci *		tolerances and jitter.
152662306a36Sopenharmony_ci * @target_freq: The target clock frequency in Hz. A frequency will be
152762306a36Sopenharmony_ci *		processed as close to this target frequency as possible.
152862306a36Sopenharmony_ci * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
152962306a36Sopenharmony_ci *		allowable programmed frequency and does not account for clock
153062306a36Sopenharmony_ci *		tolerances and jitter.
153162306a36Sopenharmony_ci *
153262306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
153362306a36Sopenharmony_ci */
153462306a36Sopenharmony_cistatic int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
153562306a36Sopenharmony_ci				   u32 dev_id, u32 clk_id, u64 min_freq,
153662306a36Sopenharmony_ci				   u64 target_freq, u64 max_freq)
153762306a36Sopenharmony_ci{
153862306a36Sopenharmony_ci	struct ti_sci_info *info;
153962306a36Sopenharmony_ci	struct ti_sci_msg_req_set_clock_freq *req;
154062306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
154162306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
154262306a36Sopenharmony_ci	struct device *dev;
154362306a36Sopenharmony_ci	int ret = 0;
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci	if (IS_ERR(handle))
154662306a36Sopenharmony_ci		return PTR_ERR(handle);
154762306a36Sopenharmony_ci	if (!handle)
154862306a36Sopenharmony_ci		return -EINVAL;
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
155162306a36Sopenharmony_ci	dev = info->dev;
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
155462306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
155562306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
155662306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
155762306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
155862306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
155962306a36Sopenharmony_ci		return ret;
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_set_clock_freq *)xfer->xfer_buf;
156262306a36Sopenharmony_ci	req->dev_id = dev_id;
156362306a36Sopenharmony_ci	if (clk_id < 255) {
156462306a36Sopenharmony_ci		req->clk_id = clk_id;
156562306a36Sopenharmony_ci	} else {
156662306a36Sopenharmony_ci		req->clk_id = 255;
156762306a36Sopenharmony_ci		req->clk_id_32 = clk_id;
156862306a36Sopenharmony_ci	}
156962306a36Sopenharmony_ci	req->min_freq_hz = min_freq;
157062306a36Sopenharmony_ci	req->target_freq_hz = target_freq;
157162306a36Sopenharmony_ci	req->max_freq_hz = max_freq;
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
157462306a36Sopenharmony_ci	if (ret) {
157562306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
157662306a36Sopenharmony_ci		goto fail;
157762306a36Sopenharmony_ci	}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_cifail:
158462306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci	return ret;
158762306a36Sopenharmony_ci}
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci/**
159062306a36Sopenharmony_ci * ti_sci_cmd_clk_get_freq() - Get current frequency
159162306a36Sopenharmony_ci * @handle:	pointer to TI SCI handle
159262306a36Sopenharmony_ci * @dev_id:	Device identifier this request is for
159362306a36Sopenharmony_ci * @clk_id:	Clock identifier for the device for this request.
159462306a36Sopenharmony_ci *		Each device has it's own set of clock inputs. This indexes
159562306a36Sopenharmony_ci *		which clock input to modify.
159662306a36Sopenharmony_ci * @freq:	Currently frequency in Hz
159762306a36Sopenharmony_ci *
159862306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
159962306a36Sopenharmony_ci */
160062306a36Sopenharmony_cistatic int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
160162306a36Sopenharmony_ci				   u32 dev_id, u32 clk_id, u64 *freq)
160262306a36Sopenharmony_ci{
160362306a36Sopenharmony_ci	struct ti_sci_info *info;
160462306a36Sopenharmony_ci	struct ti_sci_msg_req_get_clock_freq *req;
160562306a36Sopenharmony_ci	struct ti_sci_msg_resp_get_clock_freq *resp;
160662306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
160762306a36Sopenharmony_ci	struct device *dev;
160862306a36Sopenharmony_ci	int ret = 0;
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	if (IS_ERR(handle))
161162306a36Sopenharmony_ci		return PTR_ERR(handle);
161262306a36Sopenharmony_ci	if (!handle || !freq)
161362306a36Sopenharmony_ci		return -EINVAL;
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
161662306a36Sopenharmony_ci	dev = info->dev;
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
161962306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
162062306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
162162306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
162262306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
162362306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
162462306a36Sopenharmony_ci		return ret;
162562306a36Sopenharmony_ci	}
162662306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_get_clock_freq *)xfer->xfer_buf;
162762306a36Sopenharmony_ci	req->dev_id = dev_id;
162862306a36Sopenharmony_ci	if (clk_id < 255) {
162962306a36Sopenharmony_ci		req->clk_id = clk_id;
163062306a36Sopenharmony_ci	} else {
163162306a36Sopenharmony_ci		req->clk_id = 255;
163262306a36Sopenharmony_ci		req->clk_id_32 = clk_id;
163362306a36Sopenharmony_ci	}
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
163662306a36Sopenharmony_ci	if (ret) {
163762306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
163862306a36Sopenharmony_ci		goto fail;
163962306a36Sopenharmony_ci	}
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->xfer_buf;
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	if (!ti_sci_is_response_ack(resp))
164462306a36Sopenharmony_ci		ret = -ENODEV;
164562306a36Sopenharmony_ci	else
164662306a36Sopenharmony_ci		*freq = resp->freq_hz;
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_cifail:
164962306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	return ret;
165262306a36Sopenharmony_ci}
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_cistatic int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
165562306a36Sopenharmony_ci{
165662306a36Sopenharmony_ci	struct ti_sci_info *info;
165762306a36Sopenharmony_ci	struct ti_sci_msg_req_reboot *req;
165862306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
165962306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
166062306a36Sopenharmony_ci	struct device *dev;
166162306a36Sopenharmony_ci	int ret = 0;
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci	if (IS_ERR(handle))
166462306a36Sopenharmony_ci		return PTR_ERR(handle);
166562306a36Sopenharmony_ci	if (!handle)
166662306a36Sopenharmony_ci		return -EINVAL;
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
166962306a36Sopenharmony_ci	dev = info->dev;
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SYS_RESET,
167262306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
167362306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
167462306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
167562306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
167662306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
167762306a36Sopenharmony_ci		return ret;
167862306a36Sopenharmony_ci	}
167962306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_reboot *)xfer->xfer_buf;
168062306a36Sopenharmony_ci
168162306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
168262306a36Sopenharmony_ci	if (ret) {
168362306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
168462306a36Sopenharmony_ci		goto fail;
168562306a36Sopenharmony_ci	}
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	if (!ti_sci_is_response_ack(resp))
169062306a36Sopenharmony_ci		ret = -ENODEV;
169162306a36Sopenharmony_ci	else
169262306a36Sopenharmony_ci		ret = 0;
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_cifail:
169562306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci	return ret;
169862306a36Sopenharmony_ci}
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci/**
170162306a36Sopenharmony_ci * ti_sci_get_resource_range - Helper to get a range of resources assigned
170262306a36Sopenharmony_ci *			       to a host. Resource is uniquely identified by
170362306a36Sopenharmony_ci *			       type and subtype.
170462306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
170562306a36Sopenharmony_ci * @dev_id:		TISCI device ID.
170662306a36Sopenharmony_ci * @subtype:		Resource assignment subtype that is being requested
170762306a36Sopenharmony_ci *			from the given device.
170862306a36Sopenharmony_ci * @s_host:		Host processor ID to which the resources are allocated
170962306a36Sopenharmony_ci * @desc:		Pointer to ti_sci_resource_desc to be updated with the
171062306a36Sopenharmony_ci *			resource range start index and number of resources
171162306a36Sopenharmony_ci *
171262306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
171362306a36Sopenharmony_ci */
171462306a36Sopenharmony_cistatic int ti_sci_get_resource_range(const struct ti_sci_handle *handle,
171562306a36Sopenharmony_ci				     u32 dev_id, u8 subtype, u8 s_host,
171662306a36Sopenharmony_ci				     struct ti_sci_resource_desc *desc)
171762306a36Sopenharmony_ci{
171862306a36Sopenharmony_ci	struct ti_sci_msg_resp_get_resource_range *resp;
171962306a36Sopenharmony_ci	struct ti_sci_msg_req_get_resource_range *req;
172062306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
172162306a36Sopenharmony_ci	struct ti_sci_info *info;
172262306a36Sopenharmony_ci	struct device *dev;
172362306a36Sopenharmony_ci	int ret = 0;
172462306a36Sopenharmony_ci
172562306a36Sopenharmony_ci	if (IS_ERR(handle))
172662306a36Sopenharmony_ci		return PTR_ERR(handle);
172762306a36Sopenharmony_ci	if (!handle || !desc)
172862306a36Sopenharmony_ci		return -EINVAL;
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
173162306a36Sopenharmony_ci	dev = info->dev;
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_RESOURCE_RANGE,
173462306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
173562306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
173662306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
173762306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
173862306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
173962306a36Sopenharmony_ci		return ret;
174062306a36Sopenharmony_ci	}
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_get_resource_range *)xfer->xfer_buf;
174362306a36Sopenharmony_ci	req->secondary_host = s_host;
174462306a36Sopenharmony_ci	req->type = dev_id & MSG_RM_RESOURCE_TYPE_MASK;
174562306a36Sopenharmony_ci	req->subtype = subtype & MSG_RM_RESOURCE_SUBTYPE_MASK;
174662306a36Sopenharmony_ci
174762306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
174862306a36Sopenharmony_ci	if (ret) {
174962306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
175062306a36Sopenharmony_ci		goto fail;
175162306a36Sopenharmony_ci	}
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	resp = (struct ti_sci_msg_resp_get_resource_range *)xfer->xfer_buf;
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	if (!ti_sci_is_response_ack(resp)) {
175662306a36Sopenharmony_ci		ret = -ENODEV;
175762306a36Sopenharmony_ci	} else if (!resp->range_num && !resp->range_num_sec) {
175862306a36Sopenharmony_ci		/* Neither of the two resource range is valid */
175962306a36Sopenharmony_ci		ret = -ENODEV;
176062306a36Sopenharmony_ci	} else {
176162306a36Sopenharmony_ci		desc->start = resp->range_start;
176262306a36Sopenharmony_ci		desc->num = resp->range_num;
176362306a36Sopenharmony_ci		desc->start_sec = resp->range_start_sec;
176462306a36Sopenharmony_ci		desc->num_sec = resp->range_num_sec;
176562306a36Sopenharmony_ci	}
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_cifail:
176862306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci	return ret;
177162306a36Sopenharmony_ci}
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci/**
177462306a36Sopenharmony_ci * ti_sci_cmd_get_resource_range - Get a range of resources assigned to host
177562306a36Sopenharmony_ci *				   that is same as ti sci interface host.
177662306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
177762306a36Sopenharmony_ci * @dev_id:		TISCI device ID.
177862306a36Sopenharmony_ci * @subtype:		Resource assignment subtype that is being requested
177962306a36Sopenharmony_ci *			from the given device.
178062306a36Sopenharmony_ci * @desc:		Pointer to ti_sci_resource_desc to be updated with the
178162306a36Sopenharmony_ci *			resource range start index and number of resources
178262306a36Sopenharmony_ci *
178362306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
178462306a36Sopenharmony_ci */
178562306a36Sopenharmony_cistatic int ti_sci_cmd_get_resource_range(const struct ti_sci_handle *handle,
178662306a36Sopenharmony_ci					 u32 dev_id, u8 subtype,
178762306a36Sopenharmony_ci					 struct ti_sci_resource_desc *desc)
178862306a36Sopenharmony_ci{
178962306a36Sopenharmony_ci	return ti_sci_get_resource_range(handle, dev_id, subtype,
179062306a36Sopenharmony_ci					 TI_SCI_IRQ_SECONDARY_HOST_INVALID,
179162306a36Sopenharmony_ci					 desc);
179262306a36Sopenharmony_ci}
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci/**
179562306a36Sopenharmony_ci * ti_sci_cmd_get_resource_range_from_shost - Get a range of resources
179662306a36Sopenharmony_ci *					      assigned to a specified host.
179762306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
179862306a36Sopenharmony_ci * @dev_id:		TISCI device ID.
179962306a36Sopenharmony_ci * @subtype:		Resource assignment subtype that is being requested
180062306a36Sopenharmony_ci *			from the given device.
180162306a36Sopenharmony_ci * @s_host:		Host processor ID to which the resources are allocated
180262306a36Sopenharmony_ci * @desc:		Pointer to ti_sci_resource_desc to be updated with the
180362306a36Sopenharmony_ci *			resource range start index and number of resources
180462306a36Sopenharmony_ci *
180562306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
180662306a36Sopenharmony_ci */
180762306a36Sopenharmony_cistatic
180862306a36Sopenharmony_ciint ti_sci_cmd_get_resource_range_from_shost(const struct ti_sci_handle *handle,
180962306a36Sopenharmony_ci					     u32 dev_id, u8 subtype, u8 s_host,
181062306a36Sopenharmony_ci					     struct ti_sci_resource_desc *desc)
181162306a36Sopenharmony_ci{
181262306a36Sopenharmony_ci	return ti_sci_get_resource_range(handle, dev_id, subtype, s_host, desc);
181362306a36Sopenharmony_ci}
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci/**
181662306a36Sopenharmony_ci * ti_sci_manage_irq() - Helper api to configure/release the irq route between
181762306a36Sopenharmony_ci *			 the requested source and destination
181862306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
181962306a36Sopenharmony_ci * @valid_params:	Bit fields defining the validity of certain params
182062306a36Sopenharmony_ci * @src_id:		Device ID of the IRQ source
182162306a36Sopenharmony_ci * @src_index:		IRQ source index within the source device
182262306a36Sopenharmony_ci * @dst_id:		Device ID of the IRQ destination
182362306a36Sopenharmony_ci * @dst_host_irq:	IRQ number of the destination device
182462306a36Sopenharmony_ci * @ia_id:		Device ID of the IA, if the IRQ flows through this IA
182562306a36Sopenharmony_ci * @vint:		Virtual interrupt to be used within the IA
182662306a36Sopenharmony_ci * @global_event:	Global event number to be used for the requesting event
182762306a36Sopenharmony_ci * @vint_status_bit:	Virtual interrupt status bit to be used for the event
182862306a36Sopenharmony_ci * @s_host:		Secondary host ID to which the irq/event is being
182962306a36Sopenharmony_ci *			requested for.
183062306a36Sopenharmony_ci * @type:		Request type irq set or release.
183162306a36Sopenharmony_ci *
183262306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
183362306a36Sopenharmony_ci */
183462306a36Sopenharmony_cistatic int ti_sci_manage_irq(const struct ti_sci_handle *handle,
183562306a36Sopenharmony_ci			     u32 valid_params, u16 src_id, u16 src_index,
183662306a36Sopenharmony_ci			     u16 dst_id, u16 dst_host_irq, u16 ia_id, u16 vint,
183762306a36Sopenharmony_ci			     u16 global_event, u8 vint_status_bit, u8 s_host,
183862306a36Sopenharmony_ci			     u16 type)
183962306a36Sopenharmony_ci{
184062306a36Sopenharmony_ci	struct ti_sci_msg_req_manage_irq *req;
184162306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
184262306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
184362306a36Sopenharmony_ci	struct ti_sci_info *info;
184462306a36Sopenharmony_ci	struct device *dev;
184562306a36Sopenharmony_ci	int ret = 0;
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci	if (IS_ERR(handle))
184862306a36Sopenharmony_ci		return PTR_ERR(handle);
184962306a36Sopenharmony_ci	if (!handle)
185062306a36Sopenharmony_ci		return -EINVAL;
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
185362306a36Sopenharmony_ci	dev = info->dev;
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, type, TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
185662306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
185762306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
185862306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
185962306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
186062306a36Sopenharmony_ci		return ret;
186162306a36Sopenharmony_ci	}
186262306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_manage_irq *)xfer->xfer_buf;
186362306a36Sopenharmony_ci	req->valid_params = valid_params;
186462306a36Sopenharmony_ci	req->src_id = src_id;
186562306a36Sopenharmony_ci	req->src_index = src_index;
186662306a36Sopenharmony_ci	req->dst_id = dst_id;
186762306a36Sopenharmony_ci	req->dst_host_irq = dst_host_irq;
186862306a36Sopenharmony_ci	req->ia_id = ia_id;
186962306a36Sopenharmony_ci	req->vint = vint;
187062306a36Sopenharmony_ci	req->global_event = global_event;
187162306a36Sopenharmony_ci	req->vint_status_bit = vint_status_bit;
187262306a36Sopenharmony_ci	req->secondary_host = s_host;
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
187562306a36Sopenharmony_ci	if (ret) {
187662306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
187762306a36Sopenharmony_ci		goto fail;
187862306a36Sopenharmony_ci	}
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_cifail:
188562306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	return ret;
188862306a36Sopenharmony_ci}
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci/**
189162306a36Sopenharmony_ci * ti_sci_set_irq() - Helper api to configure the irq route between the
189262306a36Sopenharmony_ci *		      requested source and destination
189362306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
189462306a36Sopenharmony_ci * @valid_params:	Bit fields defining the validity of certain params
189562306a36Sopenharmony_ci * @src_id:		Device ID of the IRQ source
189662306a36Sopenharmony_ci * @src_index:		IRQ source index within the source device
189762306a36Sopenharmony_ci * @dst_id:		Device ID of the IRQ destination
189862306a36Sopenharmony_ci * @dst_host_irq:	IRQ number of the destination device
189962306a36Sopenharmony_ci * @ia_id:		Device ID of the IA, if the IRQ flows through this IA
190062306a36Sopenharmony_ci * @vint:		Virtual interrupt to be used within the IA
190162306a36Sopenharmony_ci * @global_event:	Global event number to be used for the requesting event
190262306a36Sopenharmony_ci * @vint_status_bit:	Virtual interrupt status bit to be used for the event
190362306a36Sopenharmony_ci * @s_host:		Secondary host ID to which the irq/event is being
190462306a36Sopenharmony_ci *			requested for.
190562306a36Sopenharmony_ci *
190662306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
190762306a36Sopenharmony_ci */
190862306a36Sopenharmony_cistatic int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params,
190962306a36Sopenharmony_ci			  u16 src_id, u16 src_index, u16 dst_id,
191062306a36Sopenharmony_ci			  u16 dst_host_irq, u16 ia_id, u16 vint,
191162306a36Sopenharmony_ci			  u16 global_event, u8 vint_status_bit, u8 s_host)
191262306a36Sopenharmony_ci{
191362306a36Sopenharmony_ci	pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
191462306a36Sopenharmony_ci		 __func__, valid_params, src_id, src_index,
191562306a36Sopenharmony_ci		 dst_id, dst_host_irq, ia_id, vint, global_event,
191662306a36Sopenharmony_ci		 vint_status_bit);
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_ci	return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
191962306a36Sopenharmony_ci				 dst_id, dst_host_irq, ia_id, vint,
192062306a36Sopenharmony_ci				 global_event, vint_status_bit, s_host,
192162306a36Sopenharmony_ci				 TI_SCI_MSG_SET_IRQ);
192262306a36Sopenharmony_ci}
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci/**
192562306a36Sopenharmony_ci * ti_sci_free_irq() - Helper api to free the irq route between the
192662306a36Sopenharmony_ci *			   requested source and destination
192762306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
192862306a36Sopenharmony_ci * @valid_params:	Bit fields defining the validity of certain params
192962306a36Sopenharmony_ci * @src_id:		Device ID of the IRQ source
193062306a36Sopenharmony_ci * @src_index:		IRQ source index within the source device
193162306a36Sopenharmony_ci * @dst_id:		Device ID of the IRQ destination
193262306a36Sopenharmony_ci * @dst_host_irq:	IRQ number of the destination device
193362306a36Sopenharmony_ci * @ia_id:		Device ID of the IA, if the IRQ flows through this IA
193462306a36Sopenharmony_ci * @vint:		Virtual interrupt to be used within the IA
193562306a36Sopenharmony_ci * @global_event:	Global event number to be used for the requesting event
193662306a36Sopenharmony_ci * @vint_status_bit:	Virtual interrupt status bit to be used for the event
193762306a36Sopenharmony_ci * @s_host:		Secondary host ID to which the irq/event is being
193862306a36Sopenharmony_ci *			requested for.
193962306a36Sopenharmony_ci *
194062306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
194162306a36Sopenharmony_ci */
194262306a36Sopenharmony_cistatic int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params,
194362306a36Sopenharmony_ci			   u16 src_id, u16 src_index, u16 dst_id,
194462306a36Sopenharmony_ci			   u16 dst_host_irq, u16 ia_id, u16 vint,
194562306a36Sopenharmony_ci			   u16 global_event, u8 vint_status_bit, u8 s_host)
194662306a36Sopenharmony_ci{
194762306a36Sopenharmony_ci	pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
194862306a36Sopenharmony_ci		 __func__, valid_params, src_id, src_index,
194962306a36Sopenharmony_ci		 dst_id, dst_host_irq, ia_id, vint, global_event,
195062306a36Sopenharmony_ci		 vint_status_bit);
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ci	return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
195362306a36Sopenharmony_ci				 dst_id, dst_host_irq, ia_id, vint,
195462306a36Sopenharmony_ci				 global_event, vint_status_bit, s_host,
195562306a36Sopenharmony_ci				 TI_SCI_MSG_FREE_IRQ);
195662306a36Sopenharmony_ci}
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_ci/**
195962306a36Sopenharmony_ci * ti_sci_cmd_set_irq() - Configure a host irq route between the requested
196062306a36Sopenharmony_ci *			  source and destination.
196162306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
196262306a36Sopenharmony_ci * @src_id:		Device ID of the IRQ source
196362306a36Sopenharmony_ci * @src_index:		IRQ source index within the source device
196462306a36Sopenharmony_ci * @dst_id:		Device ID of the IRQ destination
196562306a36Sopenharmony_ci * @dst_host_irq:	IRQ number of the destination device
196662306a36Sopenharmony_ci *
196762306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
196862306a36Sopenharmony_ci */
196962306a36Sopenharmony_cistatic int ti_sci_cmd_set_irq(const struct ti_sci_handle *handle, u16 src_id,
197062306a36Sopenharmony_ci			      u16 src_index, u16 dst_id, u16 dst_host_irq)
197162306a36Sopenharmony_ci{
197262306a36Sopenharmony_ci	u32 valid_params = MSG_FLAG_DST_ID_VALID | MSG_FLAG_DST_HOST_IRQ_VALID;
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci	return ti_sci_set_irq(handle, valid_params, src_id, src_index, dst_id,
197562306a36Sopenharmony_ci			      dst_host_irq, 0, 0, 0, 0, 0);
197662306a36Sopenharmony_ci}
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_ci/**
197962306a36Sopenharmony_ci * ti_sci_cmd_set_event_map() - Configure an event based irq route between the
198062306a36Sopenharmony_ci *				requested source and Interrupt Aggregator.
198162306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
198262306a36Sopenharmony_ci * @src_id:		Device ID of the IRQ source
198362306a36Sopenharmony_ci * @src_index:		IRQ source index within the source device
198462306a36Sopenharmony_ci * @ia_id:		Device ID of the IA, if the IRQ flows through this IA
198562306a36Sopenharmony_ci * @vint:		Virtual interrupt to be used within the IA
198662306a36Sopenharmony_ci * @global_event:	Global event number to be used for the requesting event
198762306a36Sopenharmony_ci * @vint_status_bit:	Virtual interrupt status bit to be used for the event
198862306a36Sopenharmony_ci *
198962306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
199062306a36Sopenharmony_ci */
199162306a36Sopenharmony_cistatic int ti_sci_cmd_set_event_map(const struct ti_sci_handle *handle,
199262306a36Sopenharmony_ci				    u16 src_id, u16 src_index, u16 ia_id,
199362306a36Sopenharmony_ci				    u16 vint, u16 global_event,
199462306a36Sopenharmony_ci				    u8 vint_status_bit)
199562306a36Sopenharmony_ci{
199662306a36Sopenharmony_ci	u32 valid_params = MSG_FLAG_IA_ID_VALID | MSG_FLAG_VINT_VALID |
199762306a36Sopenharmony_ci			   MSG_FLAG_GLB_EVNT_VALID |
199862306a36Sopenharmony_ci			   MSG_FLAG_VINT_STS_BIT_VALID;
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci	return ti_sci_set_irq(handle, valid_params, src_id, src_index, 0, 0,
200162306a36Sopenharmony_ci			      ia_id, vint, global_event, vint_status_bit, 0);
200262306a36Sopenharmony_ci}
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_ci/**
200562306a36Sopenharmony_ci * ti_sci_cmd_free_irq() - Free a host irq route between the between the
200662306a36Sopenharmony_ci *			   requested source and destination.
200762306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
200862306a36Sopenharmony_ci * @src_id:		Device ID of the IRQ source
200962306a36Sopenharmony_ci * @src_index:		IRQ source index within the source device
201062306a36Sopenharmony_ci * @dst_id:		Device ID of the IRQ destination
201162306a36Sopenharmony_ci * @dst_host_irq:	IRQ number of the destination device
201262306a36Sopenharmony_ci *
201362306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
201462306a36Sopenharmony_ci */
201562306a36Sopenharmony_cistatic int ti_sci_cmd_free_irq(const struct ti_sci_handle *handle, u16 src_id,
201662306a36Sopenharmony_ci			       u16 src_index, u16 dst_id, u16 dst_host_irq)
201762306a36Sopenharmony_ci{
201862306a36Sopenharmony_ci	u32 valid_params = MSG_FLAG_DST_ID_VALID | MSG_FLAG_DST_HOST_IRQ_VALID;
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_ci	return ti_sci_free_irq(handle, valid_params, src_id, src_index, dst_id,
202162306a36Sopenharmony_ci			       dst_host_irq, 0, 0, 0, 0, 0);
202262306a36Sopenharmony_ci}
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_ci/**
202562306a36Sopenharmony_ci * ti_sci_cmd_free_event_map() - Free an event map between the requested source
202662306a36Sopenharmony_ci *				 and Interrupt Aggregator.
202762306a36Sopenharmony_ci * @handle:		Pointer to TISCI handle.
202862306a36Sopenharmony_ci * @src_id:		Device ID of the IRQ source
202962306a36Sopenharmony_ci * @src_index:		IRQ source index within the source device
203062306a36Sopenharmony_ci * @ia_id:		Device ID of the IA, if the IRQ flows through this IA
203162306a36Sopenharmony_ci * @vint:		Virtual interrupt to be used within the IA
203262306a36Sopenharmony_ci * @global_event:	Global event number to be used for the requesting event
203362306a36Sopenharmony_ci * @vint_status_bit:	Virtual interrupt status bit to be used for the event
203462306a36Sopenharmony_ci *
203562306a36Sopenharmony_ci * Return: 0 if all went fine, else return appropriate error.
203662306a36Sopenharmony_ci */
203762306a36Sopenharmony_cistatic int ti_sci_cmd_free_event_map(const struct ti_sci_handle *handle,
203862306a36Sopenharmony_ci				     u16 src_id, u16 src_index, u16 ia_id,
203962306a36Sopenharmony_ci				     u16 vint, u16 global_event,
204062306a36Sopenharmony_ci				     u8 vint_status_bit)
204162306a36Sopenharmony_ci{
204262306a36Sopenharmony_ci	u32 valid_params = MSG_FLAG_IA_ID_VALID |
204362306a36Sopenharmony_ci			   MSG_FLAG_VINT_VALID | MSG_FLAG_GLB_EVNT_VALID |
204462306a36Sopenharmony_ci			   MSG_FLAG_VINT_STS_BIT_VALID;
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_ci	return ti_sci_free_irq(handle, valid_params, src_id, src_index, 0, 0,
204762306a36Sopenharmony_ci			       ia_id, vint, global_event, vint_status_bit, 0);
204862306a36Sopenharmony_ci}
204962306a36Sopenharmony_ci
205062306a36Sopenharmony_ci/**
205162306a36Sopenharmony_ci * ti_sci_cmd_rm_ring_cfg() - Configure a NAVSS ring
205262306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle.
205362306a36Sopenharmony_ci * @params:	Pointer to ti_sci_msg_rm_ring_cfg ring config structure
205462306a36Sopenharmony_ci *
205562306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
205662306a36Sopenharmony_ci *
205762306a36Sopenharmony_ci * See @ti_sci_msg_rm_ring_cfg and @ti_sci_msg_rm_ring_cfg_req for
205862306a36Sopenharmony_ci * more info.
205962306a36Sopenharmony_ci */
206062306a36Sopenharmony_cistatic int ti_sci_cmd_rm_ring_cfg(const struct ti_sci_handle *handle,
206162306a36Sopenharmony_ci				  const struct ti_sci_msg_rm_ring_cfg *params)
206262306a36Sopenharmony_ci{
206362306a36Sopenharmony_ci	struct ti_sci_msg_rm_ring_cfg_req *req;
206462306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
206562306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
206662306a36Sopenharmony_ci	struct ti_sci_info *info;
206762306a36Sopenharmony_ci	struct device *dev;
206862306a36Sopenharmony_ci	int ret = 0;
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(handle))
207162306a36Sopenharmony_ci		return -EINVAL;
207262306a36Sopenharmony_ci
207362306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
207462306a36Sopenharmony_ci	dev = info->dev;
207562306a36Sopenharmony_ci
207662306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_RING_CFG,
207762306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
207862306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
207962306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
208062306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
208162306a36Sopenharmony_ci		dev_err(dev, "RM_RA:Message config failed(%d)\n", ret);
208262306a36Sopenharmony_ci		return ret;
208362306a36Sopenharmony_ci	}
208462306a36Sopenharmony_ci	req = (struct ti_sci_msg_rm_ring_cfg_req *)xfer->xfer_buf;
208562306a36Sopenharmony_ci	req->valid_params = params->valid_params;
208662306a36Sopenharmony_ci	req->nav_id = params->nav_id;
208762306a36Sopenharmony_ci	req->index = params->index;
208862306a36Sopenharmony_ci	req->addr_lo = params->addr_lo;
208962306a36Sopenharmony_ci	req->addr_hi = params->addr_hi;
209062306a36Sopenharmony_ci	req->count = params->count;
209162306a36Sopenharmony_ci	req->mode = params->mode;
209262306a36Sopenharmony_ci	req->size = params->size;
209362306a36Sopenharmony_ci	req->order_id = params->order_id;
209462306a36Sopenharmony_ci	req->virtid = params->virtid;
209562306a36Sopenharmony_ci	req->asel = params->asel;
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
209862306a36Sopenharmony_ci	if (ret) {
209962306a36Sopenharmony_ci		dev_err(dev, "RM_RA:Mbox config send fail %d\n", ret);
210062306a36Sopenharmony_ci		goto fail;
210162306a36Sopenharmony_ci	}
210262306a36Sopenharmony_ci
210362306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
210462306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_cifail:
210762306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
210862306a36Sopenharmony_ci	dev_dbg(dev, "RM_RA:config ring %u ret:%d\n", params->index, ret);
210962306a36Sopenharmony_ci	return ret;
211062306a36Sopenharmony_ci}
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci/**
211362306a36Sopenharmony_ci * ti_sci_cmd_rm_psil_pair() - Pair PSI-L source to destination thread
211462306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle.
211562306a36Sopenharmony_ci * @nav_id:	Device ID of Navigator Subsystem which should be used for
211662306a36Sopenharmony_ci *		pairing
211762306a36Sopenharmony_ci * @src_thread:	Source PSI-L thread ID
211862306a36Sopenharmony_ci * @dst_thread: Destination PSI-L thread ID
211962306a36Sopenharmony_ci *
212062306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
212162306a36Sopenharmony_ci */
212262306a36Sopenharmony_cistatic int ti_sci_cmd_rm_psil_pair(const struct ti_sci_handle *handle,
212362306a36Sopenharmony_ci				   u32 nav_id, u32 src_thread, u32 dst_thread)
212462306a36Sopenharmony_ci{
212562306a36Sopenharmony_ci	struct ti_sci_msg_psil_pair *req;
212662306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
212762306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
212862306a36Sopenharmony_ci	struct ti_sci_info *info;
212962306a36Sopenharmony_ci	struct device *dev;
213062306a36Sopenharmony_ci	int ret = 0;
213162306a36Sopenharmony_ci
213262306a36Sopenharmony_ci	if (IS_ERR(handle))
213362306a36Sopenharmony_ci		return PTR_ERR(handle);
213462306a36Sopenharmony_ci	if (!handle)
213562306a36Sopenharmony_ci		return -EINVAL;
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
213862306a36Sopenharmony_ci	dev = info->dev;
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_PSIL_PAIR,
214162306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
214262306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
214362306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
214462306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
214562306a36Sopenharmony_ci		dev_err(dev, "RM_PSIL:Message reconfig failed(%d)\n", ret);
214662306a36Sopenharmony_ci		return ret;
214762306a36Sopenharmony_ci	}
214862306a36Sopenharmony_ci	req = (struct ti_sci_msg_psil_pair *)xfer->xfer_buf;
214962306a36Sopenharmony_ci	req->nav_id = nav_id;
215062306a36Sopenharmony_ci	req->src_thread = src_thread;
215162306a36Sopenharmony_ci	req->dst_thread = dst_thread;
215262306a36Sopenharmony_ci
215362306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
215462306a36Sopenharmony_ci	if (ret) {
215562306a36Sopenharmony_ci		dev_err(dev, "RM_PSIL:Mbox send fail %d\n", ret);
215662306a36Sopenharmony_ci		goto fail;
215762306a36Sopenharmony_ci	}
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
216062306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_cifail:
216362306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci	return ret;
216662306a36Sopenharmony_ci}
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci/**
216962306a36Sopenharmony_ci * ti_sci_cmd_rm_psil_unpair() - Unpair PSI-L source from destination thread
217062306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle.
217162306a36Sopenharmony_ci * @nav_id:	Device ID of Navigator Subsystem which should be used for
217262306a36Sopenharmony_ci *		unpairing
217362306a36Sopenharmony_ci * @src_thread:	Source PSI-L thread ID
217462306a36Sopenharmony_ci * @dst_thread:	Destination PSI-L thread ID
217562306a36Sopenharmony_ci *
217662306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
217762306a36Sopenharmony_ci */
217862306a36Sopenharmony_cistatic int ti_sci_cmd_rm_psil_unpair(const struct ti_sci_handle *handle,
217962306a36Sopenharmony_ci				     u32 nav_id, u32 src_thread, u32 dst_thread)
218062306a36Sopenharmony_ci{
218162306a36Sopenharmony_ci	struct ti_sci_msg_psil_unpair *req;
218262306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
218362306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
218462306a36Sopenharmony_ci	struct ti_sci_info *info;
218562306a36Sopenharmony_ci	struct device *dev;
218662306a36Sopenharmony_ci	int ret = 0;
218762306a36Sopenharmony_ci
218862306a36Sopenharmony_ci	if (IS_ERR(handle))
218962306a36Sopenharmony_ci		return PTR_ERR(handle);
219062306a36Sopenharmony_ci	if (!handle)
219162306a36Sopenharmony_ci		return -EINVAL;
219262306a36Sopenharmony_ci
219362306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
219462306a36Sopenharmony_ci	dev = info->dev;
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_PSIL_UNPAIR,
219762306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
219862306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
219962306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
220062306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
220162306a36Sopenharmony_ci		dev_err(dev, "RM_PSIL:Message reconfig failed(%d)\n", ret);
220262306a36Sopenharmony_ci		return ret;
220362306a36Sopenharmony_ci	}
220462306a36Sopenharmony_ci	req = (struct ti_sci_msg_psil_unpair *)xfer->xfer_buf;
220562306a36Sopenharmony_ci	req->nav_id = nav_id;
220662306a36Sopenharmony_ci	req->src_thread = src_thread;
220762306a36Sopenharmony_ci	req->dst_thread = dst_thread;
220862306a36Sopenharmony_ci
220962306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
221062306a36Sopenharmony_ci	if (ret) {
221162306a36Sopenharmony_ci		dev_err(dev, "RM_PSIL:Mbox send fail %d\n", ret);
221262306a36Sopenharmony_ci		goto fail;
221362306a36Sopenharmony_ci	}
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
221662306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
221762306a36Sopenharmony_ci
221862306a36Sopenharmony_cifail:
221962306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci	return ret;
222262306a36Sopenharmony_ci}
222362306a36Sopenharmony_ci
222462306a36Sopenharmony_ci/**
222562306a36Sopenharmony_ci * ti_sci_cmd_rm_udmap_tx_ch_cfg() - Configure a UDMAP TX channel
222662306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle.
222762306a36Sopenharmony_ci * @params:	Pointer to ti_sci_msg_rm_udmap_tx_ch_cfg TX channel config
222862306a36Sopenharmony_ci *		structure
222962306a36Sopenharmony_ci *
223062306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
223162306a36Sopenharmony_ci *
223262306a36Sopenharmony_ci * See @ti_sci_msg_rm_udmap_tx_ch_cfg and @ti_sci_msg_rm_udmap_tx_ch_cfg_req for
223362306a36Sopenharmony_ci * more info.
223462306a36Sopenharmony_ci */
223562306a36Sopenharmony_cistatic int ti_sci_cmd_rm_udmap_tx_ch_cfg(const struct ti_sci_handle *handle,
223662306a36Sopenharmony_ci			const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params)
223762306a36Sopenharmony_ci{
223862306a36Sopenharmony_ci	struct ti_sci_msg_rm_udmap_tx_ch_cfg_req *req;
223962306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
224062306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
224162306a36Sopenharmony_ci	struct ti_sci_info *info;
224262306a36Sopenharmony_ci	struct device *dev;
224362306a36Sopenharmony_ci	int ret = 0;
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(handle))
224662306a36Sopenharmony_ci		return -EINVAL;
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
224962306a36Sopenharmony_ci	dev = info->dev;
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TISCI_MSG_RM_UDMAP_TX_CH_CFG,
225262306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
225362306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
225462306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
225562306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
225662306a36Sopenharmony_ci		dev_err(dev, "Message TX_CH_CFG alloc failed(%d)\n", ret);
225762306a36Sopenharmony_ci		return ret;
225862306a36Sopenharmony_ci	}
225962306a36Sopenharmony_ci	req = (struct ti_sci_msg_rm_udmap_tx_ch_cfg_req *)xfer->xfer_buf;
226062306a36Sopenharmony_ci	req->valid_params = params->valid_params;
226162306a36Sopenharmony_ci	req->nav_id = params->nav_id;
226262306a36Sopenharmony_ci	req->index = params->index;
226362306a36Sopenharmony_ci	req->tx_pause_on_err = params->tx_pause_on_err;
226462306a36Sopenharmony_ci	req->tx_filt_einfo = params->tx_filt_einfo;
226562306a36Sopenharmony_ci	req->tx_filt_pswords = params->tx_filt_pswords;
226662306a36Sopenharmony_ci	req->tx_atype = params->tx_atype;
226762306a36Sopenharmony_ci	req->tx_chan_type = params->tx_chan_type;
226862306a36Sopenharmony_ci	req->tx_supr_tdpkt = params->tx_supr_tdpkt;
226962306a36Sopenharmony_ci	req->tx_fetch_size = params->tx_fetch_size;
227062306a36Sopenharmony_ci	req->tx_credit_count = params->tx_credit_count;
227162306a36Sopenharmony_ci	req->txcq_qnum = params->txcq_qnum;
227262306a36Sopenharmony_ci	req->tx_priority = params->tx_priority;
227362306a36Sopenharmony_ci	req->tx_qos = params->tx_qos;
227462306a36Sopenharmony_ci	req->tx_orderid = params->tx_orderid;
227562306a36Sopenharmony_ci	req->fdepth = params->fdepth;
227662306a36Sopenharmony_ci	req->tx_sched_priority = params->tx_sched_priority;
227762306a36Sopenharmony_ci	req->tx_burst_size = params->tx_burst_size;
227862306a36Sopenharmony_ci	req->tx_tdtype = params->tx_tdtype;
227962306a36Sopenharmony_ci	req->extended_ch_type = params->extended_ch_type;
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
228262306a36Sopenharmony_ci	if (ret) {
228362306a36Sopenharmony_ci		dev_err(dev, "Mbox send TX_CH_CFG fail %d\n", ret);
228462306a36Sopenharmony_ci		goto fail;
228562306a36Sopenharmony_ci	}
228662306a36Sopenharmony_ci
228762306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
228862306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_cifail:
229162306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
229262306a36Sopenharmony_ci	dev_dbg(dev, "TX_CH_CFG: chn %u ret:%u\n", params->index, ret);
229362306a36Sopenharmony_ci	return ret;
229462306a36Sopenharmony_ci}
229562306a36Sopenharmony_ci
229662306a36Sopenharmony_ci/**
229762306a36Sopenharmony_ci * ti_sci_cmd_rm_udmap_rx_ch_cfg() - Configure a UDMAP RX channel
229862306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle.
229962306a36Sopenharmony_ci * @params:	Pointer to ti_sci_msg_rm_udmap_rx_ch_cfg RX channel config
230062306a36Sopenharmony_ci *		structure
230162306a36Sopenharmony_ci *
230262306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
230362306a36Sopenharmony_ci *
230462306a36Sopenharmony_ci * See @ti_sci_msg_rm_udmap_rx_ch_cfg and @ti_sci_msg_rm_udmap_rx_ch_cfg_req for
230562306a36Sopenharmony_ci * more info.
230662306a36Sopenharmony_ci */
230762306a36Sopenharmony_cistatic int ti_sci_cmd_rm_udmap_rx_ch_cfg(const struct ti_sci_handle *handle,
230862306a36Sopenharmony_ci			const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params)
230962306a36Sopenharmony_ci{
231062306a36Sopenharmony_ci	struct ti_sci_msg_rm_udmap_rx_ch_cfg_req *req;
231162306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
231262306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
231362306a36Sopenharmony_ci	struct ti_sci_info *info;
231462306a36Sopenharmony_ci	struct device *dev;
231562306a36Sopenharmony_ci	int ret = 0;
231662306a36Sopenharmony_ci
231762306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(handle))
231862306a36Sopenharmony_ci		return -EINVAL;
231962306a36Sopenharmony_ci
232062306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
232162306a36Sopenharmony_ci	dev = info->dev;
232262306a36Sopenharmony_ci
232362306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TISCI_MSG_RM_UDMAP_RX_CH_CFG,
232462306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
232562306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
232662306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
232762306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
232862306a36Sopenharmony_ci		dev_err(dev, "Message RX_CH_CFG alloc failed(%d)\n", ret);
232962306a36Sopenharmony_ci		return ret;
233062306a36Sopenharmony_ci	}
233162306a36Sopenharmony_ci	req = (struct ti_sci_msg_rm_udmap_rx_ch_cfg_req *)xfer->xfer_buf;
233262306a36Sopenharmony_ci	req->valid_params = params->valid_params;
233362306a36Sopenharmony_ci	req->nav_id = params->nav_id;
233462306a36Sopenharmony_ci	req->index = params->index;
233562306a36Sopenharmony_ci	req->rx_fetch_size = params->rx_fetch_size;
233662306a36Sopenharmony_ci	req->rxcq_qnum = params->rxcq_qnum;
233762306a36Sopenharmony_ci	req->rx_priority = params->rx_priority;
233862306a36Sopenharmony_ci	req->rx_qos = params->rx_qos;
233962306a36Sopenharmony_ci	req->rx_orderid = params->rx_orderid;
234062306a36Sopenharmony_ci	req->rx_sched_priority = params->rx_sched_priority;
234162306a36Sopenharmony_ci	req->flowid_start = params->flowid_start;
234262306a36Sopenharmony_ci	req->flowid_cnt = params->flowid_cnt;
234362306a36Sopenharmony_ci	req->rx_pause_on_err = params->rx_pause_on_err;
234462306a36Sopenharmony_ci	req->rx_atype = params->rx_atype;
234562306a36Sopenharmony_ci	req->rx_chan_type = params->rx_chan_type;
234662306a36Sopenharmony_ci	req->rx_ignore_short = params->rx_ignore_short;
234762306a36Sopenharmony_ci	req->rx_ignore_long = params->rx_ignore_long;
234862306a36Sopenharmony_ci	req->rx_burst_size = params->rx_burst_size;
234962306a36Sopenharmony_ci
235062306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
235162306a36Sopenharmony_ci	if (ret) {
235262306a36Sopenharmony_ci		dev_err(dev, "Mbox send RX_CH_CFG fail %d\n", ret);
235362306a36Sopenharmony_ci		goto fail;
235462306a36Sopenharmony_ci	}
235562306a36Sopenharmony_ci
235662306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
235762306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
235862306a36Sopenharmony_ci
235962306a36Sopenharmony_cifail:
236062306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
236162306a36Sopenharmony_ci	dev_dbg(dev, "RX_CH_CFG: chn %u ret:%d\n", params->index, ret);
236262306a36Sopenharmony_ci	return ret;
236362306a36Sopenharmony_ci}
236462306a36Sopenharmony_ci
236562306a36Sopenharmony_ci/**
236662306a36Sopenharmony_ci * ti_sci_cmd_rm_udmap_rx_flow_cfg() - Configure UDMAP RX FLOW
236762306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle.
236862306a36Sopenharmony_ci * @params:	Pointer to ti_sci_msg_rm_udmap_flow_cfg RX FLOW config
236962306a36Sopenharmony_ci *		structure
237062306a36Sopenharmony_ci *
237162306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
237262306a36Sopenharmony_ci *
237362306a36Sopenharmony_ci * See @ti_sci_msg_rm_udmap_flow_cfg and @ti_sci_msg_rm_udmap_flow_cfg_req for
237462306a36Sopenharmony_ci * more info.
237562306a36Sopenharmony_ci */
237662306a36Sopenharmony_cistatic int ti_sci_cmd_rm_udmap_rx_flow_cfg(const struct ti_sci_handle *handle,
237762306a36Sopenharmony_ci			const struct ti_sci_msg_rm_udmap_flow_cfg *params)
237862306a36Sopenharmony_ci{
237962306a36Sopenharmony_ci	struct ti_sci_msg_rm_udmap_flow_cfg_req *req;
238062306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
238162306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
238262306a36Sopenharmony_ci	struct ti_sci_info *info;
238362306a36Sopenharmony_ci	struct device *dev;
238462306a36Sopenharmony_ci	int ret = 0;
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(handle))
238762306a36Sopenharmony_ci		return -EINVAL;
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
239062306a36Sopenharmony_ci	dev = info->dev;
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TISCI_MSG_RM_UDMAP_FLOW_CFG,
239362306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
239462306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
239562306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
239662306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
239762306a36Sopenharmony_ci		dev_err(dev, "RX_FL_CFG: Message alloc failed(%d)\n", ret);
239862306a36Sopenharmony_ci		return ret;
239962306a36Sopenharmony_ci	}
240062306a36Sopenharmony_ci	req = (struct ti_sci_msg_rm_udmap_flow_cfg_req *)xfer->xfer_buf;
240162306a36Sopenharmony_ci	req->valid_params = params->valid_params;
240262306a36Sopenharmony_ci	req->nav_id = params->nav_id;
240362306a36Sopenharmony_ci	req->flow_index = params->flow_index;
240462306a36Sopenharmony_ci	req->rx_einfo_present = params->rx_einfo_present;
240562306a36Sopenharmony_ci	req->rx_psinfo_present = params->rx_psinfo_present;
240662306a36Sopenharmony_ci	req->rx_error_handling = params->rx_error_handling;
240762306a36Sopenharmony_ci	req->rx_desc_type = params->rx_desc_type;
240862306a36Sopenharmony_ci	req->rx_sop_offset = params->rx_sop_offset;
240962306a36Sopenharmony_ci	req->rx_dest_qnum = params->rx_dest_qnum;
241062306a36Sopenharmony_ci	req->rx_src_tag_hi = params->rx_src_tag_hi;
241162306a36Sopenharmony_ci	req->rx_src_tag_lo = params->rx_src_tag_lo;
241262306a36Sopenharmony_ci	req->rx_dest_tag_hi = params->rx_dest_tag_hi;
241362306a36Sopenharmony_ci	req->rx_dest_tag_lo = params->rx_dest_tag_lo;
241462306a36Sopenharmony_ci	req->rx_src_tag_hi_sel = params->rx_src_tag_hi_sel;
241562306a36Sopenharmony_ci	req->rx_src_tag_lo_sel = params->rx_src_tag_lo_sel;
241662306a36Sopenharmony_ci	req->rx_dest_tag_hi_sel = params->rx_dest_tag_hi_sel;
241762306a36Sopenharmony_ci	req->rx_dest_tag_lo_sel = params->rx_dest_tag_lo_sel;
241862306a36Sopenharmony_ci	req->rx_fdq0_sz0_qnum = params->rx_fdq0_sz0_qnum;
241962306a36Sopenharmony_ci	req->rx_fdq1_qnum = params->rx_fdq1_qnum;
242062306a36Sopenharmony_ci	req->rx_fdq2_qnum = params->rx_fdq2_qnum;
242162306a36Sopenharmony_ci	req->rx_fdq3_qnum = params->rx_fdq3_qnum;
242262306a36Sopenharmony_ci	req->rx_ps_location = params->rx_ps_location;
242362306a36Sopenharmony_ci
242462306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
242562306a36Sopenharmony_ci	if (ret) {
242662306a36Sopenharmony_ci		dev_err(dev, "RX_FL_CFG: Mbox send fail %d\n", ret);
242762306a36Sopenharmony_ci		goto fail;
242862306a36Sopenharmony_ci	}
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
243162306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_cifail:
243462306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
243562306a36Sopenharmony_ci	dev_dbg(info->dev, "RX_FL_CFG: %u ret:%d\n", params->flow_index, ret);
243662306a36Sopenharmony_ci	return ret;
243762306a36Sopenharmony_ci}
243862306a36Sopenharmony_ci
243962306a36Sopenharmony_ci/**
244062306a36Sopenharmony_ci * ti_sci_cmd_proc_request() - Command to request a physical processor control
244162306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle
244262306a36Sopenharmony_ci * @proc_id:	Processor ID this request is for
244362306a36Sopenharmony_ci *
244462306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
244562306a36Sopenharmony_ci */
244662306a36Sopenharmony_cistatic int ti_sci_cmd_proc_request(const struct ti_sci_handle *handle,
244762306a36Sopenharmony_ci				   u8 proc_id)
244862306a36Sopenharmony_ci{
244962306a36Sopenharmony_ci	struct ti_sci_msg_req_proc_request *req;
245062306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
245162306a36Sopenharmony_ci	struct ti_sci_info *info;
245262306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
245362306a36Sopenharmony_ci	struct device *dev;
245462306a36Sopenharmony_ci	int ret = 0;
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	if (!handle)
245762306a36Sopenharmony_ci		return -EINVAL;
245862306a36Sopenharmony_ci	if (IS_ERR(handle))
245962306a36Sopenharmony_ci		return PTR_ERR(handle);
246062306a36Sopenharmony_ci
246162306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
246262306a36Sopenharmony_ci	dev = info->dev;
246362306a36Sopenharmony_ci
246462306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_REQUEST,
246562306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
246662306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
246762306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
246862306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
246962306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
247062306a36Sopenharmony_ci		return ret;
247162306a36Sopenharmony_ci	}
247262306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_proc_request *)xfer->xfer_buf;
247362306a36Sopenharmony_ci	req->processor_id = proc_id;
247462306a36Sopenharmony_ci
247562306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
247662306a36Sopenharmony_ci	if (ret) {
247762306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
247862306a36Sopenharmony_ci		goto fail;
247962306a36Sopenharmony_ci	}
248062306a36Sopenharmony_ci
248162306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_cifail:
248662306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_ci	return ret;
248962306a36Sopenharmony_ci}
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_ci/**
249262306a36Sopenharmony_ci * ti_sci_cmd_proc_release() - Command to release a physical processor control
249362306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle
249462306a36Sopenharmony_ci * @proc_id:	Processor ID this request is for
249562306a36Sopenharmony_ci *
249662306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
249762306a36Sopenharmony_ci */
249862306a36Sopenharmony_cistatic int ti_sci_cmd_proc_release(const struct ti_sci_handle *handle,
249962306a36Sopenharmony_ci				   u8 proc_id)
250062306a36Sopenharmony_ci{
250162306a36Sopenharmony_ci	struct ti_sci_msg_req_proc_release *req;
250262306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
250362306a36Sopenharmony_ci	struct ti_sci_info *info;
250462306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
250562306a36Sopenharmony_ci	struct device *dev;
250662306a36Sopenharmony_ci	int ret = 0;
250762306a36Sopenharmony_ci
250862306a36Sopenharmony_ci	if (!handle)
250962306a36Sopenharmony_ci		return -EINVAL;
251062306a36Sopenharmony_ci	if (IS_ERR(handle))
251162306a36Sopenharmony_ci		return PTR_ERR(handle);
251262306a36Sopenharmony_ci
251362306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
251462306a36Sopenharmony_ci	dev = info->dev;
251562306a36Sopenharmony_ci
251662306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_RELEASE,
251762306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
251862306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
251962306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
252062306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
252162306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
252262306a36Sopenharmony_ci		return ret;
252362306a36Sopenharmony_ci	}
252462306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_proc_release *)xfer->xfer_buf;
252562306a36Sopenharmony_ci	req->processor_id = proc_id;
252662306a36Sopenharmony_ci
252762306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
252862306a36Sopenharmony_ci	if (ret) {
252962306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
253062306a36Sopenharmony_ci		goto fail;
253162306a36Sopenharmony_ci	}
253262306a36Sopenharmony_ci
253362306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
253662306a36Sopenharmony_ci
253762306a36Sopenharmony_cifail:
253862306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_ci	return ret;
254162306a36Sopenharmony_ci}
254262306a36Sopenharmony_ci
254362306a36Sopenharmony_ci/**
254462306a36Sopenharmony_ci * ti_sci_cmd_proc_handover() - Command to handover a physical processor
254562306a36Sopenharmony_ci *				control to a host in the processor's access
254662306a36Sopenharmony_ci *				control list.
254762306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle
254862306a36Sopenharmony_ci * @proc_id:	Processor ID this request is for
254962306a36Sopenharmony_ci * @host_id:	Host ID to get the control of the processor
255062306a36Sopenharmony_ci *
255162306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
255262306a36Sopenharmony_ci */
255362306a36Sopenharmony_cistatic int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle,
255462306a36Sopenharmony_ci				    u8 proc_id, u8 host_id)
255562306a36Sopenharmony_ci{
255662306a36Sopenharmony_ci	struct ti_sci_msg_req_proc_handover *req;
255762306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
255862306a36Sopenharmony_ci	struct ti_sci_info *info;
255962306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
256062306a36Sopenharmony_ci	struct device *dev;
256162306a36Sopenharmony_ci	int ret = 0;
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci	if (!handle)
256462306a36Sopenharmony_ci		return -EINVAL;
256562306a36Sopenharmony_ci	if (IS_ERR(handle))
256662306a36Sopenharmony_ci		return PTR_ERR(handle);
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
256962306a36Sopenharmony_ci	dev = info->dev;
257062306a36Sopenharmony_ci
257162306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_HANDOVER,
257262306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
257362306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
257462306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
257562306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
257662306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
257762306a36Sopenharmony_ci		return ret;
257862306a36Sopenharmony_ci	}
257962306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_proc_handover *)xfer->xfer_buf;
258062306a36Sopenharmony_ci	req->processor_id = proc_id;
258162306a36Sopenharmony_ci	req->host_id = host_id;
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
258462306a36Sopenharmony_ci	if (ret) {
258562306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
258662306a36Sopenharmony_ci		goto fail;
258762306a36Sopenharmony_ci	}
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
259062306a36Sopenharmony_ci
259162306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_cifail:
259462306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci	return ret;
259762306a36Sopenharmony_ci}
259862306a36Sopenharmony_ci
259962306a36Sopenharmony_ci/**
260062306a36Sopenharmony_ci * ti_sci_cmd_proc_set_config() - Command to set the processor boot
260162306a36Sopenharmony_ci *				    configuration flags
260262306a36Sopenharmony_ci * @handle:		Pointer to TI SCI handle
260362306a36Sopenharmony_ci * @proc_id:		Processor ID this request is for
260462306a36Sopenharmony_ci * @bootvector:		Processor Boot vector (start address)
260562306a36Sopenharmony_ci * @config_flags_set:	Configuration flags to be set
260662306a36Sopenharmony_ci * @config_flags_clear:	Configuration flags to be cleared.
260762306a36Sopenharmony_ci *
260862306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
260962306a36Sopenharmony_ci */
261062306a36Sopenharmony_cistatic int ti_sci_cmd_proc_set_config(const struct ti_sci_handle *handle,
261162306a36Sopenharmony_ci				      u8 proc_id, u64 bootvector,
261262306a36Sopenharmony_ci				      u32 config_flags_set,
261362306a36Sopenharmony_ci				      u32 config_flags_clear)
261462306a36Sopenharmony_ci{
261562306a36Sopenharmony_ci	struct ti_sci_msg_req_set_config *req;
261662306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
261762306a36Sopenharmony_ci	struct ti_sci_info *info;
261862306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
261962306a36Sopenharmony_ci	struct device *dev;
262062306a36Sopenharmony_ci	int ret = 0;
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_ci	if (!handle)
262362306a36Sopenharmony_ci		return -EINVAL;
262462306a36Sopenharmony_ci	if (IS_ERR(handle))
262562306a36Sopenharmony_ci		return PTR_ERR(handle);
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
262862306a36Sopenharmony_ci	dev = info->dev;
262962306a36Sopenharmony_ci
263062306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CONFIG,
263162306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
263262306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
263362306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
263462306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
263562306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
263662306a36Sopenharmony_ci		return ret;
263762306a36Sopenharmony_ci	}
263862306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_set_config *)xfer->xfer_buf;
263962306a36Sopenharmony_ci	req->processor_id = proc_id;
264062306a36Sopenharmony_ci	req->bootvector_low = bootvector & TI_SCI_ADDR_LOW_MASK;
264162306a36Sopenharmony_ci	req->bootvector_high = (bootvector & TI_SCI_ADDR_HIGH_MASK) >>
264262306a36Sopenharmony_ci				TI_SCI_ADDR_HIGH_SHIFT;
264362306a36Sopenharmony_ci	req->config_flags_set = config_flags_set;
264462306a36Sopenharmony_ci	req->config_flags_clear = config_flags_clear;
264562306a36Sopenharmony_ci
264662306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
264762306a36Sopenharmony_ci	if (ret) {
264862306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
264962306a36Sopenharmony_ci		goto fail;
265062306a36Sopenharmony_ci	}
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
265362306a36Sopenharmony_ci
265462306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_cifail:
265762306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_ci	return ret;
266062306a36Sopenharmony_ci}
266162306a36Sopenharmony_ci
266262306a36Sopenharmony_ci/**
266362306a36Sopenharmony_ci * ti_sci_cmd_proc_set_control() - Command to set the processor boot
266462306a36Sopenharmony_ci *				     control flags
266562306a36Sopenharmony_ci * @handle:			Pointer to TI SCI handle
266662306a36Sopenharmony_ci * @proc_id:			Processor ID this request is for
266762306a36Sopenharmony_ci * @control_flags_set:		Control flags to be set
266862306a36Sopenharmony_ci * @control_flags_clear:	Control flags to be cleared
266962306a36Sopenharmony_ci *
267062306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
267162306a36Sopenharmony_ci */
267262306a36Sopenharmony_cistatic int ti_sci_cmd_proc_set_control(const struct ti_sci_handle *handle,
267362306a36Sopenharmony_ci				       u8 proc_id, u32 control_flags_set,
267462306a36Sopenharmony_ci				       u32 control_flags_clear)
267562306a36Sopenharmony_ci{
267662306a36Sopenharmony_ci	struct ti_sci_msg_req_set_ctrl *req;
267762306a36Sopenharmony_ci	struct ti_sci_msg_hdr *resp;
267862306a36Sopenharmony_ci	struct ti_sci_info *info;
267962306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
268062306a36Sopenharmony_ci	struct device *dev;
268162306a36Sopenharmony_ci	int ret = 0;
268262306a36Sopenharmony_ci
268362306a36Sopenharmony_ci	if (!handle)
268462306a36Sopenharmony_ci		return -EINVAL;
268562306a36Sopenharmony_ci	if (IS_ERR(handle))
268662306a36Sopenharmony_ci		return PTR_ERR(handle);
268762306a36Sopenharmony_ci
268862306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
268962306a36Sopenharmony_ci	dev = info->dev;
269062306a36Sopenharmony_ci
269162306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CTRL,
269262306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
269362306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
269462306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
269562306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
269662306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
269762306a36Sopenharmony_ci		return ret;
269862306a36Sopenharmony_ci	}
269962306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_set_ctrl *)xfer->xfer_buf;
270062306a36Sopenharmony_ci	req->processor_id = proc_id;
270162306a36Sopenharmony_ci	req->control_flags_set = control_flags_set;
270262306a36Sopenharmony_ci	req->control_flags_clear = control_flags_clear;
270362306a36Sopenharmony_ci
270462306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
270562306a36Sopenharmony_ci	if (ret) {
270662306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
270762306a36Sopenharmony_ci		goto fail;
270862306a36Sopenharmony_ci	}
270962306a36Sopenharmony_ci
271062306a36Sopenharmony_ci	resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
271162306a36Sopenharmony_ci
271262306a36Sopenharmony_ci	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
271362306a36Sopenharmony_ci
271462306a36Sopenharmony_cifail:
271562306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
271662306a36Sopenharmony_ci
271762306a36Sopenharmony_ci	return ret;
271862306a36Sopenharmony_ci}
271962306a36Sopenharmony_ci
272062306a36Sopenharmony_ci/**
272162306a36Sopenharmony_ci * ti_sci_cmd_proc_get_status() - Command to get the processor boot status
272262306a36Sopenharmony_ci * @handle:	Pointer to TI SCI handle
272362306a36Sopenharmony_ci * @proc_id:	Processor ID this request is for
272462306a36Sopenharmony_ci * @bv:		Processor Boot vector (start address)
272562306a36Sopenharmony_ci * @cfg_flags:	Processor specific configuration flags
272662306a36Sopenharmony_ci * @ctrl_flags:	Processor specific control flags
272762306a36Sopenharmony_ci * @sts_flags:	Processor specific status flags
272862306a36Sopenharmony_ci *
272962306a36Sopenharmony_ci * Return: 0 if all went well, else returns appropriate error value.
273062306a36Sopenharmony_ci */
273162306a36Sopenharmony_cistatic int ti_sci_cmd_proc_get_status(const struct ti_sci_handle *handle,
273262306a36Sopenharmony_ci				      u8 proc_id, u64 *bv, u32 *cfg_flags,
273362306a36Sopenharmony_ci				      u32 *ctrl_flags, u32 *sts_flags)
273462306a36Sopenharmony_ci{
273562306a36Sopenharmony_ci	struct ti_sci_msg_resp_get_status *resp;
273662306a36Sopenharmony_ci	struct ti_sci_msg_req_get_status *req;
273762306a36Sopenharmony_ci	struct ti_sci_info *info;
273862306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
273962306a36Sopenharmony_ci	struct device *dev;
274062306a36Sopenharmony_ci	int ret = 0;
274162306a36Sopenharmony_ci
274262306a36Sopenharmony_ci	if (!handle)
274362306a36Sopenharmony_ci		return -EINVAL;
274462306a36Sopenharmony_ci	if (IS_ERR(handle))
274562306a36Sopenharmony_ci		return PTR_ERR(handle);
274662306a36Sopenharmony_ci
274762306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
274862306a36Sopenharmony_ci	dev = info->dev;
274962306a36Sopenharmony_ci
275062306a36Sopenharmony_ci	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_STATUS,
275162306a36Sopenharmony_ci				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
275262306a36Sopenharmony_ci				   sizeof(*req), sizeof(*resp));
275362306a36Sopenharmony_ci	if (IS_ERR(xfer)) {
275462306a36Sopenharmony_ci		ret = PTR_ERR(xfer);
275562306a36Sopenharmony_ci		dev_err(dev, "Message alloc failed(%d)\n", ret);
275662306a36Sopenharmony_ci		return ret;
275762306a36Sopenharmony_ci	}
275862306a36Sopenharmony_ci	req = (struct ti_sci_msg_req_get_status *)xfer->xfer_buf;
275962306a36Sopenharmony_ci	req->processor_id = proc_id;
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci	ret = ti_sci_do_xfer(info, xfer);
276262306a36Sopenharmony_ci	if (ret) {
276362306a36Sopenharmony_ci		dev_err(dev, "Mbox send fail %d\n", ret);
276462306a36Sopenharmony_ci		goto fail;
276562306a36Sopenharmony_ci	}
276662306a36Sopenharmony_ci
276762306a36Sopenharmony_ci	resp = (struct ti_sci_msg_resp_get_status *)xfer->tx_message.buf;
276862306a36Sopenharmony_ci
276962306a36Sopenharmony_ci	if (!ti_sci_is_response_ack(resp)) {
277062306a36Sopenharmony_ci		ret = -ENODEV;
277162306a36Sopenharmony_ci	} else {
277262306a36Sopenharmony_ci		*bv = (resp->bootvector_low & TI_SCI_ADDR_LOW_MASK) |
277362306a36Sopenharmony_ci		      (((u64)resp->bootvector_high << TI_SCI_ADDR_HIGH_SHIFT) &
277462306a36Sopenharmony_ci		       TI_SCI_ADDR_HIGH_MASK);
277562306a36Sopenharmony_ci		*cfg_flags = resp->config_flags;
277662306a36Sopenharmony_ci		*ctrl_flags = resp->control_flags;
277762306a36Sopenharmony_ci		*sts_flags = resp->status_flags;
277862306a36Sopenharmony_ci	}
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_cifail:
278162306a36Sopenharmony_ci	ti_sci_put_one_xfer(&info->minfo, xfer);
278262306a36Sopenharmony_ci
278362306a36Sopenharmony_ci	return ret;
278462306a36Sopenharmony_ci}
278562306a36Sopenharmony_ci
278662306a36Sopenharmony_ci/*
278762306a36Sopenharmony_ci * ti_sci_setup_ops() - Setup the operations structures
278862306a36Sopenharmony_ci * @info:	pointer to TISCI pointer
278962306a36Sopenharmony_ci */
279062306a36Sopenharmony_cistatic void ti_sci_setup_ops(struct ti_sci_info *info)
279162306a36Sopenharmony_ci{
279262306a36Sopenharmony_ci	struct ti_sci_ops *ops = &info->handle.ops;
279362306a36Sopenharmony_ci	struct ti_sci_core_ops *core_ops = &ops->core_ops;
279462306a36Sopenharmony_ci	struct ti_sci_dev_ops *dops = &ops->dev_ops;
279562306a36Sopenharmony_ci	struct ti_sci_clk_ops *cops = &ops->clk_ops;
279662306a36Sopenharmony_ci	struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
279762306a36Sopenharmony_ci	struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops;
279862306a36Sopenharmony_ci	struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
279962306a36Sopenharmony_ci	struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops;
280062306a36Sopenharmony_ci	struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops;
280162306a36Sopenharmony_ci	struct ti_sci_proc_ops *pops = &ops->proc_ops;
280262306a36Sopenharmony_ci
280362306a36Sopenharmony_ci	core_ops->reboot_device = ti_sci_cmd_core_reboot;
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_ci	dops->get_device = ti_sci_cmd_get_device;
280662306a36Sopenharmony_ci	dops->get_device_exclusive = ti_sci_cmd_get_device_exclusive;
280762306a36Sopenharmony_ci	dops->idle_device = ti_sci_cmd_idle_device;
280862306a36Sopenharmony_ci	dops->idle_device_exclusive = ti_sci_cmd_idle_device_exclusive;
280962306a36Sopenharmony_ci	dops->put_device = ti_sci_cmd_put_device;
281062306a36Sopenharmony_ci
281162306a36Sopenharmony_ci	dops->is_valid = ti_sci_cmd_dev_is_valid;
281262306a36Sopenharmony_ci	dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
281362306a36Sopenharmony_ci	dops->is_idle = ti_sci_cmd_dev_is_idle;
281462306a36Sopenharmony_ci	dops->is_stop = ti_sci_cmd_dev_is_stop;
281562306a36Sopenharmony_ci	dops->is_on = ti_sci_cmd_dev_is_on;
281662306a36Sopenharmony_ci	dops->is_transitioning = ti_sci_cmd_dev_is_trans;
281762306a36Sopenharmony_ci	dops->set_device_resets = ti_sci_cmd_set_device_resets;
281862306a36Sopenharmony_ci	dops->get_device_resets = ti_sci_cmd_get_device_resets;
281962306a36Sopenharmony_ci
282062306a36Sopenharmony_ci	cops->get_clock = ti_sci_cmd_get_clock;
282162306a36Sopenharmony_ci	cops->idle_clock = ti_sci_cmd_idle_clock;
282262306a36Sopenharmony_ci	cops->put_clock = ti_sci_cmd_put_clock;
282362306a36Sopenharmony_ci	cops->is_auto = ti_sci_cmd_clk_is_auto;
282462306a36Sopenharmony_ci	cops->is_on = ti_sci_cmd_clk_is_on;
282562306a36Sopenharmony_ci	cops->is_off = ti_sci_cmd_clk_is_off;
282662306a36Sopenharmony_ci
282762306a36Sopenharmony_ci	cops->set_parent = ti_sci_cmd_clk_set_parent;
282862306a36Sopenharmony_ci	cops->get_parent = ti_sci_cmd_clk_get_parent;
282962306a36Sopenharmony_ci	cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
283062306a36Sopenharmony_ci
283162306a36Sopenharmony_ci	cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
283262306a36Sopenharmony_ci	cops->set_freq = ti_sci_cmd_clk_set_freq;
283362306a36Sopenharmony_ci	cops->get_freq = ti_sci_cmd_clk_get_freq;
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_ci	rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
283662306a36Sopenharmony_ci	rm_core_ops->get_range_from_shost =
283762306a36Sopenharmony_ci				ti_sci_cmd_get_resource_range_from_shost;
283862306a36Sopenharmony_ci
283962306a36Sopenharmony_ci	iops->set_irq = ti_sci_cmd_set_irq;
284062306a36Sopenharmony_ci	iops->set_event_map = ti_sci_cmd_set_event_map;
284162306a36Sopenharmony_ci	iops->free_irq = ti_sci_cmd_free_irq;
284262306a36Sopenharmony_ci	iops->free_event_map = ti_sci_cmd_free_event_map;
284362306a36Sopenharmony_ci
284462306a36Sopenharmony_ci	rops->set_cfg = ti_sci_cmd_rm_ring_cfg;
284562306a36Sopenharmony_ci
284662306a36Sopenharmony_ci	psilops->pair = ti_sci_cmd_rm_psil_pair;
284762306a36Sopenharmony_ci	psilops->unpair = ti_sci_cmd_rm_psil_unpair;
284862306a36Sopenharmony_ci
284962306a36Sopenharmony_ci	udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg;
285062306a36Sopenharmony_ci	udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg;
285162306a36Sopenharmony_ci	udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg;
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci	pops->request = ti_sci_cmd_proc_request;
285462306a36Sopenharmony_ci	pops->release = ti_sci_cmd_proc_release;
285562306a36Sopenharmony_ci	pops->handover = ti_sci_cmd_proc_handover;
285662306a36Sopenharmony_ci	pops->set_config = ti_sci_cmd_proc_set_config;
285762306a36Sopenharmony_ci	pops->set_control = ti_sci_cmd_proc_set_control;
285862306a36Sopenharmony_ci	pops->get_status = ti_sci_cmd_proc_get_status;
285962306a36Sopenharmony_ci}
286062306a36Sopenharmony_ci
286162306a36Sopenharmony_ci/**
286262306a36Sopenharmony_ci * ti_sci_get_handle() - Get the TI SCI handle for a device
286362306a36Sopenharmony_ci * @dev:	Pointer to device for which we want SCI handle
286462306a36Sopenharmony_ci *
286562306a36Sopenharmony_ci * NOTE: The function does not track individual clients of the framework
286662306a36Sopenharmony_ci * and is expected to be maintained by caller of TI SCI protocol library.
286762306a36Sopenharmony_ci * ti_sci_put_handle must be balanced with successful ti_sci_get_handle
286862306a36Sopenharmony_ci * Return: pointer to handle if successful, else:
286962306a36Sopenharmony_ci * -EPROBE_DEFER if the instance is not ready
287062306a36Sopenharmony_ci * -ENODEV if the required node handler is missing
287162306a36Sopenharmony_ci * -EINVAL if invalid conditions are encountered.
287262306a36Sopenharmony_ci */
287362306a36Sopenharmony_ciconst struct ti_sci_handle *ti_sci_get_handle(struct device *dev)
287462306a36Sopenharmony_ci{
287562306a36Sopenharmony_ci	struct device_node *ti_sci_np;
287662306a36Sopenharmony_ci	struct list_head *p;
287762306a36Sopenharmony_ci	struct ti_sci_handle *handle = NULL;
287862306a36Sopenharmony_ci	struct ti_sci_info *info;
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	if (!dev) {
288162306a36Sopenharmony_ci		pr_err("I need a device pointer\n");
288262306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
288362306a36Sopenharmony_ci	}
288462306a36Sopenharmony_ci	ti_sci_np = of_get_parent(dev->of_node);
288562306a36Sopenharmony_ci	if (!ti_sci_np) {
288662306a36Sopenharmony_ci		dev_err(dev, "No OF information\n");
288762306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
288862306a36Sopenharmony_ci	}
288962306a36Sopenharmony_ci
289062306a36Sopenharmony_ci	mutex_lock(&ti_sci_list_mutex);
289162306a36Sopenharmony_ci	list_for_each(p, &ti_sci_list) {
289262306a36Sopenharmony_ci		info = list_entry(p, struct ti_sci_info, node);
289362306a36Sopenharmony_ci		if (ti_sci_np == info->dev->of_node) {
289462306a36Sopenharmony_ci			handle = &info->handle;
289562306a36Sopenharmony_ci			info->users++;
289662306a36Sopenharmony_ci			break;
289762306a36Sopenharmony_ci		}
289862306a36Sopenharmony_ci	}
289962306a36Sopenharmony_ci	mutex_unlock(&ti_sci_list_mutex);
290062306a36Sopenharmony_ci	of_node_put(ti_sci_np);
290162306a36Sopenharmony_ci
290262306a36Sopenharmony_ci	if (!handle)
290362306a36Sopenharmony_ci		return ERR_PTR(-EPROBE_DEFER);
290462306a36Sopenharmony_ci
290562306a36Sopenharmony_ci	return handle;
290662306a36Sopenharmony_ci}
290762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ti_sci_get_handle);
290862306a36Sopenharmony_ci
290962306a36Sopenharmony_ci/**
291062306a36Sopenharmony_ci * ti_sci_put_handle() - Release the handle acquired by ti_sci_get_handle
291162306a36Sopenharmony_ci * @handle:	Handle acquired by ti_sci_get_handle
291262306a36Sopenharmony_ci *
291362306a36Sopenharmony_ci * NOTE: The function does not track individual clients of the framework
291462306a36Sopenharmony_ci * and is expected to be maintained by caller of TI SCI protocol library.
291562306a36Sopenharmony_ci * ti_sci_put_handle must be balanced with successful ti_sci_get_handle
291662306a36Sopenharmony_ci *
291762306a36Sopenharmony_ci * Return: 0 is successfully released
291862306a36Sopenharmony_ci * if an error pointer was passed, it returns the error value back,
291962306a36Sopenharmony_ci * if null was passed, it returns -EINVAL;
292062306a36Sopenharmony_ci */
292162306a36Sopenharmony_ciint ti_sci_put_handle(const struct ti_sci_handle *handle)
292262306a36Sopenharmony_ci{
292362306a36Sopenharmony_ci	struct ti_sci_info *info;
292462306a36Sopenharmony_ci
292562306a36Sopenharmony_ci	if (IS_ERR(handle))
292662306a36Sopenharmony_ci		return PTR_ERR(handle);
292762306a36Sopenharmony_ci	if (!handle)
292862306a36Sopenharmony_ci		return -EINVAL;
292962306a36Sopenharmony_ci
293062306a36Sopenharmony_ci	info = handle_to_ti_sci_info(handle);
293162306a36Sopenharmony_ci	mutex_lock(&ti_sci_list_mutex);
293262306a36Sopenharmony_ci	if (!WARN_ON(!info->users))
293362306a36Sopenharmony_ci		info->users--;
293462306a36Sopenharmony_ci	mutex_unlock(&ti_sci_list_mutex);
293562306a36Sopenharmony_ci
293662306a36Sopenharmony_ci	return 0;
293762306a36Sopenharmony_ci}
293862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ti_sci_put_handle);
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_cistatic void devm_ti_sci_release(struct device *dev, void *res)
294162306a36Sopenharmony_ci{
294262306a36Sopenharmony_ci	const struct ti_sci_handle **ptr = res;
294362306a36Sopenharmony_ci	const struct ti_sci_handle *handle = *ptr;
294462306a36Sopenharmony_ci	int ret;
294562306a36Sopenharmony_ci
294662306a36Sopenharmony_ci	ret = ti_sci_put_handle(handle);
294762306a36Sopenharmony_ci	if (ret)
294862306a36Sopenharmony_ci		dev_err(dev, "failed to put handle %d\n", ret);
294962306a36Sopenharmony_ci}
295062306a36Sopenharmony_ci
295162306a36Sopenharmony_ci/**
295262306a36Sopenharmony_ci * devm_ti_sci_get_handle() - Managed get handle
295362306a36Sopenharmony_ci * @dev:	device for which we want SCI handle for.
295462306a36Sopenharmony_ci *
295562306a36Sopenharmony_ci * NOTE: This releases the handle once the device resources are
295662306a36Sopenharmony_ci * no longer needed. MUST NOT BE released with ti_sci_put_handle.
295762306a36Sopenharmony_ci * The function does not track individual clients of the framework
295862306a36Sopenharmony_ci * and is expected to be maintained by caller of TI SCI protocol library.
295962306a36Sopenharmony_ci *
296062306a36Sopenharmony_ci * Return: 0 if all went fine, else corresponding error.
296162306a36Sopenharmony_ci */
296262306a36Sopenharmony_ciconst struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev)
296362306a36Sopenharmony_ci{
296462306a36Sopenharmony_ci	const struct ti_sci_handle **ptr;
296562306a36Sopenharmony_ci	const struct ti_sci_handle *handle;
296662306a36Sopenharmony_ci
296762306a36Sopenharmony_ci	ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL);
296862306a36Sopenharmony_ci	if (!ptr)
296962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
297062306a36Sopenharmony_ci	handle = ti_sci_get_handle(dev);
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_ci	if (!IS_ERR(handle)) {
297362306a36Sopenharmony_ci		*ptr = handle;
297462306a36Sopenharmony_ci		devres_add(dev, ptr);
297562306a36Sopenharmony_ci	} else {
297662306a36Sopenharmony_ci		devres_free(ptr);
297762306a36Sopenharmony_ci	}
297862306a36Sopenharmony_ci
297962306a36Sopenharmony_ci	return handle;
298062306a36Sopenharmony_ci}
298162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_ti_sci_get_handle);
298262306a36Sopenharmony_ci
298362306a36Sopenharmony_ci/**
298462306a36Sopenharmony_ci * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
298562306a36Sopenharmony_ci * @np:		device node
298662306a36Sopenharmony_ci * @property:	property name containing phandle on TISCI node
298762306a36Sopenharmony_ci *
298862306a36Sopenharmony_ci * NOTE: The function does not track individual clients of the framework
298962306a36Sopenharmony_ci * and is expected to be maintained by caller of TI SCI protocol library.
299062306a36Sopenharmony_ci * ti_sci_put_handle must be balanced with successful ti_sci_get_by_phandle
299162306a36Sopenharmony_ci * Return: pointer to handle if successful, else:
299262306a36Sopenharmony_ci * -EPROBE_DEFER if the instance is not ready
299362306a36Sopenharmony_ci * -ENODEV if the required node handler is missing
299462306a36Sopenharmony_ci * -EINVAL if invalid conditions are encountered.
299562306a36Sopenharmony_ci */
299662306a36Sopenharmony_ciconst struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
299762306a36Sopenharmony_ci						  const char *property)
299862306a36Sopenharmony_ci{
299962306a36Sopenharmony_ci	struct ti_sci_handle *handle = NULL;
300062306a36Sopenharmony_ci	struct device_node *ti_sci_np;
300162306a36Sopenharmony_ci	struct ti_sci_info *info;
300262306a36Sopenharmony_ci	struct list_head *p;
300362306a36Sopenharmony_ci
300462306a36Sopenharmony_ci	if (!np) {
300562306a36Sopenharmony_ci		pr_err("I need a device pointer\n");
300662306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
300762306a36Sopenharmony_ci	}
300862306a36Sopenharmony_ci
300962306a36Sopenharmony_ci	ti_sci_np = of_parse_phandle(np, property, 0);
301062306a36Sopenharmony_ci	if (!ti_sci_np)
301162306a36Sopenharmony_ci		return ERR_PTR(-ENODEV);
301262306a36Sopenharmony_ci
301362306a36Sopenharmony_ci	mutex_lock(&ti_sci_list_mutex);
301462306a36Sopenharmony_ci	list_for_each(p, &ti_sci_list) {
301562306a36Sopenharmony_ci		info = list_entry(p, struct ti_sci_info, node);
301662306a36Sopenharmony_ci		if (ti_sci_np == info->dev->of_node) {
301762306a36Sopenharmony_ci			handle = &info->handle;
301862306a36Sopenharmony_ci			info->users++;
301962306a36Sopenharmony_ci			break;
302062306a36Sopenharmony_ci		}
302162306a36Sopenharmony_ci	}
302262306a36Sopenharmony_ci	mutex_unlock(&ti_sci_list_mutex);
302362306a36Sopenharmony_ci	of_node_put(ti_sci_np);
302462306a36Sopenharmony_ci
302562306a36Sopenharmony_ci	if (!handle)
302662306a36Sopenharmony_ci		return ERR_PTR(-EPROBE_DEFER);
302762306a36Sopenharmony_ci
302862306a36Sopenharmony_ci	return handle;
302962306a36Sopenharmony_ci}
303062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ti_sci_get_by_phandle);
303162306a36Sopenharmony_ci
303262306a36Sopenharmony_ci/**
303362306a36Sopenharmony_ci * devm_ti_sci_get_by_phandle() - Managed get handle using phandle
303462306a36Sopenharmony_ci * @dev:	Device pointer requesting TISCI handle
303562306a36Sopenharmony_ci * @property:	property name containing phandle on TISCI node
303662306a36Sopenharmony_ci *
303762306a36Sopenharmony_ci * NOTE: This releases the handle once the device resources are
303862306a36Sopenharmony_ci * no longer needed. MUST NOT BE released with ti_sci_put_handle.
303962306a36Sopenharmony_ci * The function does not track individual clients of the framework
304062306a36Sopenharmony_ci * and is expected to be maintained by caller of TI SCI protocol library.
304162306a36Sopenharmony_ci *
304262306a36Sopenharmony_ci * Return: 0 if all went fine, else corresponding error.
304362306a36Sopenharmony_ci */
304462306a36Sopenharmony_ciconst struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
304562306a36Sopenharmony_ci						       const char *property)
304662306a36Sopenharmony_ci{
304762306a36Sopenharmony_ci	const struct ti_sci_handle *handle;
304862306a36Sopenharmony_ci	const struct ti_sci_handle **ptr;
304962306a36Sopenharmony_ci
305062306a36Sopenharmony_ci	ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL);
305162306a36Sopenharmony_ci	if (!ptr)
305262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
305362306a36Sopenharmony_ci	handle = ti_sci_get_by_phandle(dev_of_node(dev), property);
305462306a36Sopenharmony_ci
305562306a36Sopenharmony_ci	if (!IS_ERR(handle)) {
305662306a36Sopenharmony_ci		*ptr = handle;
305762306a36Sopenharmony_ci		devres_add(dev, ptr);
305862306a36Sopenharmony_ci	} else {
305962306a36Sopenharmony_ci		devres_free(ptr);
306062306a36Sopenharmony_ci	}
306162306a36Sopenharmony_ci
306262306a36Sopenharmony_ci	return handle;
306362306a36Sopenharmony_ci}
306462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_ti_sci_get_by_phandle);
306562306a36Sopenharmony_ci
306662306a36Sopenharmony_ci/**
306762306a36Sopenharmony_ci * ti_sci_get_free_resource() - Get a free resource from TISCI resource.
306862306a36Sopenharmony_ci * @res:	Pointer to the TISCI resource
306962306a36Sopenharmony_ci *
307062306a36Sopenharmony_ci * Return: resource num if all went ok else TI_SCI_RESOURCE_NULL.
307162306a36Sopenharmony_ci */
307262306a36Sopenharmony_ciu16 ti_sci_get_free_resource(struct ti_sci_resource *res)
307362306a36Sopenharmony_ci{
307462306a36Sopenharmony_ci	unsigned long flags;
307562306a36Sopenharmony_ci	u16 set, free_bit;
307662306a36Sopenharmony_ci
307762306a36Sopenharmony_ci	raw_spin_lock_irqsave(&res->lock, flags);
307862306a36Sopenharmony_ci	for (set = 0; set < res->sets; set++) {
307962306a36Sopenharmony_ci		struct ti_sci_resource_desc *desc = &res->desc[set];
308062306a36Sopenharmony_ci		int res_count = desc->num + desc->num_sec;
308162306a36Sopenharmony_ci
308262306a36Sopenharmony_ci		free_bit = find_first_zero_bit(desc->res_map, res_count);
308362306a36Sopenharmony_ci		if (free_bit != res_count) {
308462306a36Sopenharmony_ci			__set_bit(free_bit, desc->res_map);
308562306a36Sopenharmony_ci			raw_spin_unlock_irqrestore(&res->lock, flags);
308662306a36Sopenharmony_ci
308762306a36Sopenharmony_ci			if (desc->num && free_bit < desc->num)
308862306a36Sopenharmony_ci				return desc->start + free_bit;
308962306a36Sopenharmony_ci			else
309062306a36Sopenharmony_ci				return desc->start_sec + free_bit;
309162306a36Sopenharmony_ci		}
309262306a36Sopenharmony_ci	}
309362306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&res->lock, flags);
309462306a36Sopenharmony_ci
309562306a36Sopenharmony_ci	return TI_SCI_RESOURCE_NULL;
309662306a36Sopenharmony_ci}
309762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ti_sci_get_free_resource);
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ci/**
310062306a36Sopenharmony_ci * ti_sci_release_resource() - Release a resource from TISCI resource.
310162306a36Sopenharmony_ci * @res:	Pointer to the TISCI resource
310262306a36Sopenharmony_ci * @id:		Resource id to be released.
310362306a36Sopenharmony_ci */
310462306a36Sopenharmony_civoid ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
310562306a36Sopenharmony_ci{
310662306a36Sopenharmony_ci	unsigned long flags;
310762306a36Sopenharmony_ci	u16 set;
310862306a36Sopenharmony_ci
310962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&res->lock, flags);
311062306a36Sopenharmony_ci	for (set = 0; set < res->sets; set++) {
311162306a36Sopenharmony_ci		struct ti_sci_resource_desc *desc = &res->desc[set];
311262306a36Sopenharmony_ci
311362306a36Sopenharmony_ci		if (desc->num && desc->start <= id &&
311462306a36Sopenharmony_ci		    (desc->start + desc->num) > id)
311562306a36Sopenharmony_ci			__clear_bit(id - desc->start, desc->res_map);
311662306a36Sopenharmony_ci		else if (desc->num_sec && desc->start_sec <= id &&
311762306a36Sopenharmony_ci			 (desc->start_sec + desc->num_sec) > id)
311862306a36Sopenharmony_ci			__clear_bit(id - desc->start_sec, desc->res_map);
311962306a36Sopenharmony_ci	}
312062306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&res->lock, flags);
312162306a36Sopenharmony_ci}
312262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ti_sci_release_resource);
312362306a36Sopenharmony_ci
312462306a36Sopenharmony_ci/**
312562306a36Sopenharmony_ci * ti_sci_get_num_resources() - Get the number of resources in TISCI resource
312662306a36Sopenharmony_ci * @res:	Pointer to the TISCI resource
312762306a36Sopenharmony_ci *
312862306a36Sopenharmony_ci * Return: Total number of available resources.
312962306a36Sopenharmony_ci */
313062306a36Sopenharmony_ciu32 ti_sci_get_num_resources(struct ti_sci_resource *res)
313162306a36Sopenharmony_ci{
313262306a36Sopenharmony_ci	u32 set, count = 0;
313362306a36Sopenharmony_ci
313462306a36Sopenharmony_ci	for (set = 0; set < res->sets; set++)
313562306a36Sopenharmony_ci		count += res->desc[set].num + res->desc[set].num_sec;
313662306a36Sopenharmony_ci
313762306a36Sopenharmony_ci	return count;
313862306a36Sopenharmony_ci}
313962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ti_sci_get_num_resources);
314062306a36Sopenharmony_ci
314162306a36Sopenharmony_ci/**
314262306a36Sopenharmony_ci * devm_ti_sci_get_resource_sets() - Get a TISCI resources assigned to a device
314362306a36Sopenharmony_ci * @handle:	TISCI handle
314462306a36Sopenharmony_ci * @dev:	Device pointer to which the resource is assigned
314562306a36Sopenharmony_ci * @dev_id:	TISCI device id to which the resource is assigned
314662306a36Sopenharmony_ci * @sub_types:	Array of sub_types assigned corresponding to device
314762306a36Sopenharmony_ci * @sets:	Number of sub_types
314862306a36Sopenharmony_ci *
314962306a36Sopenharmony_ci * Return: Pointer to ti_sci_resource if all went well else appropriate
315062306a36Sopenharmony_ci *	   error pointer.
315162306a36Sopenharmony_ci */
315262306a36Sopenharmony_cistatic struct ti_sci_resource *
315362306a36Sopenharmony_cidevm_ti_sci_get_resource_sets(const struct ti_sci_handle *handle,
315462306a36Sopenharmony_ci			      struct device *dev, u32 dev_id, u32 *sub_types,
315562306a36Sopenharmony_ci			      u32 sets)
315662306a36Sopenharmony_ci{
315762306a36Sopenharmony_ci	struct ti_sci_resource *res;
315862306a36Sopenharmony_ci	bool valid_set = false;
315962306a36Sopenharmony_ci	int i, ret, res_count;
316062306a36Sopenharmony_ci
316162306a36Sopenharmony_ci	res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
316262306a36Sopenharmony_ci	if (!res)
316362306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
316462306a36Sopenharmony_ci
316562306a36Sopenharmony_ci	res->sets = sets;
316662306a36Sopenharmony_ci	res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc),
316762306a36Sopenharmony_ci				 GFP_KERNEL);
316862306a36Sopenharmony_ci	if (!res->desc)
316962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
317062306a36Sopenharmony_ci
317162306a36Sopenharmony_ci	for (i = 0; i < res->sets; i++) {
317262306a36Sopenharmony_ci		ret = handle->ops.rm_core_ops.get_range(handle, dev_id,
317362306a36Sopenharmony_ci							sub_types[i],
317462306a36Sopenharmony_ci							&res->desc[i]);
317562306a36Sopenharmony_ci		if (ret) {
317662306a36Sopenharmony_ci			dev_dbg(dev, "dev = %d subtype %d not allocated for this host\n",
317762306a36Sopenharmony_ci				dev_id, sub_types[i]);
317862306a36Sopenharmony_ci			memset(&res->desc[i], 0, sizeof(res->desc[i]));
317962306a36Sopenharmony_ci			continue;
318062306a36Sopenharmony_ci		}
318162306a36Sopenharmony_ci
318262306a36Sopenharmony_ci		dev_dbg(dev, "dev/sub_type: %d/%d, start/num: %d/%d | %d/%d\n",
318362306a36Sopenharmony_ci			dev_id, sub_types[i], res->desc[i].start,
318462306a36Sopenharmony_ci			res->desc[i].num, res->desc[i].start_sec,
318562306a36Sopenharmony_ci			res->desc[i].num_sec);
318662306a36Sopenharmony_ci
318762306a36Sopenharmony_ci		valid_set = true;
318862306a36Sopenharmony_ci		res_count = res->desc[i].num + res->desc[i].num_sec;
318962306a36Sopenharmony_ci		res->desc[i].res_map = devm_bitmap_zalloc(dev, res_count,
319062306a36Sopenharmony_ci							  GFP_KERNEL);
319162306a36Sopenharmony_ci		if (!res->desc[i].res_map)
319262306a36Sopenharmony_ci			return ERR_PTR(-ENOMEM);
319362306a36Sopenharmony_ci	}
319462306a36Sopenharmony_ci	raw_spin_lock_init(&res->lock);
319562306a36Sopenharmony_ci
319662306a36Sopenharmony_ci	if (valid_set)
319762306a36Sopenharmony_ci		return res;
319862306a36Sopenharmony_ci
319962306a36Sopenharmony_ci	return ERR_PTR(-EINVAL);
320062306a36Sopenharmony_ci}
320162306a36Sopenharmony_ci
320262306a36Sopenharmony_ci/**
320362306a36Sopenharmony_ci * devm_ti_sci_get_of_resource() - Get a TISCI resource assigned to a device
320462306a36Sopenharmony_ci * @handle:	TISCI handle
320562306a36Sopenharmony_ci * @dev:	Device pointer to which the resource is assigned
320662306a36Sopenharmony_ci * @dev_id:	TISCI device id to which the resource is assigned
320762306a36Sopenharmony_ci * @of_prop:	property name by which the resource are represented
320862306a36Sopenharmony_ci *
320962306a36Sopenharmony_ci * Return: Pointer to ti_sci_resource if all went well else appropriate
321062306a36Sopenharmony_ci *	   error pointer.
321162306a36Sopenharmony_ci */
321262306a36Sopenharmony_cistruct ti_sci_resource *
321362306a36Sopenharmony_cidevm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
321462306a36Sopenharmony_ci			    struct device *dev, u32 dev_id, char *of_prop)
321562306a36Sopenharmony_ci{
321662306a36Sopenharmony_ci	struct ti_sci_resource *res;
321762306a36Sopenharmony_ci	u32 *sub_types;
321862306a36Sopenharmony_ci	int sets;
321962306a36Sopenharmony_ci
322062306a36Sopenharmony_ci	sets = of_property_count_elems_of_size(dev_of_node(dev), of_prop,
322162306a36Sopenharmony_ci					       sizeof(u32));
322262306a36Sopenharmony_ci	if (sets < 0) {
322362306a36Sopenharmony_ci		dev_err(dev, "%s resource type ids not available\n", of_prop);
322462306a36Sopenharmony_ci		return ERR_PTR(sets);
322562306a36Sopenharmony_ci	}
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_ci	sub_types = kcalloc(sets, sizeof(*sub_types), GFP_KERNEL);
322862306a36Sopenharmony_ci	if (!sub_types)
322962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
323062306a36Sopenharmony_ci
323162306a36Sopenharmony_ci	of_property_read_u32_array(dev_of_node(dev), of_prop, sub_types, sets);
323262306a36Sopenharmony_ci	res = devm_ti_sci_get_resource_sets(handle, dev, dev_id, sub_types,
323362306a36Sopenharmony_ci					    sets);
323462306a36Sopenharmony_ci
323562306a36Sopenharmony_ci	kfree(sub_types);
323662306a36Sopenharmony_ci	return res;
323762306a36Sopenharmony_ci}
323862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_ti_sci_get_of_resource);
323962306a36Sopenharmony_ci
324062306a36Sopenharmony_ci/**
324162306a36Sopenharmony_ci * devm_ti_sci_get_resource() - Get a resource range assigned to the device
324262306a36Sopenharmony_ci * @handle:	TISCI handle
324362306a36Sopenharmony_ci * @dev:	Device pointer to which the resource is assigned
324462306a36Sopenharmony_ci * @dev_id:	TISCI device id to which the resource is assigned
324562306a36Sopenharmony_ci * @sub_type:	TISCI resource subytpe representing the resource.
324662306a36Sopenharmony_ci *
324762306a36Sopenharmony_ci * Return: Pointer to ti_sci_resource if all went well else appropriate
324862306a36Sopenharmony_ci *	   error pointer.
324962306a36Sopenharmony_ci */
325062306a36Sopenharmony_cistruct ti_sci_resource *
325162306a36Sopenharmony_cidevm_ti_sci_get_resource(const struct ti_sci_handle *handle, struct device *dev,
325262306a36Sopenharmony_ci			 u32 dev_id, u32 sub_type)
325362306a36Sopenharmony_ci{
325462306a36Sopenharmony_ci	return devm_ti_sci_get_resource_sets(handle, dev, dev_id, &sub_type, 1);
325562306a36Sopenharmony_ci}
325662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_ti_sci_get_resource);
325762306a36Sopenharmony_ci
325862306a36Sopenharmony_cistatic int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode,
325962306a36Sopenharmony_ci				void *cmd)
326062306a36Sopenharmony_ci{
326162306a36Sopenharmony_ci	struct ti_sci_info *info = reboot_to_ti_sci_info(nb);
326262306a36Sopenharmony_ci	const struct ti_sci_handle *handle = &info->handle;
326362306a36Sopenharmony_ci
326462306a36Sopenharmony_ci	ti_sci_cmd_core_reboot(handle);
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci	/* call fail OR pass, we should not be here in the first place */
326762306a36Sopenharmony_ci	return NOTIFY_BAD;
326862306a36Sopenharmony_ci}
326962306a36Sopenharmony_ci
327062306a36Sopenharmony_ci/* Description for K2G */
327162306a36Sopenharmony_cistatic const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
327262306a36Sopenharmony_ci	.default_host_id = 2,
327362306a36Sopenharmony_ci	/* Conservative duration */
327462306a36Sopenharmony_ci	.max_rx_timeout_ms = 1000,
327562306a36Sopenharmony_ci	/* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
327662306a36Sopenharmony_ci	.max_msgs = 20,
327762306a36Sopenharmony_ci	.max_msg_size = 64,
327862306a36Sopenharmony_ci};
327962306a36Sopenharmony_ci
328062306a36Sopenharmony_ci/* Description for AM654 */
328162306a36Sopenharmony_cistatic const struct ti_sci_desc ti_sci_pmmc_am654_desc = {
328262306a36Sopenharmony_ci	.default_host_id = 12,
328362306a36Sopenharmony_ci	/* Conservative duration */
328462306a36Sopenharmony_ci	.max_rx_timeout_ms = 10000,
328562306a36Sopenharmony_ci	/* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
328662306a36Sopenharmony_ci	.max_msgs = 20,
328762306a36Sopenharmony_ci	.max_msg_size = 60,
328862306a36Sopenharmony_ci};
328962306a36Sopenharmony_ci
329062306a36Sopenharmony_cistatic const struct of_device_id ti_sci_of_match[] = {
329162306a36Sopenharmony_ci	{.compatible = "ti,k2g-sci", .data = &ti_sci_pmmc_k2g_desc},
329262306a36Sopenharmony_ci	{.compatible = "ti,am654-sci", .data = &ti_sci_pmmc_am654_desc},
329362306a36Sopenharmony_ci	{ /* Sentinel */ },
329462306a36Sopenharmony_ci};
329562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ti_sci_of_match);
329662306a36Sopenharmony_ci
329762306a36Sopenharmony_cistatic int ti_sci_probe(struct platform_device *pdev)
329862306a36Sopenharmony_ci{
329962306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
330062306a36Sopenharmony_ci	const struct of_device_id *of_id;
330162306a36Sopenharmony_ci	const struct ti_sci_desc *desc;
330262306a36Sopenharmony_ci	struct ti_sci_xfer *xfer;
330362306a36Sopenharmony_ci	struct ti_sci_info *info = NULL;
330462306a36Sopenharmony_ci	struct ti_sci_xfers_info *minfo;
330562306a36Sopenharmony_ci	struct mbox_client *cl;
330662306a36Sopenharmony_ci	int ret = -EINVAL;
330762306a36Sopenharmony_ci	int i;
330862306a36Sopenharmony_ci	int reboot = 0;
330962306a36Sopenharmony_ci	u32 h_id;
331062306a36Sopenharmony_ci
331162306a36Sopenharmony_ci	of_id = of_match_device(ti_sci_of_match, dev);
331262306a36Sopenharmony_ci	if (!of_id) {
331362306a36Sopenharmony_ci		dev_err(dev, "OF data missing\n");
331462306a36Sopenharmony_ci		return -EINVAL;
331562306a36Sopenharmony_ci	}
331662306a36Sopenharmony_ci	desc = of_id->data;
331762306a36Sopenharmony_ci
331862306a36Sopenharmony_ci	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
331962306a36Sopenharmony_ci	if (!info)
332062306a36Sopenharmony_ci		return -ENOMEM;
332162306a36Sopenharmony_ci
332262306a36Sopenharmony_ci	info->dev = dev;
332362306a36Sopenharmony_ci	info->desc = desc;
332462306a36Sopenharmony_ci	ret = of_property_read_u32(dev->of_node, "ti,host-id", &h_id);
332562306a36Sopenharmony_ci	/* if the property is not present in DT, use a default from desc */
332662306a36Sopenharmony_ci	if (ret < 0) {
332762306a36Sopenharmony_ci		info->host_id = info->desc->default_host_id;
332862306a36Sopenharmony_ci	} else {
332962306a36Sopenharmony_ci		if (!h_id) {
333062306a36Sopenharmony_ci			dev_warn(dev, "Host ID 0 is reserved for firmware\n");
333162306a36Sopenharmony_ci			info->host_id = info->desc->default_host_id;
333262306a36Sopenharmony_ci		} else {
333362306a36Sopenharmony_ci			info->host_id = h_id;
333462306a36Sopenharmony_ci		}
333562306a36Sopenharmony_ci	}
333662306a36Sopenharmony_ci
333762306a36Sopenharmony_ci	reboot = of_property_read_bool(dev->of_node,
333862306a36Sopenharmony_ci				       "ti,system-reboot-controller");
333962306a36Sopenharmony_ci	INIT_LIST_HEAD(&info->node);
334062306a36Sopenharmony_ci	minfo = &info->minfo;
334162306a36Sopenharmony_ci
334262306a36Sopenharmony_ci	/*
334362306a36Sopenharmony_ci	 * Pre-allocate messages
334462306a36Sopenharmony_ci	 * NEVER allocate more than what we can indicate in hdr.seq
334562306a36Sopenharmony_ci	 * if we have data description bug, force a fix..
334662306a36Sopenharmony_ci	 */
334762306a36Sopenharmony_ci	if (WARN_ON(desc->max_msgs >=
334862306a36Sopenharmony_ci		    1 << 8 * sizeof(((struct ti_sci_msg_hdr *)0)->seq)))
334962306a36Sopenharmony_ci		return -EINVAL;
335062306a36Sopenharmony_ci
335162306a36Sopenharmony_ci	minfo->xfer_block = devm_kcalloc(dev,
335262306a36Sopenharmony_ci					 desc->max_msgs,
335362306a36Sopenharmony_ci					 sizeof(*minfo->xfer_block),
335462306a36Sopenharmony_ci					 GFP_KERNEL);
335562306a36Sopenharmony_ci	if (!minfo->xfer_block)
335662306a36Sopenharmony_ci		return -ENOMEM;
335762306a36Sopenharmony_ci
335862306a36Sopenharmony_ci	minfo->xfer_alloc_table = devm_bitmap_zalloc(dev,
335962306a36Sopenharmony_ci						     desc->max_msgs,
336062306a36Sopenharmony_ci						     GFP_KERNEL);
336162306a36Sopenharmony_ci	if (!minfo->xfer_alloc_table)
336262306a36Sopenharmony_ci		return -ENOMEM;
336362306a36Sopenharmony_ci
336462306a36Sopenharmony_ci	/* Pre-initialize the buffer pointer to pre-allocated buffers */
336562306a36Sopenharmony_ci	for (i = 0, xfer = minfo->xfer_block; i < desc->max_msgs; i++, xfer++) {
336662306a36Sopenharmony_ci		xfer->xfer_buf = devm_kcalloc(dev, 1, desc->max_msg_size,
336762306a36Sopenharmony_ci					      GFP_KERNEL);
336862306a36Sopenharmony_ci		if (!xfer->xfer_buf)
336962306a36Sopenharmony_ci			return -ENOMEM;
337062306a36Sopenharmony_ci
337162306a36Sopenharmony_ci		xfer->tx_message.buf = xfer->xfer_buf;
337262306a36Sopenharmony_ci		init_completion(&xfer->done);
337362306a36Sopenharmony_ci	}
337462306a36Sopenharmony_ci
337562306a36Sopenharmony_ci	ret = ti_sci_debugfs_create(pdev, info);
337662306a36Sopenharmony_ci	if (ret)
337762306a36Sopenharmony_ci		dev_warn(dev, "Failed to create debug file\n");
337862306a36Sopenharmony_ci
337962306a36Sopenharmony_ci	platform_set_drvdata(pdev, info);
338062306a36Sopenharmony_ci
338162306a36Sopenharmony_ci	cl = &info->cl;
338262306a36Sopenharmony_ci	cl->dev = dev;
338362306a36Sopenharmony_ci	cl->tx_block = false;
338462306a36Sopenharmony_ci	cl->rx_callback = ti_sci_rx_callback;
338562306a36Sopenharmony_ci	cl->knows_txdone = true;
338662306a36Sopenharmony_ci
338762306a36Sopenharmony_ci	spin_lock_init(&minfo->xfer_lock);
338862306a36Sopenharmony_ci	sema_init(&minfo->sem_xfer_count, desc->max_msgs);
338962306a36Sopenharmony_ci
339062306a36Sopenharmony_ci	info->chan_rx = mbox_request_channel_byname(cl, "rx");
339162306a36Sopenharmony_ci	if (IS_ERR(info->chan_rx)) {
339262306a36Sopenharmony_ci		ret = PTR_ERR(info->chan_rx);
339362306a36Sopenharmony_ci		goto out;
339462306a36Sopenharmony_ci	}
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_ci	info->chan_tx = mbox_request_channel_byname(cl, "tx");
339762306a36Sopenharmony_ci	if (IS_ERR(info->chan_tx)) {
339862306a36Sopenharmony_ci		ret = PTR_ERR(info->chan_tx);
339962306a36Sopenharmony_ci		goto out;
340062306a36Sopenharmony_ci	}
340162306a36Sopenharmony_ci	ret = ti_sci_cmd_get_revision(info);
340262306a36Sopenharmony_ci	if (ret) {
340362306a36Sopenharmony_ci		dev_err(dev, "Unable to communicate with TISCI(%d)\n", ret);
340462306a36Sopenharmony_ci		goto out;
340562306a36Sopenharmony_ci	}
340662306a36Sopenharmony_ci
340762306a36Sopenharmony_ci	ti_sci_setup_ops(info);
340862306a36Sopenharmony_ci
340962306a36Sopenharmony_ci	if (reboot) {
341062306a36Sopenharmony_ci		info->nb.notifier_call = tisci_reboot_handler;
341162306a36Sopenharmony_ci		info->nb.priority = 128;
341262306a36Sopenharmony_ci
341362306a36Sopenharmony_ci		ret = register_restart_handler(&info->nb);
341462306a36Sopenharmony_ci		if (ret) {
341562306a36Sopenharmony_ci			dev_err(dev, "reboot registration fail(%d)\n", ret);
341662306a36Sopenharmony_ci			goto out;
341762306a36Sopenharmony_ci		}
341862306a36Sopenharmony_ci	}
341962306a36Sopenharmony_ci
342062306a36Sopenharmony_ci	dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n",
342162306a36Sopenharmony_ci		 info->handle.version.abi_major, info->handle.version.abi_minor,
342262306a36Sopenharmony_ci		 info->handle.version.firmware_revision,
342362306a36Sopenharmony_ci		 info->handle.version.firmware_description);
342462306a36Sopenharmony_ci
342562306a36Sopenharmony_ci	mutex_lock(&ti_sci_list_mutex);
342662306a36Sopenharmony_ci	list_add_tail(&info->node, &ti_sci_list);
342762306a36Sopenharmony_ci	mutex_unlock(&ti_sci_list_mutex);
342862306a36Sopenharmony_ci
342962306a36Sopenharmony_ci	return of_platform_populate(dev->of_node, NULL, NULL, dev);
343062306a36Sopenharmony_ciout:
343162306a36Sopenharmony_ci	if (!IS_ERR(info->chan_tx))
343262306a36Sopenharmony_ci		mbox_free_channel(info->chan_tx);
343362306a36Sopenharmony_ci	if (!IS_ERR(info->chan_rx))
343462306a36Sopenharmony_ci		mbox_free_channel(info->chan_rx);
343562306a36Sopenharmony_ci	debugfs_remove(info->d);
343662306a36Sopenharmony_ci	return ret;
343762306a36Sopenharmony_ci}
343862306a36Sopenharmony_ci
343962306a36Sopenharmony_cistatic struct platform_driver ti_sci_driver = {
344062306a36Sopenharmony_ci	.probe = ti_sci_probe,
344162306a36Sopenharmony_ci	.driver = {
344262306a36Sopenharmony_ci		   .name = "ti-sci",
344362306a36Sopenharmony_ci		   .of_match_table = of_match_ptr(ti_sci_of_match),
344462306a36Sopenharmony_ci		   .suppress_bind_attrs = true,
344562306a36Sopenharmony_ci	},
344662306a36Sopenharmony_ci};
344762306a36Sopenharmony_cimodule_platform_driver(ti_sci_driver);
344862306a36Sopenharmony_ci
344962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
345062306a36Sopenharmony_ciMODULE_DESCRIPTION("TI System Control Interface(SCI) driver");
345162306a36Sopenharmony_ciMODULE_AUTHOR("Nishanth Menon");
345262306a36Sopenharmony_ciMODULE_ALIAS("platform:ti-sci");
3453