1936afd9fSDhruva Gole /* 2936afd9fSDhruva Gole * Texas Instruments System Control Interface Driver 3936afd9fSDhruva Gole * Based on Linux and U-Boot implementation 4936afd9fSDhruva Gole * 5936afd9fSDhruva Gole * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/ 6936afd9fSDhruva Gole * 7936afd9fSDhruva Gole * SPDX-License-Identifier: BSD-3-Clause 8936afd9fSDhruva Gole */ 9936afd9fSDhruva Gole 10936afd9fSDhruva Gole #include <errno.h> 11936afd9fSDhruva Gole #include <stdbool.h> 12936afd9fSDhruva Gole #include <stddef.h> 13936afd9fSDhruva Gole #include <string.h> 14936afd9fSDhruva Gole 15936afd9fSDhruva Gole #include <platform_def.h> 16936afd9fSDhruva Gole #include <lib/bakery_lock.h> 17936afd9fSDhruva Gole 18936afd9fSDhruva Gole #include <common/debug.h> 19*f70572eeSDhruva Gole #include <ti_sci_transport.h> 20936afd9fSDhruva Gole 21936afd9fSDhruva Gole #include "ti_sci_protocol.h" 22936afd9fSDhruva Gole #include "ti_sci.h" 23936afd9fSDhruva Gole 24936afd9fSDhruva Gole #if USE_COHERENT_MEM 25936afd9fSDhruva Gole __section(".tzfw_coherent_mem") 26936afd9fSDhruva Gole #endif 27936afd9fSDhruva Gole static uint8_t message_sequence; 28936afd9fSDhruva Gole 29936afd9fSDhruva Gole DEFINE_BAKERY_LOCK(ti_sci_xfer_lock); 30936afd9fSDhruva Gole 31936afd9fSDhruva Gole /** 32936afd9fSDhruva Gole * struct ti_sci_xfer - Structure representing a message flow 33936afd9fSDhruva Gole * @tx_message: Transmit message 34936afd9fSDhruva Gole * @rx_message: Receive message 35936afd9fSDhruva Gole */ 36936afd9fSDhruva Gole struct ti_sci_xfer { 37936afd9fSDhruva Gole struct k3_sec_proxy_msg tx_message; 38936afd9fSDhruva Gole struct k3_sec_proxy_msg rx_message; 39936afd9fSDhruva Gole }; 40936afd9fSDhruva Gole 41936afd9fSDhruva Gole /** 42936afd9fSDhruva Gole * ti_sci_setup_one_xfer() - Setup one message type 43936afd9fSDhruva Gole * 44936afd9fSDhruva Gole * @msg_type: Message type 45936afd9fSDhruva Gole * @msg_flags: Flag to set for the message 46936afd9fSDhruva Gole * @tx_buf: Buffer to be sent to mailbox channel 47936afd9fSDhruva Gole * @tx_message_size: transmit message size 48936afd9fSDhruva Gole * @rx_buf: Buffer to be received from mailbox channel 49936afd9fSDhruva Gole * @rx_message_size: receive message size 50936afd9fSDhruva Gole * 51936afd9fSDhruva Gole * Helper function which is used by various command functions that are 52936afd9fSDhruva Gole * exposed to clients of this driver for allocating a message traffic event. 53936afd9fSDhruva Gole * 54936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 55936afd9fSDhruva Gole */ 56936afd9fSDhruva Gole static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags, 57936afd9fSDhruva Gole void *tx_buf, 58936afd9fSDhruva Gole size_t tx_message_size, 59936afd9fSDhruva Gole void *rx_buf, 60936afd9fSDhruva Gole size_t rx_message_size, 61936afd9fSDhruva Gole struct ti_sci_xfer *xfer) 62936afd9fSDhruva Gole { 63936afd9fSDhruva Gole struct ti_sci_msg_hdr *hdr; 64936afd9fSDhruva Gole 65936afd9fSDhruva Gole /* Ensure we have sane transfer sizes */ 66936afd9fSDhruva Gole if (rx_message_size > TI_SCI_MAX_MESSAGE_SIZE || 67936afd9fSDhruva Gole tx_message_size > TI_SCI_MAX_MESSAGE_SIZE || 68936afd9fSDhruva Gole tx_message_size < sizeof(*hdr)) 69936afd9fSDhruva Gole return -ERANGE; 70936afd9fSDhruva Gole 71936afd9fSDhruva Gole hdr = (struct ti_sci_msg_hdr *)tx_buf; 72936afd9fSDhruva Gole hdr->seq = ++message_sequence; 73936afd9fSDhruva Gole hdr->type = msg_type; 74936afd9fSDhruva Gole hdr->host = TI_SCI_HOST_ID; 75936afd9fSDhruva Gole hdr->flags = msg_flags; 76936afd9fSDhruva Gole /* Request a response if rx_message_size is non-zero */ 77936afd9fSDhruva Gole if (rx_message_size != 0U) { 78936afd9fSDhruva Gole hdr->flags |= TI_SCI_FLAG_REQ_ACK_ON_PROCESSED; 79936afd9fSDhruva Gole } 80936afd9fSDhruva Gole 81936afd9fSDhruva Gole xfer->tx_message.buf = tx_buf; 82936afd9fSDhruva Gole xfer->tx_message.len = tx_message_size; 83936afd9fSDhruva Gole 84936afd9fSDhruva Gole xfer->rx_message.buf = rx_buf; 85936afd9fSDhruva Gole xfer->rx_message.len = rx_message_size; 86936afd9fSDhruva Gole 87936afd9fSDhruva Gole return 0; 88936afd9fSDhruva Gole } 89936afd9fSDhruva Gole 90936afd9fSDhruva Gole /** 91936afd9fSDhruva Gole * ti_sci_get_response() - Receive response from mailbox channel 92936afd9fSDhruva Gole * 93936afd9fSDhruva Gole * @xfer: Transfer to initiate and wait for response 94936afd9fSDhruva Gole * @chan: Channel to receive the response 95936afd9fSDhruva Gole * 96936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 97936afd9fSDhruva Gole */ 98936afd9fSDhruva Gole static int ti_sci_get_response(struct k3_sec_proxy_msg *msg, 99936afd9fSDhruva Gole enum k3_sec_proxy_chan_id chan) 100936afd9fSDhruva Gole { 101936afd9fSDhruva Gole struct ti_sci_msg_hdr *hdr; 102936afd9fSDhruva Gole unsigned int retry = 5; 103936afd9fSDhruva Gole int ret; 104936afd9fSDhruva Gole 105936afd9fSDhruva Gole for (; retry > 0; retry--) { 106936afd9fSDhruva Gole /* Receive the response */ 107936afd9fSDhruva Gole ret = k3_sec_proxy_recv(chan, msg); 108936afd9fSDhruva Gole if (ret) { 109936afd9fSDhruva Gole ERROR("Message receive failed (%d)\n", ret); 110936afd9fSDhruva Gole return ret; 111936afd9fSDhruva Gole } 112936afd9fSDhruva Gole 113936afd9fSDhruva Gole /* msg is updated by Secure Proxy driver */ 114936afd9fSDhruva Gole hdr = (struct ti_sci_msg_hdr *)msg->buf; 115936afd9fSDhruva Gole 116936afd9fSDhruva Gole /* Sanity check for message response */ 117936afd9fSDhruva Gole if (hdr->seq == message_sequence) 118936afd9fSDhruva Gole break; 119936afd9fSDhruva Gole else 120936afd9fSDhruva Gole WARN("Message with sequence ID %u is not expected\n", hdr->seq); 121936afd9fSDhruva Gole } 122936afd9fSDhruva Gole if (!retry) { 123936afd9fSDhruva Gole ERROR("Timed out waiting for message\n"); 124936afd9fSDhruva Gole return -EINVAL; 125936afd9fSDhruva Gole } 126936afd9fSDhruva Gole 127936afd9fSDhruva Gole if (msg->len > TI_SCI_MAX_MESSAGE_SIZE) { 128936afd9fSDhruva Gole ERROR("Unable to handle %lu xfer (max %d)\n", 129936afd9fSDhruva Gole msg->len, TI_SCI_MAX_MESSAGE_SIZE); 130936afd9fSDhruva Gole return -EINVAL; 131936afd9fSDhruva Gole } 132936afd9fSDhruva Gole 133936afd9fSDhruva Gole if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK)) 134936afd9fSDhruva Gole return -ENODEV; 135936afd9fSDhruva Gole 136936afd9fSDhruva Gole return 0; 137936afd9fSDhruva Gole } 138936afd9fSDhruva Gole 139936afd9fSDhruva Gole /** 140936afd9fSDhruva Gole * ti_sci_do_xfer() - Do one transfer 141936afd9fSDhruva Gole * 142936afd9fSDhruva Gole * @xfer: Transfer to initiate and wait for response 143936afd9fSDhruva Gole * 144936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 145936afd9fSDhruva Gole */ 146936afd9fSDhruva Gole static int ti_sci_do_xfer(struct ti_sci_xfer *xfer) 147936afd9fSDhruva Gole { 148936afd9fSDhruva Gole struct k3_sec_proxy_msg *tx_msg = &xfer->tx_message; 149936afd9fSDhruva Gole struct k3_sec_proxy_msg *rx_msg = &xfer->rx_message; 150936afd9fSDhruva Gole int ret; 151936afd9fSDhruva Gole 152936afd9fSDhruva Gole bakery_lock_get(&ti_sci_xfer_lock); 153936afd9fSDhruva Gole 154936afd9fSDhruva Gole /* Clear any spurious messages in receive queue */ 155936afd9fSDhruva Gole ret = k3_sec_proxy_clear_rx_thread(SP_RESPONSE); 156936afd9fSDhruva Gole if (ret) { 157936afd9fSDhruva Gole ERROR("Could not clear response queue (%d)\n", ret); 158936afd9fSDhruva Gole goto unlock; 159936afd9fSDhruva Gole } 160936afd9fSDhruva Gole 161936afd9fSDhruva Gole /* Send the message */ 162936afd9fSDhruva Gole ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, tx_msg); 163936afd9fSDhruva Gole if (ret) { 164936afd9fSDhruva Gole ERROR("Message sending failed (%d)\n", ret); 165936afd9fSDhruva Gole goto unlock; 166936afd9fSDhruva Gole } 167936afd9fSDhruva Gole 168936afd9fSDhruva Gole /* Get the response if requested */ 169936afd9fSDhruva Gole if (rx_msg->len != 0U) { 170936afd9fSDhruva Gole ret = ti_sci_get_response(rx_msg, SP_RESPONSE); 171936afd9fSDhruva Gole if (ret != 0U) { 172936afd9fSDhruva Gole ERROR("Failed to get response (%d)\n", ret); 173936afd9fSDhruva Gole goto unlock; 174936afd9fSDhruva Gole } 175936afd9fSDhruva Gole } 176936afd9fSDhruva Gole 177936afd9fSDhruva Gole unlock: 178936afd9fSDhruva Gole bakery_lock_release(&ti_sci_xfer_lock); 179936afd9fSDhruva Gole 180936afd9fSDhruva Gole return ret; 181936afd9fSDhruva Gole } 182936afd9fSDhruva Gole 183936afd9fSDhruva Gole /** 184936afd9fSDhruva Gole * ti_sci_get_revision() - Get the revision of the SCI entity 185936afd9fSDhruva Gole * 186936afd9fSDhruva Gole * Updates the SCI information in the internal data structure. 187936afd9fSDhruva Gole * 188936afd9fSDhruva Gole * @version: Structure containing the version info 189936afd9fSDhruva Gole * 190936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 191936afd9fSDhruva Gole */ 192936afd9fSDhruva Gole int ti_sci_get_revision(struct ti_sci_msg_version *version) 193936afd9fSDhruva Gole { 194936afd9fSDhruva Gole struct ti_sci_msg_resp_version rev_info; 195936afd9fSDhruva Gole struct ti_sci_msg_hdr hdr; 196936afd9fSDhruva Gole struct ti_sci_xfer xfer; 197936afd9fSDhruva Gole int ret; 198936afd9fSDhruva Gole 199936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_VERSION, 0x0, 200936afd9fSDhruva Gole &hdr, sizeof(hdr), 201936afd9fSDhruva Gole &rev_info, sizeof(rev_info), 202936afd9fSDhruva Gole &xfer); 203936afd9fSDhruva Gole if (ret) { 204936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 205936afd9fSDhruva Gole return ret; 206936afd9fSDhruva Gole } 207936afd9fSDhruva Gole 208936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 209936afd9fSDhruva Gole if (ret) { 210936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 211936afd9fSDhruva Gole return ret; 212936afd9fSDhruva Gole } 213936afd9fSDhruva Gole 214936afd9fSDhruva Gole memcpy(version->firmware_description, rev_info.firmware_description, 215936afd9fSDhruva Gole sizeof(rev_info.firmware_description)); 216936afd9fSDhruva Gole version->abi_major = rev_info.abi_major; 217936afd9fSDhruva Gole version->abi_minor = rev_info.abi_minor; 218936afd9fSDhruva Gole version->firmware_revision = rev_info.firmware_revision; 219936afd9fSDhruva Gole version->sub_version = rev_info.sub_version; 220936afd9fSDhruva Gole version->patch_version = rev_info.patch_version; 221936afd9fSDhruva Gole 222936afd9fSDhruva Gole return 0; 223936afd9fSDhruva Gole } 224936afd9fSDhruva Gole 225936afd9fSDhruva Gole /** 226936afd9fSDhruva Gole * ti_sci_query_fw_caps() - Get the FW/SoC capabilities 227936afd9fSDhruva Gole * @handle: Pointer to TI SCI handle 228936afd9fSDhruva Gole * @fw_caps: Each bit in fw_caps indicating one FW/SOC capability 229936afd9fSDhruva Gole * 230936afd9fSDhruva Gole * Return: 0 if all went well, else returns appropriate error value. 231936afd9fSDhruva Gole */ 232936afd9fSDhruva Gole int ti_sci_query_fw_caps(uint64_t *fw_caps) 233936afd9fSDhruva Gole { 234936afd9fSDhruva Gole struct ti_sci_msg_hdr req; 235936afd9fSDhruva Gole struct ti_sci_msg_resp_query_fw_caps resp; 236936afd9fSDhruva Gole 237936afd9fSDhruva Gole struct ti_sci_xfer xfer; 238936afd9fSDhruva Gole int ret; 239936afd9fSDhruva Gole 240936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_FW_CAPS, 0, 241936afd9fSDhruva Gole &req, sizeof(req), 242936afd9fSDhruva Gole &resp, sizeof(resp), 243936afd9fSDhruva Gole &xfer); 244936afd9fSDhruva Gole if (ret != 0U) { 245936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 246936afd9fSDhruva Gole return ret; 247936afd9fSDhruva Gole } 248936afd9fSDhruva Gole 249936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 250936afd9fSDhruva Gole if (ret != 0U) { 251936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 252936afd9fSDhruva Gole return ret; 253936afd9fSDhruva Gole } 254936afd9fSDhruva Gole 255936afd9fSDhruva Gole if (fw_caps) 256936afd9fSDhruva Gole *fw_caps = resp.fw_caps; 257936afd9fSDhruva Gole 258936afd9fSDhruva Gole return 0; 259936afd9fSDhruva Gole } 260936afd9fSDhruva Gole 261936afd9fSDhruva Gole /** 262936afd9fSDhruva Gole * ti_sci_device_set_state() - Set device state 263936afd9fSDhruva Gole * 264936afd9fSDhruva Gole * @id: Device identifier 265936afd9fSDhruva Gole * @flags: flags to setup for the device 266936afd9fSDhruva Gole * @state: State to move the device to 267936afd9fSDhruva Gole * 268936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 269936afd9fSDhruva Gole */ 270936afd9fSDhruva Gole static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state) 271936afd9fSDhruva Gole { 272936afd9fSDhruva Gole struct ti_sci_msg_req_set_device_state req; 273936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 274936afd9fSDhruva Gole 275936afd9fSDhruva Gole struct ti_sci_xfer xfer; 276936afd9fSDhruva Gole int ret; 277936afd9fSDhruva Gole 278936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags, 279936afd9fSDhruva Gole &req, sizeof(req), 280936afd9fSDhruva Gole &resp, sizeof(resp), 281936afd9fSDhruva Gole &xfer); 282936afd9fSDhruva Gole if (ret) { 283936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 284936afd9fSDhruva Gole return ret; 285936afd9fSDhruva Gole } 286936afd9fSDhruva Gole 287936afd9fSDhruva Gole req.id = id; 288936afd9fSDhruva Gole req.state = state; 289936afd9fSDhruva Gole 290936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 291936afd9fSDhruva Gole if (ret) { 292936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 293936afd9fSDhruva Gole return ret; 294936afd9fSDhruva Gole } 295936afd9fSDhruva Gole 296936afd9fSDhruva Gole return 0; 297936afd9fSDhruva Gole } 298936afd9fSDhruva Gole 299936afd9fSDhruva Gole /** 300936afd9fSDhruva Gole * ti_sci_device_get_state() - Get device state 301936afd9fSDhruva Gole * 302936afd9fSDhruva Gole * @id: Device Identifier 303936afd9fSDhruva Gole * @clcnt: Pointer to Context Loss Count 304936afd9fSDhruva Gole * @resets: pointer to resets 305936afd9fSDhruva Gole * @p_state: pointer to p_state 306936afd9fSDhruva Gole * @c_state: pointer to c_state 307936afd9fSDhruva Gole * 308936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 309936afd9fSDhruva Gole */ 310936afd9fSDhruva Gole static int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt, 311936afd9fSDhruva Gole uint32_t *resets, uint8_t *p_state, 312936afd9fSDhruva Gole uint8_t *c_state) 313936afd9fSDhruva Gole { 314936afd9fSDhruva Gole struct ti_sci_msg_req_get_device_state req; 315936afd9fSDhruva Gole struct ti_sci_msg_resp_get_device_state resp; 316936afd9fSDhruva Gole 317936afd9fSDhruva Gole struct ti_sci_xfer xfer; 318936afd9fSDhruva Gole int ret; 319936afd9fSDhruva Gole 320936afd9fSDhruva Gole if (!clcnt && !resets && !p_state && !c_state) 321936afd9fSDhruva Gole return -EINVAL; 322936afd9fSDhruva Gole 323936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0, 324936afd9fSDhruva Gole &req, sizeof(req), 325936afd9fSDhruva Gole &resp, sizeof(resp), 326936afd9fSDhruva Gole &xfer); 327936afd9fSDhruva Gole if (ret) { 328936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 329936afd9fSDhruva Gole return ret; 330936afd9fSDhruva Gole } 331936afd9fSDhruva Gole 332936afd9fSDhruva Gole req.id = id; 333936afd9fSDhruva Gole 334936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 335936afd9fSDhruva Gole if (ret) { 336936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 337936afd9fSDhruva Gole return ret; 338936afd9fSDhruva Gole } 339936afd9fSDhruva Gole 340936afd9fSDhruva Gole if (clcnt) 341936afd9fSDhruva Gole *clcnt = resp.context_loss_count; 342936afd9fSDhruva Gole if (resets) 343936afd9fSDhruva Gole *resets = resp.resets; 344936afd9fSDhruva Gole if (p_state) 345936afd9fSDhruva Gole *p_state = resp.programmed_state; 346936afd9fSDhruva Gole if (c_state) 347936afd9fSDhruva Gole *c_state = resp.current_state; 348936afd9fSDhruva Gole 349936afd9fSDhruva Gole return 0; 350936afd9fSDhruva Gole } 351936afd9fSDhruva Gole 352936afd9fSDhruva Gole /** 353936afd9fSDhruva Gole * ti_sci_device_get() - Request for device managed by TISCI 354936afd9fSDhruva Gole * 355936afd9fSDhruva Gole * @id: Device Identifier 356936afd9fSDhruva Gole * 357936afd9fSDhruva Gole * Request for the device - NOTE: the client MUST maintain integrity of 358936afd9fSDhruva Gole * usage count by balancing get_device with put_device. No refcounting is 359936afd9fSDhruva Gole * managed by driver for that purpose. 360936afd9fSDhruva Gole * 361936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 362936afd9fSDhruva Gole */ 363936afd9fSDhruva Gole int ti_sci_device_get(uint32_t id) 364936afd9fSDhruva Gole { 365936afd9fSDhruva Gole return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON); 366936afd9fSDhruva Gole } 367936afd9fSDhruva Gole 368936afd9fSDhruva Gole /** 369936afd9fSDhruva Gole * ti_sci_device_get_exclusive() - Exclusive request for device managed by TISCI 370936afd9fSDhruva Gole * 371936afd9fSDhruva Gole * @id: Device Identifier 372936afd9fSDhruva Gole * 373936afd9fSDhruva Gole * Request for the device - NOTE: the client MUST maintain integrity of 374936afd9fSDhruva Gole * usage count by balancing get_device with put_device. No refcounting is 375936afd9fSDhruva Gole * managed by driver for that purpose. 376936afd9fSDhruva Gole * 377936afd9fSDhruva Gole * NOTE: This _exclusive version of the get API is for exclusive access to the 378936afd9fSDhruva Gole * device. Any other host in the system will fail to get this device after this 379936afd9fSDhruva Gole * call until exclusive access is released with device_put or a non-exclusive 380936afd9fSDhruva Gole * set call. 381936afd9fSDhruva Gole * 382936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 383936afd9fSDhruva Gole */ 384936afd9fSDhruva Gole int ti_sci_device_get_exclusive(uint32_t id) 385936afd9fSDhruva Gole { 386936afd9fSDhruva Gole return ti_sci_device_set_state(id, 387936afd9fSDhruva Gole MSG_FLAG_DEVICE_EXCLUSIVE, 388936afd9fSDhruva Gole MSG_DEVICE_SW_STATE_ON); 389936afd9fSDhruva Gole } 390936afd9fSDhruva Gole 391936afd9fSDhruva Gole /** 392936afd9fSDhruva Gole * ti_sci_device_idle() - Idle a device managed by TISCI 393936afd9fSDhruva Gole * 394936afd9fSDhruva Gole * @id: Device Identifier 395936afd9fSDhruva Gole * 396936afd9fSDhruva Gole * Request for the device - NOTE: the client MUST maintain integrity of 397936afd9fSDhruva Gole * usage count by balancing get_device with put_device. No refcounting is 398936afd9fSDhruva Gole * managed by driver for that purpose. 399936afd9fSDhruva Gole * 400936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 401936afd9fSDhruva Gole */ 402936afd9fSDhruva Gole int ti_sci_device_idle(uint32_t id) 403936afd9fSDhruva Gole { 404936afd9fSDhruva Gole return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_RETENTION); 405936afd9fSDhruva Gole } 406936afd9fSDhruva Gole 407936afd9fSDhruva Gole /** 408936afd9fSDhruva Gole * ti_sci_device_idle_exclusive() - Exclusive idle a device managed by TISCI 409936afd9fSDhruva Gole * 410936afd9fSDhruva Gole * @id: Device Identifier 411936afd9fSDhruva Gole * 412936afd9fSDhruva Gole * Request for the device - NOTE: the client MUST maintain integrity of 413936afd9fSDhruva Gole * usage count by balancing get_device with put_device. No refcounting is 414936afd9fSDhruva Gole * managed by driver for that purpose. 415936afd9fSDhruva Gole * 416936afd9fSDhruva Gole * NOTE: This _exclusive version of the idle API is for exclusive access to 417936afd9fSDhruva Gole * the device. Any other host in the system will fail to get this device after 418936afd9fSDhruva Gole * this call until exclusive access is released with device_put or a 419936afd9fSDhruva Gole * non-exclusive set call. 420936afd9fSDhruva Gole * 421936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 422936afd9fSDhruva Gole */ 423936afd9fSDhruva Gole int ti_sci_device_idle_exclusive(uint32_t id) 424936afd9fSDhruva Gole { 425936afd9fSDhruva Gole return ti_sci_device_set_state(id, 426936afd9fSDhruva Gole MSG_FLAG_DEVICE_EXCLUSIVE, 427936afd9fSDhruva Gole MSG_DEVICE_SW_STATE_RETENTION); 428936afd9fSDhruva Gole } 429936afd9fSDhruva Gole 430936afd9fSDhruva Gole /** 431936afd9fSDhruva Gole * ti_sci_device_put() - Release a device managed by TISCI 432936afd9fSDhruva Gole * 433936afd9fSDhruva Gole * @id: Device Identifier 434936afd9fSDhruva Gole * 435936afd9fSDhruva Gole * Request for the device - NOTE: the client MUST maintain integrity of 436936afd9fSDhruva Gole * usage count by balancing get_device with put_device. No refcounting is 437936afd9fSDhruva Gole * managed by driver for that purpose. 438936afd9fSDhruva Gole * 439936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 440936afd9fSDhruva Gole */ 441936afd9fSDhruva Gole int ti_sci_device_put(uint32_t id) 442936afd9fSDhruva Gole { 443936afd9fSDhruva Gole return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF); 444936afd9fSDhruva Gole } 445936afd9fSDhruva Gole 446936afd9fSDhruva Gole /** 447936afd9fSDhruva Gole * ti_sci_device_put_no_wait() - Release a device without requesting or waiting 448936afd9fSDhruva Gole * for a response. 449936afd9fSDhruva Gole * 450936afd9fSDhruva Gole * @id: Device Identifier 451936afd9fSDhruva Gole * 452936afd9fSDhruva Gole * Request for the device - NOTE: the client MUST maintain integrity of 453936afd9fSDhruva Gole * usage count by balancing get_device with put_device. No refcounting is 454936afd9fSDhruva Gole * managed by driver for that purpose. 455936afd9fSDhruva Gole * 456936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 457936afd9fSDhruva Gole */ 458936afd9fSDhruva Gole int ti_sci_device_put_no_wait(uint32_t id) 459936afd9fSDhruva Gole { 460936afd9fSDhruva Gole struct ti_sci_msg_req_set_device_state req; 461936afd9fSDhruva Gole struct ti_sci_xfer xfer; 462936afd9fSDhruva Gole int ret; 463936afd9fSDhruva Gole 464936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, 0, 465936afd9fSDhruva Gole &req, sizeof(req), 466936afd9fSDhruva Gole NULL, 0, 467936afd9fSDhruva Gole &xfer); 468936afd9fSDhruva Gole if (ret != 0U) { 469936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 470936afd9fSDhruva Gole return ret; 471936afd9fSDhruva Gole } 472936afd9fSDhruva Gole 473936afd9fSDhruva Gole req.id = id; 474936afd9fSDhruva Gole req.state = MSG_DEVICE_SW_STATE_AUTO_OFF; 475936afd9fSDhruva Gole 476936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 477936afd9fSDhruva Gole if (ret != 0U) { 478936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 479936afd9fSDhruva Gole return ret; 480936afd9fSDhruva Gole } 481936afd9fSDhruva Gole 482936afd9fSDhruva Gole return 0; 483936afd9fSDhruva Gole } 484936afd9fSDhruva Gole 485936afd9fSDhruva Gole /** 486936afd9fSDhruva Gole * ti_sci_device_is_valid() - Is the device valid 487936afd9fSDhruva Gole * 488936afd9fSDhruva Gole * @id: Device Identifier 489936afd9fSDhruva Gole * 490936afd9fSDhruva Gole * Return: 0 if all goes well and the device ID is valid, else return 491936afd9fSDhruva Gole * appropriate error 492936afd9fSDhruva Gole */ 493936afd9fSDhruva Gole int ti_sci_device_is_valid(uint32_t id) 494936afd9fSDhruva Gole { 495936afd9fSDhruva Gole uint8_t unused; 496936afd9fSDhruva Gole 497936afd9fSDhruva Gole /* check the device state which will also tell us if the ID is valid */ 498936afd9fSDhruva Gole return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused); 499936afd9fSDhruva Gole } 500936afd9fSDhruva Gole 501936afd9fSDhruva Gole /** 502936afd9fSDhruva Gole * ti_sci_device_get_clcnt() - Get context loss counter 503936afd9fSDhruva Gole * 504936afd9fSDhruva Gole * @id: Device Identifier 505936afd9fSDhruva Gole * @count: Pointer to Context Loss counter to populate 506936afd9fSDhruva Gole * 507936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 508936afd9fSDhruva Gole */ 509936afd9fSDhruva Gole int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count) 510936afd9fSDhruva Gole { 511936afd9fSDhruva Gole return ti_sci_device_get_state(id, count, NULL, NULL, NULL); 512936afd9fSDhruva Gole } 513936afd9fSDhruva Gole 514936afd9fSDhruva Gole /** 515936afd9fSDhruva Gole * ti_sci_device_is_idle() - Check if the device is requested to be idle 516936afd9fSDhruva Gole * 517936afd9fSDhruva Gole * @id: Device Identifier 518936afd9fSDhruva Gole * @r_state: true if requested to be idle 519936afd9fSDhruva Gole * 520936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 521936afd9fSDhruva Gole */ 522936afd9fSDhruva Gole int ti_sci_device_is_idle(uint32_t id, bool *r_state) 523936afd9fSDhruva Gole { 524936afd9fSDhruva Gole int ret; 525936afd9fSDhruva Gole uint8_t state; 526936afd9fSDhruva Gole 527936afd9fSDhruva Gole if (!r_state) 528936afd9fSDhruva Gole return -EINVAL; 529936afd9fSDhruva Gole 530936afd9fSDhruva Gole ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL); 531936afd9fSDhruva Gole if (ret) 532936afd9fSDhruva Gole return ret; 533936afd9fSDhruva Gole 534936afd9fSDhruva Gole *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION); 535936afd9fSDhruva Gole 536936afd9fSDhruva Gole return 0; 537936afd9fSDhruva Gole } 538936afd9fSDhruva Gole 539936afd9fSDhruva Gole /** 540936afd9fSDhruva Gole * ti_sci_device_is_stop() - Check if the device is requested to be stopped 541936afd9fSDhruva Gole * 542936afd9fSDhruva Gole * @id: Device Identifier 543936afd9fSDhruva Gole * @r_state: true if requested to be stopped 544936afd9fSDhruva Gole * @curr_state: true if currently stopped 545936afd9fSDhruva Gole * 546936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 547936afd9fSDhruva Gole */ 548936afd9fSDhruva Gole int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state) 549936afd9fSDhruva Gole { 550936afd9fSDhruva Gole int ret; 551936afd9fSDhruva Gole uint8_t p_state, c_state; 552936afd9fSDhruva Gole 553936afd9fSDhruva Gole if (!r_state && !curr_state) 554936afd9fSDhruva Gole return -EINVAL; 555936afd9fSDhruva Gole 556936afd9fSDhruva Gole ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state); 557936afd9fSDhruva Gole if (ret) 558936afd9fSDhruva Gole return ret; 559936afd9fSDhruva Gole 560936afd9fSDhruva Gole if (r_state) 561936afd9fSDhruva Gole *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF); 562936afd9fSDhruva Gole if (curr_state) 563936afd9fSDhruva Gole *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF); 564936afd9fSDhruva Gole 565936afd9fSDhruva Gole return 0; 566936afd9fSDhruva Gole } 567936afd9fSDhruva Gole 568936afd9fSDhruva Gole /** 569936afd9fSDhruva Gole * ti_sci_device_is_on() - Check if the device is requested to be ON 570936afd9fSDhruva Gole * 571936afd9fSDhruva Gole * @id: Device Identifier 572936afd9fSDhruva Gole * @r_state: true if requested to be ON 573936afd9fSDhruva Gole * @curr_state: true if currently ON and active 574936afd9fSDhruva Gole * 575936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 576936afd9fSDhruva Gole */ 577936afd9fSDhruva Gole int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state) 578936afd9fSDhruva Gole { 579936afd9fSDhruva Gole int ret; 580936afd9fSDhruva Gole uint8_t p_state, c_state; 581936afd9fSDhruva Gole 582936afd9fSDhruva Gole if (!r_state && !curr_state) 583936afd9fSDhruva Gole return -EINVAL; 584936afd9fSDhruva Gole 585936afd9fSDhruva Gole ret = 586936afd9fSDhruva Gole ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state); 587936afd9fSDhruva Gole if (ret) 588936afd9fSDhruva Gole return ret; 589936afd9fSDhruva Gole 590936afd9fSDhruva Gole if (r_state) 591936afd9fSDhruva Gole *r_state = (p_state == MSG_DEVICE_SW_STATE_ON); 592936afd9fSDhruva Gole if (curr_state) 593936afd9fSDhruva Gole *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON); 594936afd9fSDhruva Gole 595936afd9fSDhruva Gole return 0; 596936afd9fSDhruva Gole } 597936afd9fSDhruva Gole 598936afd9fSDhruva Gole /** 599936afd9fSDhruva Gole * ti_sci_device_is_trans() - Check if the device is currently transitioning 600936afd9fSDhruva Gole * 601936afd9fSDhruva Gole * @id: Device Identifier 602936afd9fSDhruva Gole * @curr_state: true if currently transitioning 603936afd9fSDhruva Gole * 604936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 605936afd9fSDhruva Gole */ 606936afd9fSDhruva Gole int ti_sci_device_is_trans(uint32_t id, bool *curr_state) 607936afd9fSDhruva Gole { 608936afd9fSDhruva Gole int ret; 609936afd9fSDhruva Gole uint8_t state; 610936afd9fSDhruva Gole 611936afd9fSDhruva Gole if (!curr_state) 612936afd9fSDhruva Gole return -EINVAL; 613936afd9fSDhruva Gole 614936afd9fSDhruva Gole ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state); 615936afd9fSDhruva Gole if (ret) 616936afd9fSDhruva Gole return ret; 617936afd9fSDhruva Gole 618936afd9fSDhruva Gole *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS); 619936afd9fSDhruva Gole 620936afd9fSDhruva Gole return 0; 621936afd9fSDhruva Gole } 622936afd9fSDhruva Gole 623936afd9fSDhruva Gole /** 624936afd9fSDhruva Gole * ti_sci_device_set_resets() - Set resets for device managed by TISCI 625936afd9fSDhruva Gole * 626936afd9fSDhruva Gole * @id: Device Identifier 627936afd9fSDhruva Gole * @reset_state: Device specific reset bit field 628936afd9fSDhruva Gole * 629936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 630936afd9fSDhruva Gole */ 631936afd9fSDhruva Gole int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state) 632936afd9fSDhruva Gole { 633936afd9fSDhruva Gole struct ti_sci_msg_req_set_device_resets req; 634936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 635936afd9fSDhruva Gole 636936afd9fSDhruva Gole struct ti_sci_xfer xfer; 637936afd9fSDhruva Gole int ret; 638936afd9fSDhruva Gole 639936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS, 0, 640936afd9fSDhruva Gole &req, sizeof(req), 641936afd9fSDhruva Gole &resp, sizeof(resp), 642936afd9fSDhruva Gole &xfer); 643936afd9fSDhruva Gole if (ret) { 644936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 645936afd9fSDhruva Gole return ret; 646936afd9fSDhruva Gole } 647936afd9fSDhruva Gole 648936afd9fSDhruva Gole req.id = id; 649936afd9fSDhruva Gole req.resets = reset_state; 650936afd9fSDhruva Gole 651936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 652936afd9fSDhruva Gole if (ret) { 653936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 654936afd9fSDhruva Gole return ret; 655936afd9fSDhruva Gole } 656936afd9fSDhruva Gole 657936afd9fSDhruva Gole return 0; 658936afd9fSDhruva Gole } 659936afd9fSDhruva Gole 660936afd9fSDhruva Gole /** 661936afd9fSDhruva Gole * ti_sci_device_get_resets() - Get reset state for device managed by TISCI 662936afd9fSDhruva Gole * 663936afd9fSDhruva Gole * @id: Device Identifier 664936afd9fSDhruva Gole * @reset_state: Pointer to reset state to populate 665936afd9fSDhruva Gole * 666936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 667936afd9fSDhruva Gole */ 668936afd9fSDhruva Gole int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state) 669936afd9fSDhruva Gole { 670936afd9fSDhruva Gole return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL); 671936afd9fSDhruva Gole } 672936afd9fSDhruva Gole 673936afd9fSDhruva Gole /** 674936afd9fSDhruva Gole * ti_sci_clock_set_state() - Set clock state helper 675936afd9fSDhruva Gole * 676936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 677936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request, 678936afd9fSDhruva Gole * Each device has its own set of clock inputs, This indexes 679936afd9fSDhruva Gole * which clock input to modify 680936afd9fSDhruva Gole * @flags: Header flags as needed 681936afd9fSDhruva Gole * @state: State to request for the clock 682936afd9fSDhruva Gole * 683936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 684936afd9fSDhruva Gole */ 685936afd9fSDhruva Gole int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id, 686936afd9fSDhruva Gole uint32_t flags, uint8_t state) 687936afd9fSDhruva Gole { 688936afd9fSDhruva Gole struct ti_sci_msg_req_set_clock_state req; 689936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 690936afd9fSDhruva Gole 691936afd9fSDhruva Gole struct ti_sci_xfer xfer; 692936afd9fSDhruva Gole int ret; 693936afd9fSDhruva Gole 694936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_STATE, flags, 695936afd9fSDhruva Gole &req, sizeof(req), 696936afd9fSDhruva Gole &resp, sizeof(resp), 697936afd9fSDhruva Gole &xfer); 698936afd9fSDhruva Gole if (ret) { 699936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 700936afd9fSDhruva Gole return ret; 701936afd9fSDhruva Gole } 702936afd9fSDhruva Gole 703936afd9fSDhruva Gole req.dev_id = dev_id; 704936afd9fSDhruva Gole req.clk_id = clk_id; 705936afd9fSDhruva Gole req.request_state = state; 706936afd9fSDhruva Gole 707936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 708936afd9fSDhruva Gole if (ret) { 709936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 710936afd9fSDhruva Gole return ret; 711936afd9fSDhruva Gole } 712936afd9fSDhruva Gole 713936afd9fSDhruva Gole return 0; 714936afd9fSDhruva Gole } 715936afd9fSDhruva Gole 716936afd9fSDhruva Gole /** 717936afd9fSDhruva Gole * ti_sci_clock_get_state() - Get clock state helper 718936afd9fSDhruva Gole * 719936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 720936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 721936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 722936afd9fSDhruva Gole * which clock input to modify. 723936afd9fSDhruva Gole * @programmed_state: State requested for clock to move to 724936afd9fSDhruva Gole * @current_state: State that the clock is currently in 725936afd9fSDhruva Gole * 726936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 727936afd9fSDhruva Gole */ 728936afd9fSDhruva Gole int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id, 729936afd9fSDhruva Gole uint8_t *programmed_state, 730936afd9fSDhruva Gole uint8_t *current_state) 731936afd9fSDhruva Gole { 732936afd9fSDhruva Gole struct ti_sci_msg_req_get_clock_state req; 733936afd9fSDhruva Gole struct ti_sci_msg_resp_get_clock_state resp; 734936afd9fSDhruva Gole 735936afd9fSDhruva Gole struct ti_sci_xfer xfer; 736936afd9fSDhruva Gole int ret; 737936afd9fSDhruva Gole 738936afd9fSDhruva Gole if (!programmed_state && !current_state) 739936afd9fSDhruva Gole return -EINVAL; 740936afd9fSDhruva Gole 741936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_STATE, 0, 742936afd9fSDhruva Gole &req, sizeof(req), 743936afd9fSDhruva Gole &resp, sizeof(resp), 744936afd9fSDhruva Gole &xfer); 745936afd9fSDhruva Gole if (ret) { 746936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 747936afd9fSDhruva Gole return ret; 748936afd9fSDhruva Gole } 749936afd9fSDhruva Gole 750936afd9fSDhruva Gole req.dev_id = dev_id; 751936afd9fSDhruva Gole req.clk_id = clk_id; 752936afd9fSDhruva Gole 753936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 754936afd9fSDhruva Gole if (ret) { 755936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 756936afd9fSDhruva Gole return ret; 757936afd9fSDhruva Gole } 758936afd9fSDhruva Gole 759936afd9fSDhruva Gole if (programmed_state) 760936afd9fSDhruva Gole *programmed_state = resp.programmed_state; 761936afd9fSDhruva Gole if (current_state) 762936afd9fSDhruva Gole *current_state = resp.current_state; 763936afd9fSDhruva Gole 764936afd9fSDhruva Gole return 0; 765936afd9fSDhruva Gole } 766936afd9fSDhruva Gole 767936afd9fSDhruva Gole /** 768936afd9fSDhruva Gole * ti_sci_clock_get() - Get control of a clock from TI SCI 769936afd9fSDhruva Gole 770936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 771936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 772936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 773936afd9fSDhruva Gole * which clock input to modify. 774936afd9fSDhruva Gole * @needs_ssc: 'true' iff Spread Spectrum clock is desired 775936afd9fSDhruva Gole * @can_change_freq: 'true' iff frequency change is desired 776936afd9fSDhruva Gole * @enable_input_term: 'true' iff input termination is desired 777936afd9fSDhruva Gole * 778936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 779936afd9fSDhruva Gole */ 780936afd9fSDhruva Gole int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id, 781936afd9fSDhruva Gole bool needs_ssc, bool can_change_freq, 782936afd9fSDhruva Gole bool enable_input_term) 783936afd9fSDhruva Gole { 784936afd9fSDhruva Gole uint32_t flags = 0; 785936afd9fSDhruva Gole 786936afd9fSDhruva Gole flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0; 787936afd9fSDhruva Gole flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0; 788936afd9fSDhruva Gole flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0; 789936afd9fSDhruva Gole 790936afd9fSDhruva Gole return ti_sci_clock_set_state(dev_id, clk_id, flags, 791936afd9fSDhruva Gole MSG_CLOCK_SW_STATE_REQ); 792936afd9fSDhruva Gole } 793936afd9fSDhruva Gole 794936afd9fSDhruva Gole /** 795936afd9fSDhruva Gole * ti_sci_clock_idle() - Idle a clock which is in our control 796936afd9fSDhruva Gole 797936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 798936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 799936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 800936afd9fSDhruva Gole * which clock input to modify. 801936afd9fSDhruva Gole * 802936afd9fSDhruva Gole * NOTE: This clock must have been requested by get_clock previously. 803936afd9fSDhruva Gole * 804936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 805936afd9fSDhruva Gole */ 806936afd9fSDhruva Gole int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id) 807936afd9fSDhruva Gole { 808936afd9fSDhruva Gole return ti_sci_clock_set_state(dev_id, clk_id, 0, 809936afd9fSDhruva Gole MSG_CLOCK_SW_STATE_UNREQ); 810936afd9fSDhruva Gole } 811936afd9fSDhruva Gole 812936afd9fSDhruva Gole /** 813936afd9fSDhruva Gole * ti_sci_clock_put() - Release a clock from our control 814936afd9fSDhruva Gole * 815936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 816936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 817936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 818936afd9fSDhruva Gole * which clock input to modify. 819936afd9fSDhruva Gole * 820936afd9fSDhruva Gole * NOTE: This clock must have been requested by get_clock previously. 821936afd9fSDhruva Gole * 822936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 823936afd9fSDhruva Gole */ 824936afd9fSDhruva Gole int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id) 825936afd9fSDhruva Gole { 826936afd9fSDhruva Gole return ti_sci_clock_set_state(dev_id, clk_id, 0, 827936afd9fSDhruva Gole MSG_CLOCK_SW_STATE_AUTO); 828936afd9fSDhruva Gole } 829936afd9fSDhruva Gole 830936afd9fSDhruva Gole /** 831936afd9fSDhruva Gole * ti_sci_clock_is_auto() - Is the clock being auto managed 832936afd9fSDhruva Gole * 833936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 834936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 835936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 836936afd9fSDhruva Gole * which clock input to modify. 837936afd9fSDhruva Gole * @req_state: state indicating if the clock is auto managed 838936afd9fSDhruva Gole * 839936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 840936afd9fSDhruva Gole */ 841936afd9fSDhruva Gole int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, bool *req_state) 842936afd9fSDhruva Gole { 843936afd9fSDhruva Gole uint8_t state = 0; 844936afd9fSDhruva Gole int ret; 845936afd9fSDhruva Gole 846936afd9fSDhruva Gole if (!req_state) 847936afd9fSDhruva Gole return -EINVAL; 848936afd9fSDhruva Gole 849936afd9fSDhruva Gole ret = ti_sci_clock_get_state(dev_id, clk_id, &state, NULL); 850936afd9fSDhruva Gole if (ret) 851936afd9fSDhruva Gole return ret; 852936afd9fSDhruva Gole 853936afd9fSDhruva Gole *req_state = (state == MSG_CLOCK_SW_STATE_AUTO); 854936afd9fSDhruva Gole 855936afd9fSDhruva Gole return 0; 856936afd9fSDhruva Gole } 857936afd9fSDhruva Gole 858936afd9fSDhruva Gole /** 859936afd9fSDhruva Gole * ti_sci_clock_is_on() - Is the clock ON 860936afd9fSDhruva Gole * 861936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 862936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 863936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 864936afd9fSDhruva Gole * which clock input to modify. 865936afd9fSDhruva Gole * @req_state: state indicating if the clock is managed by us and enabled 866936afd9fSDhruva Gole * @curr_state: state indicating if the clock is ready for operation 867936afd9fSDhruva Gole * 868936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 869936afd9fSDhruva Gole */ 870936afd9fSDhruva Gole int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id, 871936afd9fSDhruva Gole bool *req_state, bool *curr_state) 872936afd9fSDhruva Gole { 873936afd9fSDhruva Gole uint8_t c_state = 0, r_state = 0; 874936afd9fSDhruva Gole int ret; 875936afd9fSDhruva Gole 876936afd9fSDhruva Gole if (!req_state && !curr_state) 877936afd9fSDhruva Gole return -EINVAL; 878936afd9fSDhruva Gole 879936afd9fSDhruva Gole ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state); 880936afd9fSDhruva Gole if (ret) 881936afd9fSDhruva Gole return ret; 882936afd9fSDhruva Gole 883936afd9fSDhruva Gole if (req_state) 884936afd9fSDhruva Gole *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ); 885936afd9fSDhruva Gole if (curr_state) 886936afd9fSDhruva Gole *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY); 887936afd9fSDhruva Gole 888936afd9fSDhruva Gole return 0; 889936afd9fSDhruva Gole } 890936afd9fSDhruva Gole 891936afd9fSDhruva Gole /** 892936afd9fSDhruva Gole * ti_sci_clock_is_off() - Is the clock OFF 893936afd9fSDhruva Gole * 894936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 895936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 896936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 897936afd9fSDhruva Gole * which clock input to modify. 898936afd9fSDhruva Gole * @req_state: state indicating if the clock is managed by us and disabled 899936afd9fSDhruva Gole * @curr_state: state indicating if the clock is NOT ready for operation 900936afd9fSDhruva Gole * 901936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 902936afd9fSDhruva Gole */ 903936afd9fSDhruva Gole int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id, 904936afd9fSDhruva Gole bool *req_state, bool *curr_state) 905936afd9fSDhruva Gole { 906936afd9fSDhruva Gole uint8_t c_state = 0, r_state = 0; 907936afd9fSDhruva Gole int ret; 908936afd9fSDhruva Gole 909936afd9fSDhruva Gole if (!req_state && !curr_state) 910936afd9fSDhruva Gole return -EINVAL; 911936afd9fSDhruva Gole 912936afd9fSDhruva Gole ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state); 913936afd9fSDhruva Gole if (ret) 914936afd9fSDhruva Gole return ret; 915936afd9fSDhruva Gole 916936afd9fSDhruva Gole if (req_state) 917936afd9fSDhruva Gole *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ); 918936afd9fSDhruva Gole if (curr_state) 919936afd9fSDhruva Gole *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY); 920936afd9fSDhruva Gole 921936afd9fSDhruva Gole return 0; 922936afd9fSDhruva Gole } 923936afd9fSDhruva Gole 924936afd9fSDhruva Gole /** 925936afd9fSDhruva Gole * ti_sci_clock_set_parent() - Set the clock source of a specific device clock 926936afd9fSDhruva Gole * 927936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 928936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 929936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 930936afd9fSDhruva Gole * which clock input to modify. 931936afd9fSDhruva Gole * @parent_id: Parent clock identifier to set 932936afd9fSDhruva Gole * 933936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 934936afd9fSDhruva Gole */ 935936afd9fSDhruva Gole int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, uint8_t parent_id) 936936afd9fSDhruva Gole { 937936afd9fSDhruva Gole struct ti_sci_msg_req_set_clock_parent req; 938936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 939936afd9fSDhruva Gole 940936afd9fSDhruva Gole struct ti_sci_xfer xfer; 941936afd9fSDhruva Gole int ret; 942936afd9fSDhruva Gole 943936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_PARENT, 0, 944936afd9fSDhruva Gole &req, sizeof(req), 945936afd9fSDhruva Gole &resp, sizeof(resp), 946936afd9fSDhruva Gole &xfer); 947936afd9fSDhruva Gole if (ret) { 948936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 949936afd9fSDhruva Gole return ret; 950936afd9fSDhruva Gole } 951936afd9fSDhruva Gole 952936afd9fSDhruva Gole req.dev_id = dev_id; 953936afd9fSDhruva Gole req.clk_id = clk_id; 954936afd9fSDhruva Gole req.parent_id = parent_id; 955936afd9fSDhruva Gole 956936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 957936afd9fSDhruva Gole if (ret) { 958936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 959936afd9fSDhruva Gole return ret; 960936afd9fSDhruva Gole } 961936afd9fSDhruva Gole 962936afd9fSDhruva Gole return 0; 963936afd9fSDhruva Gole } 964936afd9fSDhruva Gole 965936afd9fSDhruva Gole /** 966936afd9fSDhruva Gole * ti_sci_clock_get_parent() - Get current parent clock source 967936afd9fSDhruva Gole * 968936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 969936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 970936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 971936afd9fSDhruva Gole * which clock input to modify. 972936afd9fSDhruva Gole * @parent_id: Current clock parent 973936afd9fSDhruva Gole * 974936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 975936afd9fSDhruva Gole */ 976936afd9fSDhruva Gole int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, uint8_t *parent_id) 977936afd9fSDhruva Gole { 978936afd9fSDhruva Gole struct ti_sci_msg_req_get_clock_parent req; 979936afd9fSDhruva Gole struct ti_sci_msg_resp_get_clock_parent resp; 980936afd9fSDhruva Gole 981936afd9fSDhruva Gole struct ti_sci_xfer xfer; 982936afd9fSDhruva Gole int ret; 983936afd9fSDhruva Gole 984936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_PARENT, 0, 985936afd9fSDhruva Gole &req, sizeof(req), 986936afd9fSDhruva Gole &resp, sizeof(resp), 987936afd9fSDhruva Gole &xfer); 988936afd9fSDhruva Gole if (ret) { 989936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 990936afd9fSDhruva Gole return ret; 991936afd9fSDhruva Gole } 992936afd9fSDhruva Gole 993936afd9fSDhruva Gole req.dev_id = dev_id; 994936afd9fSDhruva Gole req.clk_id = clk_id; 995936afd9fSDhruva Gole 996936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 997936afd9fSDhruva Gole if (ret) { 998936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 999936afd9fSDhruva Gole return ret; 1000936afd9fSDhruva Gole } 1001936afd9fSDhruva Gole 1002936afd9fSDhruva Gole *parent_id = resp.parent_id; 1003936afd9fSDhruva Gole 1004936afd9fSDhruva Gole return 0; 1005936afd9fSDhruva Gole } 1006936afd9fSDhruva Gole 1007936afd9fSDhruva Gole /** 1008936afd9fSDhruva Gole * ti_sci_clock_get_num_parents() - Get num parents of the current clk source 1009936afd9fSDhruva Gole * 1010936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 1011936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 1012936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 1013936afd9fSDhruva Gole * which clock input to modify. 1014936afd9fSDhruva Gole * @num_parents: Returns he number of parents to the current clock. 1015936afd9fSDhruva Gole * 1016936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1017936afd9fSDhruva Gole */ 1018936afd9fSDhruva Gole int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id, 1019936afd9fSDhruva Gole uint8_t *num_parents) 1020936afd9fSDhruva Gole { 1021936afd9fSDhruva Gole struct ti_sci_msg_req_get_clock_num_parents req; 1022936afd9fSDhruva Gole struct ti_sci_msg_resp_get_clock_num_parents resp; 1023936afd9fSDhruva Gole 1024936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1025936afd9fSDhruva Gole int ret; 1026936afd9fSDhruva Gole 1027936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, 0, 1028936afd9fSDhruva Gole &req, sizeof(req), 1029936afd9fSDhruva Gole &resp, sizeof(resp), 1030936afd9fSDhruva Gole &xfer); 1031936afd9fSDhruva Gole if (ret) { 1032936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1033936afd9fSDhruva Gole return ret; 1034936afd9fSDhruva Gole } 1035936afd9fSDhruva Gole 1036936afd9fSDhruva Gole req.dev_id = dev_id; 1037936afd9fSDhruva Gole req.clk_id = clk_id; 1038936afd9fSDhruva Gole 1039936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1040936afd9fSDhruva Gole if (ret) { 1041936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1042936afd9fSDhruva Gole return ret; 1043936afd9fSDhruva Gole } 1044936afd9fSDhruva Gole 1045936afd9fSDhruva Gole *num_parents = resp.num_parents; 1046936afd9fSDhruva Gole 1047936afd9fSDhruva Gole return 0; 1048936afd9fSDhruva Gole } 1049936afd9fSDhruva Gole 1050936afd9fSDhruva Gole /** 1051936afd9fSDhruva Gole * ti_sci_clock_get_match_freq() - Find a good match for frequency 1052936afd9fSDhruva Gole * 1053936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 1054936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 1055936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 1056936afd9fSDhruva Gole * which clock input to modify. 1057936afd9fSDhruva Gole * @min_freq: The minimum allowable frequency in Hz. This is the minimum 1058936afd9fSDhruva Gole * allowable programmed frequency and does not account for clock 1059936afd9fSDhruva Gole * tolerances and jitter. 1060936afd9fSDhruva Gole * @target_freq: The target clock frequency in Hz. A frequency will be 1061936afd9fSDhruva Gole * processed as close to this target frequency as possible. 1062936afd9fSDhruva Gole * @max_freq: The maximum allowable frequency in Hz. This is the maximum 1063936afd9fSDhruva Gole * allowable programmed frequency and does not account for clock 1064936afd9fSDhruva Gole * tolerances and jitter. 1065936afd9fSDhruva Gole * @match_freq: Frequency match in Hz response. 1066936afd9fSDhruva Gole * 1067936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1068936afd9fSDhruva Gole */ 1069936afd9fSDhruva Gole int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id, 1070936afd9fSDhruva Gole uint64_t min_freq, uint64_t target_freq, 1071936afd9fSDhruva Gole uint64_t max_freq, uint64_t *match_freq) 1072936afd9fSDhruva Gole { 1073936afd9fSDhruva Gole struct ti_sci_msg_req_query_clock_freq req; 1074936afd9fSDhruva Gole struct ti_sci_msg_resp_query_clock_freq resp; 1075936afd9fSDhruva Gole 1076936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1077936afd9fSDhruva Gole int ret; 1078936afd9fSDhruva Gole 1079936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_CLOCK_FREQ, 0, 1080936afd9fSDhruva Gole &req, sizeof(req), 1081936afd9fSDhruva Gole &resp, sizeof(resp), 1082936afd9fSDhruva Gole &xfer); 1083936afd9fSDhruva Gole if (ret) { 1084936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1085936afd9fSDhruva Gole return ret; 1086936afd9fSDhruva Gole } 1087936afd9fSDhruva Gole 1088936afd9fSDhruva Gole req.dev_id = dev_id; 1089936afd9fSDhruva Gole req.clk_id = clk_id; 1090936afd9fSDhruva Gole req.min_freq_hz = min_freq; 1091936afd9fSDhruva Gole req.target_freq_hz = target_freq; 1092936afd9fSDhruva Gole req.max_freq_hz = max_freq; 1093936afd9fSDhruva Gole 1094936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1095936afd9fSDhruva Gole if (ret) { 1096936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1097936afd9fSDhruva Gole return ret; 1098936afd9fSDhruva Gole } 1099936afd9fSDhruva Gole 1100936afd9fSDhruva Gole *match_freq = resp.freq_hz; 1101936afd9fSDhruva Gole 1102936afd9fSDhruva Gole return 0; 1103936afd9fSDhruva Gole } 1104936afd9fSDhruva Gole 1105936afd9fSDhruva Gole /** 1106936afd9fSDhruva Gole * ti_sci_clock_set_freq() - Set a frequency for clock 1107936afd9fSDhruva Gole * 1108936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 1109936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 1110936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 1111936afd9fSDhruva Gole * which clock input to modify. 1112936afd9fSDhruva Gole * @min_freq: The minimum allowable frequency in Hz. This is the minimum 1113936afd9fSDhruva Gole * allowable programmed frequency and does not account for clock 1114936afd9fSDhruva Gole * tolerances and jitter. 1115936afd9fSDhruva Gole * @target_freq: The target clock frequency in Hz. A frequency will be 1116936afd9fSDhruva Gole * processed as close to this target frequency as possible. 1117936afd9fSDhruva Gole * @max_freq: The maximum allowable frequency in Hz. This is the maximum 1118936afd9fSDhruva Gole * allowable programmed frequency and does not account for clock 1119936afd9fSDhruva Gole * tolerances and jitter. 1120936afd9fSDhruva Gole * 1121936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1122936afd9fSDhruva Gole */ 1123936afd9fSDhruva Gole int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, uint64_t min_freq, 1124936afd9fSDhruva Gole uint64_t target_freq, uint64_t max_freq) 1125936afd9fSDhruva Gole { 1126936afd9fSDhruva Gole struct ti_sci_msg_req_set_clock_freq req; 1127936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 1128936afd9fSDhruva Gole 1129936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1130936afd9fSDhruva Gole int ret; 1131936afd9fSDhruva Gole 1132936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_FREQ, 0, 1133936afd9fSDhruva Gole &req, sizeof(req), 1134936afd9fSDhruva Gole &resp, sizeof(resp), 1135936afd9fSDhruva Gole &xfer); 1136936afd9fSDhruva Gole if (ret) { 1137936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1138936afd9fSDhruva Gole return ret; 1139936afd9fSDhruva Gole } 1140936afd9fSDhruva Gole req.dev_id = dev_id; 1141936afd9fSDhruva Gole req.clk_id = clk_id; 1142936afd9fSDhruva Gole req.min_freq_hz = min_freq; 1143936afd9fSDhruva Gole req.target_freq_hz = target_freq; 1144936afd9fSDhruva Gole req.max_freq_hz = max_freq; 1145936afd9fSDhruva Gole 1146936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1147936afd9fSDhruva Gole if (ret) { 1148936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1149936afd9fSDhruva Gole return ret; 1150936afd9fSDhruva Gole } 1151936afd9fSDhruva Gole 1152936afd9fSDhruva Gole return 0; 1153936afd9fSDhruva Gole } 1154936afd9fSDhruva Gole 1155936afd9fSDhruva Gole /** 1156936afd9fSDhruva Gole * ti_sci_clock_get_freq() - Get current frequency 1157936afd9fSDhruva Gole * 1158936afd9fSDhruva Gole * @dev_id: Device identifier this request is for 1159936afd9fSDhruva Gole * @clk_id: Clock identifier for the device for this request. 1160936afd9fSDhruva Gole * Each device has its own set of clock inputs. This indexes 1161936afd9fSDhruva Gole * which clock input to modify. 1162936afd9fSDhruva Gole * @freq: Currently frequency in Hz 1163936afd9fSDhruva Gole * 1164936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1165936afd9fSDhruva Gole */ 1166936afd9fSDhruva Gole int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq) 1167936afd9fSDhruva Gole { 1168936afd9fSDhruva Gole struct ti_sci_msg_req_get_clock_freq req; 1169936afd9fSDhruva Gole struct ti_sci_msg_resp_get_clock_freq resp; 1170936afd9fSDhruva Gole 1171936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1172936afd9fSDhruva Gole int ret; 1173936afd9fSDhruva Gole 1174936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_FREQ, 0, 1175936afd9fSDhruva Gole &req, sizeof(req), 1176936afd9fSDhruva Gole &resp, sizeof(resp), 1177936afd9fSDhruva Gole &xfer); 1178936afd9fSDhruva Gole if (ret) { 1179936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1180936afd9fSDhruva Gole return ret; 1181936afd9fSDhruva Gole } 1182936afd9fSDhruva Gole 1183936afd9fSDhruva Gole req.dev_id = dev_id; 1184936afd9fSDhruva Gole req.clk_id = clk_id; 1185936afd9fSDhruva Gole 1186936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1187936afd9fSDhruva Gole if (ret) { 1188936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1189936afd9fSDhruva Gole return ret; 1190936afd9fSDhruva Gole } 1191936afd9fSDhruva Gole 1192936afd9fSDhruva Gole *freq = resp.freq_hz; 1193936afd9fSDhruva Gole 1194936afd9fSDhruva Gole return 0; 1195936afd9fSDhruva Gole } 1196936afd9fSDhruva Gole 1197936afd9fSDhruva Gole /** 1198936afd9fSDhruva Gole * ti_sci_core_reboot() - Command to request system reset 1199936afd9fSDhruva Gole * 1200936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1201936afd9fSDhruva Gole */ 1202936afd9fSDhruva Gole int ti_sci_core_reboot(void) 1203936afd9fSDhruva Gole { 1204936afd9fSDhruva Gole struct ti_sci_msg_req_reboot req; 1205936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 1206936afd9fSDhruva Gole 1207936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1208936afd9fSDhruva Gole int ret; 1209936afd9fSDhruva Gole 1210936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SYS_RESET, 0, 1211936afd9fSDhruva Gole &req, sizeof(req), 1212936afd9fSDhruva Gole &resp, sizeof(resp), 1213936afd9fSDhruva Gole &xfer); 1214936afd9fSDhruva Gole if (ret) { 1215936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1216936afd9fSDhruva Gole return ret; 1217936afd9fSDhruva Gole } 1218936afd9fSDhruva Gole req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET; 1219936afd9fSDhruva Gole 1220936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1221936afd9fSDhruva Gole if (ret) { 1222936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1223936afd9fSDhruva Gole return ret; 1224936afd9fSDhruva Gole } 1225936afd9fSDhruva Gole 1226936afd9fSDhruva Gole return 0; 1227936afd9fSDhruva Gole } 1228936afd9fSDhruva Gole 1229936afd9fSDhruva Gole /** 1230936afd9fSDhruva Gole * ti_sci_proc_request() - Request a physical processor control 1231936afd9fSDhruva Gole * 1232936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1233936afd9fSDhruva Gole * 1234936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1235936afd9fSDhruva Gole */ 1236936afd9fSDhruva Gole int ti_sci_proc_request(uint8_t proc_id) 1237936afd9fSDhruva Gole { 1238936afd9fSDhruva Gole struct ti_sci_msg_req_proc_request req; 1239936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 1240936afd9fSDhruva Gole 1241936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1242936afd9fSDhruva Gole int ret; 1243936afd9fSDhruva Gole 1244936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST, 0, 1245936afd9fSDhruva Gole &req, sizeof(req), 1246936afd9fSDhruva Gole &resp, sizeof(resp), 1247936afd9fSDhruva Gole &xfer); 1248936afd9fSDhruva Gole if (ret) { 1249936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1250936afd9fSDhruva Gole return ret; 1251936afd9fSDhruva Gole } 1252936afd9fSDhruva Gole 1253936afd9fSDhruva Gole req.processor_id = proc_id; 1254936afd9fSDhruva Gole 1255936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1256936afd9fSDhruva Gole if (ret) { 1257936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1258936afd9fSDhruva Gole return ret; 1259936afd9fSDhruva Gole } 1260936afd9fSDhruva Gole 1261936afd9fSDhruva Gole return 0; 1262936afd9fSDhruva Gole } 1263936afd9fSDhruva Gole 1264936afd9fSDhruva Gole /** 1265936afd9fSDhruva Gole * ti_sci_proc_release() - Release a physical processor control 1266936afd9fSDhruva Gole * 1267936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1268936afd9fSDhruva Gole * 1269936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1270936afd9fSDhruva Gole */ 1271936afd9fSDhruva Gole int ti_sci_proc_release(uint8_t proc_id) 1272936afd9fSDhruva Gole { 1273936afd9fSDhruva Gole struct ti_sci_msg_req_proc_release req; 1274936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 1275936afd9fSDhruva Gole 1276936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1277936afd9fSDhruva Gole int ret; 1278936afd9fSDhruva Gole 1279936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE, 0, 1280936afd9fSDhruva Gole &req, sizeof(req), 1281936afd9fSDhruva Gole &resp, sizeof(resp), 1282936afd9fSDhruva Gole &xfer); 1283936afd9fSDhruva Gole if (ret) { 1284936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1285936afd9fSDhruva Gole return ret; 1286936afd9fSDhruva Gole } 1287936afd9fSDhruva Gole 1288936afd9fSDhruva Gole req.processor_id = proc_id; 1289936afd9fSDhruva Gole 1290936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1291936afd9fSDhruva Gole if (ret) { 1292936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1293936afd9fSDhruva Gole return ret; 1294936afd9fSDhruva Gole } 1295936afd9fSDhruva Gole 1296936afd9fSDhruva Gole return 0; 1297936afd9fSDhruva Gole } 1298936afd9fSDhruva Gole 1299936afd9fSDhruva Gole /** 1300936afd9fSDhruva Gole * ti_sci_proc_handover() - Handover a physical processor control to a host in 1301936afd9fSDhruva Gole * the processor's access control list. 1302936afd9fSDhruva Gole * 1303936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1304936afd9fSDhruva Gole * @host_id: Host ID to get the control of the processor 1305936afd9fSDhruva Gole * 1306936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1307936afd9fSDhruva Gole */ 1308936afd9fSDhruva Gole int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id) 1309936afd9fSDhruva Gole { 1310936afd9fSDhruva Gole struct ti_sci_msg_req_proc_handover req; 1311936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 1312936afd9fSDhruva Gole 1313936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1314936afd9fSDhruva Gole int ret; 1315936afd9fSDhruva Gole 1316936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER, 0, 1317936afd9fSDhruva Gole &req, sizeof(req), 1318936afd9fSDhruva Gole &resp, sizeof(resp), 1319936afd9fSDhruva Gole &xfer); 1320936afd9fSDhruva Gole if (ret) { 1321936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1322936afd9fSDhruva Gole return ret; 1323936afd9fSDhruva Gole } 1324936afd9fSDhruva Gole 1325936afd9fSDhruva Gole req.processor_id = proc_id; 1326936afd9fSDhruva Gole req.host_id = host_id; 1327936afd9fSDhruva Gole 1328936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1329936afd9fSDhruva Gole if (ret) { 1330936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1331936afd9fSDhruva Gole return ret; 1332936afd9fSDhruva Gole } 1333936afd9fSDhruva Gole 1334936afd9fSDhruva Gole return 0; 1335936afd9fSDhruva Gole } 1336936afd9fSDhruva Gole 1337936afd9fSDhruva Gole /** 1338936afd9fSDhruva Gole * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags 1339936afd9fSDhruva Gole * 1340936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1341936afd9fSDhruva Gole * @config_flags_set: Configuration flags to be set 1342936afd9fSDhruva Gole * @config_flags_clear: Configuration flags to be cleared 1343936afd9fSDhruva Gole * 1344936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1345936afd9fSDhruva Gole */ 1346936afd9fSDhruva Gole int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector, 1347936afd9fSDhruva Gole uint32_t config_flags_set, 1348936afd9fSDhruva Gole uint32_t config_flags_clear) 1349936afd9fSDhruva Gole { 1350936afd9fSDhruva Gole struct ti_sci_msg_req_set_proc_boot_config req; 1351936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 1352936afd9fSDhruva Gole 1353936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1354936afd9fSDhruva Gole int ret; 1355936afd9fSDhruva Gole 1356936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG, 0, 1357936afd9fSDhruva Gole &req, sizeof(req), 1358936afd9fSDhruva Gole &resp, sizeof(resp), 1359936afd9fSDhruva Gole &xfer); 1360936afd9fSDhruva Gole if (ret) { 1361936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1362936afd9fSDhruva Gole return ret; 1363936afd9fSDhruva Gole } 1364936afd9fSDhruva Gole 1365936afd9fSDhruva Gole req.processor_id = proc_id; 1366936afd9fSDhruva Gole req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK; 1367936afd9fSDhruva Gole req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >> 1368936afd9fSDhruva Gole TISCI_ADDR_HIGH_SHIFT; 1369936afd9fSDhruva Gole req.config_flags_set = config_flags_set; 1370936afd9fSDhruva Gole req.config_flags_clear = config_flags_clear; 1371936afd9fSDhruva Gole 1372936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1373936afd9fSDhruva Gole if (ret) { 1374936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1375936afd9fSDhruva Gole return ret; 1376936afd9fSDhruva Gole } 1377936afd9fSDhruva Gole 1378936afd9fSDhruva Gole return 0; 1379936afd9fSDhruva Gole } 1380936afd9fSDhruva Gole 1381936afd9fSDhruva Gole /** 1382936afd9fSDhruva Gole * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags 1383936afd9fSDhruva Gole * 1384936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1385936afd9fSDhruva Gole * @control_flags_set: Control flags to be set 1386936afd9fSDhruva Gole * @control_flags_clear: Control flags to be cleared 1387936afd9fSDhruva Gole * 1388936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1389936afd9fSDhruva Gole */ 1390936afd9fSDhruva Gole int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set, 1391936afd9fSDhruva Gole uint32_t control_flags_clear) 1392936afd9fSDhruva Gole { 1393936afd9fSDhruva Gole struct ti_sci_msg_req_set_proc_boot_ctrl req; 1394936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 1395936afd9fSDhruva Gole 1396936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1397936afd9fSDhruva Gole int ret; 1398936afd9fSDhruva Gole 1399936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0, 1400936afd9fSDhruva Gole &req, sizeof(req), 1401936afd9fSDhruva Gole &resp, sizeof(resp), 1402936afd9fSDhruva Gole &xfer); 1403936afd9fSDhruva Gole if (ret) { 1404936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1405936afd9fSDhruva Gole return ret; 1406936afd9fSDhruva Gole } 1407936afd9fSDhruva Gole 1408936afd9fSDhruva Gole req.processor_id = proc_id; 1409936afd9fSDhruva Gole req.control_flags_set = control_flags_set; 1410936afd9fSDhruva Gole req.control_flags_clear = control_flags_clear; 1411936afd9fSDhruva Gole 1412936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1413936afd9fSDhruva Gole if (ret) { 1414936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1415936afd9fSDhruva Gole return ret; 1416936afd9fSDhruva Gole } 1417936afd9fSDhruva Gole 1418936afd9fSDhruva Gole return 0; 1419936afd9fSDhruva Gole } 1420936afd9fSDhruva Gole 1421936afd9fSDhruva Gole /** 1422936afd9fSDhruva Gole * ti_sci_proc_set_boot_ctrl_no_wait() - Set the processor boot control flags 1423936afd9fSDhruva Gole * without requesting or waiting for a 1424936afd9fSDhruva Gole * response. 1425936afd9fSDhruva Gole * 1426936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1427936afd9fSDhruva Gole * @control_flags_set: Control flags to be set 1428936afd9fSDhruva Gole * @control_flags_clear: Control flags to be cleared 1429936afd9fSDhruva Gole * 1430936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1431936afd9fSDhruva Gole */ 1432936afd9fSDhruva Gole int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id, 1433936afd9fSDhruva Gole uint32_t control_flags_set, 1434936afd9fSDhruva Gole uint32_t control_flags_clear) 1435936afd9fSDhruva Gole { 1436936afd9fSDhruva Gole struct ti_sci_msg_req_set_proc_boot_ctrl req; 1437936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1438936afd9fSDhruva Gole int ret; 1439936afd9fSDhruva Gole 1440936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0, 1441936afd9fSDhruva Gole &req, sizeof(req), 1442936afd9fSDhruva Gole NULL, 0, 1443936afd9fSDhruva Gole &xfer); 1444936afd9fSDhruva Gole if (ret != 0U) { 1445936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1446936afd9fSDhruva Gole return ret; 1447936afd9fSDhruva Gole } 1448936afd9fSDhruva Gole 1449936afd9fSDhruva Gole req.processor_id = proc_id; 1450936afd9fSDhruva Gole req.control_flags_set = control_flags_set; 1451936afd9fSDhruva Gole req.control_flags_clear = control_flags_clear; 1452936afd9fSDhruva Gole 1453936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1454936afd9fSDhruva Gole if (ret != 0U) { 1455936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1456936afd9fSDhruva Gole return ret; 1457936afd9fSDhruva Gole } 1458936afd9fSDhruva Gole 1459936afd9fSDhruva Gole return 0; 1460936afd9fSDhruva Gole } 1461936afd9fSDhruva Gole 1462936afd9fSDhruva Gole /** 1463936afd9fSDhruva Gole * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the 1464936afd9fSDhruva Gole * processor configuration flags 1465936afd9fSDhruva Gole * 1466936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1467936afd9fSDhruva Gole * @cert_addr: Memory address at which payload image certificate is located 1468936afd9fSDhruva Gole * 1469936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1470936afd9fSDhruva Gole */ 1471936afd9fSDhruva Gole int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr) 1472936afd9fSDhruva Gole { 1473936afd9fSDhruva Gole struct ti_sci_msg_req_proc_auth_boot_image req; 1474936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 1475936afd9fSDhruva Gole 1476936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1477936afd9fSDhruva Gole int ret; 1478936afd9fSDhruva Gole 1479936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMAGE, 0, 1480936afd9fSDhruva Gole &req, sizeof(req), 1481936afd9fSDhruva Gole &resp, sizeof(resp), 1482936afd9fSDhruva Gole &xfer); 1483936afd9fSDhruva Gole if (ret) { 1484936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1485936afd9fSDhruva Gole return ret; 1486936afd9fSDhruva Gole } 1487936afd9fSDhruva Gole 1488936afd9fSDhruva Gole req.processor_id = proc_id; 1489936afd9fSDhruva Gole req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK; 1490936afd9fSDhruva Gole req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >> 1491936afd9fSDhruva Gole TISCI_ADDR_HIGH_SHIFT; 1492936afd9fSDhruva Gole 1493936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1494936afd9fSDhruva Gole if (ret) { 1495936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1496936afd9fSDhruva Gole return ret; 1497936afd9fSDhruva Gole } 1498936afd9fSDhruva Gole 1499936afd9fSDhruva Gole return 0; 1500936afd9fSDhruva Gole } 1501936afd9fSDhruva Gole 1502936afd9fSDhruva Gole /** 1503936afd9fSDhruva Gole * ti_sci_proc_get_boot_status() - Get the processor boot status 1504936afd9fSDhruva Gole * 1505936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1506936afd9fSDhruva Gole * 1507936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1508936afd9fSDhruva Gole */ 1509936afd9fSDhruva Gole int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv, 1510936afd9fSDhruva Gole uint32_t *cfg_flags, 1511936afd9fSDhruva Gole uint32_t *ctrl_flags, 1512936afd9fSDhruva Gole uint32_t *sts_flags) 1513936afd9fSDhruva Gole { 1514936afd9fSDhruva Gole struct ti_sci_msg_req_get_proc_boot_status req; 1515936afd9fSDhruva Gole struct ti_sci_msg_resp_get_proc_boot_status resp; 1516936afd9fSDhruva Gole 1517936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1518936afd9fSDhruva Gole int ret; 1519936afd9fSDhruva Gole 1520936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS, 0, 1521936afd9fSDhruva Gole &req, sizeof(req), 1522936afd9fSDhruva Gole &resp, sizeof(resp), 1523936afd9fSDhruva Gole &xfer); 1524936afd9fSDhruva Gole if (ret) { 1525936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1526936afd9fSDhruva Gole return ret; 1527936afd9fSDhruva Gole } 1528936afd9fSDhruva Gole 1529936afd9fSDhruva Gole req.processor_id = proc_id; 1530936afd9fSDhruva Gole 1531936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1532936afd9fSDhruva Gole if (ret) { 1533936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1534936afd9fSDhruva Gole return ret; 1535936afd9fSDhruva Gole } 1536936afd9fSDhruva Gole 1537936afd9fSDhruva Gole *bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) | 1538936afd9fSDhruva Gole (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) & 1539936afd9fSDhruva Gole TISCI_ADDR_HIGH_MASK); 1540936afd9fSDhruva Gole *cfg_flags = resp.config_flags; 1541936afd9fSDhruva Gole *ctrl_flags = resp.control_flags; 1542936afd9fSDhruva Gole *sts_flags = resp.status_flags; 1543936afd9fSDhruva Gole 1544936afd9fSDhruva Gole return 0; 1545936afd9fSDhruva Gole } 1546936afd9fSDhruva Gole 1547936afd9fSDhruva Gole /** 1548936afd9fSDhruva Gole * ti_sci_proc_wait_boot_status() - Wait for a processor boot status 1549936afd9fSDhruva Gole * 1550936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1551936afd9fSDhruva Gole * @num_wait_iterations Total number of iterations we will check before 1552936afd9fSDhruva Gole * we will timeout and give up 1553936afd9fSDhruva Gole * @num_match_iterations How many iterations should we have continued 1554936afd9fSDhruva Gole * status to account for status bits glitching. 1555936afd9fSDhruva Gole * This is to make sure that match occurs for 1556936afd9fSDhruva Gole * consecutive checks. This implies that the 1557936afd9fSDhruva Gole * worst case should consider that the stable 1558936afd9fSDhruva Gole * time should at the worst be num_wait_iterations 1559936afd9fSDhruva Gole * num_match_iterations to prevent timeout. 1560936afd9fSDhruva Gole * @delay_per_iteration_us Specifies how long to wait (in micro seconds) 1561936afd9fSDhruva Gole * between each status checks. This is the minimum 1562936afd9fSDhruva Gole * duration, and overhead of register reads and 1563936afd9fSDhruva Gole * checks are on top of this and can vary based on 1564936afd9fSDhruva Gole * varied conditions. 1565936afd9fSDhruva Gole * @delay_before_iterations_us Specifies how long to wait (in micro seconds) 1566936afd9fSDhruva Gole * before the very first check in the first 1567936afd9fSDhruva Gole * iteration of status check loop. This is the 1568936afd9fSDhruva Gole * minimum duration, and overhead of register 1569936afd9fSDhruva Gole * reads and checks are. 1570936afd9fSDhruva Gole * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the 1571936afd9fSDhruva Gole * status matching this field requested MUST be 1. 1572936afd9fSDhruva Gole * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the 1573936afd9fSDhruva Gole * bits matching this field requested MUST be 1. 1574936afd9fSDhruva Gole * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the 1575936afd9fSDhruva Gole * status matching this field requested MUST be 0. 1576936afd9fSDhruva Gole * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the 1577936afd9fSDhruva Gole * bits matching this field requested MUST be 0. 1578936afd9fSDhruva Gole * 1579936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1580936afd9fSDhruva Gole */ 1581936afd9fSDhruva Gole int ti_sci_proc_wait_boot_status(uint8_t proc_id, uint8_t num_wait_iterations, 1582936afd9fSDhruva Gole uint8_t num_match_iterations, 1583936afd9fSDhruva Gole uint8_t delay_per_iteration_us, 1584936afd9fSDhruva Gole uint8_t delay_before_iterations_us, 1585936afd9fSDhruva Gole uint32_t status_flags_1_set_all_wait, 1586936afd9fSDhruva Gole uint32_t status_flags_1_set_any_wait, 1587936afd9fSDhruva Gole uint32_t status_flags_1_clr_all_wait, 1588936afd9fSDhruva Gole uint32_t status_flags_1_clr_any_wait) 1589936afd9fSDhruva Gole { 1590936afd9fSDhruva Gole struct ti_sci_msg_req_wait_proc_boot_status req; 1591936afd9fSDhruva Gole struct ti_sci_msg_hdr resp; 1592936afd9fSDhruva Gole 1593936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1594936afd9fSDhruva Gole int ret; 1595936afd9fSDhruva Gole 1596936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0, 1597936afd9fSDhruva Gole &req, sizeof(req), 1598936afd9fSDhruva Gole &resp, sizeof(resp), 1599936afd9fSDhruva Gole &xfer); 1600936afd9fSDhruva Gole if (ret) { 1601936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1602936afd9fSDhruva Gole return ret; 1603936afd9fSDhruva Gole } 1604936afd9fSDhruva Gole 1605936afd9fSDhruva Gole req.processor_id = proc_id; 1606936afd9fSDhruva Gole req.num_wait_iterations = num_wait_iterations; 1607936afd9fSDhruva Gole req.num_match_iterations = num_match_iterations; 1608936afd9fSDhruva Gole req.delay_per_iteration_us = delay_per_iteration_us; 1609936afd9fSDhruva Gole req.delay_before_iterations_us = delay_before_iterations_us; 1610936afd9fSDhruva Gole req.status_flags_1_set_all_wait = status_flags_1_set_all_wait; 1611936afd9fSDhruva Gole req.status_flags_1_set_any_wait = status_flags_1_set_any_wait; 1612936afd9fSDhruva Gole req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait; 1613936afd9fSDhruva Gole req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait; 1614936afd9fSDhruva Gole 1615936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1616936afd9fSDhruva Gole if (ret) { 1617936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1618936afd9fSDhruva Gole return ret; 1619936afd9fSDhruva Gole } 1620936afd9fSDhruva Gole 1621936afd9fSDhruva Gole return 0; 1622936afd9fSDhruva Gole } 1623936afd9fSDhruva Gole 1624936afd9fSDhruva Gole /** 1625936afd9fSDhruva Gole * ti_sci_proc_wait_boot_status_no_wait() - Wait for a processor boot status 1626936afd9fSDhruva Gole * without requesting or waiting for 1627936afd9fSDhruva Gole * a response. 1628936afd9fSDhruva Gole * 1629936afd9fSDhruva Gole * @proc_id: Processor ID this request is for 1630936afd9fSDhruva Gole * @num_wait_iterations Total number of iterations we will check before 1631936afd9fSDhruva Gole * we will timeout and give up 1632936afd9fSDhruva Gole * @num_match_iterations How many iterations should we have continued 1633936afd9fSDhruva Gole * status to account for status bits glitching. 1634936afd9fSDhruva Gole * This is to make sure that match occurs for 1635936afd9fSDhruva Gole * consecutive checks. This implies that the 1636936afd9fSDhruva Gole * worst case should consider that the stable 1637936afd9fSDhruva Gole * time should at the worst be num_wait_iterations 1638936afd9fSDhruva Gole * num_match_iterations to prevent timeout. 1639936afd9fSDhruva Gole * @delay_per_iteration_us Specifies how long to wait (in micro seconds) 1640936afd9fSDhruva Gole * between each status checks. This is the minimum 1641936afd9fSDhruva Gole * duration, and overhead of register reads and 1642936afd9fSDhruva Gole * checks are on top of this and can vary based on 1643936afd9fSDhruva Gole * varied conditions. 1644936afd9fSDhruva Gole * @delay_before_iterations_us Specifies how long to wait (in micro seconds) 1645936afd9fSDhruva Gole * before the very first check in the first 1646936afd9fSDhruva Gole * iteration of status check loop. This is the 1647936afd9fSDhruva Gole * minimum duration, and overhead of register 1648936afd9fSDhruva Gole * reads and checks are. 1649936afd9fSDhruva Gole * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the 1650936afd9fSDhruva Gole * status matching this field requested MUST be 1. 1651936afd9fSDhruva Gole * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the 1652936afd9fSDhruva Gole * bits matching this field requested MUST be 1. 1653936afd9fSDhruva Gole * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the 1654936afd9fSDhruva Gole * status matching this field requested MUST be 0. 1655936afd9fSDhruva Gole * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the 1656936afd9fSDhruva Gole * bits matching this field requested MUST be 0. 1657936afd9fSDhruva Gole * 1658936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1659936afd9fSDhruva Gole */ 1660936afd9fSDhruva Gole int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id, 1661936afd9fSDhruva Gole uint8_t num_wait_iterations, 1662936afd9fSDhruva Gole uint8_t num_match_iterations, 1663936afd9fSDhruva Gole uint8_t delay_per_iteration_us, 1664936afd9fSDhruva Gole uint8_t delay_before_iterations_us, 1665936afd9fSDhruva Gole uint32_t status_flags_1_set_all_wait, 1666936afd9fSDhruva Gole uint32_t status_flags_1_set_any_wait, 1667936afd9fSDhruva Gole uint32_t status_flags_1_clr_all_wait, 1668936afd9fSDhruva Gole uint32_t status_flags_1_clr_any_wait) 1669936afd9fSDhruva Gole { 1670936afd9fSDhruva Gole struct ti_sci_msg_req_wait_proc_boot_status req; 1671936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1672936afd9fSDhruva Gole int ret; 1673936afd9fSDhruva Gole 1674936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0, 1675936afd9fSDhruva Gole &req, sizeof(req), 1676936afd9fSDhruva Gole NULL, 0, 1677936afd9fSDhruva Gole &xfer); 1678936afd9fSDhruva Gole if (ret != 0U) { 1679936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1680936afd9fSDhruva Gole return ret; 1681936afd9fSDhruva Gole } 1682936afd9fSDhruva Gole 1683936afd9fSDhruva Gole req.processor_id = proc_id; 1684936afd9fSDhruva Gole req.num_wait_iterations = num_wait_iterations; 1685936afd9fSDhruva Gole req.num_match_iterations = num_match_iterations; 1686936afd9fSDhruva Gole req.delay_per_iteration_us = delay_per_iteration_us; 1687936afd9fSDhruva Gole req.delay_before_iterations_us = delay_before_iterations_us; 1688936afd9fSDhruva Gole req.status_flags_1_set_all_wait = status_flags_1_set_all_wait; 1689936afd9fSDhruva Gole req.status_flags_1_set_any_wait = status_flags_1_set_any_wait; 1690936afd9fSDhruva Gole req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait; 1691936afd9fSDhruva Gole req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait; 1692936afd9fSDhruva Gole 1693936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1694936afd9fSDhruva Gole if (ret != 0U) { 1695936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1696936afd9fSDhruva Gole return ret; 1697936afd9fSDhruva Gole } 1698936afd9fSDhruva Gole 1699936afd9fSDhruva Gole return 0; 1700936afd9fSDhruva Gole } 1701936afd9fSDhruva Gole 1702936afd9fSDhruva Gole /** 1703936afd9fSDhruva Gole * ti_sci_enter_sleep - Command to initiate system transition into suspend. 1704936afd9fSDhruva Gole * 1705936afd9fSDhruva Gole * @proc_id: Processor ID. 1706936afd9fSDhruva Gole * @mode: Low power mode to enter. 1707936afd9fSDhruva Gole * @core_resume_addr: Address that core should be 1708936afd9fSDhruva Gole * resumed from after low power transition. 1709936afd9fSDhruva Gole * 1710936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1711936afd9fSDhruva Gole */ 1712936afd9fSDhruva Gole int ti_sci_enter_sleep(uint8_t proc_id, 1713936afd9fSDhruva Gole uint8_t mode, 1714936afd9fSDhruva Gole uint64_t core_resume_addr) 1715936afd9fSDhruva Gole { 1716936afd9fSDhruva Gole struct ti_sci_msg_req_enter_sleep req; 1717936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1718936afd9fSDhruva Gole int ret; 1719936afd9fSDhruva Gole 1720936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_ENTER_SLEEP, 0, 1721936afd9fSDhruva Gole &req, sizeof(req), 1722936afd9fSDhruva Gole NULL, 0, 1723936afd9fSDhruva Gole &xfer); 1724936afd9fSDhruva Gole if (ret != 0U) { 1725936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1726936afd9fSDhruva Gole return ret; 1727936afd9fSDhruva Gole } 1728936afd9fSDhruva Gole 1729936afd9fSDhruva Gole req.processor_id = proc_id; 1730936afd9fSDhruva Gole req.mode = mode; 1731936afd9fSDhruva Gole req.core_resume_lo = core_resume_addr & TISCI_ADDR_LOW_MASK; 1732936afd9fSDhruva Gole req.core_resume_hi = (core_resume_addr & TISCI_ADDR_HIGH_MASK) >> 1733936afd9fSDhruva Gole TISCI_ADDR_HIGH_SHIFT; 1734936afd9fSDhruva Gole 1735936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1736936afd9fSDhruva Gole if (ret != 0U) { 1737936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1738936afd9fSDhruva Gole return ret; 1739936afd9fSDhruva Gole } 1740936afd9fSDhruva Gole 1741936afd9fSDhruva Gole return 0; 1742936afd9fSDhruva Gole } 1743936afd9fSDhruva Gole 1744936afd9fSDhruva Gole /** 1745936afd9fSDhruva Gole * ti_sci_lpm_get_next_sys_mode() - Get next LPM system mode 1746936afd9fSDhruva Gole * 1747936afd9fSDhruva Gole * @next_mode: pointer to a variable that will store the next mode 1748936afd9fSDhruva Gole * 1749936afd9fSDhruva Gole * Return: 0 if all goes well, else appropriate error message 1750936afd9fSDhruva Gole */ 1751936afd9fSDhruva Gole int ti_sci_lpm_get_next_sys_mode(uint8_t *next_mode) 1752936afd9fSDhruva Gole { 1753936afd9fSDhruva Gole struct ti_sci_msg_req_lpm_get_next_sys_mode req; 1754936afd9fSDhruva Gole struct ti_sci_msg_resp_lpm_get_next_sys_mode resp; 1755936afd9fSDhruva Gole struct ti_sci_xfer xfer; 1756936afd9fSDhruva Gole int ret; 1757936afd9fSDhruva Gole 1758936afd9fSDhruva Gole if (next_mode == NULL) { 1759936afd9fSDhruva Gole return -EINVAL; 1760936afd9fSDhruva Gole } 1761936afd9fSDhruva Gole 1762936afd9fSDhruva Gole ret = ti_sci_setup_one_xfer(TI_SCI_MSG_LPM_GET_NEXT_SYS_MODE, 0, 1763936afd9fSDhruva Gole &req, sizeof(req), 1764936afd9fSDhruva Gole &resp, sizeof(resp), 1765936afd9fSDhruva Gole &xfer); 1766936afd9fSDhruva Gole if (ret != 0) { 1767936afd9fSDhruva Gole ERROR("Message alloc failed (%d)\n", ret); 1768936afd9fSDhruva Gole return ret; 1769936afd9fSDhruva Gole } 1770936afd9fSDhruva Gole 1771936afd9fSDhruva Gole ret = ti_sci_do_xfer(&xfer); 1772936afd9fSDhruva Gole if (ret != 0) { 1773936afd9fSDhruva Gole ERROR("Transfer send failed (%d)\n", ret); 1774936afd9fSDhruva Gole return ret; 1775936afd9fSDhruva Gole } 1776936afd9fSDhruva Gole 1777936afd9fSDhruva Gole *next_mode = resp.mode; 1778936afd9fSDhruva Gole 1779936afd9fSDhruva Gole return 0; 1780936afd9fSDhruva Gole } 1781