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