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