1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Texas Instruments System Control Interface Driver 3*91f16700Schasinglulu * Based on Linux and U-Boot implementation 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/ 6*91f16700Schasinglulu * 7*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 8*91f16700Schasinglulu */ 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <errno.h> 11*91f16700Schasinglulu #include <stdbool.h> 12*91f16700Schasinglulu #include <stddef.h> 13*91f16700Schasinglulu #include <string.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include <platform_def.h> 16*91f16700Schasinglulu #include <lib/bakery_lock.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #include <common/debug.h> 19*91f16700Schasinglulu #include <sec_proxy.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu #include "ti_sci_protocol.h" 22*91f16700Schasinglulu #include "ti_sci.h" 23*91f16700Schasinglulu 24*91f16700Schasinglulu #if USE_COHERENT_MEM 25*91f16700Schasinglulu __section(".tzfw_coherent_mem") 26*91f16700Schasinglulu #endif 27*91f16700Schasinglulu static uint8_t message_sequence; 28*91f16700Schasinglulu 29*91f16700Schasinglulu DEFINE_BAKERY_LOCK(ti_sci_xfer_lock); 30*91f16700Schasinglulu 31*91f16700Schasinglulu /** 32*91f16700Schasinglulu * struct ti_sci_xfer - Structure representing a message flow 33*91f16700Schasinglulu * @tx_message: Transmit message 34*91f16700Schasinglulu * @rx_message: Receive message 35*91f16700Schasinglulu */ 36*91f16700Schasinglulu struct ti_sci_xfer { 37*91f16700Schasinglulu struct k3_sec_proxy_msg tx_message; 38*91f16700Schasinglulu struct k3_sec_proxy_msg rx_message; 39*91f16700Schasinglulu }; 40*91f16700Schasinglulu 41*91f16700Schasinglulu /** 42*91f16700Schasinglulu * ti_sci_setup_one_xfer() - Setup one message type 43*91f16700Schasinglulu * 44*91f16700Schasinglulu * @msg_type: Message type 45*91f16700Schasinglulu * @msg_flags: Flag to set for the message 46*91f16700Schasinglulu * @tx_buf: Buffer to be sent to mailbox channel 47*91f16700Schasinglulu * @tx_message_size: transmit message size 48*91f16700Schasinglulu * @rx_buf: Buffer to be received from mailbox channel 49*91f16700Schasinglulu * @rx_message_size: receive message size 50*91f16700Schasinglulu * 51*91f16700Schasinglulu * Helper function which is used by various command functions that are 52*91f16700Schasinglulu * exposed to clients of this driver for allocating a message traffic event. 53*91f16700Schasinglulu * 54*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 55*91f16700Schasinglulu */ 56*91f16700Schasinglulu static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags, 57*91f16700Schasinglulu void *tx_buf, 58*91f16700Schasinglulu size_t tx_message_size, 59*91f16700Schasinglulu void *rx_buf, 60*91f16700Schasinglulu size_t rx_message_size, 61*91f16700Schasinglulu struct ti_sci_xfer *xfer) 62*91f16700Schasinglulu { 63*91f16700Schasinglulu struct ti_sci_msg_hdr *hdr; 64*91f16700Schasinglulu 65*91f16700Schasinglulu /* Ensure we have sane transfer sizes */ 66*91f16700Schasinglulu if (rx_message_size > TI_SCI_MAX_MESSAGE_SIZE || 67*91f16700Schasinglulu tx_message_size > TI_SCI_MAX_MESSAGE_SIZE || 68*91f16700Schasinglulu tx_message_size < sizeof(*hdr)) 69*91f16700Schasinglulu return -ERANGE; 70*91f16700Schasinglulu 71*91f16700Schasinglulu hdr = (struct ti_sci_msg_hdr *)tx_buf; 72*91f16700Schasinglulu hdr->seq = ++message_sequence; 73*91f16700Schasinglulu hdr->type = msg_type; 74*91f16700Schasinglulu hdr->host = TI_SCI_HOST_ID; 75*91f16700Schasinglulu hdr->flags = msg_flags; 76*91f16700Schasinglulu /* Request a response if rx_message_size is non-zero */ 77*91f16700Schasinglulu if (rx_message_size != 0U) { 78*91f16700Schasinglulu hdr->flags |= TI_SCI_FLAG_REQ_ACK_ON_PROCESSED; 79*91f16700Schasinglulu } 80*91f16700Schasinglulu 81*91f16700Schasinglulu xfer->tx_message.buf = tx_buf; 82*91f16700Schasinglulu xfer->tx_message.len = tx_message_size; 83*91f16700Schasinglulu 84*91f16700Schasinglulu xfer->rx_message.buf = rx_buf; 85*91f16700Schasinglulu xfer->rx_message.len = rx_message_size; 86*91f16700Schasinglulu 87*91f16700Schasinglulu return 0; 88*91f16700Schasinglulu } 89*91f16700Schasinglulu 90*91f16700Schasinglulu /** 91*91f16700Schasinglulu * ti_sci_get_response() - Receive response from mailbox channel 92*91f16700Schasinglulu * 93*91f16700Schasinglulu * @xfer: Transfer to initiate and wait for response 94*91f16700Schasinglulu * @chan: Channel to receive the response 95*91f16700Schasinglulu * 96*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 97*91f16700Schasinglulu */ 98*91f16700Schasinglulu static int ti_sci_get_response(struct k3_sec_proxy_msg *msg, 99*91f16700Schasinglulu enum k3_sec_proxy_chan_id chan) 100*91f16700Schasinglulu { 101*91f16700Schasinglulu struct ti_sci_msg_hdr *hdr; 102*91f16700Schasinglulu unsigned int retry = 5; 103*91f16700Schasinglulu int ret; 104*91f16700Schasinglulu 105*91f16700Schasinglulu for (; retry > 0; retry--) { 106*91f16700Schasinglulu /* Receive the response */ 107*91f16700Schasinglulu ret = k3_sec_proxy_recv(chan, msg); 108*91f16700Schasinglulu if (ret) { 109*91f16700Schasinglulu ERROR("Message receive failed (%d)\n", ret); 110*91f16700Schasinglulu return ret; 111*91f16700Schasinglulu } 112*91f16700Schasinglulu 113*91f16700Schasinglulu /* msg is updated by Secure Proxy driver */ 114*91f16700Schasinglulu hdr = (struct ti_sci_msg_hdr *)msg->buf; 115*91f16700Schasinglulu 116*91f16700Schasinglulu /* Sanity check for message response */ 117*91f16700Schasinglulu if (hdr->seq == message_sequence) 118*91f16700Schasinglulu break; 119*91f16700Schasinglulu else 120*91f16700Schasinglulu WARN("Message with sequence ID %u is not expected\n", hdr->seq); 121*91f16700Schasinglulu } 122*91f16700Schasinglulu if (!retry) { 123*91f16700Schasinglulu ERROR("Timed out waiting for message\n"); 124*91f16700Schasinglulu return -EINVAL; 125*91f16700Schasinglulu } 126*91f16700Schasinglulu 127*91f16700Schasinglulu if (msg->len > TI_SCI_MAX_MESSAGE_SIZE) { 128*91f16700Schasinglulu ERROR("Unable to handle %lu xfer (max %d)\n", 129*91f16700Schasinglulu msg->len, TI_SCI_MAX_MESSAGE_SIZE); 130*91f16700Schasinglulu return -EINVAL; 131*91f16700Schasinglulu } 132*91f16700Schasinglulu 133*91f16700Schasinglulu if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK)) 134*91f16700Schasinglulu return -ENODEV; 135*91f16700Schasinglulu 136*91f16700Schasinglulu return 0; 137*91f16700Schasinglulu } 138*91f16700Schasinglulu 139*91f16700Schasinglulu /** 140*91f16700Schasinglulu * ti_sci_do_xfer() - Do one transfer 141*91f16700Schasinglulu * 142*91f16700Schasinglulu * @xfer: Transfer to initiate and wait for response 143*91f16700Schasinglulu * 144*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 145*91f16700Schasinglulu */ 146*91f16700Schasinglulu static int ti_sci_do_xfer(struct ti_sci_xfer *xfer) 147*91f16700Schasinglulu { 148*91f16700Schasinglulu struct k3_sec_proxy_msg *tx_msg = &xfer->tx_message; 149*91f16700Schasinglulu struct k3_sec_proxy_msg *rx_msg = &xfer->rx_message; 150*91f16700Schasinglulu int ret; 151*91f16700Schasinglulu 152*91f16700Schasinglulu bakery_lock_get(&ti_sci_xfer_lock); 153*91f16700Schasinglulu 154*91f16700Schasinglulu /* Clear any spurious messages in receive queue */ 155*91f16700Schasinglulu ret = k3_sec_proxy_clear_rx_thread(SP_RESPONSE); 156*91f16700Schasinglulu if (ret) { 157*91f16700Schasinglulu ERROR("Could not clear response queue (%d)\n", ret); 158*91f16700Schasinglulu goto unlock; 159*91f16700Schasinglulu } 160*91f16700Schasinglulu 161*91f16700Schasinglulu /* Send the message */ 162*91f16700Schasinglulu ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, tx_msg); 163*91f16700Schasinglulu if (ret) { 164*91f16700Schasinglulu ERROR("Message sending failed (%d)\n", ret); 165*91f16700Schasinglulu goto unlock; 166*91f16700Schasinglulu } 167*91f16700Schasinglulu 168*91f16700Schasinglulu /* Get the response if requested */ 169*91f16700Schasinglulu if (rx_msg->len != 0U) { 170*91f16700Schasinglulu ret = ti_sci_get_response(rx_msg, SP_RESPONSE); 171*91f16700Schasinglulu if (ret != 0U) { 172*91f16700Schasinglulu ERROR("Failed to get response (%d)\n", ret); 173*91f16700Schasinglulu goto unlock; 174*91f16700Schasinglulu } 175*91f16700Schasinglulu } 176*91f16700Schasinglulu 177*91f16700Schasinglulu unlock: 178*91f16700Schasinglulu bakery_lock_release(&ti_sci_xfer_lock); 179*91f16700Schasinglulu 180*91f16700Schasinglulu return ret; 181*91f16700Schasinglulu } 182*91f16700Schasinglulu 183*91f16700Schasinglulu /** 184*91f16700Schasinglulu * ti_sci_get_revision() - Get the revision of the SCI entity 185*91f16700Schasinglulu * 186*91f16700Schasinglulu * Updates the SCI information in the internal data structure. 187*91f16700Schasinglulu * 188*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 189*91f16700Schasinglulu */ 190*91f16700Schasinglulu int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info) 191*91f16700Schasinglulu { 192*91f16700Schasinglulu struct ti_sci_msg_hdr hdr; 193*91f16700Schasinglulu struct ti_sci_xfer xfer; 194*91f16700Schasinglulu int ret; 195*91f16700Schasinglulu 196*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_VERSION, 0x0, 197*91f16700Schasinglulu &hdr, sizeof(hdr), 198*91f16700Schasinglulu rev_info, sizeof(*rev_info), 199*91f16700Schasinglulu &xfer); 200*91f16700Schasinglulu if (ret) { 201*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 202*91f16700Schasinglulu return ret; 203*91f16700Schasinglulu } 204*91f16700Schasinglulu 205*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 206*91f16700Schasinglulu if (ret) { 207*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 208*91f16700Schasinglulu return ret; 209*91f16700Schasinglulu } 210*91f16700Schasinglulu 211*91f16700Schasinglulu return 0; 212*91f16700Schasinglulu } 213*91f16700Schasinglulu 214*91f16700Schasinglulu /** 215*91f16700Schasinglulu * ti_sci_query_fw_caps() - Get the FW/SoC capabilities 216*91f16700Schasinglulu * @handle: Pointer to TI SCI handle 217*91f16700Schasinglulu * @fw_caps: Each bit in fw_caps indicating one FW/SOC capability 218*91f16700Schasinglulu * 219*91f16700Schasinglulu * Return: 0 if all went well, else returns appropriate error value. 220*91f16700Schasinglulu */ 221*91f16700Schasinglulu int ti_sci_query_fw_caps(uint64_t *fw_caps) 222*91f16700Schasinglulu { 223*91f16700Schasinglulu struct ti_sci_msg_hdr req; 224*91f16700Schasinglulu struct ti_sci_msg_resp_query_fw_caps resp; 225*91f16700Schasinglulu 226*91f16700Schasinglulu struct ti_sci_xfer xfer; 227*91f16700Schasinglulu int ret; 228*91f16700Schasinglulu 229*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_FW_CAPS, 0, 230*91f16700Schasinglulu &req, sizeof(req), 231*91f16700Schasinglulu &resp, sizeof(resp), 232*91f16700Schasinglulu &xfer); 233*91f16700Schasinglulu if (ret != 0U) { 234*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 235*91f16700Schasinglulu return ret; 236*91f16700Schasinglulu } 237*91f16700Schasinglulu 238*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 239*91f16700Schasinglulu if (ret != 0U) { 240*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 241*91f16700Schasinglulu return ret; 242*91f16700Schasinglulu } 243*91f16700Schasinglulu 244*91f16700Schasinglulu if (fw_caps) 245*91f16700Schasinglulu *fw_caps = resp.fw_caps; 246*91f16700Schasinglulu 247*91f16700Schasinglulu return 0; 248*91f16700Schasinglulu } 249*91f16700Schasinglulu 250*91f16700Schasinglulu /** 251*91f16700Schasinglulu * ti_sci_device_set_state() - Set device state 252*91f16700Schasinglulu * 253*91f16700Schasinglulu * @id: Device identifier 254*91f16700Schasinglulu * @flags: flags to setup for the device 255*91f16700Schasinglulu * @state: State to move the device to 256*91f16700Schasinglulu * 257*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 258*91f16700Schasinglulu */ 259*91f16700Schasinglulu static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state) 260*91f16700Schasinglulu { 261*91f16700Schasinglulu struct ti_sci_msg_req_set_device_state req; 262*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 263*91f16700Schasinglulu 264*91f16700Schasinglulu struct ti_sci_xfer xfer; 265*91f16700Schasinglulu int ret; 266*91f16700Schasinglulu 267*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags, 268*91f16700Schasinglulu &req, sizeof(req), 269*91f16700Schasinglulu &resp, sizeof(resp), 270*91f16700Schasinglulu &xfer); 271*91f16700Schasinglulu if (ret) { 272*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 273*91f16700Schasinglulu return ret; 274*91f16700Schasinglulu } 275*91f16700Schasinglulu 276*91f16700Schasinglulu req.id = id; 277*91f16700Schasinglulu req.state = state; 278*91f16700Schasinglulu 279*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 280*91f16700Schasinglulu if (ret) { 281*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 282*91f16700Schasinglulu return ret; 283*91f16700Schasinglulu } 284*91f16700Schasinglulu 285*91f16700Schasinglulu return 0; 286*91f16700Schasinglulu } 287*91f16700Schasinglulu 288*91f16700Schasinglulu /** 289*91f16700Schasinglulu * ti_sci_device_get_state() - Get device state 290*91f16700Schasinglulu * 291*91f16700Schasinglulu * @id: Device Identifier 292*91f16700Schasinglulu * @clcnt: Pointer to Context Loss Count 293*91f16700Schasinglulu * @resets: pointer to resets 294*91f16700Schasinglulu * @p_state: pointer to p_state 295*91f16700Schasinglulu * @c_state: pointer to c_state 296*91f16700Schasinglulu * 297*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 298*91f16700Schasinglulu */ 299*91f16700Schasinglulu static int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt, 300*91f16700Schasinglulu uint32_t *resets, uint8_t *p_state, 301*91f16700Schasinglulu uint8_t *c_state) 302*91f16700Schasinglulu { 303*91f16700Schasinglulu struct ti_sci_msg_req_get_device_state req; 304*91f16700Schasinglulu struct ti_sci_msg_resp_get_device_state resp; 305*91f16700Schasinglulu 306*91f16700Schasinglulu struct ti_sci_xfer xfer; 307*91f16700Schasinglulu int ret; 308*91f16700Schasinglulu 309*91f16700Schasinglulu if (!clcnt && !resets && !p_state && !c_state) 310*91f16700Schasinglulu return -EINVAL; 311*91f16700Schasinglulu 312*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0, 313*91f16700Schasinglulu &req, sizeof(req), 314*91f16700Schasinglulu &resp, sizeof(resp), 315*91f16700Schasinglulu &xfer); 316*91f16700Schasinglulu if (ret) { 317*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 318*91f16700Schasinglulu return ret; 319*91f16700Schasinglulu } 320*91f16700Schasinglulu 321*91f16700Schasinglulu req.id = id; 322*91f16700Schasinglulu 323*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 324*91f16700Schasinglulu if (ret) { 325*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 326*91f16700Schasinglulu return ret; 327*91f16700Schasinglulu } 328*91f16700Schasinglulu 329*91f16700Schasinglulu if (clcnt) 330*91f16700Schasinglulu *clcnt = resp.context_loss_count; 331*91f16700Schasinglulu if (resets) 332*91f16700Schasinglulu *resets = resp.resets; 333*91f16700Schasinglulu if (p_state) 334*91f16700Schasinglulu *p_state = resp.programmed_state; 335*91f16700Schasinglulu if (c_state) 336*91f16700Schasinglulu *c_state = resp.current_state; 337*91f16700Schasinglulu 338*91f16700Schasinglulu return 0; 339*91f16700Schasinglulu } 340*91f16700Schasinglulu 341*91f16700Schasinglulu /** 342*91f16700Schasinglulu * ti_sci_device_get() - Request for device managed by TISCI 343*91f16700Schasinglulu * 344*91f16700Schasinglulu * @id: Device Identifier 345*91f16700Schasinglulu * 346*91f16700Schasinglulu * Request for the device - NOTE: the client MUST maintain integrity of 347*91f16700Schasinglulu * usage count by balancing get_device with put_device. No refcounting is 348*91f16700Schasinglulu * managed by driver for that purpose. 349*91f16700Schasinglulu * 350*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 351*91f16700Schasinglulu */ 352*91f16700Schasinglulu int ti_sci_device_get(uint32_t id) 353*91f16700Schasinglulu { 354*91f16700Schasinglulu return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON); 355*91f16700Schasinglulu } 356*91f16700Schasinglulu 357*91f16700Schasinglulu /** 358*91f16700Schasinglulu * ti_sci_device_get_exclusive() - Exclusive request for device managed by TISCI 359*91f16700Schasinglulu * 360*91f16700Schasinglulu * @id: Device Identifier 361*91f16700Schasinglulu * 362*91f16700Schasinglulu * Request for the device - NOTE: the client MUST maintain integrity of 363*91f16700Schasinglulu * usage count by balancing get_device with put_device. No refcounting is 364*91f16700Schasinglulu * managed by driver for that purpose. 365*91f16700Schasinglulu * 366*91f16700Schasinglulu * NOTE: This _exclusive version of the get API is for exclusive access to the 367*91f16700Schasinglulu * device. Any other host in the system will fail to get this device after this 368*91f16700Schasinglulu * call until exclusive access is released with device_put or a non-exclusive 369*91f16700Schasinglulu * set call. 370*91f16700Schasinglulu * 371*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 372*91f16700Schasinglulu */ 373*91f16700Schasinglulu int ti_sci_device_get_exclusive(uint32_t id) 374*91f16700Schasinglulu { 375*91f16700Schasinglulu return ti_sci_device_set_state(id, 376*91f16700Schasinglulu MSG_FLAG_DEVICE_EXCLUSIVE, 377*91f16700Schasinglulu MSG_DEVICE_SW_STATE_ON); 378*91f16700Schasinglulu } 379*91f16700Schasinglulu 380*91f16700Schasinglulu /** 381*91f16700Schasinglulu * ti_sci_device_idle() - Idle a device managed by TISCI 382*91f16700Schasinglulu * 383*91f16700Schasinglulu * @id: Device Identifier 384*91f16700Schasinglulu * 385*91f16700Schasinglulu * Request for the device - NOTE: the client MUST maintain integrity of 386*91f16700Schasinglulu * usage count by balancing get_device with put_device. No refcounting is 387*91f16700Schasinglulu * managed by driver for that purpose. 388*91f16700Schasinglulu * 389*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 390*91f16700Schasinglulu */ 391*91f16700Schasinglulu int ti_sci_device_idle(uint32_t id) 392*91f16700Schasinglulu { 393*91f16700Schasinglulu return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_RETENTION); 394*91f16700Schasinglulu } 395*91f16700Schasinglulu 396*91f16700Schasinglulu /** 397*91f16700Schasinglulu * ti_sci_device_idle_exclusive() - Exclusive idle a device managed by TISCI 398*91f16700Schasinglulu * 399*91f16700Schasinglulu * @id: Device Identifier 400*91f16700Schasinglulu * 401*91f16700Schasinglulu * Request for the device - NOTE: the client MUST maintain integrity of 402*91f16700Schasinglulu * usage count by balancing get_device with put_device. No refcounting is 403*91f16700Schasinglulu * managed by driver for that purpose. 404*91f16700Schasinglulu * 405*91f16700Schasinglulu * NOTE: This _exclusive version of the idle API is for exclusive access to 406*91f16700Schasinglulu * the device. Any other host in the system will fail to get this device after 407*91f16700Schasinglulu * this call until exclusive access is released with device_put or a 408*91f16700Schasinglulu * non-exclusive set call. 409*91f16700Schasinglulu * 410*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 411*91f16700Schasinglulu */ 412*91f16700Schasinglulu int ti_sci_device_idle_exclusive(uint32_t id) 413*91f16700Schasinglulu { 414*91f16700Schasinglulu return ti_sci_device_set_state(id, 415*91f16700Schasinglulu MSG_FLAG_DEVICE_EXCLUSIVE, 416*91f16700Schasinglulu MSG_DEVICE_SW_STATE_RETENTION); 417*91f16700Schasinglulu } 418*91f16700Schasinglulu 419*91f16700Schasinglulu /** 420*91f16700Schasinglulu * ti_sci_device_put() - Release a device managed by TISCI 421*91f16700Schasinglulu * 422*91f16700Schasinglulu * @id: Device Identifier 423*91f16700Schasinglulu * 424*91f16700Schasinglulu * Request for the device - NOTE: the client MUST maintain integrity of 425*91f16700Schasinglulu * usage count by balancing get_device with put_device. No refcounting is 426*91f16700Schasinglulu * managed by driver for that purpose. 427*91f16700Schasinglulu * 428*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 429*91f16700Schasinglulu */ 430*91f16700Schasinglulu int ti_sci_device_put(uint32_t id) 431*91f16700Schasinglulu { 432*91f16700Schasinglulu return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF); 433*91f16700Schasinglulu } 434*91f16700Schasinglulu 435*91f16700Schasinglulu /** 436*91f16700Schasinglulu * ti_sci_device_put_no_wait() - Release a device without requesting or waiting 437*91f16700Schasinglulu * for a response. 438*91f16700Schasinglulu * 439*91f16700Schasinglulu * @id: Device Identifier 440*91f16700Schasinglulu * 441*91f16700Schasinglulu * Request for the device - NOTE: the client MUST maintain integrity of 442*91f16700Schasinglulu * usage count by balancing get_device with put_device. No refcounting is 443*91f16700Schasinglulu * managed by driver for that purpose. 444*91f16700Schasinglulu * 445*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 446*91f16700Schasinglulu */ 447*91f16700Schasinglulu int ti_sci_device_put_no_wait(uint32_t id) 448*91f16700Schasinglulu { 449*91f16700Schasinglulu struct ti_sci_msg_req_set_device_state req; 450*91f16700Schasinglulu struct ti_sci_xfer xfer; 451*91f16700Schasinglulu int ret; 452*91f16700Schasinglulu 453*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, 0, 454*91f16700Schasinglulu &req, sizeof(req), 455*91f16700Schasinglulu NULL, 0, 456*91f16700Schasinglulu &xfer); 457*91f16700Schasinglulu if (ret != 0U) { 458*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 459*91f16700Schasinglulu return ret; 460*91f16700Schasinglulu } 461*91f16700Schasinglulu 462*91f16700Schasinglulu req.id = id; 463*91f16700Schasinglulu req.state = MSG_DEVICE_SW_STATE_AUTO_OFF; 464*91f16700Schasinglulu 465*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 466*91f16700Schasinglulu if (ret != 0U) { 467*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 468*91f16700Schasinglulu return ret; 469*91f16700Schasinglulu } 470*91f16700Schasinglulu 471*91f16700Schasinglulu return 0; 472*91f16700Schasinglulu } 473*91f16700Schasinglulu 474*91f16700Schasinglulu /** 475*91f16700Schasinglulu * ti_sci_device_is_valid() - Is the device valid 476*91f16700Schasinglulu * 477*91f16700Schasinglulu * @id: Device Identifier 478*91f16700Schasinglulu * 479*91f16700Schasinglulu * Return: 0 if all goes well and the device ID is valid, else return 480*91f16700Schasinglulu * appropriate error 481*91f16700Schasinglulu */ 482*91f16700Schasinglulu int ti_sci_device_is_valid(uint32_t id) 483*91f16700Schasinglulu { 484*91f16700Schasinglulu uint8_t unused; 485*91f16700Schasinglulu 486*91f16700Schasinglulu /* check the device state which will also tell us if the ID is valid */ 487*91f16700Schasinglulu return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused); 488*91f16700Schasinglulu } 489*91f16700Schasinglulu 490*91f16700Schasinglulu /** 491*91f16700Schasinglulu * ti_sci_device_get_clcnt() - Get context loss counter 492*91f16700Schasinglulu * 493*91f16700Schasinglulu * @id: Device Identifier 494*91f16700Schasinglulu * @count: Pointer to Context Loss counter to populate 495*91f16700Schasinglulu * 496*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 497*91f16700Schasinglulu */ 498*91f16700Schasinglulu int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count) 499*91f16700Schasinglulu { 500*91f16700Schasinglulu return ti_sci_device_get_state(id, count, NULL, NULL, NULL); 501*91f16700Schasinglulu } 502*91f16700Schasinglulu 503*91f16700Schasinglulu /** 504*91f16700Schasinglulu * ti_sci_device_is_idle() - Check if the device is requested to be idle 505*91f16700Schasinglulu * 506*91f16700Schasinglulu * @id: Device Identifier 507*91f16700Schasinglulu * @r_state: true if requested to be idle 508*91f16700Schasinglulu * 509*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 510*91f16700Schasinglulu */ 511*91f16700Schasinglulu int ti_sci_device_is_idle(uint32_t id, bool *r_state) 512*91f16700Schasinglulu { 513*91f16700Schasinglulu int ret; 514*91f16700Schasinglulu uint8_t state; 515*91f16700Schasinglulu 516*91f16700Schasinglulu if (!r_state) 517*91f16700Schasinglulu return -EINVAL; 518*91f16700Schasinglulu 519*91f16700Schasinglulu ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL); 520*91f16700Schasinglulu if (ret) 521*91f16700Schasinglulu return ret; 522*91f16700Schasinglulu 523*91f16700Schasinglulu *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION); 524*91f16700Schasinglulu 525*91f16700Schasinglulu return 0; 526*91f16700Schasinglulu } 527*91f16700Schasinglulu 528*91f16700Schasinglulu /** 529*91f16700Schasinglulu * ti_sci_device_is_stop() - Check if the device is requested to be stopped 530*91f16700Schasinglulu * 531*91f16700Schasinglulu * @id: Device Identifier 532*91f16700Schasinglulu * @r_state: true if requested to be stopped 533*91f16700Schasinglulu * @curr_state: true if currently stopped 534*91f16700Schasinglulu * 535*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 536*91f16700Schasinglulu */ 537*91f16700Schasinglulu int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state) 538*91f16700Schasinglulu { 539*91f16700Schasinglulu int ret; 540*91f16700Schasinglulu uint8_t p_state, c_state; 541*91f16700Schasinglulu 542*91f16700Schasinglulu if (!r_state && !curr_state) 543*91f16700Schasinglulu return -EINVAL; 544*91f16700Schasinglulu 545*91f16700Schasinglulu ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state); 546*91f16700Schasinglulu if (ret) 547*91f16700Schasinglulu return ret; 548*91f16700Schasinglulu 549*91f16700Schasinglulu if (r_state) 550*91f16700Schasinglulu *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF); 551*91f16700Schasinglulu if (curr_state) 552*91f16700Schasinglulu *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF); 553*91f16700Schasinglulu 554*91f16700Schasinglulu return 0; 555*91f16700Schasinglulu } 556*91f16700Schasinglulu 557*91f16700Schasinglulu /** 558*91f16700Schasinglulu * ti_sci_device_is_on() - Check if the device is requested to be ON 559*91f16700Schasinglulu * 560*91f16700Schasinglulu * @id: Device Identifier 561*91f16700Schasinglulu * @r_state: true if requested to be ON 562*91f16700Schasinglulu * @curr_state: true if currently ON and active 563*91f16700Schasinglulu * 564*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 565*91f16700Schasinglulu */ 566*91f16700Schasinglulu int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state) 567*91f16700Schasinglulu { 568*91f16700Schasinglulu int ret; 569*91f16700Schasinglulu uint8_t p_state, c_state; 570*91f16700Schasinglulu 571*91f16700Schasinglulu if (!r_state && !curr_state) 572*91f16700Schasinglulu return -EINVAL; 573*91f16700Schasinglulu 574*91f16700Schasinglulu ret = 575*91f16700Schasinglulu ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state); 576*91f16700Schasinglulu if (ret) 577*91f16700Schasinglulu return ret; 578*91f16700Schasinglulu 579*91f16700Schasinglulu if (r_state) 580*91f16700Schasinglulu *r_state = (p_state == MSG_DEVICE_SW_STATE_ON); 581*91f16700Schasinglulu if (curr_state) 582*91f16700Schasinglulu *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON); 583*91f16700Schasinglulu 584*91f16700Schasinglulu return 0; 585*91f16700Schasinglulu } 586*91f16700Schasinglulu 587*91f16700Schasinglulu /** 588*91f16700Schasinglulu * ti_sci_device_is_trans() - Check if the device is currently transitioning 589*91f16700Schasinglulu * 590*91f16700Schasinglulu * @id: Device Identifier 591*91f16700Schasinglulu * @curr_state: true if currently transitioning 592*91f16700Schasinglulu * 593*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 594*91f16700Schasinglulu */ 595*91f16700Schasinglulu int ti_sci_device_is_trans(uint32_t id, bool *curr_state) 596*91f16700Schasinglulu { 597*91f16700Schasinglulu int ret; 598*91f16700Schasinglulu uint8_t state; 599*91f16700Schasinglulu 600*91f16700Schasinglulu if (!curr_state) 601*91f16700Schasinglulu return -EINVAL; 602*91f16700Schasinglulu 603*91f16700Schasinglulu ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state); 604*91f16700Schasinglulu if (ret) 605*91f16700Schasinglulu return ret; 606*91f16700Schasinglulu 607*91f16700Schasinglulu *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS); 608*91f16700Schasinglulu 609*91f16700Schasinglulu return 0; 610*91f16700Schasinglulu } 611*91f16700Schasinglulu 612*91f16700Schasinglulu /** 613*91f16700Schasinglulu * ti_sci_device_set_resets() - Set resets for device managed by TISCI 614*91f16700Schasinglulu * 615*91f16700Schasinglulu * @id: Device Identifier 616*91f16700Schasinglulu * @reset_state: Device specific reset bit field 617*91f16700Schasinglulu * 618*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 619*91f16700Schasinglulu */ 620*91f16700Schasinglulu int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state) 621*91f16700Schasinglulu { 622*91f16700Schasinglulu struct ti_sci_msg_req_set_device_resets req; 623*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 624*91f16700Schasinglulu 625*91f16700Schasinglulu struct ti_sci_xfer xfer; 626*91f16700Schasinglulu int ret; 627*91f16700Schasinglulu 628*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS, 0, 629*91f16700Schasinglulu &req, sizeof(req), 630*91f16700Schasinglulu &resp, sizeof(resp), 631*91f16700Schasinglulu &xfer); 632*91f16700Schasinglulu if (ret) { 633*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 634*91f16700Schasinglulu return ret; 635*91f16700Schasinglulu } 636*91f16700Schasinglulu 637*91f16700Schasinglulu req.id = id; 638*91f16700Schasinglulu req.resets = reset_state; 639*91f16700Schasinglulu 640*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 641*91f16700Schasinglulu if (ret) { 642*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 643*91f16700Schasinglulu return ret; 644*91f16700Schasinglulu } 645*91f16700Schasinglulu 646*91f16700Schasinglulu return 0; 647*91f16700Schasinglulu } 648*91f16700Schasinglulu 649*91f16700Schasinglulu /** 650*91f16700Schasinglulu * ti_sci_device_get_resets() - Get reset state for device managed by TISCI 651*91f16700Schasinglulu * 652*91f16700Schasinglulu * @id: Device Identifier 653*91f16700Schasinglulu * @reset_state: Pointer to reset state to populate 654*91f16700Schasinglulu * 655*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 656*91f16700Schasinglulu */ 657*91f16700Schasinglulu int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state) 658*91f16700Schasinglulu { 659*91f16700Schasinglulu return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL); 660*91f16700Schasinglulu } 661*91f16700Schasinglulu 662*91f16700Schasinglulu /** 663*91f16700Schasinglulu * ti_sci_clock_set_state() - Set clock state helper 664*91f16700Schasinglulu * 665*91f16700Schasinglulu * @dev_id: Device identifier this request is for 666*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request, 667*91f16700Schasinglulu * Each device has its own set of clock inputs, This indexes 668*91f16700Schasinglulu * which clock input to modify 669*91f16700Schasinglulu * @flags: Header flags as needed 670*91f16700Schasinglulu * @state: State to request for the clock 671*91f16700Schasinglulu * 672*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 673*91f16700Schasinglulu */ 674*91f16700Schasinglulu int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id, 675*91f16700Schasinglulu uint32_t flags, uint8_t state) 676*91f16700Schasinglulu { 677*91f16700Schasinglulu struct ti_sci_msg_req_set_clock_state req; 678*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 679*91f16700Schasinglulu 680*91f16700Schasinglulu struct ti_sci_xfer xfer; 681*91f16700Schasinglulu int ret; 682*91f16700Schasinglulu 683*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_STATE, flags, 684*91f16700Schasinglulu &req, sizeof(req), 685*91f16700Schasinglulu &resp, sizeof(resp), 686*91f16700Schasinglulu &xfer); 687*91f16700Schasinglulu if (ret) { 688*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 689*91f16700Schasinglulu return ret; 690*91f16700Schasinglulu } 691*91f16700Schasinglulu 692*91f16700Schasinglulu req.dev_id = dev_id; 693*91f16700Schasinglulu req.clk_id = clk_id; 694*91f16700Schasinglulu req.request_state = state; 695*91f16700Schasinglulu 696*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 697*91f16700Schasinglulu if (ret) { 698*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 699*91f16700Schasinglulu return ret; 700*91f16700Schasinglulu } 701*91f16700Schasinglulu 702*91f16700Schasinglulu return 0; 703*91f16700Schasinglulu } 704*91f16700Schasinglulu 705*91f16700Schasinglulu /** 706*91f16700Schasinglulu * ti_sci_clock_get_state() - Get clock state helper 707*91f16700Schasinglulu * 708*91f16700Schasinglulu * @dev_id: Device identifier this request is for 709*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 710*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 711*91f16700Schasinglulu * which clock input to modify. 712*91f16700Schasinglulu * @programmed_state: State requested for clock to move to 713*91f16700Schasinglulu * @current_state: State that the clock is currently in 714*91f16700Schasinglulu * 715*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 716*91f16700Schasinglulu */ 717*91f16700Schasinglulu int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id, 718*91f16700Schasinglulu uint8_t *programmed_state, 719*91f16700Schasinglulu uint8_t *current_state) 720*91f16700Schasinglulu { 721*91f16700Schasinglulu struct ti_sci_msg_req_get_clock_state req; 722*91f16700Schasinglulu struct ti_sci_msg_resp_get_clock_state resp; 723*91f16700Schasinglulu 724*91f16700Schasinglulu struct ti_sci_xfer xfer; 725*91f16700Schasinglulu int ret; 726*91f16700Schasinglulu 727*91f16700Schasinglulu if (!programmed_state && !current_state) 728*91f16700Schasinglulu return -EINVAL; 729*91f16700Schasinglulu 730*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_STATE, 0, 731*91f16700Schasinglulu &req, sizeof(req), 732*91f16700Schasinglulu &resp, sizeof(resp), 733*91f16700Schasinglulu &xfer); 734*91f16700Schasinglulu if (ret) { 735*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 736*91f16700Schasinglulu return ret; 737*91f16700Schasinglulu } 738*91f16700Schasinglulu 739*91f16700Schasinglulu req.dev_id = dev_id; 740*91f16700Schasinglulu req.clk_id = clk_id; 741*91f16700Schasinglulu 742*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 743*91f16700Schasinglulu if (ret) { 744*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 745*91f16700Schasinglulu return ret; 746*91f16700Schasinglulu } 747*91f16700Schasinglulu 748*91f16700Schasinglulu if (programmed_state) 749*91f16700Schasinglulu *programmed_state = resp.programmed_state; 750*91f16700Schasinglulu if (current_state) 751*91f16700Schasinglulu *current_state = resp.current_state; 752*91f16700Schasinglulu 753*91f16700Schasinglulu return 0; 754*91f16700Schasinglulu } 755*91f16700Schasinglulu 756*91f16700Schasinglulu /** 757*91f16700Schasinglulu * ti_sci_clock_get() - Get control of a clock from TI SCI 758*91f16700Schasinglulu 759*91f16700Schasinglulu * @dev_id: Device identifier this request is for 760*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 761*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 762*91f16700Schasinglulu * which clock input to modify. 763*91f16700Schasinglulu * @needs_ssc: 'true' iff Spread Spectrum clock is desired 764*91f16700Schasinglulu * @can_change_freq: 'true' iff frequency change is desired 765*91f16700Schasinglulu * @enable_input_term: 'true' iff input termination is desired 766*91f16700Schasinglulu * 767*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 768*91f16700Schasinglulu */ 769*91f16700Schasinglulu int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id, 770*91f16700Schasinglulu bool needs_ssc, bool can_change_freq, 771*91f16700Schasinglulu bool enable_input_term) 772*91f16700Schasinglulu { 773*91f16700Schasinglulu uint32_t flags = 0; 774*91f16700Schasinglulu 775*91f16700Schasinglulu flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0; 776*91f16700Schasinglulu flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0; 777*91f16700Schasinglulu flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0; 778*91f16700Schasinglulu 779*91f16700Schasinglulu return ti_sci_clock_set_state(dev_id, clk_id, flags, 780*91f16700Schasinglulu MSG_CLOCK_SW_STATE_REQ); 781*91f16700Schasinglulu } 782*91f16700Schasinglulu 783*91f16700Schasinglulu /** 784*91f16700Schasinglulu * ti_sci_clock_idle() - Idle a clock which is in our control 785*91f16700Schasinglulu 786*91f16700Schasinglulu * @dev_id: Device identifier this request is for 787*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 788*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 789*91f16700Schasinglulu * which clock input to modify. 790*91f16700Schasinglulu * 791*91f16700Schasinglulu * NOTE: This clock must have been requested by get_clock previously. 792*91f16700Schasinglulu * 793*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 794*91f16700Schasinglulu */ 795*91f16700Schasinglulu int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id) 796*91f16700Schasinglulu { 797*91f16700Schasinglulu return ti_sci_clock_set_state(dev_id, clk_id, 0, 798*91f16700Schasinglulu MSG_CLOCK_SW_STATE_UNREQ); 799*91f16700Schasinglulu } 800*91f16700Schasinglulu 801*91f16700Schasinglulu /** 802*91f16700Schasinglulu * ti_sci_clock_put() - Release a clock from our control 803*91f16700Schasinglulu * 804*91f16700Schasinglulu * @dev_id: Device identifier this request is for 805*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 806*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 807*91f16700Schasinglulu * which clock input to modify. 808*91f16700Schasinglulu * 809*91f16700Schasinglulu * NOTE: This clock must have been requested by get_clock previously. 810*91f16700Schasinglulu * 811*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 812*91f16700Schasinglulu */ 813*91f16700Schasinglulu int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id) 814*91f16700Schasinglulu { 815*91f16700Schasinglulu return ti_sci_clock_set_state(dev_id, clk_id, 0, 816*91f16700Schasinglulu MSG_CLOCK_SW_STATE_AUTO); 817*91f16700Schasinglulu } 818*91f16700Schasinglulu 819*91f16700Schasinglulu /** 820*91f16700Schasinglulu * ti_sci_clock_is_auto() - Is the clock being auto managed 821*91f16700Schasinglulu * 822*91f16700Schasinglulu * @dev_id: Device identifier this request is for 823*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 824*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 825*91f16700Schasinglulu * which clock input to modify. 826*91f16700Schasinglulu * @req_state: state indicating if the clock is auto managed 827*91f16700Schasinglulu * 828*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 829*91f16700Schasinglulu */ 830*91f16700Schasinglulu int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, bool *req_state) 831*91f16700Schasinglulu { 832*91f16700Schasinglulu uint8_t state = 0; 833*91f16700Schasinglulu int ret; 834*91f16700Schasinglulu 835*91f16700Schasinglulu if (!req_state) 836*91f16700Schasinglulu return -EINVAL; 837*91f16700Schasinglulu 838*91f16700Schasinglulu ret = ti_sci_clock_get_state(dev_id, clk_id, &state, NULL); 839*91f16700Schasinglulu if (ret) 840*91f16700Schasinglulu return ret; 841*91f16700Schasinglulu 842*91f16700Schasinglulu *req_state = (state == MSG_CLOCK_SW_STATE_AUTO); 843*91f16700Schasinglulu 844*91f16700Schasinglulu return 0; 845*91f16700Schasinglulu } 846*91f16700Schasinglulu 847*91f16700Schasinglulu /** 848*91f16700Schasinglulu * ti_sci_clock_is_on() - Is the clock ON 849*91f16700Schasinglulu * 850*91f16700Schasinglulu * @dev_id: Device identifier this request is for 851*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 852*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 853*91f16700Schasinglulu * which clock input to modify. 854*91f16700Schasinglulu * @req_state: state indicating if the clock is managed by us and enabled 855*91f16700Schasinglulu * @curr_state: state indicating if the clock is ready for operation 856*91f16700Schasinglulu * 857*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 858*91f16700Schasinglulu */ 859*91f16700Schasinglulu int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id, 860*91f16700Schasinglulu bool *req_state, bool *curr_state) 861*91f16700Schasinglulu { 862*91f16700Schasinglulu uint8_t c_state = 0, r_state = 0; 863*91f16700Schasinglulu int ret; 864*91f16700Schasinglulu 865*91f16700Schasinglulu if (!req_state && !curr_state) 866*91f16700Schasinglulu return -EINVAL; 867*91f16700Schasinglulu 868*91f16700Schasinglulu ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state); 869*91f16700Schasinglulu if (ret) 870*91f16700Schasinglulu return ret; 871*91f16700Schasinglulu 872*91f16700Schasinglulu if (req_state) 873*91f16700Schasinglulu *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ); 874*91f16700Schasinglulu if (curr_state) 875*91f16700Schasinglulu *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY); 876*91f16700Schasinglulu 877*91f16700Schasinglulu return 0; 878*91f16700Schasinglulu } 879*91f16700Schasinglulu 880*91f16700Schasinglulu /** 881*91f16700Schasinglulu * ti_sci_clock_is_off() - Is the clock OFF 882*91f16700Schasinglulu * 883*91f16700Schasinglulu * @dev_id: Device identifier this request is for 884*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 885*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 886*91f16700Schasinglulu * which clock input to modify. 887*91f16700Schasinglulu * @req_state: state indicating if the clock is managed by us and disabled 888*91f16700Schasinglulu * @curr_state: state indicating if the clock is NOT ready for operation 889*91f16700Schasinglulu * 890*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 891*91f16700Schasinglulu */ 892*91f16700Schasinglulu int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id, 893*91f16700Schasinglulu bool *req_state, bool *curr_state) 894*91f16700Schasinglulu { 895*91f16700Schasinglulu uint8_t c_state = 0, r_state = 0; 896*91f16700Schasinglulu int ret; 897*91f16700Schasinglulu 898*91f16700Schasinglulu if (!req_state && !curr_state) 899*91f16700Schasinglulu return -EINVAL; 900*91f16700Schasinglulu 901*91f16700Schasinglulu ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state); 902*91f16700Schasinglulu if (ret) 903*91f16700Schasinglulu return ret; 904*91f16700Schasinglulu 905*91f16700Schasinglulu if (req_state) 906*91f16700Schasinglulu *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ); 907*91f16700Schasinglulu if (curr_state) 908*91f16700Schasinglulu *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY); 909*91f16700Schasinglulu 910*91f16700Schasinglulu return 0; 911*91f16700Schasinglulu } 912*91f16700Schasinglulu 913*91f16700Schasinglulu /** 914*91f16700Schasinglulu * ti_sci_clock_set_parent() - Set the clock source of a specific device clock 915*91f16700Schasinglulu * 916*91f16700Schasinglulu * @dev_id: Device identifier this request is for 917*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 918*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 919*91f16700Schasinglulu * which clock input to modify. 920*91f16700Schasinglulu * @parent_id: Parent clock identifier to set 921*91f16700Schasinglulu * 922*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 923*91f16700Schasinglulu */ 924*91f16700Schasinglulu int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, uint8_t parent_id) 925*91f16700Schasinglulu { 926*91f16700Schasinglulu struct ti_sci_msg_req_set_clock_parent req; 927*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 928*91f16700Schasinglulu 929*91f16700Schasinglulu struct ti_sci_xfer xfer; 930*91f16700Schasinglulu int ret; 931*91f16700Schasinglulu 932*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_PARENT, 0, 933*91f16700Schasinglulu &req, sizeof(req), 934*91f16700Schasinglulu &resp, sizeof(resp), 935*91f16700Schasinglulu &xfer); 936*91f16700Schasinglulu if (ret) { 937*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 938*91f16700Schasinglulu return ret; 939*91f16700Schasinglulu } 940*91f16700Schasinglulu 941*91f16700Schasinglulu req.dev_id = dev_id; 942*91f16700Schasinglulu req.clk_id = clk_id; 943*91f16700Schasinglulu req.parent_id = parent_id; 944*91f16700Schasinglulu 945*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 946*91f16700Schasinglulu if (ret) { 947*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 948*91f16700Schasinglulu return ret; 949*91f16700Schasinglulu } 950*91f16700Schasinglulu 951*91f16700Schasinglulu return 0; 952*91f16700Schasinglulu } 953*91f16700Schasinglulu 954*91f16700Schasinglulu /** 955*91f16700Schasinglulu * ti_sci_clock_get_parent() - Get current parent clock source 956*91f16700Schasinglulu * 957*91f16700Schasinglulu * @dev_id: Device identifier this request is for 958*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 959*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 960*91f16700Schasinglulu * which clock input to modify. 961*91f16700Schasinglulu * @parent_id: Current clock parent 962*91f16700Schasinglulu * 963*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 964*91f16700Schasinglulu */ 965*91f16700Schasinglulu int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, uint8_t *parent_id) 966*91f16700Schasinglulu { 967*91f16700Schasinglulu struct ti_sci_msg_req_get_clock_parent req; 968*91f16700Schasinglulu struct ti_sci_msg_resp_get_clock_parent resp; 969*91f16700Schasinglulu 970*91f16700Schasinglulu struct ti_sci_xfer xfer; 971*91f16700Schasinglulu int ret; 972*91f16700Schasinglulu 973*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_PARENT, 0, 974*91f16700Schasinglulu &req, sizeof(req), 975*91f16700Schasinglulu &resp, sizeof(resp), 976*91f16700Schasinglulu &xfer); 977*91f16700Schasinglulu if (ret) { 978*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 979*91f16700Schasinglulu return ret; 980*91f16700Schasinglulu } 981*91f16700Schasinglulu 982*91f16700Schasinglulu req.dev_id = dev_id; 983*91f16700Schasinglulu req.clk_id = clk_id; 984*91f16700Schasinglulu 985*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 986*91f16700Schasinglulu if (ret) { 987*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 988*91f16700Schasinglulu return ret; 989*91f16700Schasinglulu } 990*91f16700Schasinglulu 991*91f16700Schasinglulu *parent_id = resp.parent_id; 992*91f16700Schasinglulu 993*91f16700Schasinglulu return 0; 994*91f16700Schasinglulu } 995*91f16700Schasinglulu 996*91f16700Schasinglulu /** 997*91f16700Schasinglulu * ti_sci_clock_get_num_parents() - Get num parents of the current clk source 998*91f16700Schasinglulu * 999*91f16700Schasinglulu * @dev_id: Device identifier this request is for 1000*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 1001*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 1002*91f16700Schasinglulu * which clock input to modify. 1003*91f16700Schasinglulu * @num_parents: Returns he number of parents to the current clock. 1004*91f16700Schasinglulu * 1005*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1006*91f16700Schasinglulu */ 1007*91f16700Schasinglulu int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id, 1008*91f16700Schasinglulu uint8_t *num_parents) 1009*91f16700Schasinglulu { 1010*91f16700Schasinglulu struct ti_sci_msg_req_get_clock_num_parents req; 1011*91f16700Schasinglulu struct ti_sci_msg_resp_get_clock_num_parents resp; 1012*91f16700Schasinglulu 1013*91f16700Schasinglulu struct ti_sci_xfer xfer; 1014*91f16700Schasinglulu int ret; 1015*91f16700Schasinglulu 1016*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, 0, 1017*91f16700Schasinglulu &req, sizeof(req), 1018*91f16700Schasinglulu &resp, sizeof(resp), 1019*91f16700Schasinglulu &xfer); 1020*91f16700Schasinglulu if (ret) { 1021*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1022*91f16700Schasinglulu return ret; 1023*91f16700Schasinglulu } 1024*91f16700Schasinglulu 1025*91f16700Schasinglulu req.dev_id = dev_id; 1026*91f16700Schasinglulu req.clk_id = clk_id; 1027*91f16700Schasinglulu 1028*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1029*91f16700Schasinglulu if (ret) { 1030*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1031*91f16700Schasinglulu return ret; 1032*91f16700Schasinglulu } 1033*91f16700Schasinglulu 1034*91f16700Schasinglulu *num_parents = resp.num_parents; 1035*91f16700Schasinglulu 1036*91f16700Schasinglulu return 0; 1037*91f16700Schasinglulu } 1038*91f16700Schasinglulu 1039*91f16700Schasinglulu /** 1040*91f16700Schasinglulu * ti_sci_clock_get_match_freq() - Find a good match for frequency 1041*91f16700Schasinglulu * 1042*91f16700Schasinglulu * @dev_id: Device identifier this request is for 1043*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 1044*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 1045*91f16700Schasinglulu * which clock input to modify. 1046*91f16700Schasinglulu * @min_freq: The minimum allowable frequency in Hz. This is the minimum 1047*91f16700Schasinglulu * allowable programmed frequency and does not account for clock 1048*91f16700Schasinglulu * tolerances and jitter. 1049*91f16700Schasinglulu * @target_freq: The target clock frequency in Hz. A frequency will be 1050*91f16700Schasinglulu * processed as close to this target frequency as possible. 1051*91f16700Schasinglulu * @max_freq: The maximum allowable frequency in Hz. This is the maximum 1052*91f16700Schasinglulu * allowable programmed frequency and does not account for clock 1053*91f16700Schasinglulu * tolerances and jitter. 1054*91f16700Schasinglulu * @match_freq: Frequency match in Hz response. 1055*91f16700Schasinglulu * 1056*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1057*91f16700Schasinglulu */ 1058*91f16700Schasinglulu int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id, 1059*91f16700Schasinglulu uint64_t min_freq, uint64_t target_freq, 1060*91f16700Schasinglulu uint64_t max_freq, uint64_t *match_freq) 1061*91f16700Schasinglulu { 1062*91f16700Schasinglulu struct ti_sci_msg_req_query_clock_freq req; 1063*91f16700Schasinglulu struct ti_sci_msg_resp_query_clock_freq resp; 1064*91f16700Schasinglulu 1065*91f16700Schasinglulu struct ti_sci_xfer xfer; 1066*91f16700Schasinglulu int ret; 1067*91f16700Schasinglulu 1068*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_CLOCK_FREQ, 0, 1069*91f16700Schasinglulu &req, sizeof(req), 1070*91f16700Schasinglulu &resp, sizeof(resp), 1071*91f16700Schasinglulu &xfer); 1072*91f16700Schasinglulu if (ret) { 1073*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1074*91f16700Schasinglulu return ret; 1075*91f16700Schasinglulu } 1076*91f16700Schasinglulu 1077*91f16700Schasinglulu req.dev_id = dev_id; 1078*91f16700Schasinglulu req.clk_id = clk_id; 1079*91f16700Schasinglulu req.min_freq_hz = min_freq; 1080*91f16700Schasinglulu req.target_freq_hz = target_freq; 1081*91f16700Schasinglulu req.max_freq_hz = max_freq; 1082*91f16700Schasinglulu 1083*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1084*91f16700Schasinglulu if (ret) { 1085*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1086*91f16700Schasinglulu return ret; 1087*91f16700Schasinglulu } 1088*91f16700Schasinglulu 1089*91f16700Schasinglulu *match_freq = resp.freq_hz; 1090*91f16700Schasinglulu 1091*91f16700Schasinglulu return 0; 1092*91f16700Schasinglulu } 1093*91f16700Schasinglulu 1094*91f16700Schasinglulu /** 1095*91f16700Schasinglulu * ti_sci_clock_set_freq() - Set a frequency for clock 1096*91f16700Schasinglulu * 1097*91f16700Schasinglulu * @dev_id: Device identifier this request is for 1098*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 1099*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 1100*91f16700Schasinglulu * which clock input to modify. 1101*91f16700Schasinglulu * @min_freq: The minimum allowable frequency in Hz. This is the minimum 1102*91f16700Schasinglulu * allowable programmed frequency and does not account for clock 1103*91f16700Schasinglulu * tolerances and jitter. 1104*91f16700Schasinglulu * @target_freq: The target clock frequency in Hz. A frequency will be 1105*91f16700Schasinglulu * processed as close to this target frequency as possible. 1106*91f16700Schasinglulu * @max_freq: The maximum allowable frequency in Hz. This is the maximum 1107*91f16700Schasinglulu * allowable programmed frequency and does not account for clock 1108*91f16700Schasinglulu * tolerances and jitter. 1109*91f16700Schasinglulu * 1110*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1111*91f16700Schasinglulu */ 1112*91f16700Schasinglulu int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, uint64_t min_freq, 1113*91f16700Schasinglulu uint64_t target_freq, uint64_t max_freq) 1114*91f16700Schasinglulu { 1115*91f16700Schasinglulu struct ti_sci_msg_req_set_clock_freq req; 1116*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 1117*91f16700Schasinglulu 1118*91f16700Schasinglulu struct ti_sci_xfer xfer; 1119*91f16700Schasinglulu int ret; 1120*91f16700Schasinglulu 1121*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_FREQ, 0, 1122*91f16700Schasinglulu &req, sizeof(req), 1123*91f16700Schasinglulu &resp, sizeof(resp), 1124*91f16700Schasinglulu &xfer); 1125*91f16700Schasinglulu if (ret) { 1126*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1127*91f16700Schasinglulu return ret; 1128*91f16700Schasinglulu } 1129*91f16700Schasinglulu req.dev_id = dev_id; 1130*91f16700Schasinglulu req.clk_id = clk_id; 1131*91f16700Schasinglulu req.min_freq_hz = min_freq; 1132*91f16700Schasinglulu req.target_freq_hz = target_freq; 1133*91f16700Schasinglulu req.max_freq_hz = max_freq; 1134*91f16700Schasinglulu 1135*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1136*91f16700Schasinglulu if (ret) { 1137*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1138*91f16700Schasinglulu return ret; 1139*91f16700Schasinglulu } 1140*91f16700Schasinglulu 1141*91f16700Schasinglulu return 0; 1142*91f16700Schasinglulu } 1143*91f16700Schasinglulu 1144*91f16700Schasinglulu /** 1145*91f16700Schasinglulu * ti_sci_clock_get_freq() - Get current frequency 1146*91f16700Schasinglulu * 1147*91f16700Schasinglulu * @dev_id: Device identifier this request is for 1148*91f16700Schasinglulu * @clk_id: Clock identifier for the device for this request. 1149*91f16700Schasinglulu * Each device has its own set of clock inputs. This indexes 1150*91f16700Schasinglulu * which clock input to modify. 1151*91f16700Schasinglulu * @freq: Currently frequency in Hz 1152*91f16700Schasinglulu * 1153*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1154*91f16700Schasinglulu */ 1155*91f16700Schasinglulu int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq) 1156*91f16700Schasinglulu { 1157*91f16700Schasinglulu struct ti_sci_msg_req_get_clock_freq req; 1158*91f16700Schasinglulu struct ti_sci_msg_resp_get_clock_freq resp; 1159*91f16700Schasinglulu 1160*91f16700Schasinglulu struct ti_sci_xfer xfer; 1161*91f16700Schasinglulu int ret; 1162*91f16700Schasinglulu 1163*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_FREQ, 0, 1164*91f16700Schasinglulu &req, sizeof(req), 1165*91f16700Schasinglulu &resp, sizeof(resp), 1166*91f16700Schasinglulu &xfer); 1167*91f16700Schasinglulu if (ret) { 1168*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1169*91f16700Schasinglulu return ret; 1170*91f16700Schasinglulu } 1171*91f16700Schasinglulu 1172*91f16700Schasinglulu req.dev_id = dev_id; 1173*91f16700Schasinglulu req.clk_id = clk_id; 1174*91f16700Schasinglulu 1175*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1176*91f16700Schasinglulu if (ret) { 1177*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1178*91f16700Schasinglulu return ret; 1179*91f16700Schasinglulu } 1180*91f16700Schasinglulu 1181*91f16700Schasinglulu *freq = resp.freq_hz; 1182*91f16700Schasinglulu 1183*91f16700Schasinglulu return 0; 1184*91f16700Schasinglulu } 1185*91f16700Schasinglulu 1186*91f16700Schasinglulu /** 1187*91f16700Schasinglulu * ti_sci_core_reboot() - Command to request system reset 1188*91f16700Schasinglulu * 1189*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1190*91f16700Schasinglulu */ 1191*91f16700Schasinglulu int ti_sci_core_reboot(void) 1192*91f16700Schasinglulu { 1193*91f16700Schasinglulu struct ti_sci_msg_req_reboot req; 1194*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 1195*91f16700Schasinglulu 1196*91f16700Schasinglulu struct ti_sci_xfer xfer; 1197*91f16700Schasinglulu int ret; 1198*91f16700Schasinglulu 1199*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SYS_RESET, 0, 1200*91f16700Schasinglulu &req, sizeof(req), 1201*91f16700Schasinglulu &resp, sizeof(resp), 1202*91f16700Schasinglulu &xfer); 1203*91f16700Schasinglulu if (ret) { 1204*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1205*91f16700Schasinglulu return ret; 1206*91f16700Schasinglulu } 1207*91f16700Schasinglulu req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET; 1208*91f16700Schasinglulu 1209*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1210*91f16700Schasinglulu if (ret) { 1211*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1212*91f16700Schasinglulu return ret; 1213*91f16700Schasinglulu } 1214*91f16700Schasinglulu 1215*91f16700Schasinglulu return 0; 1216*91f16700Schasinglulu } 1217*91f16700Schasinglulu 1218*91f16700Schasinglulu /** 1219*91f16700Schasinglulu * ti_sci_proc_request() - Request a physical processor control 1220*91f16700Schasinglulu * 1221*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1222*91f16700Schasinglulu * 1223*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1224*91f16700Schasinglulu */ 1225*91f16700Schasinglulu int ti_sci_proc_request(uint8_t proc_id) 1226*91f16700Schasinglulu { 1227*91f16700Schasinglulu struct ti_sci_msg_req_proc_request req; 1228*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 1229*91f16700Schasinglulu 1230*91f16700Schasinglulu struct ti_sci_xfer xfer; 1231*91f16700Schasinglulu int ret; 1232*91f16700Schasinglulu 1233*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST, 0, 1234*91f16700Schasinglulu &req, sizeof(req), 1235*91f16700Schasinglulu &resp, sizeof(resp), 1236*91f16700Schasinglulu &xfer); 1237*91f16700Schasinglulu if (ret) { 1238*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1239*91f16700Schasinglulu return ret; 1240*91f16700Schasinglulu } 1241*91f16700Schasinglulu 1242*91f16700Schasinglulu req.processor_id = proc_id; 1243*91f16700Schasinglulu 1244*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1245*91f16700Schasinglulu if (ret) { 1246*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1247*91f16700Schasinglulu return ret; 1248*91f16700Schasinglulu } 1249*91f16700Schasinglulu 1250*91f16700Schasinglulu return 0; 1251*91f16700Schasinglulu } 1252*91f16700Schasinglulu 1253*91f16700Schasinglulu /** 1254*91f16700Schasinglulu * ti_sci_proc_release() - Release a physical processor control 1255*91f16700Schasinglulu * 1256*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1257*91f16700Schasinglulu * 1258*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1259*91f16700Schasinglulu */ 1260*91f16700Schasinglulu int ti_sci_proc_release(uint8_t proc_id) 1261*91f16700Schasinglulu { 1262*91f16700Schasinglulu struct ti_sci_msg_req_proc_release req; 1263*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 1264*91f16700Schasinglulu 1265*91f16700Schasinglulu struct ti_sci_xfer xfer; 1266*91f16700Schasinglulu int ret; 1267*91f16700Schasinglulu 1268*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE, 0, 1269*91f16700Schasinglulu &req, sizeof(req), 1270*91f16700Schasinglulu &resp, sizeof(resp), 1271*91f16700Schasinglulu &xfer); 1272*91f16700Schasinglulu if (ret) { 1273*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1274*91f16700Schasinglulu return ret; 1275*91f16700Schasinglulu } 1276*91f16700Schasinglulu 1277*91f16700Schasinglulu req.processor_id = proc_id; 1278*91f16700Schasinglulu 1279*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1280*91f16700Schasinglulu if (ret) { 1281*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1282*91f16700Schasinglulu return ret; 1283*91f16700Schasinglulu } 1284*91f16700Schasinglulu 1285*91f16700Schasinglulu return 0; 1286*91f16700Schasinglulu } 1287*91f16700Schasinglulu 1288*91f16700Schasinglulu /** 1289*91f16700Schasinglulu * ti_sci_proc_handover() - Handover a physical processor control to a host in 1290*91f16700Schasinglulu * the processor's access control list. 1291*91f16700Schasinglulu * 1292*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1293*91f16700Schasinglulu * @host_id: Host ID to get the control of the processor 1294*91f16700Schasinglulu * 1295*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1296*91f16700Schasinglulu */ 1297*91f16700Schasinglulu int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id) 1298*91f16700Schasinglulu { 1299*91f16700Schasinglulu struct ti_sci_msg_req_proc_handover req; 1300*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 1301*91f16700Schasinglulu 1302*91f16700Schasinglulu struct ti_sci_xfer xfer; 1303*91f16700Schasinglulu int ret; 1304*91f16700Schasinglulu 1305*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER, 0, 1306*91f16700Schasinglulu &req, sizeof(req), 1307*91f16700Schasinglulu &resp, sizeof(resp), 1308*91f16700Schasinglulu &xfer); 1309*91f16700Schasinglulu if (ret) { 1310*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1311*91f16700Schasinglulu return ret; 1312*91f16700Schasinglulu } 1313*91f16700Schasinglulu 1314*91f16700Schasinglulu req.processor_id = proc_id; 1315*91f16700Schasinglulu req.host_id = host_id; 1316*91f16700Schasinglulu 1317*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1318*91f16700Schasinglulu if (ret) { 1319*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1320*91f16700Schasinglulu return ret; 1321*91f16700Schasinglulu } 1322*91f16700Schasinglulu 1323*91f16700Schasinglulu return 0; 1324*91f16700Schasinglulu } 1325*91f16700Schasinglulu 1326*91f16700Schasinglulu /** 1327*91f16700Schasinglulu * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags 1328*91f16700Schasinglulu * 1329*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1330*91f16700Schasinglulu * @config_flags_set: Configuration flags to be set 1331*91f16700Schasinglulu * @config_flags_clear: Configuration flags to be cleared 1332*91f16700Schasinglulu * 1333*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1334*91f16700Schasinglulu */ 1335*91f16700Schasinglulu int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector, 1336*91f16700Schasinglulu uint32_t config_flags_set, 1337*91f16700Schasinglulu uint32_t config_flags_clear) 1338*91f16700Schasinglulu { 1339*91f16700Schasinglulu struct ti_sci_msg_req_set_proc_boot_config req; 1340*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 1341*91f16700Schasinglulu 1342*91f16700Schasinglulu struct ti_sci_xfer xfer; 1343*91f16700Schasinglulu int ret; 1344*91f16700Schasinglulu 1345*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG, 0, 1346*91f16700Schasinglulu &req, sizeof(req), 1347*91f16700Schasinglulu &resp, sizeof(resp), 1348*91f16700Schasinglulu &xfer); 1349*91f16700Schasinglulu if (ret) { 1350*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1351*91f16700Schasinglulu return ret; 1352*91f16700Schasinglulu } 1353*91f16700Schasinglulu 1354*91f16700Schasinglulu req.processor_id = proc_id; 1355*91f16700Schasinglulu req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK; 1356*91f16700Schasinglulu req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >> 1357*91f16700Schasinglulu TISCI_ADDR_HIGH_SHIFT; 1358*91f16700Schasinglulu req.config_flags_set = config_flags_set; 1359*91f16700Schasinglulu req.config_flags_clear = config_flags_clear; 1360*91f16700Schasinglulu 1361*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1362*91f16700Schasinglulu if (ret) { 1363*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1364*91f16700Schasinglulu return ret; 1365*91f16700Schasinglulu } 1366*91f16700Schasinglulu 1367*91f16700Schasinglulu return 0; 1368*91f16700Schasinglulu } 1369*91f16700Schasinglulu 1370*91f16700Schasinglulu /** 1371*91f16700Schasinglulu * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags 1372*91f16700Schasinglulu * 1373*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1374*91f16700Schasinglulu * @control_flags_set: Control flags to be set 1375*91f16700Schasinglulu * @control_flags_clear: Control flags to be cleared 1376*91f16700Schasinglulu * 1377*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1378*91f16700Schasinglulu */ 1379*91f16700Schasinglulu int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set, 1380*91f16700Schasinglulu uint32_t control_flags_clear) 1381*91f16700Schasinglulu { 1382*91f16700Schasinglulu struct ti_sci_msg_req_set_proc_boot_ctrl req; 1383*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 1384*91f16700Schasinglulu 1385*91f16700Schasinglulu struct ti_sci_xfer xfer; 1386*91f16700Schasinglulu int ret; 1387*91f16700Schasinglulu 1388*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0, 1389*91f16700Schasinglulu &req, sizeof(req), 1390*91f16700Schasinglulu &resp, sizeof(resp), 1391*91f16700Schasinglulu &xfer); 1392*91f16700Schasinglulu if (ret) { 1393*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1394*91f16700Schasinglulu return ret; 1395*91f16700Schasinglulu } 1396*91f16700Schasinglulu 1397*91f16700Schasinglulu req.processor_id = proc_id; 1398*91f16700Schasinglulu req.control_flags_set = control_flags_set; 1399*91f16700Schasinglulu req.control_flags_clear = control_flags_clear; 1400*91f16700Schasinglulu 1401*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1402*91f16700Schasinglulu if (ret) { 1403*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1404*91f16700Schasinglulu return ret; 1405*91f16700Schasinglulu } 1406*91f16700Schasinglulu 1407*91f16700Schasinglulu return 0; 1408*91f16700Schasinglulu } 1409*91f16700Schasinglulu 1410*91f16700Schasinglulu /** 1411*91f16700Schasinglulu * ti_sci_proc_set_boot_ctrl_no_wait() - Set the processor boot control flags 1412*91f16700Schasinglulu * without requesting or waiting for a 1413*91f16700Schasinglulu * response. 1414*91f16700Schasinglulu * 1415*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1416*91f16700Schasinglulu * @control_flags_set: Control flags to be set 1417*91f16700Schasinglulu * @control_flags_clear: Control flags to be cleared 1418*91f16700Schasinglulu * 1419*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1420*91f16700Schasinglulu */ 1421*91f16700Schasinglulu int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id, 1422*91f16700Schasinglulu uint32_t control_flags_set, 1423*91f16700Schasinglulu uint32_t control_flags_clear) 1424*91f16700Schasinglulu { 1425*91f16700Schasinglulu struct ti_sci_msg_req_set_proc_boot_ctrl req; 1426*91f16700Schasinglulu struct ti_sci_xfer xfer; 1427*91f16700Schasinglulu int ret; 1428*91f16700Schasinglulu 1429*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0, 1430*91f16700Schasinglulu &req, sizeof(req), 1431*91f16700Schasinglulu NULL, 0, 1432*91f16700Schasinglulu &xfer); 1433*91f16700Schasinglulu if (ret != 0U) { 1434*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1435*91f16700Schasinglulu return ret; 1436*91f16700Schasinglulu } 1437*91f16700Schasinglulu 1438*91f16700Schasinglulu req.processor_id = proc_id; 1439*91f16700Schasinglulu req.control_flags_set = control_flags_set; 1440*91f16700Schasinglulu req.control_flags_clear = control_flags_clear; 1441*91f16700Schasinglulu 1442*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1443*91f16700Schasinglulu if (ret != 0U) { 1444*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1445*91f16700Schasinglulu return ret; 1446*91f16700Schasinglulu } 1447*91f16700Schasinglulu 1448*91f16700Schasinglulu return 0; 1449*91f16700Schasinglulu } 1450*91f16700Schasinglulu 1451*91f16700Schasinglulu /** 1452*91f16700Schasinglulu * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the 1453*91f16700Schasinglulu * processor configuration flags 1454*91f16700Schasinglulu * 1455*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1456*91f16700Schasinglulu * @cert_addr: Memory address at which payload image certificate is located 1457*91f16700Schasinglulu * 1458*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1459*91f16700Schasinglulu */ 1460*91f16700Schasinglulu int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr) 1461*91f16700Schasinglulu { 1462*91f16700Schasinglulu struct ti_sci_msg_req_proc_auth_boot_image req; 1463*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 1464*91f16700Schasinglulu 1465*91f16700Schasinglulu struct ti_sci_xfer xfer; 1466*91f16700Schasinglulu int ret; 1467*91f16700Schasinglulu 1468*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMAGE, 0, 1469*91f16700Schasinglulu &req, sizeof(req), 1470*91f16700Schasinglulu &resp, sizeof(resp), 1471*91f16700Schasinglulu &xfer); 1472*91f16700Schasinglulu if (ret) { 1473*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1474*91f16700Schasinglulu return ret; 1475*91f16700Schasinglulu } 1476*91f16700Schasinglulu 1477*91f16700Schasinglulu req.processor_id = proc_id; 1478*91f16700Schasinglulu req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK; 1479*91f16700Schasinglulu req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >> 1480*91f16700Schasinglulu TISCI_ADDR_HIGH_SHIFT; 1481*91f16700Schasinglulu 1482*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1483*91f16700Schasinglulu if (ret) { 1484*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1485*91f16700Schasinglulu return ret; 1486*91f16700Schasinglulu } 1487*91f16700Schasinglulu 1488*91f16700Schasinglulu return 0; 1489*91f16700Schasinglulu } 1490*91f16700Schasinglulu 1491*91f16700Schasinglulu /** 1492*91f16700Schasinglulu * ti_sci_proc_get_boot_status() - Get the processor boot status 1493*91f16700Schasinglulu * 1494*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1495*91f16700Schasinglulu * 1496*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1497*91f16700Schasinglulu */ 1498*91f16700Schasinglulu int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv, 1499*91f16700Schasinglulu uint32_t *cfg_flags, 1500*91f16700Schasinglulu uint32_t *ctrl_flags, 1501*91f16700Schasinglulu uint32_t *sts_flags) 1502*91f16700Schasinglulu { 1503*91f16700Schasinglulu struct ti_sci_msg_req_get_proc_boot_status req; 1504*91f16700Schasinglulu struct ti_sci_msg_resp_get_proc_boot_status resp; 1505*91f16700Schasinglulu 1506*91f16700Schasinglulu struct ti_sci_xfer xfer; 1507*91f16700Schasinglulu int ret; 1508*91f16700Schasinglulu 1509*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS, 0, 1510*91f16700Schasinglulu &req, sizeof(req), 1511*91f16700Schasinglulu &resp, sizeof(resp), 1512*91f16700Schasinglulu &xfer); 1513*91f16700Schasinglulu if (ret) { 1514*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1515*91f16700Schasinglulu return ret; 1516*91f16700Schasinglulu } 1517*91f16700Schasinglulu 1518*91f16700Schasinglulu req.processor_id = proc_id; 1519*91f16700Schasinglulu 1520*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1521*91f16700Schasinglulu if (ret) { 1522*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1523*91f16700Schasinglulu return ret; 1524*91f16700Schasinglulu } 1525*91f16700Schasinglulu 1526*91f16700Schasinglulu *bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) | 1527*91f16700Schasinglulu (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) & 1528*91f16700Schasinglulu TISCI_ADDR_HIGH_MASK); 1529*91f16700Schasinglulu *cfg_flags = resp.config_flags; 1530*91f16700Schasinglulu *ctrl_flags = resp.control_flags; 1531*91f16700Schasinglulu *sts_flags = resp.status_flags; 1532*91f16700Schasinglulu 1533*91f16700Schasinglulu return 0; 1534*91f16700Schasinglulu } 1535*91f16700Schasinglulu 1536*91f16700Schasinglulu /** 1537*91f16700Schasinglulu * ti_sci_proc_wait_boot_status() - Wait for a processor boot status 1538*91f16700Schasinglulu * 1539*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1540*91f16700Schasinglulu * @num_wait_iterations Total number of iterations we will check before 1541*91f16700Schasinglulu * we will timeout and give up 1542*91f16700Schasinglulu * @num_match_iterations How many iterations should we have continued 1543*91f16700Schasinglulu * status to account for status bits glitching. 1544*91f16700Schasinglulu * This is to make sure that match occurs for 1545*91f16700Schasinglulu * consecutive checks. This implies that the 1546*91f16700Schasinglulu * worst case should consider that the stable 1547*91f16700Schasinglulu * time should at the worst be num_wait_iterations 1548*91f16700Schasinglulu * num_match_iterations to prevent timeout. 1549*91f16700Schasinglulu * @delay_per_iteration_us Specifies how long to wait (in micro seconds) 1550*91f16700Schasinglulu * between each status checks. This is the minimum 1551*91f16700Schasinglulu * duration, and overhead of register reads and 1552*91f16700Schasinglulu * checks are on top of this and can vary based on 1553*91f16700Schasinglulu * varied conditions. 1554*91f16700Schasinglulu * @delay_before_iterations_us Specifies how long to wait (in micro seconds) 1555*91f16700Schasinglulu * before the very first check in the first 1556*91f16700Schasinglulu * iteration of status check loop. This is the 1557*91f16700Schasinglulu * minimum duration, and overhead of register 1558*91f16700Schasinglulu * reads and checks are. 1559*91f16700Schasinglulu * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the 1560*91f16700Schasinglulu * status matching this field requested MUST be 1. 1561*91f16700Schasinglulu * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the 1562*91f16700Schasinglulu * bits matching this field requested MUST be 1. 1563*91f16700Schasinglulu * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the 1564*91f16700Schasinglulu * status matching this field requested MUST be 0. 1565*91f16700Schasinglulu * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the 1566*91f16700Schasinglulu * bits matching this field requested MUST be 0. 1567*91f16700Schasinglulu * 1568*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1569*91f16700Schasinglulu */ 1570*91f16700Schasinglulu int ti_sci_proc_wait_boot_status(uint8_t proc_id, uint8_t num_wait_iterations, 1571*91f16700Schasinglulu uint8_t num_match_iterations, 1572*91f16700Schasinglulu uint8_t delay_per_iteration_us, 1573*91f16700Schasinglulu uint8_t delay_before_iterations_us, 1574*91f16700Schasinglulu uint32_t status_flags_1_set_all_wait, 1575*91f16700Schasinglulu uint32_t status_flags_1_set_any_wait, 1576*91f16700Schasinglulu uint32_t status_flags_1_clr_all_wait, 1577*91f16700Schasinglulu uint32_t status_flags_1_clr_any_wait) 1578*91f16700Schasinglulu { 1579*91f16700Schasinglulu struct ti_sci_msg_req_wait_proc_boot_status req; 1580*91f16700Schasinglulu struct ti_sci_msg_hdr resp; 1581*91f16700Schasinglulu 1582*91f16700Schasinglulu struct ti_sci_xfer xfer; 1583*91f16700Schasinglulu int ret; 1584*91f16700Schasinglulu 1585*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0, 1586*91f16700Schasinglulu &req, sizeof(req), 1587*91f16700Schasinglulu &resp, sizeof(resp), 1588*91f16700Schasinglulu &xfer); 1589*91f16700Schasinglulu if (ret) { 1590*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1591*91f16700Schasinglulu return ret; 1592*91f16700Schasinglulu } 1593*91f16700Schasinglulu 1594*91f16700Schasinglulu req.processor_id = proc_id; 1595*91f16700Schasinglulu req.num_wait_iterations = num_wait_iterations; 1596*91f16700Schasinglulu req.num_match_iterations = num_match_iterations; 1597*91f16700Schasinglulu req.delay_per_iteration_us = delay_per_iteration_us; 1598*91f16700Schasinglulu req.delay_before_iterations_us = delay_before_iterations_us; 1599*91f16700Schasinglulu req.status_flags_1_set_all_wait = status_flags_1_set_all_wait; 1600*91f16700Schasinglulu req.status_flags_1_set_any_wait = status_flags_1_set_any_wait; 1601*91f16700Schasinglulu req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait; 1602*91f16700Schasinglulu req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait; 1603*91f16700Schasinglulu 1604*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1605*91f16700Schasinglulu if (ret) { 1606*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1607*91f16700Schasinglulu return ret; 1608*91f16700Schasinglulu } 1609*91f16700Schasinglulu 1610*91f16700Schasinglulu return 0; 1611*91f16700Schasinglulu } 1612*91f16700Schasinglulu 1613*91f16700Schasinglulu /** 1614*91f16700Schasinglulu * ti_sci_proc_wait_boot_status_no_wait() - Wait for a processor boot status 1615*91f16700Schasinglulu * without requesting or waiting for 1616*91f16700Schasinglulu * a response. 1617*91f16700Schasinglulu * 1618*91f16700Schasinglulu * @proc_id: Processor ID this request is for 1619*91f16700Schasinglulu * @num_wait_iterations Total number of iterations we will check before 1620*91f16700Schasinglulu * we will timeout and give up 1621*91f16700Schasinglulu * @num_match_iterations How many iterations should we have continued 1622*91f16700Schasinglulu * status to account for status bits glitching. 1623*91f16700Schasinglulu * This is to make sure that match occurs for 1624*91f16700Schasinglulu * consecutive checks. This implies that the 1625*91f16700Schasinglulu * worst case should consider that the stable 1626*91f16700Schasinglulu * time should at the worst be num_wait_iterations 1627*91f16700Schasinglulu * num_match_iterations to prevent timeout. 1628*91f16700Schasinglulu * @delay_per_iteration_us Specifies how long to wait (in micro seconds) 1629*91f16700Schasinglulu * between each status checks. This is the minimum 1630*91f16700Schasinglulu * duration, and overhead of register reads and 1631*91f16700Schasinglulu * checks are on top of this and can vary based on 1632*91f16700Schasinglulu * varied conditions. 1633*91f16700Schasinglulu * @delay_before_iterations_us Specifies how long to wait (in micro seconds) 1634*91f16700Schasinglulu * before the very first check in the first 1635*91f16700Schasinglulu * iteration of status check loop. This is the 1636*91f16700Schasinglulu * minimum duration, and overhead of register 1637*91f16700Schasinglulu * reads and checks are. 1638*91f16700Schasinglulu * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the 1639*91f16700Schasinglulu * status matching this field requested MUST be 1. 1640*91f16700Schasinglulu * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the 1641*91f16700Schasinglulu * bits matching this field requested MUST be 1. 1642*91f16700Schasinglulu * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the 1643*91f16700Schasinglulu * status matching this field requested MUST be 0. 1644*91f16700Schasinglulu * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the 1645*91f16700Schasinglulu * bits matching this field requested MUST be 0. 1646*91f16700Schasinglulu * 1647*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1648*91f16700Schasinglulu */ 1649*91f16700Schasinglulu int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id, 1650*91f16700Schasinglulu uint8_t num_wait_iterations, 1651*91f16700Schasinglulu uint8_t num_match_iterations, 1652*91f16700Schasinglulu uint8_t delay_per_iteration_us, 1653*91f16700Schasinglulu uint8_t delay_before_iterations_us, 1654*91f16700Schasinglulu uint32_t status_flags_1_set_all_wait, 1655*91f16700Schasinglulu uint32_t status_flags_1_set_any_wait, 1656*91f16700Schasinglulu uint32_t status_flags_1_clr_all_wait, 1657*91f16700Schasinglulu uint32_t status_flags_1_clr_any_wait) 1658*91f16700Schasinglulu { 1659*91f16700Schasinglulu struct ti_sci_msg_req_wait_proc_boot_status req; 1660*91f16700Schasinglulu struct ti_sci_xfer xfer; 1661*91f16700Schasinglulu int ret; 1662*91f16700Schasinglulu 1663*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0, 1664*91f16700Schasinglulu &req, sizeof(req), 1665*91f16700Schasinglulu NULL, 0, 1666*91f16700Schasinglulu &xfer); 1667*91f16700Schasinglulu if (ret != 0U) { 1668*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1669*91f16700Schasinglulu return ret; 1670*91f16700Schasinglulu } 1671*91f16700Schasinglulu 1672*91f16700Schasinglulu req.processor_id = proc_id; 1673*91f16700Schasinglulu req.num_wait_iterations = num_wait_iterations; 1674*91f16700Schasinglulu req.num_match_iterations = num_match_iterations; 1675*91f16700Schasinglulu req.delay_per_iteration_us = delay_per_iteration_us; 1676*91f16700Schasinglulu req.delay_before_iterations_us = delay_before_iterations_us; 1677*91f16700Schasinglulu req.status_flags_1_set_all_wait = status_flags_1_set_all_wait; 1678*91f16700Schasinglulu req.status_flags_1_set_any_wait = status_flags_1_set_any_wait; 1679*91f16700Schasinglulu req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait; 1680*91f16700Schasinglulu req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait; 1681*91f16700Schasinglulu 1682*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1683*91f16700Schasinglulu if (ret != 0U) { 1684*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1685*91f16700Schasinglulu return ret; 1686*91f16700Schasinglulu } 1687*91f16700Schasinglulu 1688*91f16700Schasinglulu return 0; 1689*91f16700Schasinglulu } 1690*91f16700Schasinglulu 1691*91f16700Schasinglulu /** 1692*91f16700Schasinglulu * ti_sci_enter_sleep - Command to initiate system transition into suspend. 1693*91f16700Schasinglulu * 1694*91f16700Schasinglulu * @proc_id: Processor ID. 1695*91f16700Schasinglulu * @mode: Low power mode to enter. 1696*91f16700Schasinglulu * @core_resume_addr: Address that core should be 1697*91f16700Schasinglulu * resumed from after low power transition. 1698*91f16700Schasinglulu * 1699*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1700*91f16700Schasinglulu */ 1701*91f16700Schasinglulu int ti_sci_enter_sleep(uint8_t proc_id, 1702*91f16700Schasinglulu uint8_t mode, 1703*91f16700Schasinglulu uint64_t core_resume_addr) 1704*91f16700Schasinglulu { 1705*91f16700Schasinglulu struct ti_sci_msg_req_enter_sleep req; 1706*91f16700Schasinglulu struct ti_sci_xfer xfer; 1707*91f16700Schasinglulu int ret; 1708*91f16700Schasinglulu 1709*91f16700Schasinglulu ret = ti_sci_setup_one_xfer(TI_SCI_MSG_ENTER_SLEEP, 0, 1710*91f16700Schasinglulu &req, sizeof(req), 1711*91f16700Schasinglulu NULL, 0, 1712*91f16700Schasinglulu &xfer); 1713*91f16700Schasinglulu if (ret != 0U) { 1714*91f16700Schasinglulu ERROR("Message alloc failed (%d)\n", ret); 1715*91f16700Schasinglulu return ret; 1716*91f16700Schasinglulu } 1717*91f16700Schasinglulu 1718*91f16700Schasinglulu req.processor_id = proc_id; 1719*91f16700Schasinglulu req.mode = mode; 1720*91f16700Schasinglulu req.core_resume_lo = core_resume_addr & TISCI_ADDR_LOW_MASK; 1721*91f16700Schasinglulu req.core_resume_hi = (core_resume_addr & TISCI_ADDR_HIGH_MASK) >> 1722*91f16700Schasinglulu TISCI_ADDR_HIGH_SHIFT; 1723*91f16700Schasinglulu 1724*91f16700Schasinglulu ret = ti_sci_do_xfer(&xfer); 1725*91f16700Schasinglulu if (ret != 0U) { 1726*91f16700Schasinglulu ERROR("Transfer send failed (%d)\n", ret); 1727*91f16700Schasinglulu return ret; 1728*91f16700Schasinglulu } 1729*91f16700Schasinglulu 1730*91f16700Schasinglulu return 0; 1731*91f16700Schasinglulu } 1732*91f16700Schasinglulu 1733*91f16700Schasinglulu /** 1734*91f16700Schasinglulu * ti_sci_init() - Basic initialization 1735*91f16700Schasinglulu * 1736*91f16700Schasinglulu * Return: 0 if all goes well, else appropriate error message 1737*91f16700Schasinglulu */ 1738*91f16700Schasinglulu int ti_sci_init(void) 1739*91f16700Schasinglulu { 1740*91f16700Schasinglulu struct ti_sci_msg_resp_version rev_info; 1741*91f16700Schasinglulu int ret; 1742*91f16700Schasinglulu 1743*91f16700Schasinglulu ret = ti_sci_get_revision(&rev_info); 1744*91f16700Schasinglulu if (ret) { 1745*91f16700Schasinglulu ERROR("Unable to communicate with control firmware (%d)\n", ret); 1746*91f16700Schasinglulu return ret; 1747*91f16700Schasinglulu } 1748*91f16700Schasinglulu 1749*91f16700Schasinglulu INFO("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n", 1750*91f16700Schasinglulu rev_info.abi_major, rev_info.abi_minor, 1751*91f16700Schasinglulu rev_info.firmware_revision, 1752*91f16700Schasinglulu rev_info.firmware_description); 1753*91f16700Schasinglulu 1754*91f16700Schasinglulu return 0; 1755*91f16700Schasinglulu } 1756