132cd2512SLokesh Vutla // SPDX-License-Identifier: GPL-2.0+ 232cd2512SLokesh Vutla /* 332cd2512SLokesh Vutla * Texas Instruments System Control Interface Protocol Driver 432cd2512SLokesh Vutla * Based on drivers/firmware/ti_sci.c from Linux. 532cd2512SLokesh Vutla * 632cd2512SLokesh Vutla * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ 732cd2512SLokesh Vutla * Lokesh Vutla <lokeshvutla@ti.com> 832cd2512SLokesh Vutla */ 932cd2512SLokesh Vutla 1032cd2512SLokesh Vutla #include <common.h> 1132cd2512SLokesh Vutla #include <dm.h> 1232cd2512SLokesh Vutla #include <errno.h> 1332cd2512SLokesh Vutla #include <mailbox.h> 1432cd2512SLokesh Vutla #include <dm/device.h> 1532cd2512SLokesh Vutla #include <linux/err.h> 1632cd2512SLokesh Vutla #include <linux/soc/ti/k3-sec-proxy.h> 1732cd2512SLokesh Vutla #include <linux/soc/ti/ti_sci_protocol.h> 1832cd2512SLokesh Vutla 1932cd2512SLokesh Vutla #include "ti_sci.h" 2032cd2512SLokesh Vutla 2132cd2512SLokesh Vutla /* List of all TI SCI devices active in system */ 2232cd2512SLokesh Vutla static LIST_HEAD(ti_sci_list); 2332cd2512SLokesh Vutla 2432cd2512SLokesh Vutla /** 2532cd2512SLokesh Vutla * struct ti_sci_xfer - Structure representing a message flow 2632cd2512SLokesh Vutla * @tx_message: Transmit message 2732cd2512SLokesh Vutla * @rx_len: Receive message length 2832cd2512SLokesh Vutla */ 2932cd2512SLokesh Vutla struct ti_sci_xfer { 3032cd2512SLokesh Vutla struct k3_sec_proxy_msg tx_message; 3132cd2512SLokesh Vutla u8 rx_len; 3232cd2512SLokesh Vutla }; 3332cd2512SLokesh Vutla 3432cd2512SLokesh Vutla /** 3532cd2512SLokesh Vutla * struct ti_sci_desc - Description of SoC integration 3632cd2512SLokesh Vutla * @host_id: Host identifier representing the compute entity 3732cd2512SLokesh Vutla * @max_rx_timeout_us: Timeout for communication with SoC (in Microseconds) 3832cd2512SLokesh Vutla * @max_msg_size: Maximum size of data per message that can be handled. 3932cd2512SLokesh Vutla */ 4032cd2512SLokesh Vutla struct ti_sci_desc { 4132cd2512SLokesh Vutla u8 host_id; 4232cd2512SLokesh Vutla int max_rx_timeout_us; 4332cd2512SLokesh Vutla int max_msg_size; 4432cd2512SLokesh Vutla }; 4532cd2512SLokesh Vutla 4632cd2512SLokesh Vutla /** 4732cd2512SLokesh Vutla * struct ti_sci_info - Structure representing a TI SCI instance 4832cd2512SLokesh Vutla * @dev: Device pointer 4932cd2512SLokesh Vutla * @desc: SoC description for this instance 5032cd2512SLokesh Vutla * @handle: Instance of TI SCI handle to send to clients. 5132cd2512SLokesh Vutla * @chan_tx: Transmit mailbox channel 5232cd2512SLokesh Vutla * @chan_rx: Receive mailbox channel 5332cd2512SLokesh Vutla * @xfer: xfer info 5432cd2512SLokesh Vutla * @list: list head 5532cd2512SLokesh Vutla * @is_secure: Determines if the communication is through secure threads. 5632cd2512SLokesh Vutla * @host_id: Host identifier representing the compute entity 5732cd2512SLokesh Vutla * @seq: Seq id used for verification for tx and rx message. 5832cd2512SLokesh Vutla */ 5932cd2512SLokesh Vutla struct ti_sci_info { 6032cd2512SLokesh Vutla struct udevice *dev; 6132cd2512SLokesh Vutla const struct ti_sci_desc *desc; 6232cd2512SLokesh Vutla struct ti_sci_handle handle; 6332cd2512SLokesh Vutla struct mbox_chan chan_tx; 6432cd2512SLokesh Vutla struct mbox_chan chan_rx; 6532cd2512SLokesh Vutla struct mbox_chan chan_notify; 6632cd2512SLokesh Vutla struct ti_sci_xfer xfer; 6732cd2512SLokesh Vutla struct list_head list; 6832cd2512SLokesh Vutla bool is_secure; 6932cd2512SLokesh Vutla u8 host_id; 7032cd2512SLokesh Vutla u8 seq; 7132cd2512SLokesh Vutla }; 7232cd2512SLokesh Vutla 7332cd2512SLokesh Vutla #define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle) 7432cd2512SLokesh Vutla 7532cd2512SLokesh Vutla /** 7632cd2512SLokesh Vutla * ti_sci_setup_one_xfer() - Setup one message type 7732cd2512SLokesh Vutla * @info: Pointer to SCI entity information 7832cd2512SLokesh Vutla * @msg_type: Message type 7932cd2512SLokesh Vutla * @msg_flags: Flag to set for the message 8032cd2512SLokesh Vutla * @buf: Buffer to be send to mailbox channel 8132cd2512SLokesh Vutla * @tx_message_size: transmit message size 8232cd2512SLokesh Vutla * @rx_message_size: receive message size 8332cd2512SLokesh Vutla * 8432cd2512SLokesh Vutla * Helper function which is used by various command functions that are 8532cd2512SLokesh Vutla * exposed to clients of this driver for allocating a message traffic event. 8632cd2512SLokesh Vutla * 8732cd2512SLokesh Vutla * Return: Corresponding ti_sci_xfer pointer if all went fine, 8832cd2512SLokesh Vutla * else appropriate error pointer. 8932cd2512SLokesh Vutla */ 9032cd2512SLokesh Vutla static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info, 9132cd2512SLokesh Vutla u16 msg_type, u32 msg_flags, 9232cd2512SLokesh Vutla u32 *buf, 9332cd2512SLokesh Vutla size_t tx_message_size, 9432cd2512SLokesh Vutla size_t rx_message_size) 9532cd2512SLokesh Vutla { 9632cd2512SLokesh Vutla struct ti_sci_xfer *xfer = &info->xfer; 9732cd2512SLokesh Vutla struct ti_sci_msg_hdr *hdr; 9832cd2512SLokesh Vutla 9932cd2512SLokesh Vutla /* Ensure we have sane transfer sizes */ 10032cd2512SLokesh Vutla if (rx_message_size > info->desc->max_msg_size || 10132cd2512SLokesh Vutla tx_message_size > info->desc->max_msg_size || 10232cd2512SLokesh Vutla rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr)) 10332cd2512SLokesh Vutla return ERR_PTR(-ERANGE); 10432cd2512SLokesh Vutla 10532cd2512SLokesh Vutla info->seq = ~info->seq; 10632cd2512SLokesh Vutla xfer->tx_message.buf = buf; 10732cd2512SLokesh Vutla xfer->tx_message.len = tx_message_size; 10832cd2512SLokesh Vutla xfer->rx_len = (u8)rx_message_size; 10932cd2512SLokesh Vutla 11032cd2512SLokesh Vutla hdr = (struct ti_sci_msg_hdr *)buf; 11132cd2512SLokesh Vutla hdr->seq = info->seq; 11232cd2512SLokesh Vutla hdr->type = msg_type; 11332cd2512SLokesh Vutla hdr->host = info->host_id; 11432cd2512SLokesh Vutla hdr->flags = msg_flags; 11532cd2512SLokesh Vutla 11632cd2512SLokesh Vutla return xfer; 11732cd2512SLokesh Vutla } 11832cd2512SLokesh Vutla 11932cd2512SLokesh Vutla /** 12032cd2512SLokesh Vutla * ti_sci_get_response() - Receive response from mailbox channel 12132cd2512SLokesh Vutla * @info: Pointer to SCI entity information 12232cd2512SLokesh Vutla * @xfer: Transfer to initiate and wait for response 12332cd2512SLokesh Vutla * @chan: Channel to receive the response 12432cd2512SLokesh Vutla * 12532cd2512SLokesh Vutla * Return: -ETIMEDOUT in case of no response, if transmit error, 12632cd2512SLokesh Vutla * return corresponding error, else if all goes well, 12732cd2512SLokesh Vutla * return 0. 12832cd2512SLokesh Vutla */ 12932cd2512SLokesh Vutla static inline int ti_sci_get_response(struct ti_sci_info *info, 13032cd2512SLokesh Vutla struct ti_sci_xfer *xfer, 13132cd2512SLokesh Vutla struct mbox_chan *chan) 13232cd2512SLokesh Vutla { 13332cd2512SLokesh Vutla struct k3_sec_proxy_msg *msg = &xfer->tx_message; 13432cd2512SLokesh Vutla struct ti_sci_secure_msg_hdr *secure_hdr; 13532cd2512SLokesh Vutla struct ti_sci_msg_hdr *hdr; 13632cd2512SLokesh Vutla int ret; 13732cd2512SLokesh Vutla 13832cd2512SLokesh Vutla /* Receive the response */ 13932cd2512SLokesh Vutla ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_us); 14032cd2512SLokesh Vutla if (ret) { 14132cd2512SLokesh Vutla dev_err(info->dev, "%s: Message receive failed. ret = %d\n", 14232cd2512SLokesh Vutla __func__, ret); 14332cd2512SLokesh Vutla return ret; 14432cd2512SLokesh Vutla } 14532cd2512SLokesh Vutla 14632cd2512SLokesh Vutla /* ToDo: Verify checksum */ 14732cd2512SLokesh Vutla if (info->is_secure) { 14832cd2512SLokesh Vutla secure_hdr = (struct ti_sci_secure_msg_hdr *)msg->buf; 14932cd2512SLokesh Vutla msg->buf = (u32 *)((void *)msg->buf + sizeof(*secure_hdr)); 15032cd2512SLokesh Vutla } 15132cd2512SLokesh Vutla 15232cd2512SLokesh Vutla /* msg is updated by mailbox driver */ 15332cd2512SLokesh Vutla hdr = (struct ti_sci_msg_hdr *)msg->buf; 15432cd2512SLokesh Vutla 15532cd2512SLokesh Vutla /* Sanity check for message response */ 15632cd2512SLokesh Vutla if (hdr->seq != info->seq) { 15732cd2512SLokesh Vutla dev_dbg(info->dev, "%s: Message for %d is not expected\n", 15832cd2512SLokesh Vutla __func__, hdr->seq); 15932cd2512SLokesh Vutla return ret; 16032cd2512SLokesh Vutla } 16132cd2512SLokesh Vutla 16232cd2512SLokesh Vutla if (msg->len > info->desc->max_msg_size) { 16332cd2512SLokesh Vutla dev_err(info->dev, "%s: Unable to handle %zu xfer (max %d)\n", 16432cd2512SLokesh Vutla __func__, msg->len, info->desc->max_msg_size); 16532cd2512SLokesh Vutla return -EINVAL; 16632cd2512SLokesh Vutla } 16732cd2512SLokesh Vutla 16832cd2512SLokesh Vutla if (msg->len < xfer->rx_len) { 16932cd2512SLokesh Vutla dev_err(info->dev, "%s: Recv xfer %zu < expected %d length\n", 17032cd2512SLokesh Vutla __func__, msg->len, xfer->rx_len); 17132cd2512SLokesh Vutla } 17232cd2512SLokesh Vutla 17332cd2512SLokesh Vutla return ret; 17432cd2512SLokesh Vutla } 17532cd2512SLokesh Vutla 17632cd2512SLokesh Vutla /** 17732cd2512SLokesh Vutla * ti_sci_do_xfer() - Do one transfer 17832cd2512SLokesh Vutla * @info: Pointer to SCI entity information 17932cd2512SLokesh Vutla * @xfer: Transfer to initiate and wait for response 18032cd2512SLokesh Vutla * 18132cd2512SLokesh Vutla * Return: 0 if all went fine, else return appropriate error. 18232cd2512SLokesh Vutla */ 18332cd2512SLokesh Vutla static inline int ti_sci_do_xfer(struct ti_sci_info *info, 18432cd2512SLokesh Vutla struct ti_sci_xfer *xfer) 18532cd2512SLokesh Vutla { 18632cd2512SLokesh Vutla struct k3_sec_proxy_msg *msg = &xfer->tx_message; 18732cd2512SLokesh Vutla u8 secure_buf[info->desc->max_msg_size]; 18832cd2512SLokesh Vutla struct ti_sci_secure_msg_hdr secure_hdr; 18932cd2512SLokesh Vutla int ret; 19032cd2512SLokesh Vutla 19132cd2512SLokesh Vutla if (info->is_secure) { 19232cd2512SLokesh Vutla /* ToDo: get checksum of the entire message */ 19332cd2512SLokesh Vutla secure_hdr.checksum = 0; 19432cd2512SLokesh Vutla secure_hdr.reserved = 0; 19532cd2512SLokesh Vutla memcpy(&secure_buf[sizeof(secure_hdr)], xfer->tx_message.buf, 19632cd2512SLokesh Vutla xfer->tx_message.len); 19732cd2512SLokesh Vutla 19832cd2512SLokesh Vutla xfer->tx_message.buf = (u32 *)secure_buf; 19932cd2512SLokesh Vutla xfer->tx_message.len += sizeof(secure_hdr); 20032cd2512SLokesh Vutla xfer->rx_len += sizeof(secure_hdr); 20132cd2512SLokesh Vutla } 20232cd2512SLokesh Vutla 20332cd2512SLokesh Vutla /* Send the message */ 20432cd2512SLokesh Vutla ret = mbox_send(&info->chan_tx, msg); 20532cd2512SLokesh Vutla if (ret) { 20632cd2512SLokesh Vutla dev_err(info->dev, "%s: Message sending failed. ret = %d\n", 20732cd2512SLokesh Vutla __func__, ret); 20832cd2512SLokesh Vutla return ret; 20932cd2512SLokesh Vutla } 21032cd2512SLokesh Vutla 21132cd2512SLokesh Vutla return ti_sci_get_response(info, xfer, &info->chan_rx); 21232cd2512SLokesh Vutla } 21332cd2512SLokesh Vutla 21432cd2512SLokesh Vutla /** 21532cd2512SLokesh Vutla * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity 21632cd2512SLokesh Vutla * @handle: pointer to TI SCI handle 21732cd2512SLokesh Vutla * 21832cd2512SLokesh Vutla * Updates the SCI information in the internal data structure. 21932cd2512SLokesh Vutla * 22032cd2512SLokesh Vutla * Return: 0 if all went fine, else return appropriate error. 22132cd2512SLokesh Vutla */ 22232cd2512SLokesh Vutla static int ti_sci_cmd_get_revision(struct ti_sci_handle *handle) 22332cd2512SLokesh Vutla { 22432cd2512SLokesh Vutla struct ti_sci_msg_resp_version *rev_info; 22532cd2512SLokesh Vutla struct ti_sci_version_info *ver; 22632cd2512SLokesh Vutla struct ti_sci_msg_hdr hdr; 22732cd2512SLokesh Vutla struct ti_sci_info *info; 22832cd2512SLokesh Vutla struct ti_sci_xfer *xfer; 22932cd2512SLokesh Vutla int ret; 23032cd2512SLokesh Vutla 23132cd2512SLokesh Vutla if (IS_ERR(handle)) 23232cd2512SLokesh Vutla return PTR_ERR(handle); 23332cd2512SLokesh Vutla if (!handle) 23432cd2512SLokesh Vutla return -EINVAL; 23532cd2512SLokesh Vutla 23632cd2512SLokesh Vutla info = handle_to_ti_sci_info(handle); 23732cd2512SLokesh Vutla 23832cd2512SLokesh Vutla xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION, 0x0, 23932cd2512SLokesh Vutla (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr), 24032cd2512SLokesh Vutla sizeof(*rev_info)); 24132cd2512SLokesh Vutla if (IS_ERR(xfer)) { 24232cd2512SLokesh Vutla ret = PTR_ERR(xfer); 24332cd2512SLokesh Vutla dev_err(info->dev, "Message alloc failed(%d)\n", ret); 24432cd2512SLokesh Vutla return ret; 24532cd2512SLokesh Vutla } 24632cd2512SLokesh Vutla 24732cd2512SLokesh Vutla ret = ti_sci_do_xfer(info, xfer); 24832cd2512SLokesh Vutla if (ret) { 24932cd2512SLokesh Vutla dev_err(info->dev, "Mbox communication fail %d\n", ret); 25032cd2512SLokesh Vutla return ret; 25132cd2512SLokesh Vutla } 25232cd2512SLokesh Vutla 25332cd2512SLokesh Vutla rev_info = (struct ti_sci_msg_resp_version *)xfer->tx_message.buf; 25432cd2512SLokesh Vutla 25532cd2512SLokesh Vutla ver = &handle->version; 25632cd2512SLokesh Vutla ver->abi_major = rev_info->abi_major; 25732cd2512SLokesh Vutla ver->abi_minor = rev_info->abi_minor; 25832cd2512SLokesh Vutla ver->firmware_revision = rev_info->firmware_revision; 25932cd2512SLokesh Vutla strncpy(ver->firmware_description, rev_info->firmware_description, 26032cd2512SLokesh Vutla sizeof(ver->firmware_description)); 26132cd2512SLokesh Vutla 26232cd2512SLokesh Vutla return 0; 26332cd2512SLokesh Vutla } 26432cd2512SLokesh Vutla 26532cd2512SLokesh Vutla /** 26632cd2512SLokesh Vutla * ti_sci_is_response_ack() - Generic ACK/NACK message checkup 26732cd2512SLokesh Vutla * @r: pointer to response buffer 26832cd2512SLokesh Vutla * 26932cd2512SLokesh Vutla * Return: true if the response was an ACK, else returns false. 27032cd2512SLokesh Vutla */ 27132cd2512SLokesh Vutla static inline bool ti_sci_is_response_ack(void *r) 27232cd2512SLokesh Vutla { 27332cd2512SLokesh Vutla struct ti_sci_msg_hdr *hdr = r; 27432cd2512SLokesh Vutla 27532cd2512SLokesh Vutla return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false; 27632cd2512SLokesh Vutla } 27732cd2512SLokesh Vutla 27832cd2512SLokesh Vutla /** 279dcfc52adSAndreas Dannenberg * cmd_set_board_config_using_msg() - Common command to send board configuration 280dcfc52adSAndreas Dannenberg * message 281dcfc52adSAndreas Dannenberg * @handle: pointer to TI SCI handle 282dcfc52adSAndreas Dannenberg * @msg_type: One of the TISCI message types to set board configuration 283dcfc52adSAndreas Dannenberg * @addr: Address where the board config structure is located 284dcfc52adSAndreas Dannenberg * @size: Size of the board config structure 285dcfc52adSAndreas Dannenberg * 286dcfc52adSAndreas Dannenberg * Return: 0 if all went well, else returns appropriate error value. 287dcfc52adSAndreas Dannenberg */ 288dcfc52adSAndreas Dannenberg static int cmd_set_board_config_using_msg(const struct ti_sci_handle *handle, 289dcfc52adSAndreas Dannenberg u16 msg_type, u64 addr, u32 size) 290dcfc52adSAndreas Dannenberg { 291dcfc52adSAndreas Dannenberg struct ti_sci_msg_board_config req; 292dcfc52adSAndreas Dannenberg struct ti_sci_msg_hdr *resp; 293dcfc52adSAndreas Dannenberg struct ti_sci_info *info; 294dcfc52adSAndreas Dannenberg struct ti_sci_xfer *xfer; 295dcfc52adSAndreas Dannenberg int ret = 0; 296dcfc52adSAndreas Dannenberg 297dcfc52adSAndreas Dannenberg if (IS_ERR(handle)) 298dcfc52adSAndreas Dannenberg return PTR_ERR(handle); 299dcfc52adSAndreas Dannenberg if (!handle) 300dcfc52adSAndreas Dannenberg return -EINVAL; 301dcfc52adSAndreas Dannenberg 302dcfc52adSAndreas Dannenberg info = handle_to_ti_sci_info(handle); 303dcfc52adSAndreas Dannenberg 304dcfc52adSAndreas Dannenberg xfer = ti_sci_setup_one_xfer(info, msg_type, 305dcfc52adSAndreas Dannenberg TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 306dcfc52adSAndreas Dannenberg (u32 *)&req, sizeof(req), sizeof(*resp)); 307dcfc52adSAndreas Dannenberg if (IS_ERR(xfer)) { 308dcfc52adSAndreas Dannenberg ret = PTR_ERR(xfer); 309dcfc52adSAndreas Dannenberg dev_err(info->dev, "Message alloc failed(%d)\n", ret); 310dcfc52adSAndreas Dannenberg return ret; 311dcfc52adSAndreas Dannenberg } 312dcfc52adSAndreas Dannenberg req.boardcfgp_high = (addr >> 32) & 0xffffffff; 313dcfc52adSAndreas Dannenberg req.boardcfgp_low = addr & 0xffffffff; 314dcfc52adSAndreas Dannenberg req.boardcfg_size = size; 315dcfc52adSAndreas Dannenberg 316dcfc52adSAndreas Dannenberg ret = ti_sci_do_xfer(info, xfer); 317dcfc52adSAndreas Dannenberg if (ret) { 318dcfc52adSAndreas Dannenberg dev_err(info->dev, "Mbox send fail %d\n", ret); 319dcfc52adSAndreas Dannenberg return ret; 320dcfc52adSAndreas Dannenberg } 321dcfc52adSAndreas Dannenberg 322dcfc52adSAndreas Dannenberg resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; 323dcfc52adSAndreas Dannenberg 324dcfc52adSAndreas Dannenberg if (!ti_sci_is_response_ack(resp)) 325dcfc52adSAndreas Dannenberg return -ENODEV; 326dcfc52adSAndreas Dannenberg 327dcfc52adSAndreas Dannenberg return ret; 328dcfc52adSAndreas Dannenberg } 329dcfc52adSAndreas Dannenberg 330dcfc52adSAndreas Dannenberg /** 331dcfc52adSAndreas Dannenberg * ti_sci_cmd_set_board_config() - Command to send board configuration message 332dcfc52adSAndreas Dannenberg * @handle: pointer to TI SCI handle 333dcfc52adSAndreas Dannenberg * @addr: Address where the board config structure is located 334dcfc52adSAndreas Dannenberg * @size: Size of the board config structure 335dcfc52adSAndreas Dannenberg * 336dcfc52adSAndreas Dannenberg * Return: 0 if all went well, else returns appropriate error value. 337dcfc52adSAndreas Dannenberg */ 338dcfc52adSAndreas Dannenberg static int ti_sci_cmd_set_board_config(const struct ti_sci_handle *handle, 339dcfc52adSAndreas Dannenberg u64 addr, u32 size) 340dcfc52adSAndreas Dannenberg { 341dcfc52adSAndreas Dannenberg return cmd_set_board_config_using_msg(handle, 342dcfc52adSAndreas Dannenberg TI_SCI_MSG_BOARD_CONFIG, 343dcfc52adSAndreas Dannenberg addr, size); 344dcfc52adSAndreas Dannenberg } 345dcfc52adSAndreas Dannenberg 346dcfc52adSAndreas Dannenberg /** 347dcfc52adSAndreas Dannenberg * ti_sci_cmd_set_board_config_rm() - Command to send board resource 348dcfc52adSAndreas Dannenberg * management configuration 349dcfc52adSAndreas Dannenberg * @handle: pointer to TI SCI handle 350dcfc52adSAndreas Dannenberg * @addr: Address where the board RM config structure is located 351dcfc52adSAndreas Dannenberg * @size: Size of the RM config structure 352dcfc52adSAndreas Dannenberg * 353dcfc52adSAndreas Dannenberg * Return: 0 if all went well, else returns appropriate error value. 354dcfc52adSAndreas Dannenberg */ 355dcfc52adSAndreas Dannenberg static 356dcfc52adSAndreas Dannenberg int ti_sci_cmd_set_board_config_rm(const struct ti_sci_handle *handle, 357dcfc52adSAndreas Dannenberg u64 addr, u32 size) 358dcfc52adSAndreas Dannenberg { 359dcfc52adSAndreas Dannenberg return cmd_set_board_config_using_msg(handle, 360dcfc52adSAndreas Dannenberg TI_SCI_MSG_BOARD_CONFIG_RM, 361dcfc52adSAndreas Dannenberg addr, size); 362dcfc52adSAndreas Dannenberg } 363dcfc52adSAndreas Dannenberg 364dcfc52adSAndreas Dannenberg /** 365dcfc52adSAndreas Dannenberg * ti_sci_cmd_set_board_config_security() - Command to send board security 366dcfc52adSAndreas Dannenberg * configuration message 367dcfc52adSAndreas Dannenberg * @handle: pointer to TI SCI handle 368dcfc52adSAndreas Dannenberg * @addr: Address where the board security config structure is located 369dcfc52adSAndreas Dannenberg * @size: Size of the security config structure 370dcfc52adSAndreas Dannenberg * 371dcfc52adSAndreas Dannenberg * Return: 0 if all went well, else returns appropriate error value. 372dcfc52adSAndreas Dannenberg */ 373dcfc52adSAndreas Dannenberg static 374dcfc52adSAndreas Dannenberg int ti_sci_cmd_set_board_config_security(const struct ti_sci_handle *handle, 375dcfc52adSAndreas Dannenberg u64 addr, u32 size) 376dcfc52adSAndreas Dannenberg { 377dcfc52adSAndreas Dannenberg return cmd_set_board_config_using_msg(handle, 378dcfc52adSAndreas Dannenberg TI_SCI_MSG_BOARD_CONFIG_SECURITY, 379dcfc52adSAndreas Dannenberg addr, size); 380dcfc52adSAndreas Dannenberg } 381dcfc52adSAndreas Dannenberg 382dcfc52adSAndreas Dannenberg /** 383dcfc52adSAndreas Dannenberg * ti_sci_cmd_set_board_config_pm() - Command to send board power and clock 384dcfc52adSAndreas Dannenberg * configuration message 385dcfc52adSAndreas Dannenberg * @handle: pointer to TI SCI handle 386dcfc52adSAndreas Dannenberg * @addr: Address where the board PM config structure is located 387dcfc52adSAndreas Dannenberg * @size: Size of the PM config structure 388dcfc52adSAndreas Dannenberg * 389dcfc52adSAndreas Dannenberg * Return: 0 if all went well, else returns appropriate error value. 390dcfc52adSAndreas Dannenberg */ 391dcfc52adSAndreas Dannenberg static int ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle *handle, 392dcfc52adSAndreas Dannenberg u64 addr, u32 size) 393dcfc52adSAndreas Dannenberg { 394dcfc52adSAndreas Dannenberg return cmd_set_board_config_using_msg(handle, 395dcfc52adSAndreas Dannenberg TI_SCI_MSG_BOARD_CONFIG_PM, 396dcfc52adSAndreas Dannenberg addr, size); 397dcfc52adSAndreas Dannenberg } 398dcfc52adSAndreas Dannenberg 3997bc33045SAndreas Dannenberg /** 4007bc33045SAndreas Dannenberg * ti_sci_set_device_state() - Set device state helper 4017bc33045SAndreas Dannenberg * @handle: pointer to TI SCI handle 4027bc33045SAndreas Dannenberg * @id: Device identifier 4037bc33045SAndreas Dannenberg * @flags: flags to setup for the device 4047bc33045SAndreas Dannenberg * @state: State to move the device to 4057bc33045SAndreas Dannenberg * 4067bc33045SAndreas Dannenberg * Return: 0 if all went well, else returns appropriate error value. 4077bc33045SAndreas Dannenberg */ 4087bc33045SAndreas Dannenberg static int ti_sci_set_device_state(const struct ti_sci_handle *handle, 4097bc33045SAndreas Dannenberg u32 id, u32 flags, u8 state) 4107bc33045SAndreas Dannenberg { 4117bc33045SAndreas Dannenberg struct ti_sci_msg_req_set_device_state req; 4127bc33045SAndreas Dannenberg struct ti_sci_msg_hdr *resp; 4137bc33045SAndreas Dannenberg struct ti_sci_info *info; 4147bc33045SAndreas Dannenberg struct ti_sci_xfer *xfer; 4157bc33045SAndreas Dannenberg int ret = 0; 4167bc33045SAndreas Dannenberg 4177bc33045SAndreas Dannenberg if (IS_ERR(handle)) 4187bc33045SAndreas Dannenberg return PTR_ERR(handle); 4197bc33045SAndreas Dannenberg if (!handle) 4207bc33045SAndreas Dannenberg return -EINVAL; 4217bc33045SAndreas Dannenberg 4227bc33045SAndreas Dannenberg info = handle_to_ti_sci_info(handle); 4237bc33045SAndreas Dannenberg 4247bc33045SAndreas Dannenberg xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE, 4257bc33045SAndreas Dannenberg flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 4267bc33045SAndreas Dannenberg (u32 *)&req, sizeof(req), sizeof(*resp)); 4277bc33045SAndreas Dannenberg if (IS_ERR(xfer)) { 4287bc33045SAndreas Dannenberg ret = PTR_ERR(xfer); 4297bc33045SAndreas Dannenberg dev_err(info->dev, "Message alloc failed(%d)\n", ret); 4307bc33045SAndreas Dannenberg return ret; 4317bc33045SAndreas Dannenberg } 4327bc33045SAndreas Dannenberg req.id = id; 4337bc33045SAndreas Dannenberg req.state = state; 4347bc33045SAndreas Dannenberg 4357bc33045SAndreas Dannenberg ret = ti_sci_do_xfer(info, xfer); 4367bc33045SAndreas Dannenberg if (ret) { 4377bc33045SAndreas Dannenberg dev_err(info->dev, "Mbox send fail %d\n", ret); 4387bc33045SAndreas Dannenberg return ret; 4397bc33045SAndreas Dannenberg } 4407bc33045SAndreas Dannenberg 4417bc33045SAndreas Dannenberg resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; 4427bc33045SAndreas Dannenberg 4437bc33045SAndreas Dannenberg if (!ti_sci_is_response_ack(resp)) 4447bc33045SAndreas Dannenberg return -ENODEV; 4457bc33045SAndreas Dannenberg 4467bc33045SAndreas Dannenberg return ret; 4477bc33045SAndreas Dannenberg } 4487bc33045SAndreas Dannenberg 4497bc33045SAndreas Dannenberg /** 4507bc33045SAndreas Dannenberg * ti_sci_get_device_state() - Get device state helper 4517bc33045SAndreas Dannenberg * @handle: Handle to the device 4527bc33045SAndreas Dannenberg * @id: Device Identifier 4537bc33045SAndreas Dannenberg * @clcnt: Pointer to Context Loss Count 4547bc33045SAndreas Dannenberg * @resets: pointer to resets 4557bc33045SAndreas Dannenberg * @p_state: pointer to p_state 4567bc33045SAndreas Dannenberg * @c_state: pointer to c_state 4577bc33045SAndreas Dannenberg * 4587bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 4597bc33045SAndreas Dannenberg */ 4607bc33045SAndreas Dannenberg static int ti_sci_get_device_state(const struct ti_sci_handle *handle, 4617bc33045SAndreas Dannenberg u32 id, u32 *clcnt, u32 *resets, 4627bc33045SAndreas Dannenberg u8 *p_state, u8 *c_state) 4637bc33045SAndreas Dannenberg { 4647bc33045SAndreas Dannenberg struct ti_sci_msg_resp_get_device_state *resp; 4657bc33045SAndreas Dannenberg struct ti_sci_msg_req_get_device_state req; 4667bc33045SAndreas Dannenberg struct ti_sci_info *info; 4677bc33045SAndreas Dannenberg struct ti_sci_xfer *xfer; 4687bc33045SAndreas Dannenberg int ret = 0; 4697bc33045SAndreas Dannenberg 4707bc33045SAndreas Dannenberg if (IS_ERR(handle)) 4717bc33045SAndreas Dannenberg return PTR_ERR(handle); 4727bc33045SAndreas Dannenberg if (!handle) 4737bc33045SAndreas Dannenberg return -EINVAL; 4747bc33045SAndreas Dannenberg 4757bc33045SAndreas Dannenberg if (!clcnt && !resets && !p_state && !c_state) 4767bc33045SAndreas Dannenberg return -EINVAL; 4777bc33045SAndreas Dannenberg 4787bc33045SAndreas Dannenberg info = handle_to_ti_sci_info(handle); 4797bc33045SAndreas Dannenberg 4807bc33045SAndreas Dannenberg /* Response is expected, so need of any flags */ 4817bc33045SAndreas Dannenberg xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE, 0, 4827bc33045SAndreas Dannenberg (u32 *)&req, sizeof(req), sizeof(*resp)); 4837bc33045SAndreas Dannenberg if (IS_ERR(xfer)) { 4847bc33045SAndreas Dannenberg ret = PTR_ERR(xfer); 4857bc33045SAndreas Dannenberg dev_err(info->dev, "Message alloc failed(%d)\n", ret); 4867bc33045SAndreas Dannenberg return ret; 4877bc33045SAndreas Dannenberg } 4887bc33045SAndreas Dannenberg req.id = id; 4897bc33045SAndreas Dannenberg 4907bc33045SAndreas Dannenberg ret = ti_sci_do_xfer(info, xfer); 4917bc33045SAndreas Dannenberg if (ret) { 4927bc33045SAndreas Dannenberg dev_err(dev, "Mbox send fail %d\n", ret); 4937bc33045SAndreas Dannenberg return ret; 4947bc33045SAndreas Dannenberg } 4957bc33045SAndreas Dannenberg 4967bc33045SAndreas Dannenberg resp = (struct ti_sci_msg_resp_get_device_state *)xfer->tx_message.buf; 4977bc33045SAndreas Dannenberg if (!ti_sci_is_response_ack(resp)) 4987bc33045SAndreas Dannenberg return -ENODEV; 4997bc33045SAndreas Dannenberg 5007bc33045SAndreas Dannenberg if (clcnt) 5017bc33045SAndreas Dannenberg *clcnt = resp->context_loss_count; 5027bc33045SAndreas Dannenberg if (resets) 5037bc33045SAndreas Dannenberg *resets = resp->resets; 5047bc33045SAndreas Dannenberg if (p_state) 5057bc33045SAndreas Dannenberg *p_state = resp->programmed_state; 5067bc33045SAndreas Dannenberg if (c_state) 5077bc33045SAndreas Dannenberg *c_state = resp->current_state; 5087bc33045SAndreas Dannenberg 5097bc33045SAndreas Dannenberg return ret; 5107bc33045SAndreas Dannenberg } 5117bc33045SAndreas Dannenberg 5127bc33045SAndreas Dannenberg /** 5137bc33045SAndreas Dannenberg * ti_sci_cmd_get_device() - command to request for device managed by TISCI 5147bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle 5157bc33045SAndreas Dannenberg * @id: Device Identifier 5167bc33045SAndreas Dannenberg * 5177bc33045SAndreas Dannenberg * Request for the device - NOTE: the client MUST maintain integrity of 5187bc33045SAndreas Dannenberg * usage count by balancing get_device with put_device. No refcounting is 5197bc33045SAndreas Dannenberg * managed by driver for that purpose. 5207bc33045SAndreas Dannenberg * 5217bc33045SAndreas Dannenberg * NOTE: The request is for exclusive access for the processor. 5227bc33045SAndreas Dannenberg * 5237bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 5247bc33045SAndreas Dannenberg */ 5257bc33045SAndreas Dannenberg static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id) 5267bc33045SAndreas Dannenberg { 5277bc33045SAndreas Dannenberg return ti_sci_set_device_state(handle, id, 5287bc33045SAndreas Dannenberg MSG_FLAG_DEVICE_EXCLUSIVE, 5297bc33045SAndreas Dannenberg MSG_DEVICE_SW_STATE_ON); 5307bc33045SAndreas Dannenberg } 5317bc33045SAndreas Dannenberg 5327bc33045SAndreas Dannenberg /** 5337bc33045SAndreas Dannenberg * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI 5347bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle 5357bc33045SAndreas Dannenberg * @id: Device Identifier 5367bc33045SAndreas Dannenberg * 5377bc33045SAndreas Dannenberg * Request for the device - NOTE: the client MUST maintain integrity of 5387bc33045SAndreas Dannenberg * usage count by balancing get_device with put_device. No refcounting is 5397bc33045SAndreas Dannenberg * managed by driver for that purpose. 5407bc33045SAndreas Dannenberg * 5417bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 5427bc33045SAndreas Dannenberg */ 5437bc33045SAndreas Dannenberg static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id) 5447bc33045SAndreas Dannenberg { 5457bc33045SAndreas Dannenberg return ti_sci_set_device_state(handle, id, 5467bc33045SAndreas Dannenberg MSG_FLAG_DEVICE_EXCLUSIVE, 5477bc33045SAndreas Dannenberg MSG_DEVICE_SW_STATE_RETENTION); 5487bc33045SAndreas Dannenberg } 5497bc33045SAndreas Dannenberg 5507bc33045SAndreas Dannenberg /** 5517bc33045SAndreas Dannenberg * ti_sci_cmd_put_device() - command to release a device managed by TISCI 5527bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle 5537bc33045SAndreas Dannenberg * @id: Device Identifier 5547bc33045SAndreas Dannenberg * 5557bc33045SAndreas Dannenberg * Request for the device - NOTE: the client MUST maintain integrity of 5567bc33045SAndreas Dannenberg * usage count by balancing get_device with put_device. No refcounting is 5577bc33045SAndreas Dannenberg * managed by driver for that purpose. 5587bc33045SAndreas Dannenberg * 5597bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 5607bc33045SAndreas Dannenberg */ 5617bc33045SAndreas Dannenberg static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id) 5627bc33045SAndreas Dannenberg { 5637bc33045SAndreas Dannenberg return ti_sci_set_device_state(handle, id, 5647bc33045SAndreas Dannenberg 0, MSG_DEVICE_SW_STATE_AUTO_OFF); 5657bc33045SAndreas Dannenberg } 5667bc33045SAndreas Dannenberg 5677bc33045SAndreas Dannenberg /** 5687bc33045SAndreas Dannenberg * ti_sci_cmd_dev_is_valid() - Is the device valid 5697bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle 5707bc33045SAndreas Dannenberg * @id: Device Identifier 5717bc33045SAndreas Dannenberg * 5727bc33045SAndreas Dannenberg * Return: 0 if all went fine and the device ID is valid, else return 5737bc33045SAndreas Dannenberg * appropriate error. 5747bc33045SAndreas Dannenberg */ 5757bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id) 5767bc33045SAndreas Dannenberg { 5777bc33045SAndreas Dannenberg u8 unused; 5787bc33045SAndreas Dannenberg 5797bc33045SAndreas Dannenberg /* check the device state which will also tell us if the ID is valid */ 5807bc33045SAndreas Dannenberg return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused); 5817bc33045SAndreas Dannenberg } 5827bc33045SAndreas Dannenberg 5837bc33045SAndreas Dannenberg /** 5847bc33045SAndreas Dannenberg * ti_sci_cmd_dev_get_clcnt() - Get context loss counter 5857bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle 5867bc33045SAndreas Dannenberg * @id: Device Identifier 5877bc33045SAndreas Dannenberg * @count: Pointer to Context Loss counter to populate 5887bc33045SAndreas Dannenberg * 5897bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 5907bc33045SAndreas Dannenberg */ 5917bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id, 5927bc33045SAndreas Dannenberg u32 *count) 5937bc33045SAndreas Dannenberg { 5947bc33045SAndreas Dannenberg return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL); 5957bc33045SAndreas Dannenberg } 5967bc33045SAndreas Dannenberg 5977bc33045SAndreas Dannenberg /** 5987bc33045SAndreas Dannenberg * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle 5997bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle 6007bc33045SAndreas Dannenberg * @id: Device Identifier 6017bc33045SAndreas Dannenberg * @r_state: true if requested to be idle 6027bc33045SAndreas Dannenberg * 6037bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 6047bc33045SAndreas Dannenberg */ 6057bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id, 6067bc33045SAndreas Dannenberg bool *r_state) 6077bc33045SAndreas Dannenberg { 6087bc33045SAndreas Dannenberg int ret; 6097bc33045SAndreas Dannenberg u8 state; 6107bc33045SAndreas Dannenberg 6117bc33045SAndreas Dannenberg if (!r_state) 6127bc33045SAndreas Dannenberg return -EINVAL; 6137bc33045SAndreas Dannenberg 6147bc33045SAndreas Dannenberg ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL); 6157bc33045SAndreas Dannenberg if (ret) 6167bc33045SAndreas Dannenberg return ret; 6177bc33045SAndreas Dannenberg 6187bc33045SAndreas Dannenberg *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION); 6197bc33045SAndreas Dannenberg 6207bc33045SAndreas Dannenberg return 0; 6217bc33045SAndreas Dannenberg } 6227bc33045SAndreas Dannenberg 6237bc33045SAndreas Dannenberg /** 6247bc33045SAndreas Dannenberg * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped 6257bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle 6267bc33045SAndreas Dannenberg * @id: Device Identifier 6277bc33045SAndreas Dannenberg * @r_state: true if requested to be stopped 6287bc33045SAndreas Dannenberg * @curr_state: true if currently stopped. 6297bc33045SAndreas Dannenberg * 6307bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 6317bc33045SAndreas Dannenberg */ 6327bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id, 6337bc33045SAndreas Dannenberg bool *r_state, bool *curr_state) 6347bc33045SAndreas Dannenberg { 6357bc33045SAndreas Dannenberg int ret; 6367bc33045SAndreas Dannenberg u8 p_state, c_state; 6377bc33045SAndreas Dannenberg 6387bc33045SAndreas Dannenberg if (!r_state && !curr_state) 6397bc33045SAndreas Dannenberg return -EINVAL; 6407bc33045SAndreas Dannenberg 6417bc33045SAndreas Dannenberg ret = 6427bc33045SAndreas Dannenberg ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state); 6437bc33045SAndreas Dannenberg if (ret) 6447bc33045SAndreas Dannenberg return ret; 6457bc33045SAndreas Dannenberg 6467bc33045SAndreas Dannenberg if (r_state) 6477bc33045SAndreas Dannenberg *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF); 6487bc33045SAndreas Dannenberg if (curr_state) 6497bc33045SAndreas Dannenberg *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF); 6507bc33045SAndreas Dannenberg 6517bc33045SAndreas Dannenberg return 0; 6527bc33045SAndreas Dannenberg } 6537bc33045SAndreas Dannenberg 6547bc33045SAndreas Dannenberg /** 6557bc33045SAndreas Dannenberg * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON 6567bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle 6577bc33045SAndreas Dannenberg * @id: Device Identifier 6587bc33045SAndreas Dannenberg * @r_state: true if requested to be ON 6597bc33045SAndreas Dannenberg * @curr_state: true if currently ON and active 6607bc33045SAndreas Dannenberg * 6617bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 6627bc33045SAndreas Dannenberg */ 6637bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id, 6647bc33045SAndreas Dannenberg bool *r_state, bool *curr_state) 6657bc33045SAndreas Dannenberg { 6667bc33045SAndreas Dannenberg int ret; 6677bc33045SAndreas Dannenberg u8 p_state, c_state; 6687bc33045SAndreas Dannenberg 6697bc33045SAndreas Dannenberg if (!r_state && !curr_state) 6707bc33045SAndreas Dannenberg return -EINVAL; 6717bc33045SAndreas Dannenberg 6727bc33045SAndreas Dannenberg ret = 6737bc33045SAndreas Dannenberg ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state); 6747bc33045SAndreas Dannenberg if (ret) 6757bc33045SAndreas Dannenberg return ret; 6767bc33045SAndreas Dannenberg 6777bc33045SAndreas Dannenberg if (r_state) 6787bc33045SAndreas Dannenberg *r_state = (p_state == MSG_DEVICE_SW_STATE_ON); 6797bc33045SAndreas Dannenberg if (curr_state) 6807bc33045SAndreas Dannenberg *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON); 6817bc33045SAndreas Dannenberg 6827bc33045SAndreas Dannenberg return 0; 6837bc33045SAndreas Dannenberg } 6847bc33045SAndreas Dannenberg 6857bc33045SAndreas Dannenberg /** 6867bc33045SAndreas Dannenberg * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning 6877bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle 6887bc33045SAndreas Dannenberg * @id: Device Identifier 6897bc33045SAndreas Dannenberg * @curr_state: true if currently transitioning. 6907bc33045SAndreas Dannenberg * 6917bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 6927bc33045SAndreas Dannenberg */ 6937bc33045SAndreas Dannenberg static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id, 6947bc33045SAndreas Dannenberg bool *curr_state) 6957bc33045SAndreas Dannenberg { 6967bc33045SAndreas Dannenberg int ret; 6977bc33045SAndreas Dannenberg u8 state; 6987bc33045SAndreas Dannenberg 6997bc33045SAndreas Dannenberg if (!curr_state) 7007bc33045SAndreas Dannenberg return -EINVAL; 7017bc33045SAndreas Dannenberg 7027bc33045SAndreas Dannenberg ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state); 7037bc33045SAndreas Dannenberg if (ret) 7047bc33045SAndreas Dannenberg return ret; 7057bc33045SAndreas Dannenberg 7067bc33045SAndreas Dannenberg *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS); 7077bc33045SAndreas Dannenberg 7087bc33045SAndreas Dannenberg return 0; 7097bc33045SAndreas Dannenberg } 7107bc33045SAndreas Dannenberg 7117bc33045SAndreas Dannenberg /** 7127bc33045SAndreas Dannenberg * ti_sci_cmd_set_device_resets() - command to set resets for device managed 7137bc33045SAndreas Dannenberg * by TISCI 7147bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle 7157bc33045SAndreas Dannenberg * @id: Device Identifier 7167bc33045SAndreas Dannenberg * @reset_state: Device specific reset bit field 7177bc33045SAndreas Dannenberg * 7187bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 7197bc33045SAndreas Dannenberg */ 7207bc33045SAndreas Dannenberg static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle, 7217bc33045SAndreas Dannenberg u32 id, u32 reset_state) 7227bc33045SAndreas Dannenberg { 7237bc33045SAndreas Dannenberg struct ti_sci_msg_req_set_device_resets req; 7247bc33045SAndreas Dannenberg struct ti_sci_msg_hdr *resp; 7257bc33045SAndreas Dannenberg struct ti_sci_info *info; 7267bc33045SAndreas Dannenberg struct ti_sci_xfer *xfer; 7277bc33045SAndreas Dannenberg int ret = 0; 7287bc33045SAndreas Dannenberg 7297bc33045SAndreas Dannenberg if (IS_ERR(handle)) 7307bc33045SAndreas Dannenberg return PTR_ERR(handle); 7317bc33045SAndreas Dannenberg if (!handle) 7327bc33045SAndreas Dannenberg return -EINVAL; 7337bc33045SAndreas Dannenberg 7347bc33045SAndreas Dannenberg info = handle_to_ti_sci_info(handle); 7357bc33045SAndreas Dannenberg 7367bc33045SAndreas Dannenberg xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS, 7377bc33045SAndreas Dannenberg TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 7387bc33045SAndreas Dannenberg (u32 *)&req, sizeof(req), sizeof(*resp)); 7397bc33045SAndreas Dannenberg if (IS_ERR(xfer)) { 7407bc33045SAndreas Dannenberg ret = PTR_ERR(xfer); 7417bc33045SAndreas Dannenberg dev_err(info->dev, "Message alloc failed(%d)\n", ret); 7427bc33045SAndreas Dannenberg return ret; 7437bc33045SAndreas Dannenberg } 7447bc33045SAndreas Dannenberg req.id = id; 7457bc33045SAndreas Dannenberg req.resets = reset_state; 7467bc33045SAndreas Dannenberg 7477bc33045SAndreas Dannenberg ret = ti_sci_do_xfer(info, xfer); 7487bc33045SAndreas Dannenberg if (ret) { 7497bc33045SAndreas Dannenberg dev_err(info->dev, "Mbox send fail %d\n", ret); 7507bc33045SAndreas Dannenberg return ret; 7517bc33045SAndreas Dannenberg } 7527bc33045SAndreas Dannenberg 7537bc33045SAndreas Dannenberg resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; 7547bc33045SAndreas Dannenberg 7557bc33045SAndreas Dannenberg if (!ti_sci_is_response_ack(resp)) 7567bc33045SAndreas Dannenberg return -ENODEV; 7577bc33045SAndreas Dannenberg 7587bc33045SAndreas Dannenberg return ret; 7597bc33045SAndreas Dannenberg } 7607bc33045SAndreas Dannenberg 7617bc33045SAndreas Dannenberg /** 7627bc33045SAndreas Dannenberg * ti_sci_cmd_get_device_resets() - Get reset state for device managed 7637bc33045SAndreas Dannenberg * by TISCI 7647bc33045SAndreas Dannenberg * @handle: Pointer to TISCI handle 7657bc33045SAndreas Dannenberg * @id: Device Identifier 7667bc33045SAndreas Dannenberg * @reset_state: Pointer to reset state to populate 7677bc33045SAndreas Dannenberg * 7687bc33045SAndreas Dannenberg * Return: 0 if all went fine, else return appropriate error. 7697bc33045SAndreas Dannenberg */ 7707bc33045SAndreas Dannenberg static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle, 7717bc33045SAndreas Dannenberg u32 id, u32 *reset_state) 7727bc33045SAndreas Dannenberg { 7737bc33045SAndreas Dannenberg return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL, 7747bc33045SAndreas Dannenberg NULL); 7757bc33045SAndreas Dannenberg } 7767bc33045SAndreas Dannenberg 777*9b87181fSLokesh Vutla /** 778*9b87181fSLokesh Vutla * ti_sci_set_clock_state() - Set clock state helper 779*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 780*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 781*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 782*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 783*9b87181fSLokesh Vutla * which clock input to modify. 784*9b87181fSLokesh Vutla * @flags: Header flags as needed 785*9b87181fSLokesh Vutla * @state: State to request for the clock. 786*9b87181fSLokesh Vutla * 787*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 788*9b87181fSLokesh Vutla */ 789*9b87181fSLokesh Vutla static int ti_sci_set_clock_state(const struct ti_sci_handle *handle, 790*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id, 791*9b87181fSLokesh Vutla u32 flags, u8 state) 792*9b87181fSLokesh Vutla { 793*9b87181fSLokesh Vutla struct ti_sci_msg_req_set_clock_state req; 794*9b87181fSLokesh Vutla struct ti_sci_msg_hdr *resp; 795*9b87181fSLokesh Vutla struct ti_sci_info *info; 796*9b87181fSLokesh Vutla struct ti_sci_xfer *xfer; 797*9b87181fSLokesh Vutla int ret = 0; 798*9b87181fSLokesh Vutla 799*9b87181fSLokesh Vutla if (IS_ERR(handle)) 800*9b87181fSLokesh Vutla return PTR_ERR(handle); 801*9b87181fSLokesh Vutla if (!handle) 802*9b87181fSLokesh Vutla return -EINVAL; 803*9b87181fSLokesh Vutla 804*9b87181fSLokesh Vutla info = handle_to_ti_sci_info(handle); 805*9b87181fSLokesh Vutla 806*9b87181fSLokesh Vutla xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE, 807*9b87181fSLokesh Vutla flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 808*9b87181fSLokesh Vutla (u32 *)&req, sizeof(req), sizeof(*resp)); 809*9b87181fSLokesh Vutla if (IS_ERR(xfer)) { 810*9b87181fSLokesh Vutla ret = PTR_ERR(xfer); 811*9b87181fSLokesh Vutla dev_err(info->dev, "Message alloc failed(%d)\n", ret); 812*9b87181fSLokesh Vutla return ret; 813*9b87181fSLokesh Vutla } 814*9b87181fSLokesh Vutla req.dev_id = dev_id; 815*9b87181fSLokesh Vutla req.clk_id = clk_id; 816*9b87181fSLokesh Vutla req.request_state = state; 817*9b87181fSLokesh Vutla 818*9b87181fSLokesh Vutla ret = ti_sci_do_xfer(info, xfer); 819*9b87181fSLokesh Vutla if (ret) { 820*9b87181fSLokesh Vutla dev_err(info->dev, "Mbox send fail %d\n", ret); 821*9b87181fSLokesh Vutla return ret; 822*9b87181fSLokesh Vutla } 823*9b87181fSLokesh Vutla 824*9b87181fSLokesh Vutla resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; 825*9b87181fSLokesh Vutla 826*9b87181fSLokesh Vutla if (!ti_sci_is_response_ack(resp)) 827*9b87181fSLokesh Vutla return -ENODEV; 828*9b87181fSLokesh Vutla 829*9b87181fSLokesh Vutla return ret; 830*9b87181fSLokesh Vutla } 831*9b87181fSLokesh Vutla 832*9b87181fSLokesh Vutla /** 833*9b87181fSLokesh Vutla * ti_sci_cmd_get_clock_state() - Get clock state helper 834*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 835*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 836*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 837*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 838*9b87181fSLokesh Vutla * which clock input to modify. 839*9b87181fSLokesh Vutla * @programmed_state: State requested for clock to move to 840*9b87181fSLokesh Vutla * @current_state: State that the clock is currently in 841*9b87181fSLokesh Vutla * 842*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 843*9b87181fSLokesh Vutla */ 844*9b87181fSLokesh Vutla static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle, 845*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id, 846*9b87181fSLokesh Vutla u8 *programmed_state, u8 *current_state) 847*9b87181fSLokesh Vutla { 848*9b87181fSLokesh Vutla struct ti_sci_msg_resp_get_clock_state *resp; 849*9b87181fSLokesh Vutla struct ti_sci_msg_req_get_clock_state req; 850*9b87181fSLokesh Vutla struct ti_sci_info *info; 851*9b87181fSLokesh Vutla struct ti_sci_xfer *xfer; 852*9b87181fSLokesh Vutla int ret = 0; 853*9b87181fSLokesh Vutla 854*9b87181fSLokesh Vutla if (IS_ERR(handle)) 855*9b87181fSLokesh Vutla return PTR_ERR(handle); 856*9b87181fSLokesh Vutla if (!handle) 857*9b87181fSLokesh Vutla return -EINVAL; 858*9b87181fSLokesh Vutla 859*9b87181fSLokesh Vutla if (!programmed_state && !current_state) 860*9b87181fSLokesh Vutla return -EINVAL; 861*9b87181fSLokesh Vutla 862*9b87181fSLokesh Vutla info = handle_to_ti_sci_info(handle); 863*9b87181fSLokesh Vutla 864*9b87181fSLokesh Vutla xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE, 865*9b87181fSLokesh Vutla TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 866*9b87181fSLokesh Vutla (u32 *)&req, sizeof(req), sizeof(*resp)); 867*9b87181fSLokesh Vutla if (IS_ERR(xfer)) { 868*9b87181fSLokesh Vutla ret = PTR_ERR(xfer); 869*9b87181fSLokesh Vutla dev_err(info->dev, "Message alloc failed(%d)\n", ret); 870*9b87181fSLokesh Vutla return ret; 871*9b87181fSLokesh Vutla } 872*9b87181fSLokesh Vutla req.dev_id = dev_id; 873*9b87181fSLokesh Vutla req.clk_id = clk_id; 874*9b87181fSLokesh Vutla 875*9b87181fSLokesh Vutla ret = ti_sci_do_xfer(info, xfer); 876*9b87181fSLokesh Vutla if (ret) { 877*9b87181fSLokesh Vutla dev_err(info->dev, "Mbox send fail %d\n", ret); 878*9b87181fSLokesh Vutla return ret; 879*9b87181fSLokesh Vutla } 880*9b87181fSLokesh Vutla 881*9b87181fSLokesh Vutla resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->tx_message.buf; 882*9b87181fSLokesh Vutla 883*9b87181fSLokesh Vutla if (!ti_sci_is_response_ack(resp)) 884*9b87181fSLokesh Vutla return -ENODEV; 885*9b87181fSLokesh Vutla 886*9b87181fSLokesh Vutla if (programmed_state) 887*9b87181fSLokesh Vutla *programmed_state = resp->programmed_state; 888*9b87181fSLokesh Vutla if (current_state) 889*9b87181fSLokesh Vutla *current_state = resp->current_state; 890*9b87181fSLokesh Vutla 891*9b87181fSLokesh Vutla return ret; 892*9b87181fSLokesh Vutla } 893*9b87181fSLokesh Vutla 894*9b87181fSLokesh Vutla /** 895*9b87181fSLokesh Vutla * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI 896*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 897*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 898*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 899*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 900*9b87181fSLokesh Vutla * which clock input to modify. 901*9b87181fSLokesh Vutla * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false' 902*9b87181fSLokesh Vutla * @can_change_freq: 'true' if frequency change is desired, else 'false' 903*9b87181fSLokesh Vutla * @enable_input_term: 'true' if input termination is desired, else 'false' 904*9b87181fSLokesh Vutla * 905*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 906*9b87181fSLokesh Vutla */ 907*9b87181fSLokesh Vutla static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id, 908*9b87181fSLokesh Vutla u8 clk_id, bool needs_ssc, bool can_change_freq, 909*9b87181fSLokesh Vutla bool enable_input_term) 910*9b87181fSLokesh Vutla { 911*9b87181fSLokesh Vutla u32 flags = 0; 912*9b87181fSLokesh Vutla 913*9b87181fSLokesh Vutla flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0; 914*9b87181fSLokesh Vutla flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0; 915*9b87181fSLokesh Vutla flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0; 916*9b87181fSLokesh Vutla 917*9b87181fSLokesh Vutla return ti_sci_set_clock_state(handle, dev_id, clk_id, flags, 918*9b87181fSLokesh Vutla MSG_CLOCK_SW_STATE_REQ); 919*9b87181fSLokesh Vutla } 920*9b87181fSLokesh Vutla 921*9b87181fSLokesh Vutla /** 922*9b87181fSLokesh Vutla * ti_sci_cmd_idle_clock() - Idle a clock which is in our control 923*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 924*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 925*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 926*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 927*9b87181fSLokesh Vutla * which clock input to modify. 928*9b87181fSLokesh Vutla * 929*9b87181fSLokesh Vutla * NOTE: This clock must have been requested by get_clock previously. 930*9b87181fSLokesh Vutla * 931*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 932*9b87181fSLokesh Vutla */ 933*9b87181fSLokesh Vutla static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle, 934*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id) 935*9b87181fSLokesh Vutla { 936*9b87181fSLokesh Vutla return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, 937*9b87181fSLokesh Vutla MSG_CLOCK_SW_STATE_UNREQ); 938*9b87181fSLokesh Vutla } 939*9b87181fSLokesh Vutla 940*9b87181fSLokesh Vutla /** 941*9b87181fSLokesh Vutla * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI 942*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 943*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 944*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 945*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 946*9b87181fSLokesh Vutla * which clock input to modify. 947*9b87181fSLokesh Vutla * 948*9b87181fSLokesh Vutla * NOTE: This clock must have been requested by get_clock previously. 949*9b87181fSLokesh Vutla * 950*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 951*9b87181fSLokesh Vutla */ 952*9b87181fSLokesh Vutla static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle, 953*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id) 954*9b87181fSLokesh Vutla { 955*9b87181fSLokesh Vutla return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, 956*9b87181fSLokesh Vutla MSG_CLOCK_SW_STATE_AUTO); 957*9b87181fSLokesh Vutla } 958*9b87181fSLokesh Vutla 959*9b87181fSLokesh Vutla /** 960*9b87181fSLokesh Vutla * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed 961*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 962*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 963*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 964*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 965*9b87181fSLokesh Vutla * which clock input to modify. 966*9b87181fSLokesh Vutla * @req_state: state indicating if the clock is auto managed 967*9b87181fSLokesh Vutla * 968*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 969*9b87181fSLokesh Vutla */ 970*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle, 971*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id, bool *req_state) 972*9b87181fSLokesh Vutla { 973*9b87181fSLokesh Vutla u8 state = 0; 974*9b87181fSLokesh Vutla int ret; 975*9b87181fSLokesh Vutla 976*9b87181fSLokesh Vutla if (!req_state) 977*9b87181fSLokesh Vutla return -EINVAL; 978*9b87181fSLokesh Vutla 979*9b87181fSLokesh Vutla ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL); 980*9b87181fSLokesh Vutla if (ret) 981*9b87181fSLokesh Vutla return ret; 982*9b87181fSLokesh Vutla 983*9b87181fSLokesh Vutla *req_state = (state == MSG_CLOCK_SW_STATE_AUTO); 984*9b87181fSLokesh Vutla return 0; 985*9b87181fSLokesh Vutla } 986*9b87181fSLokesh Vutla 987*9b87181fSLokesh Vutla /** 988*9b87181fSLokesh Vutla * ti_sci_cmd_clk_is_on() - Is the clock ON 989*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 990*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 991*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 992*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 993*9b87181fSLokesh Vutla * which clock input to modify. 994*9b87181fSLokesh Vutla * @req_state: state indicating if the clock is managed by us and enabled 995*9b87181fSLokesh Vutla * @curr_state: state indicating if the clock is ready for operation 996*9b87181fSLokesh Vutla * 997*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 998*9b87181fSLokesh Vutla */ 999*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id, 1000*9b87181fSLokesh Vutla u8 clk_id, bool *req_state, bool *curr_state) 1001*9b87181fSLokesh Vutla { 1002*9b87181fSLokesh Vutla u8 c_state = 0, r_state = 0; 1003*9b87181fSLokesh Vutla int ret; 1004*9b87181fSLokesh Vutla 1005*9b87181fSLokesh Vutla if (!req_state && !curr_state) 1006*9b87181fSLokesh Vutla return -EINVAL; 1007*9b87181fSLokesh Vutla 1008*9b87181fSLokesh Vutla ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, 1009*9b87181fSLokesh Vutla &r_state, &c_state); 1010*9b87181fSLokesh Vutla if (ret) 1011*9b87181fSLokesh Vutla return ret; 1012*9b87181fSLokesh Vutla 1013*9b87181fSLokesh Vutla if (req_state) 1014*9b87181fSLokesh Vutla *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ); 1015*9b87181fSLokesh Vutla if (curr_state) 1016*9b87181fSLokesh Vutla *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY); 1017*9b87181fSLokesh Vutla return 0; 1018*9b87181fSLokesh Vutla } 1019*9b87181fSLokesh Vutla 1020*9b87181fSLokesh Vutla /** 1021*9b87181fSLokesh Vutla * ti_sci_cmd_clk_is_off() - Is the clock OFF 1022*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 1023*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 1024*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 1025*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 1026*9b87181fSLokesh Vutla * which clock input to modify. 1027*9b87181fSLokesh Vutla * @req_state: state indicating if the clock is managed by us and disabled 1028*9b87181fSLokesh Vutla * @curr_state: state indicating if the clock is NOT ready for operation 1029*9b87181fSLokesh Vutla * 1030*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 1031*9b87181fSLokesh Vutla */ 1032*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id, 1033*9b87181fSLokesh Vutla u8 clk_id, bool *req_state, bool *curr_state) 1034*9b87181fSLokesh Vutla { 1035*9b87181fSLokesh Vutla u8 c_state = 0, r_state = 0; 1036*9b87181fSLokesh Vutla int ret; 1037*9b87181fSLokesh Vutla 1038*9b87181fSLokesh Vutla if (!req_state && !curr_state) 1039*9b87181fSLokesh Vutla return -EINVAL; 1040*9b87181fSLokesh Vutla 1041*9b87181fSLokesh Vutla ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, 1042*9b87181fSLokesh Vutla &r_state, &c_state); 1043*9b87181fSLokesh Vutla if (ret) 1044*9b87181fSLokesh Vutla return ret; 1045*9b87181fSLokesh Vutla 1046*9b87181fSLokesh Vutla if (req_state) 1047*9b87181fSLokesh Vutla *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ); 1048*9b87181fSLokesh Vutla if (curr_state) 1049*9b87181fSLokesh Vutla *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY); 1050*9b87181fSLokesh Vutla return 0; 1051*9b87181fSLokesh Vutla } 1052*9b87181fSLokesh Vutla 1053*9b87181fSLokesh Vutla /** 1054*9b87181fSLokesh Vutla * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock 1055*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 1056*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 1057*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 1058*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 1059*9b87181fSLokesh Vutla * which clock input to modify. 1060*9b87181fSLokesh Vutla * @parent_id: Parent clock identifier to set 1061*9b87181fSLokesh Vutla * 1062*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 1063*9b87181fSLokesh Vutla */ 1064*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle, 1065*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id, u8 parent_id) 1066*9b87181fSLokesh Vutla { 1067*9b87181fSLokesh Vutla struct ti_sci_msg_req_set_clock_parent req; 1068*9b87181fSLokesh Vutla struct ti_sci_msg_hdr *resp; 1069*9b87181fSLokesh Vutla struct ti_sci_info *info; 1070*9b87181fSLokesh Vutla struct ti_sci_xfer *xfer; 1071*9b87181fSLokesh Vutla int ret = 0; 1072*9b87181fSLokesh Vutla 1073*9b87181fSLokesh Vutla if (IS_ERR(handle)) 1074*9b87181fSLokesh Vutla return PTR_ERR(handle); 1075*9b87181fSLokesh Vutla if (!handle) 1076*9b87181fSLokesh Vutla return -EINVAL; 1077*9b87181fSLokesh Vutla 1078*9b87181fSLokesh Vutla info = handle_to_ti_sci_info(handle); 1079*9b87181fSLokesh Vutla 1080*9b87181fSLokesh Vutla xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT, 1081*9b87181fSLokesh Vutla TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 1082*9b87181fSLokesh Vutla (u32 *)&req, sizeof(req), sizeof(*resp)); 1083*9b87181fSLokesh Vutla if (IS_ERR(xfer)) { 1084*9b87181fSLokesh Vutla ret = PTR_ERR(xfer); 1085*9b87181fSLokesh Vutla dev_err(info->dev, "Message alloc failed(%d)\n", ret); 1086*9b87181fSLokesh Vutla return ret; 1087*9b87181fSLokesh Vutla } 1088*9b87181fSLokesh Vutla req.dev_id = dev_id; 1089*9b87181fSLokesh Vutla req.clk_id = clk_id; 1090*9b87181fSLokesh Vutla req.parent_id = parent_id; 1091*9b87181fSLokesh Vutla 1092*9b87181fSLokesh Vutla ret = ti_sci_do_xfer(info, xfer); 1093*9b87181fSLokesh Vutla if (ret) { 1094*9b87181fSLokesh Vutla dev_err(info->dev, "Mbox send fail %d\n", ret); 1095*9b87181fSLokesh Vutla return ret; 1096*9b87181fSLokesh Vutla } 1097*9b87181fSLokesh Vutla 1098*9b87181fSLokesh Vutla resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; 1099*9b87181fSLokesh Vutla 1100*9b87181fSLokesh Vutla if (!ti_sci_is_response_ack(resp)) 1101*9b87181fSLokesh Vutla return -ENODEV; 1102*9b87181fSLokesh Vutla 1103*9b87181fSLokesh Vutla return ret; 1104*9b87181fSLokesh Vutla } 1105*9b87181fSLokesh Vutla 1106*9b87181fSLokesh Vutla /** 1107*9b87181fSLokesh Vutla * ti_sci_cmd_clk_get_parent() - Get current parent clock source 1108*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 1109*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 1110*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 1111*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 1112*9b87181fSLokesh Vutla * which clock input to modify. 1113*9b87181fSLokesh Vutla * @parent_id: Current clock parent 1114*9b87181fSLokesh Vutla * 1115*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 1116*9b87181fSLokesh Vutla */ 1117*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle, 1118*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id, u8 *parent_id) 1119*9b87181fSLokesh Vutla { 1120*9b87181fSLokesh Vutla struct ti_sci_msg_resp_get_clock_parent *resp; 1121*9b87181fSLokesh Vutla struct ti_sci_msg_req_get_clock_parent req; 1122*9b87181fSLokesh Vutla struct ti_sci_info *info; 1123*9b87181fSLokesh Vutla struct ti_sci_xfer *xfer; 1124*9b87181fSLokesh Vutla int ret = 0; 1125*9b87181fSLokesh Vutla 1126*9b87181fSLokesh Vutla if (IS_ERR(handle)) 1127*9b87181fSLokesh Vutla return PTR_ERR(handle); 1128*9b87181fSLokesh Vutla if (!handle || !parent_id) 1129*9b87181fSLokesh Vutla return -EINVAL; 1130*9b87181fSLokesh Vutla 1131*9b87181fSLokesh Vutla info = handle_to_ti_sci_info(handle); 1132*9b87181fSLokesh Vutla 1133*9b87181fSLokesh Vutla xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT, 1134*9b87181fSLokesh Vutla TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 1135*9b87181fSLokesh Vutla (u32 *)&req, sizeof(req), sizeof(*resp)); 1136*9b87181fSLokesh Vutla if (IS_ERR(xfer)) { 1137*9b87181fSLokesh Vutla ret = PTR_ERR(xfer); 1138*9b87181fSLokesh Vutla dev_err(info->dev, "Message alloc failed(%d)\n", ret); 1139*9b87181fSLokesh Vutla return ret; 1140*9b87181fSLokesh Vutla } 1141*9b87181fSLokesh Vutla req.dev_id = dev_id; 1142*9b87181fSLokesh Vutla req.clk_id = clk_id; 1143*9b87181fSLokesh Vutla 1144*9b87181fSLokesh Vutla ret = ti_sci_do_xfer(info, xfer); 1145*9b87181fSLokesh Vutla if (ret) { 1146*9b87181fSLokesh Vutla dev_err(info->dev, "Mbox send fail %d\n", ret); 1147*9b87181fSLokesh Vutla return ret; 1148*9b87181fSLokesh Vutla } 1149*9b87181fSLokesh Vutla 1150*9b87181fSLokesh Vutla resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->tx_message.buf; 1151*9b87181fSLokesh Vutla 1152*9b87181fSLokesh Vutla if (!ti_sci_is_response_ack(resp)) 1153*9b87181fSLokesh Vutla ret = -ENODEV; 1154*9b87181fSLokesh Vutla else 1155*9b87181fSLokesh Vutla *parent_id = resp->parent_id; 1156*9b87181fSLokesh Vutla 1157*9b87181fSLokesh Vutla return ret; 1158*9b87181fSLokesh Vutla } 1159*9b87181fSLokesh Vutla 1160*9b87181fSLokesh Vutla /** 1161*9b87181fSLokesh Vutla * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source 1162*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 1163*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 1164*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 1165*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 1166*9b87181fSLokesh Vutla * which clock input to modify. 1167*9b87181fSLokesh Vutla * @num_parents: Returns he number of parents to the current clock. 1168*9b87181fSLokesh Vutla * 1169*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 1170*9b87181fSLokesh Vutla */ 1171*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle, 1172*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id, 1173*9b87181fSLokesh Vutla u8 *num_parents) 1174*9b87181fSLokesh Vutla { 1175*9b87181fSLokesh Vutla struct ti_sci_msg_resp_get_clock_num_parents *resp; 1176*9b87181fSLokesh Vutla struct ti_sci_msg_req_get_clock_num_parents req; 1177*9b87181fSLokesh Vutla struct ti_sci_info *info; 1178*9b87181fSLokesh Vutla struct ti_sci_xfer *xfer; 1179*9b87181fSLokesh Vutla int ret = 0; 1180*9b87181fSLokesh Vutla 1181*9b87181fSLokesh Vutla if (IS_ERR(handle)) 1182*9b87181fSLokesh Vutla return PTR_ERR(handle); 1183*9b87181fSLokesh Vutla if (!handle || !num_parents) 1184*9b87181fSLokesh Vutla return -EINVAL; 1185*9b87181fSLokesh Vutla 1186*9b87181fSLokesh Vutla info = handle_to_ti_sci_info(handle); 1187*9b87181fSLokesh Vutla 1188*9b87181fSLokesh Vutla xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, 1189*9b87181fSLokesh Vutla TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 1190*9b87181fSLokesh Vutla (u32 *)&req, sizeof(req), sizeof(*resp)); 1191*9b87181fSLokesh Vutla if (IS_ERR(xfer)) { 1192*9b87181fSLokesh Vutla ret = PTR_ERR(xfer); 1193*9b87181fSLokesh Vutla dev_err(info->dev, "Message alloc failed(%d)\n", ret); 1194*9b87181fSLokesh Vutla return ret; 1195*9b87181fSLokesh Vutla } 1196*9b87181fSLokesh Vutla req.dev_id = dev_id; 1197*9b87181fSLokesh Vutla req.clk_id = clk_id; 1198*9b87181fSLokesh Vutla 1199*9b87181fSLokesh Vutla ret = ti_sci_do_xfer(info, xfer); 1200*9b87181fSLokesh Vutla if (ret) { 1201*9b87181fSLokesh Vutla dev_err(info->dev, "Mbox send fail %d\n", ret); 1202*9b87181fSLokesh Vutla return ret; 1203*9b87181fSLokesh Vutla } 1204*9b87181fSLokesh Vutla 1205*9b87181fSLokesh Vutla resp = (struct ti_sci_msg_resp_get_clock_num_parents *) 1206*9b87181fSLokesh Vutla xfer->tx_message.buf; 1207*9b87181fSLokesh Vutla 1208*9b87181fSLokesh Vutla if (!ti_sci_is_response_ack(resp)) 1209*9b87181fSLokesh Vutla ret = -ENODEV; 1210*9b87181fSLokesh Vutla else 1211*9b87181fSLokesh Vutla *num_parents = resp->num_parents; 1212*9b87181fSLokesh Vutla 1213*9b87181fSLokesh Vutla return ret; 1214*9b87181fSLokesh Vutla } 1215*9b87181fSLokesh Vutla 1216*9b87181fSLokesh Vutla /** 1217*9b87181fSLokesh Vutla * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency 1218*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 1219*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 1220*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 1221*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 1222*9b87181fSLokesh Vutla * which clock input to modify. 1223*9b87181fSLokesh Vutla * @min_freq: The minimum allowable frequency in Hz. This is the minimum 1224*9b87181fSLokesh Vutla * allowable programmed frequency and does not account for clock 1225*9b87181fSLokesh Vutla * tolerances and jitter. 1226*9b87181fSLokesh Vutla * @target_freq: The target clock frequency in Hz. A frequency will be 1227*9b87181fSLokesh Vutla * processed as close to this target frequency as possible. 1228*9b87181fSLokesh Vutla * @max_freq: The maximum allowable frequency in Hz. This is the maximum 1229*9b87181fSLokesh Vutla * allowable programmed frequency and does not account for clock 1230*9b87181fSLokesh Vutla * tolerances and jitter. 1231*9b87181fSLokesh Vutla * @match_freq: Frequency match in Hz response. 1232*9b87181fSLokesh Vutla * 1233*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 1234*9b87181fSLokesh Vutla */ 1235*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle, 1236*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id, u64 min_freq, 1237*9b87181fSLokesh Vutla u64 target_freq, u64 max_freq, 1238*9b87181fSLokesh Vutla u64 *match_freq) 1239*9b87181fSLokesh Vutla { 1240*9b87181fSLokesh Vutla struct ti_sci_msg_resp_query_clock_freq *resp; 1241*9b87181fSLokesh Vutla struct ti_sci_msg_req_query_clock_freq req; 1242*9b87181fSLokesh Vutla struct ti_sci_info *info; 1243*9b87181fSLokesh Vutla struct ti_sci_xfer *xfer; 1244*9b87181fSLokesh Vutla int ret = 0; 1245*9b87181fSLokesh Vutla 1246*9b87181fSLokesh Vutla if (IS_ERR(handle)) 1247*9b87181fSLokesh Vutla return PTR_ERR(handle); 1248*9b87181fSLokesh Vutla if (!handle || !match_freq) 1249*9b87181fSLokesh Vutla return -EINVAL; 1250*9b87181fSLokesh Vutla 1251*9b87181fSLokesh Vutla info = handle_to_ti_sci_info(handle); 1252*9b87181fSLokesh Vutla 1253*9b87181fSLokesh Vutla xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ, 1254*9b87181fSLokesh Vutla TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 1255*9b87181fSLokesh Vutla (u32 *)&req, sizeof(req), sizeof(*resp)); 1256*9b87181fSLokesh Vutla if (IS_ERR(xfer)) { 1257*9b87181fSLokesh Vutla ret = PTR_ERR(xfer); 1258*9b87181fSLokesh Vutla dev_err(info->dev, "Message alloc failed(%d)\n", ret); 1259*9b87181fSLokesh Vutla return ret; 1260*9b87181fSLokesh Vutla } 1261*9b87181fSLokesh Vutla req.dev_id = dev_id; 1262*9b87181fSLokesh Vutla req.clk_id = clk_id; 1263*9b87181fSLokesh Vutla req.min_freq_hz = min_freq; 1264*9b87181fSLokesh Vutla req.target_freq_hz = target_freq; 1265*9b87181fSLokesh Vutla req.max_freq_hz = max_freq; 1266*9b87181fSLokesh Vutla 1267*9b87181fSLokesh Vutla ret = ti_sci_do_xfer(info, xfer); 1268*9b87181fSLokesh Vutla if (ret) { 1269*9b87181fSLokesh Vutla dev_err(info->dev, "Mbox send fail %d\n", ret); 1270*9b87181fSLokesh Vutla return ret; 1271*9b87181fSLokesh Vutla } 1272*9b87181fSLokesh Vutla 1273*9b87181fSLokesh Vutla resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->tx_message.buf; 1274*9b87181fSLokesh Vutla 1275*9b87181fSLokesh Vutla if (!ti_sci_is_response_ack(resp)) 1276*9b87181fSLokesh Vutla ret = -ENODEV; 1277*9b87181fSLokesh Vutla else 1278*9b87181fSLokesh Vutla *match_freq = resp->freq_hz; 1279*9b87181fSLokesh Vutla 1280*9b87181fSLokesh Vutla return ret; 1281*9b87181fSLokesh Vutla } 1282*9b87181fSLokesh Vutla 1283*9b87181fSLokesh Vutla /** 1284*9b87181fSLokesh Vutla * ti_sci_cmd_clk_set_freq() - Set a frequency for clock 1285*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 1286*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 1287*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 1288*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 1289*9b87181fSLokesh Vutla * which clock input to modify. 1290*9b87181fSLokesh Vutla * @min_freq: The minimum allowable frequency in Hz. This is the minimum 1291*9b87181fSLokesh Vutla * allowable programmed frequency and does not account for clock 1292*9b87181fSLokesh Vutla * tolerances and jitter. 1293*9b87181fSLokesh Vutla * @target_freq: The target clock frequency in Hz. A frequency will be 1294*9b87181fSLokesh Vutla * processed as close to this target frequency as possible. 1295*9b87181fSLokesh Vutla * @max_freq: The maximum allowable frequency in Hz. This is the maximum 1296*9b87181fSLokesh Vutla * allowable programmed frequency and does not account for clock 1297*9b87181fSLokesh Vutla * tolerances and jitter. 1298*9b87181fSLokesh Vutla * 1299*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 1300*9b87181fSLokesh Vutla */ 1301*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle, 1302*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id, u64 min_freq, 1303*9b87181fSLokesh Vutla u64 target_freq, u64 max_freq) 1304*9b87181fSLokesh Vutla { 1305*9b87181fSLokesh Vutla struct ti_sci_msg_req_set_clock_freq req; 1306*9b87181fSLokesh Vutla struct ti_sci_msg_hdr *resp; 1307*9b87181fSLokesh Vutla struct ti_sci_info *info; 1308*9b87181fSLokesh Vutla struct ti_sci_xfer *xfer; 1309*9b87181fSLokesh Vutla int ret = 0; 1310*9b87181fSLokesh Vutla 1311*9b87181fSLokesh Vutla if (IS_ERR(handle)) 1312*9b87181fSLokesh Vutla return PTR_ERR(handle); 1313*9b87181fSLokesh Vutla if (!handle) 1314*9b87181fSLokesh Vutla return -EINVAL; 1315*9b87181fSLokesh Vutla 1316*9b87181fSLokesh Vutla info = handle_to_ti_sci_info(handle); 1317*9b87181fSLokesh Vutla 1318*9b87181fSLokesh Vutla xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ, 1319*9b87181fSLokesh Vutla TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 1320*9b87181fSLokesh Vutla (u32 *)&req, sizeof(req), sizeof(*resp)); 1321*9b87181fSLokesh Vutla if (IS_ERR(xfer)) { 1322*9b87181fSLokesh Vutla ret = PTR_ERR(xfer); 1323*9b87181fSLokesh Vutla dev_err(info->dev, "Message alloc failed(%d)\n", ret); 1324*9b87181fSLokesh Vutla return ret; 1325*9b87181fSLokesh Vutla } 1326*9b87181fSLokesh Vutla req.dev_id = dev_id; 1327*9b87181fSLokesh Vutla req.clk_id = clk_id; 1328*9b87181fSLokesh Vutla req.min_freq_hz = min_freq; 1329*9b87181fSLokesh Vutla req.target_freq_hz = target_freq; 1330*9b87181fSLokesh Vutla req.max_freq_hz = max_freq; 1331*9b87181fSLokesh Vutla 1332*9b87181fSLokesh Vutla ret = ti_sci_do_xfer(info, xfer); 1333*9b87181fSLokesh Vutla if (ret) { 1334*9b87181fSLokesh Vutla dev_err(info->dev, "Mbox send fail %d\n", ret); 1335*9b87181fSLokesh Vutla return ret; 1336*9b87181fSLokesh Vutla } 1337*9b87181fSLokesh Vutla 1338*9b87181fSLokesh Vutla resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; 1339*9b87181fSLokesh Vutla 1340*9b87181fSLokesh Vutla if (!ti_sci_is_response_ack(resp)) 1341*9b87181fSLokesh Vutla return -ENODEV; 1342*9b87181fSLokesh Vutla 1343*9b87181fSLokesh Vutla return ret; 1344*9b87181fSLokesh Vutla } 1345*9b87181fSLokesh Vutla 1346*9b87181fSLokesh Vutla /** 1347*9b87181fSLokesh Vutla * ti_sci_cmd_clk_get_freq() - Get current frequency 1348*9b87181fSLokesh Vutla * @handle: pointer to TI SCI handle 1349*9b87181fSLokesh Vutla * @dev_id: Device identifier this request is for 1350*9b87181fSLokesh Vutla * @clk_id: Clock identifier for the device for this request. 1351*9b87181fSLokesh Vutla * Each device has it's own set of clock inputs. This indexes 1352*9b87181fSLokesh Vutla * which clock input to modify. 1353*9b87181fSLokesh Vutla * @freq: Currently frequency in Hz 1354*9b87181fSLokesh Vutla * 1355*9b87181fSLokesh Vutla * Return: 0 if all went well, else returns appropriate error value. 1356*9b87181fSLokesh Vutla */ 1357*9b87181fSLokesh Vutla static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle, 1358*9b87181fSLokesh Vutla u32 dev_id, u8 clk_id, u64 *freq) 1359*9b87181fSLokesh Vutla { 1360*9b87181fSLokesh Vutla struct ti_sci_msg_resp_get_clock_freq *resp; 1361*9b87181fSLokesh Vutla struct ti_sci_msg_req_get_clock_freq req; 1362*9b87181fSLokesh Vutla struct ti_sci_info *info; 1363*9b87181fSLokesh Vutla struct ti_sci_xfer *xfer; 1364*9b87181fSLokesh Vutla int ret = 0; 1365*9b87181fSLokesh Vutla 1366*9b87181fSLokesh Vutla if (IS_ERR(handle)) 1367*9b87181fSLokesh Vutla return PTR_ERR(handle); 1368*9b87181fSLokesh Vutla if (!handle || !freq) 1369*9b87181fSLokesh Vutla return -EINVAL; 1370*9b87181fSLokesh Vutla 1371*9b87181fSLokesh Vutla info = handle_to_ti_sci_info(handle); 1372*9b87181fSLokesh Vutla 1373*9b87181fSLokesh Vutla xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ, 1374*9b87181fSLokesh Vutla TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 1375*9b87181fSLokesh Vutla (u32 *)&req, sizeof(req), sizeof(*resp)); 1376*9b87181fSLokesh Vutla if (IS_ERR(xfer)) { 1377*9b87181fSLokesh Vutla ret = PTR_ERR(xfer); 1378*9b87181fSLokesh Vutla dev_err(info->dev, "Message alloc failed(%d)\n", ret); 1379*9b87181fSLokesh Vutla return ret; 1380*9b87181fSLokesh Vutla } 1381*9b87181fSLokesh Vutla req.dev_id = dev_id; 1382*9b87181fSLokesh Vutla req.clk_id = clk_id; 1383*9b87181fSLokesh Vutla 1384*9b87181fSLokesh Vutla ret = ti_sci_do_xfer(info, xfer); 1385*9b87181fSLokesh Vutla if (ret) { 1386*9b87181fSLokesh Vutla dev_err(info->dev, "Mbox send fail %d\n", ret); 1387*9b87181fSLokesh Vutla return ret; 1388*9b87181fSLokesh Vutla } 1389*9b87181fSLokesh Vutla 1390*9b87181fSLokesh Vutla resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->tx_message.buf; 1391*9b87181fSLokesh Vutla 1392*9b87181fSLokesh Vutla if (!ti_sci_is_response_ack(resp)) 1393*9b87181fSLokesh Vutla ret = -ENODEV; 1394*9b87181fSLokesh Vutla else 1395*9b87181fSLokesh Vutla *freq = resp->freq_hz; 1396*9b87181fSLokesh Vutla 1397*9b87181fSLokesh Vutla return ret; 1398*9b87181fSLokesh Vutla } 1399*9b87181fSLokesh Vutla 1400dcfc52adSAndreas Dannenberg /* 1401dcfc52adSAndreas Dannenberg * ti_sci_setup_ops() - Setup the operations structures 1402dcfc52adSAndreas Dannenberg * @info: pointer to TISCI pointer 1403dcfc52adSAndreas Dannenberg */ 1404dcfc52adSAndreas Dannenberg static void ti_sci_setup_ops(struct ti_sci_info *info) 1405dcfc52adSAndreas Dannenberg { 1406dcfc52adSAndreas Dannenberg struct ti_sci_ops *ops = &info->handle.ops; 1407dcfc52adSAndreas Dannenberg struct ti_sci_board_ops *bops = &ops->board_ops; 14087bc33045SAndreas Dannenberg struct ti_sci_dev_ops *dops = &ops->dev_ops; 1409*9b87181fSLokesh Vutla struct ti_sci_clk_ops *cops = &ops->clk_ops; 1410dcfc52adSAndreas Dannenberg 1411dcfc52adSAndreas Dannenberg bops->board_config = ti_sci_cmd_set_board_config; 1412dcfc52adSAndreas Dannenberg bops->board_config_rm = ti_sci_cmd_set_board_config_rm; 1413dcfc52adSAndreas Dannenberg bops->board_config_security = ti_sci_cmd_set_board_config_security; 1414dcfc52adSAndreas Dannenberg bops->board_config_pm = ti_sci_cmd_set_board_config_pm; 14157bc33045SAndreas Dannenberg 14167bc33045SAndreas Dannenberg dops->get_device = ti_sci_cmd_get_device; 14177bc33045SAndreas Dannenberg dops->idle_device = ti_sci_cmd_idle_device; 14187bc33045SAndreas Dannenberg dops->put_device = ti_sci_cmd_put_device; 14197bc33045SAndreas Dannenberg dops->is_valid = ti_sci_cmd_dev_is_valid; 14207bc33045SAndreas Dannenberg dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt; 14217bc33045SAndreas Dannenberg dops->is_idle = ti_sci_cmd_dev_is_idle; 14227bc33045SAndreas Dannenberg dops->is_stop = ti_sci_cmd_dev_is_stop; 14237bc33045SAndreas Dannenberg dops->is_on = ti_sci_cmd_dev_is_on; 14247bc33045SAndreas Dannenberg dops->is_transitioning = ti_sci_cmd_dev_is_trans; 14257bc33045SAndreas Dannenberg dops->set_device_resets = ti_sci_cmd_set_device_resets; 14267bc33045SAndreas Dannenberg dops->get_device_resets = ti_sci_cmd_get_device_resets; 1427*9b87181fSLokesh Vutla 1428*9b87181fSLokesh Vutla cops->get_clock = ti_sci_cmd_get_clock; 1429*9b87181fSLokesh Vutla cops->idle_clock = ti_sci_cmd_idle_clock; 1430*9b87181fSLokesh Vutla cops->put_clock = ti_sci_cmd_put_clock; 1431*9b87181fSLokesh Vutla cops->is_auto = ti_sci_cmd_clk_is_auto; 1432*9b87181fSLokesh Vutla cops->is_on = ti_sci_cmd_clk_is_on; 1433*9b87181fSLokesh Vutla cops->is_off = ti_sci_cmd_clk_is_off; 1434*9b87181fSLokesh Vutla 1435*9b87181fSLokesh Vutla cops->set_parent = ti_sci_cmd_clk_set_parent; 1436*9b87181fSLokesh Vutla cops->get_parent = ti_sci_cmd_clk_get_parent; 1437*9b87181fSLokesh Vutla cops->get_num_parents = ti_sci_cmd_clk_get_num_parents; 1438*9b87181fSLokesh Vutla 1439*9b87181fSLokesh Vutla cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq; 1440*9b87181fSLokesh Vutla cops->set_freq = ti_sci_cmd_clk_set_freq; 1441*9b87181fSLokesh Vutla cops->get_freq = ti_sci_cmd_clk_get_freq; 1442dcfc52adSAndreas Dannenberg } 1443dcfc52adSAndreas Dannenberg 1444dcfc52adSAndreas Dannenberg /** 144532cd2512SLokesh Vutla * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW 144632cd2512SLokesh Vutla * @dev: Pointer to the SYSFW device 144732cd2512SLokesh Vutla * 144832cd2512SLokesh Vutla * Return: pointer to handle if successful, else EINVAL if invalid conditions 144932cd2512SLokesh Vutla * are encountered. 145032cd2512SLokesh Vutla */ 145132cd2512SLokesh Vutla const 145232cd2512SLokesh Vutla struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev) 145332cd2512SLokesh Vutla { 145432cd2512SLokesh Vutla if (!sci_dev) 145532cd2512SLokesh Vutla return ERR_PTR(-EINVAL); 145632cd2512SLokesh Vutla 145732cd2512SLokesh Vutla struct ti_sci_info *info = dev_get_priv(sci_dev); 145832cd2512SLokesh Vutla 145932cd2512SLokesh Vutla if (!info) 146032cd2512SLokesh Vutla return ERR_PTR(-EINVAL); 146132cd2512SLokesh Vutla 146232cd2512SLokesh Vutla struct ti_sci_handle *handle = &info->handle; 146332cd2512SLokesh Vutla 146432cd2512SLokesh Vutla if (!handle) 146532cd2512SLokesh Vutla return ERR_PTR(-EINVAL); 146632cd2512SLokesh Vutla 146732cd2512SLokesh Vutla return handle; 146832cd2512SLokesh Vutla } 146932cd2512SLokesh Vutla 147032cd2512SLokesh Vutla /** 147132cd2512SLokesh Vutla * ti_sci_get_handle() - Get the TI SCI handle for a device 147232cd2512SLokesh Vutla * @dev: Pointer to device for which we want SCI handle 147332cd2512SLokesh Vutla * 147432cd2512SLokesh Vutla * Return: pointer to handle if successful, else EINVAL if invalid conditions 147532cd2512SLokesh Vutla * are encountered. 147632cd2512SLokesh Vutla */ 147732cd2512SLokesh Vutla const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev) 147832cd2512SLokesh Vutla { 147932cd2512SLokesh Vutla if (!dev) 148032cd2512SLokesh Vutla return ERR_PTR(-EINVAL); 148132cd2512SLokesh Vutla 148232cd2512SLokesh Vutla struct udevice *sci_dev = dev_get_parent(dev); 148332cd2512SLokesh Vutla 148432cd2512SLokesh Vutla return ti_sci_get_handle_from_sysfw(sci_dev); 148532cd2512SLokesh Vutla } 148632cd2512SLokesh Vutla 148732cd2512SLokesh Vutla /** 148832cd2512SLokesh Vutla * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle 148932cd2512SLokesh Vutla * @dev: device node 149032cd2512SLokesh Vutla * @propname: property name containing phandle on TISCI node 149132cd2512SLokesh Vutla * 149232cd2512SLokesh Vutla * Return: pointer to handle if successful, else appropriate error value. 149332cd2512SLokesh Vutla */ 149432cd2512SLokesh Vutla const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev, 149532cd2512SLokesh Vutla const char *property) 149632cd2512SLokesh Vutla { 149732cd2512SLokesh Vutla struct ti_sci_info *entry, *info = NULL; 149832cd2512SLokesh Vutla u32 phandle, err; 149932cd2512SLokesh Vutla ofnode node; 150032cd2512SLokesh Vutla 150132cd2512SLokesh Vutla err = ofnode_read_u32(dev_ofnode(dev), property, &phandle); 150232cd2512SLokesh Vutla if (err) 150332cd2512SLokesh Vutla return ERR_PTR(err); 150432cd2512SLokesh Vutla 150532cd2512SLokesh Vutla node = ofnode_get_by_phandle(phandle); 150632cd2512SLokesh Vutla if (!ofnode_valid(node)) 150732cd2512SLokesh Vutla return ERR_PTR(-EINVAL); 150832cd2512SLokesh Vutla 150932cd2512SLokesh Vutla list_for_each_entry(entry, &ti_sci_list, list) 151032cd2512SLokesh Vutla if (ofnode_equal(dev_ofnode(entry->dev), node)) { 151132cd2512SLokesh Vutla info = entry; 151232cd2512SLokesh Vutla break; 151332cd2512SLokesh Vutla } 151432cd2512SLokesh Vutla 151532cd2512SLokesh Vutla if (!info) 151632cd2512SLokesh Vutla return ERR_PTR(-ENODEV); 151732cd2512SLokesh Vutla 151832cd2512SLokesh Vutla return &info->handle; 151932cd2512SLokesh Vutla } 152032cd2512SLokesh Vutla 152132cd2512SLokesh Vutla /** 152232cd2512SLokesh Vutla * ti_sci_of_to_info() - generate private data from device tree 152332cd2512SLokesh Vutla * @dev: corresponding system controller interface device 152432cd2512SLokesh Vutla * @info: pointer to driver specific private data 152532cd2512SLokesh Vutla * 152632cd2512SLokesh Vutla * Return: 0 if all goes good, else appropriate error message. 152732cd2512SLokesh Vutla */ 152832cd2512SLokesh Vutla static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info) 152932cd2512SLokesh Vutla { 153032cd2512SLokesh Vutla int ret; 153132cd2512SLokesh Vutla 153232cd2512SLokesh Vutla ret = mbox_get_by_name(dev, "tx", &info->chan_tx); 153332cd2512SLokesh Vutla if (ret) { 153432cd2512SLokesh Vutla dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n", 153532cd2512SLokesh Vutla __func__, ret); 153632cd2512SLokesh Vutla return ret; 153732cd2512SLokesh Vutla } 153832cd2512SLokesh Vutla 153932cd2512SLokesh Vutla ret = mbox_get_by_name(dev, "rx", &info->chan_rx); 154032cd2512SLokesh Vutla if (ret) { 154132cd2512SLokesh Vutla dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n", 154232cd2512SLokesh Vutla __func__, ret); 154332cd2512SLokesh Vutla return ret; 154432cd2512SLokesh Vutla } 154532cd2512SLokesh Vutla 154632cd2512SLokesh Vutla /* Notify channel is optional. Enable only if populated */ 154732cd2512SLokesh Vutla ret = mbox_get_by_name(dev, "notify", &info->chan_notify); 154832cd2512SLokesh Vutla if (ret) { 154932cd2512SLokesh Vutla dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n", 155032cd2512SLokesh Vutla __func__, ret); 155132cd2512SLokesh Vutla } 155232cd2512SLokesh Vutla 155332cd2512SLokesh Vutla info->host_id = dev_read_u32_default(dev, "ti,host-id", 155432cd2512SLokesh Vutla info->desc->host_id); 155532cd2512SLokesh Vutla 155632cd2512SLokesh Vutla info->is_secure = dev_read_bool(dev, "ti,secure-host"); 155732cd2512SLokesh Vutla 155832cd2512SLokesh Vutla return 0; 155932cd2512SLokesh Vutla } 156032cd2512SLokesh Vutla 156132cd2512SLokesh Vutla /** 156232cd2512SLokesh Vutla * ti_sci_probe() - Basic probe 156332cd2512SLokesh Vutla * @dev: corresponding system controller interface device 156432cd2512SLokesh Vutla * 156532cd2512SLokesh Vutla * Return: 0 if all goes good, else appropriate error message. 156632cd2512SLokesh Vutla */ 156732cd2512SLokesh Vutla static int ti_sci_probe(struct udevice *dev) 156832cd2512SLokesh Vutla { 156932cd2512SLokesh Vutla struct ti_sci_info *info; 157032cd2512SLokesh Vutla int ret; 157132cd2512SLokesh Vutla 157232cd2512SLokesh Vutla debug("%s(dev=%p)\n", __func__, dev); 157332cd2512SLokesh Vutla 157432cd2512SLokesh Vutla info = dev_get_priv(dev); 157532cd2512SLokesh Vutla info->desc = (void *)dev_get_driver_data(dev); 157632cd2512SLokesh Vutla 157732cd2512SLokesh Vutla ret = ti_sci_of_to_info(dev, info); 157832cd2512SLokesh Vutla if (ret) { 157932cd2512SLokesh Vutla dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret); 158032cd2512SLokesh Vutla return ret; 158132cd2512SLokesh Vutla } 158232cd2512SLokesh Vutla 158332cd2512SLokesh Vutla info->dev = dev; 158432cd2512SLokesh Vutla info->seq = 0xA; 158532cd2512SLokesh Vutla 158632cd2512SLokesh Vutla list_add_tail(&info->list, &ti_sci_list); 1587dcfc52adSAndreas Dannenberg ti_sci_setup_ops(info); 158832cd2512SLokesh Vutla 158932cd2512SLokesh Vutla ret = ti_sci_cmd_get_revision(&info->handle); 159032cd2512SLokesh Vutla 159132cd2512SLokesh Vutla return ret; 159232cd2512SLokesh Vutla } 159332cd2512SLokesh Vutla 159432cd2512SLokesh Vutla /* Description for AM654 */ 159532cd2512SLokesh Vutla static const struct ti_sci_desc ti_sci_sysfw_am654_desc = { 159632cd2512SLokesh Vutla .host_id = 4, 159732cd2512SLokesh Vutla .max_rx_timeout_us = 1000000, 159832cd2512SLokesh Vutla .max_msg_size = 60, 159932cd2512SLokesh Vutla }; 160032cd2512SLokesh Vutla 160132cd2512SLokesh Vutla static const struct udevice_id ti_sci_ids[] = { 160232cd2512SLokesh Vutla { 160332cd2512SLokesh Vutla .compatible = "ti,k2g-sci", 160432cd2512SLokesh Vutla .data = (ulong)&ti_sci_sysfw_am654_desc 160532cd2512SLokesh Vutla }, 160632cd2512SLokesh Vutla { /* Sentinel */ }, 160732cd2512SLokesh Vutla }; 160832cd2512SLokesh Vutla 160932cd2512SLokesh Vutla U_BOOT_DRIVER(ti_sci) = { 161032cd2512SLokesh Vutla .name = "ti_sci", 161132cd2512SLokesh Vutla .id = UCLASS_FIRMWARE, 161232cd2512SLokesh Vutla .of_match = ti_sci_ids, 161332cd2512SLokesh Vutla .probe = ti_sci_probe, 161432cd2512SLokesh Vutla .priv_auto_alloc_size = sizeof(struct ti_sci_info), 161532cd2512SLokesh Vutla }; 1616