uboot/drivers/firmware/ti_sci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Texas Instruments System Control Interface Protocol Driver
   4 * Based on drivers/firmware/ti_sci.c from Linux.
   5 *
   6 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
   7 *      Lokesh Vutla <lokeshvutla@ti.com>
   8 */
   9
  10#include <common.h>
  11#include <dm.h>
  12#include <errno.h>
  13#include <mailbox.h>
  14#include <dm/device.h>
  15#include <linux/compat.h>
  16#include <linux/err.h>
  17#include <linux/soc/ti/k3-sec-proxy.h>
  18#include <linux/soc/ti/ti_sci_protocol.h>
  19
  20#include "ti_sci.h"
  21
  22/* List of all TI SCI devices active in system */
  23static LIST_HEAD(ti_sci_list);
  24
  25/**
  26 * struct ti_sci_xfer - Structure representing a message flow
  27 * @tx_message: Transmit message
  28 * @rx_len:     Receive message length
  29 */
  30struct ti_sci_xfer {
  31        struct k3_sec_proxy_msg tx_message;
  32        u8 rx_len;
  33};
  34
  35/**
  36 * struct ti_sci_rm_type_map - Structure representing TISCI Resource
  37 *                              management representation of dev_ids.
  38 * @dev_id:     TISCI device ID
  39 * @type:       Corresponding id as identified by TISCI RM.
  40 *
  41 * Note: This is used only as a work around for using RM range apis
  42 *      for AM654 SoC. For future SoCs dev_id will be used as type
  43 *      for RM range APIs. In order to maintain ABI backward compatibility
  44 *      type is not being changed for AM654 SoC.
  45 */
  46struct ti_sci_rm_type_map {
  47        u32 dev_id;
  48        u16 type;
  49};
  50
  51/**
  52 * struct ti_sci_desc - Description of SoC integration
  53 * @default_host_id:    Host identifier representing the compute entity
  54 * @max_rx_timeout_ms:  Timeout for communication with SoC (in Milliseconds)
  55 * @max_msgs: Maximum number of messages that can be pending
  56 *                simultaneously in the system
  57 * @max_msg_size: Maximum size of data per message that can be handled.
  58 * @rm_type_map: RM resource type mapping structure.
  59 */
  60struct ti_sci_desc {
  61        u8 default_host_id;
  62        int max_rx_timeout_ms;
  63        int max_msgs;
  64        int max_msg_size;
  65        struct ti_sci_rm_type_map *rm_type_map;
  66};
  67
  68/**
  69 * struct ti_sci_info - Structure representing a TI SCI instance
  70 * @dev:        Device pointer
  71 * @desc:       SoC description for this instance
  72 * @handle:     Instance of TI SCI handle to send to clients.
  73 * @chan_tx:    Transmit mailbox channel
  74 * @chan_rx:    Receive mailbox channel
  75 * @xfer:       xfer info
  76 * @list:       list head
  77 * @is_secure:  Determines if the communication is through secure threads.
  78 * @host_id:    Host identifier representing the compute entity
  79 * @seq:        Seq id used for verification for tx and rx message.
  80 */
  81struct ti_sci_info {
  82        struct udevice *dev;
  83        const struct ti_sci_desc *desc;
  84        struct ti_sci_handle handle;
  85        struct mbox_chan chan_tx;
  86        struct mbox_chan chan_rx;
  87        struct mbox_chan chan_notify;
  88        struct ti_sci_xfer xfer;
  89        struct list_head list;
  90        struct list_head dev_list;
  91        bool is_secure;
  92        u8 host_id;
  93        u8 seq;
  94};
  95
  96struct ti_sci_exclusive_dev {
  97        u32 id;
  98        u32 count;
  99        struct list_head list;
 100};
 101
 102#define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
 103
 104/**
 105 * ti_sci_setup_one_xfer() - Setup one message type
 106 * @info:       Pointer to SCI entity information
 107 * @msg_type:   Message type
 108 * @msg_flags:  Flag to set for the message
 109 * @buf:        Buffer to be send to mailbox channel
 110 * @tx_message_size: transmit message size
 111 * @rx_message_size: receive message size. may be set to zero for send-only
 112 *                   transactions.
 113 *
 114 * Helper function which is used by various command functions that are
 115 * exposed to clients of this driver for allocating a message traffic event.
 116 *
 117 * Return: Corresponding ti_sci_xfer pointer if all went fine,
 118 *         else appropriate error pointer.
 119 */
 120static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info,
 121                                                 u16 msg_type, u32 msg_flags,
 122                                                 u32 *buf,
 123                                                 size_t tx_message_size,
 124                                                 size_t rx_message_size)
 125{
 126        struct ti_sci_xfer *xfer = &info->xfer;
 127        struct ti_sci_msg_hdr *hdr;
 128
 129        /* Ensure we have sane transfer sizes */
 130        if (rx_message_size > info->desc->max_msg_size ||
 131            tx_message_size > info->desc->max_msg_size ||
 132            (rx_message_size > 0 && rx_message_size < sizeof(*hdr)) ||
 133            tx_message_size < sizeof(*hdr))
 134                return ERR_PTR(-ERANGE);
 135
 136        info->seq = ~info->seq;
 137        xfer->tx_message.buf = buf;
 138        xfer->tx_message.len = tx_message_size;
 139        xfer->rx_len = (u8)rx_message_size;
 140
 141        hdr = (struct ti_sci_msg_hdr *)buf;
 142        hdr->seq = info->seq;
 143        hdr->type = msg_type;
 144        hdr->host = info->host_id;
 145        hdr->flags = msg_flags;
 146
 147        return xfer;
 148}
 149
 150/**
 151 * ti_sci_get_response() - Receive response from mailbox channel
 152 * @info:       Pointer to SCI entity information
 153 * @xfer:       Transfer to initiate and wait for response
 154 * @chan:       Channel to receive the response
 155 *
 156 * Return: -ETIMEDOUT in case of no response, if transmit error,
 157 *         return corresponding error, else if all goes well,
 158 *         return 0.
 159 */
 160static inline int ti_sci_get_response(struct ti_sci_info *info,
 161                                      struct ti_sci_xfer *xfer,
 162                                      struct mbox_chan *chan)
 163{
 164        struct k3_sec_proxy_msg *msg = &xfer->tx_message;
 165        struct ti_sci_secure_msg_hdr *secure_hdr;
 166        struct ti_sci_msg_hdr *hdr;
 167        int ret;
 168
 169        /* Receive the response */
 170        ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_ms * 1000);
 171        if (ret) {
 172                dev_err(info->dev, "%s: Message receive failed. ret = %d\n",
 173                        __func__, ret);
 174                return ret;
 175        }
 176
 177        /* ToDo: Verify checksum */
 178        if (info->is_secure) {
 179                secure_hdr = (struct ti_sci_secure_msg_hdr *)msg->buf;
 180                msg->buf = (u32 *)((void *)msg->buf + sizeof(*secure_hdr));
 181        }
 182
 183        /* msg is updated by mailbox driver */
 184        hdr = (struct ti_sci_msg_hdr *)msg->buf;
 185
 186        /* Sanity check for message response */
 187        if (hdr->seq != info->seq) {
 188                dev_dbg(info->dev, "%s: Message for %d is not expected\n",
 189                        __func__, hdr->seq);
 190                return ret;
 191        }
 192
 193        if (msg->len > info->desc->max_msg_size) {
 194                dev_err(info->dev, "%s: Unable to handle %zu xfer (max %d)\n",
 195                        __func__, msg->len, info->desc->max_msg_size);
 196                return -EINVAL;
 197        }
 198
 199        if (msg->len < xfer->rx_len) {
 200                dev_err(info->dev, "%s: Recv xfer %zu < expected %d length\n",
 201                        __func__, msg->len, xfer->rx_len);
 202        }
 203
 204        return ret;
 205}
 206
 207/**
 208 * ti_sci_do_xfer() - Do one transfer
 209 * @info:       Pointer to SCI entity information
 210 * @xfer:       Transfer to initiate and wait for response
 211 *
 212 * Return: 0 if all went fine, else return appropriate error.
 213 */
 214static inline int ti_sci_do_xfer(struct ti_sci_info *info,
 215                                 struct ti_sci_xfer *xfer)
 216{
 217        struct k3_sec_proxy_msg *msg = &xfer->tx_message;
 218        u8 secure_buf[info->desc->max_msg_size];
 219        struct ti_sci_secure_msg_hdr secure_hdr;
 220        int ret;
 221
 222        if (info->is_secure) {
 223                /* ToDo: get checksum of the entire message */
 224                secure_hdr.checksum = 0;
 225                secure_hdr.reserved = 0;
 226                memcpy(&secure_buf[sizeof(secure_hdr)], xfer->tx_message.buf,
 227                       xfer->tx_message.len);
 228
 229                xfer->tx_message.buf = (u32 *)secure_buf;
 230                xfer->tx_message.len += sizeof(secure_hdr);
 231
 232                if (xfer->rx_len)
 233                        xfer->rx_len += sizeof(secure_hdr);
 234        }
 235
 236        /* Send the message */
 237        ret = mbox_send(&info->chan_tx, msg);
 238        if (ret) {
 239                dev_err(info->dev, "%s: Message sending failed. ret = %d\n",
 240                        __func__, ret);
 241                return ret;
 242        }
 243
 244        /* Get response if requested */
 245        if (xfer->rx_len)
 246                ret = ti_sci_get_response(info, xfer, &info->chan_rx);
 247
 248        return ret;
 249}
 250
 251/**
 252 * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
 253 * @handle:     pointer to TI SCI handle
 254 *
 255 * Updates the SCI information in the internal data structure.
 256 *
 257 * Return: 0 if all went fine, else return appropriate error.
 258 */
 259static int ti_sci_cmd_get_revision(struct ti_sci_handle *handle)
 260{
 261        struct ti_sci_msg_resp_version *rev_info;
 262        struct ti_sci_version_info *ver;
 263        struct ti_sci_msg_hdr hdr;
 264        struct ti_sci_info *info;
 265        struct ti_sci_xfer *xfer;
 266        int ret;
 267
 268        if (IS_ERR(handle))
 269                return PTR_ERR(handle);
 270        if (!handle)
 271                return -EINVAL;
 272
 273        info = handle_to_ti_sci_info(handle);
 274
 275        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION,
 276                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
 277                                     (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr),
 278                                     sizeof(*rev_info));
 279        if (IS_ERR(xfer)) {
 280                ret = PTR_ERR(xfer);
 281                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
 282                return ret;
 283        }
 284
 285        ret = ti_sci_do_xfer(info, xfer);
 286        if (ret) {
 287                dev_err(info->dev, "Mbox communication fail %d\n", ret);
 288                return ret;
 289        }
 290
 291        rev_info = (struct ti_sci_msg_resp_version *)xfer->tx_message.buf;
 292
 293        ver = &handle->version;
 294        ver->abi_major = rev_info->abi_major;
 295        ver->abi_minor = rev_info->abi_minor;
 296        ver->firmware_revision = rev_info->firmware_revision;
 297        strncpy(ver->firmware_description, rev_info->firmware_description,
 298                sizeof(ver->firmware_description));
 299
 300        return 0;
 301}
 302
 303/**
 304 * ti_sci_is_response_ack() - Generic ACK/NACK message checkup
 305 * @r:  pointer to response buffer
 306 *
 307 * Return: true if the response was an ACK, else returns false.
 308 */
 309static inline bool ti_sci_is_response_ack(void *r)
 310{
 311        struct ti_sci_msg_hdr *hdr = r;
 312
 313        return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
 314}
 315
 316/**
 317 * cmd_set_board_config_using_msg() - Common command to send board configuration
 318 *                                    message
 319 * @handle:     pointer to TI SCI handle
 320 * @msg_type:   One of the TISCI message types to set board configuration
 321 * @addr:       Address where the board config structure is located
 322 * @size:       Size of the board config structure
 323 *
 324 * Return: 0 if all went well, else returns appropriate error value.
 325 */
 326static int cmd_set_board_config_using_msg(const struct ti_sci_handle *handle,
 327                                          u16 msg_type, u64 addr, u32 size)
 328{
 329        struct ti_sci_msg_board_config req;
 330        struct ti_sci_msg_hdr *resp;
 331        struct ti_sci_info *info;
 332        struct ti_sci_xfer *xfer;
 333        int ret = 0;
 334
 335        if (IS_ERR(handle))
 336                return PTR_ERR(handle);
 337        if (!handle)
 338                return -EINVAL;
 339
 340        info = handle_to_ti_sci_info(handle);
 341
 342        xfer = ti_sci_setup_one_xfer(info, msg_type,
 343                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
 344                                     (u32 *)&req, sizeof(req), sizeof(*resp));
 345        if (IS_ERR(xfer)) {
 346                ret = PTR_ERR(xfer);
 347                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
 348                return ret;
 349        }
 350        req.boardcfgp_high = (addr >> 32) & 0xffffffff;
 351        req.boardcfgp_low = addr & 0xffffffff;
 352        req.boardcfg_size = size;
 353
 354        ret = ti_sci_do_xfer(info, xfer);
 355        if (ret) {
 356                dev_err(info->dev, "Mbox send fail %d\n", ret);
 357                return ret;
 358        }
 359
 360        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
 361
 362        if (!ti_sci_is_response_ack(resp))
 363                return -ENODEV;
 364
 365        return ret;
 366}
 367
 368/**
 369 * ti_sci_cmd_set_board_config() - Command to send board configuration message
 370 * @handle:     pointer to TI SCI handle
 371 * @addr:       Address where the board config structure is located
 372 * @size:       Size of the board config structure
 373 *
 374 * Return: 0 if all went well, else returns appropriate error value.
 375 */
 376static int ti_sci_cmd_set_board_config(const struct ti_sci_handle *handle,
 377                                       u64 addr, u32 size)
 378{
 379        return cmd_set_board_config_using_msg(handle,
 380                                              TI_SCI_MSG_BOARD_CONFIG,
 381                                              addr, size);
 382}
 383
 384/**
 385 * ti_sci_cmd_set_board_config_rm() - Command to send board resource
 386 *                                    management configuration
 387 * @handle:     pointer to TI SCI handle
 388 * @addr:       Address where the board RM config structure is located
 389 * @size:       Size of the RM config structure
 390 *
 391 * Return: 0 if all went well, else returns appropriate error value.
 392 */
 393static
 394int ti_sci_cmd_set_board_config_rm(const struct ti_sci_handle *handle,
 395                                   u64 addr, u32 size)
 396{
 397        return cmd_set_board_config_using_msg(handle,
 398                                              TI_SCI_MSG_BOARD_CONFIG_RM,
 399                                              addr, size);
 400}
 401
 402/**
 403 * ti_sci_cmd_set_board_config_security() - Command to send board security
 404 *                                          configuration message
 405 * @handle:     pointer to TI SCI handle
 406 * @addr:       Address where the board security config structure is located
 407 * @size:       Size of the security config structure
 408 *
 409 * Return: 0 if all went well, else returns appropriate error value.
 410 */
 411static
 412int ti_sci_cmd_set_board_config_security(const struct ti_sci_handle *handle,
 413                                         u64 addr, u32 size)
 414{
 415        return cmd_set_board_config_using_msg(handle,
 416                                              TI_SCI_MSG_BOARD_CONFIG_SECURITY,
 417                                              addr, size);
 418}
 419
 420/**
 421 * ti_sci_cmd_set_board_config_pm() - Command to send board power and clock
 422 *                                    configuration message
 423 * @handle:     pointer to TI SCI handle
 424 * @addr:       Address where the board PM config structure is located
 425 * @size:       Size of the PM config structure
 426 *
 427 * Return: 0 if all went well, else returns appropriate error value.
 428 */
 429static int ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle *handle,
 430                                          u64 addr, u32 size)
 431{
 432        return cmd_set_board_config_using_msg(handle,
 433                                              TI_SCI_MSG_BOARD_CONFIG_PM,
 434                                              addr, size);
 435}
 436
 437static struct ti_sci_exclusive_dev
 438*ti_sci_get_exclusive_dev(struct list_head *dev_list, u32 id)
 439{
 440        struct ti_sci_exclusive_dev *dev;
 441
 442        list_for_each_entry(dev, dev_list, list)
 443                if (dev->id == id)
 444                        return dev;
 445
 446        return NULL;
 447}
 448
 449static void ti_sci_add_exclusive_dev(struct ti_sci_info *info, u32 id)
 450{
 451        struct ti_sci_exclusive_dev *dev;
 452
 453        dev = ti_sci_get_exclusive_dev(&info->dev_list, id);
 454        if (dev) {
 455                dev->count++;
 456                return;
 457        }
 458
 459        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 460        dev->id = id;
 461        dev->count = 1;
 462        INIT_LIST_HEAD(&dev->list);
 463        list_add_tail(&dev->list, &info->dev_list);
 464}
 465
 466static void ti_sci_delete_exclusive_dev(struct ti_sci_info *info, u32 id)
 467{
 468        struct ti_sci_exclusive_dev *dev;
 469
 470        dev = ti_sci_get_exclusive_dev(&info->dev_list, id);
 471        if (!dev)
 472                return;
 473
 474        if (dev->count > 0)
 475                dev->count--;
 476}
 477
 478/**
 479 * ti_sci_set_device_state() - Set device state helper
 480 * @handle:     pointer to TI SCI handle
 481 * @id:         Device identifier
 482 * @flags:      flags to setup for the device
 483 * @state:      State to move the device to
 484 *
 485 * Return: 0 if all went well, else returns appropriate error value.
 486 */
 487static int ti_sci_set_device_state(const struct ti_sci_handle *handle,
 488                                   u32 id, u32 flags, u8 state)
 489{
 490        struct ti_sci_msg_req_set_device_state req;
 491        struct ti_sci_msg_hdr *resp;
 492        struct ti_sci_info *info;
 493        struct ti_sci_xfer *xfer;
 494        int ret = 0;
 495
 496        if (IS_ERR(handle))
 497                return PTR_ERR(handle);
 498        if (!handle)
 499                return -EINVAL;
 500
 501        info = handle_to_ti_sci_info(handle);
 502
 503        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
 504                                     flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
 505                                     (u32 *)&req, sizeof(req), sizeof(*resp));
 506        if (IS_ERR(xfer)) {
 507                ret = PTR_ERR(xfer);
 508                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
 509                return ret;
 510        }
 511        req.id = id;
 512        req.state = state;
 513
 514        ret = ti_sci_do_xfer(info, xfer);
 515        if (ret) {
 516                dev_err(info->dev, "Mbox send fail %d\n", ret);
 517                return ret;
 518        }
 519
 520        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
 521
 522        if (!ti_sci_is_response_ack(resp))
 523                return -ENODEV;
 524
 525        if (state == MSG_DEVICE_SW_STATE_AUTO_OFF)
 526                ti_sci_delete_exclusive_dev(info, id);
 527        else if (flags & MSG_FLAG_DEVICE_EXCLUSIVE)
 528                ti_sci_add_exclusive_dev(info, id);
 529
 530        return ret;
 531}
 532
 533/**
 534 * ti_sci_set_device_state_no_wait() - Set device state helper without
 535 *                                     requesting or waiting for a response.
 536 * @handle:     pointer to TI SCI handle
 537 * @id:         Device identifier
 538 * @flags:      flags to setup for the device
 539 * @state:      State to move the device to
 540 *
 541 * Return: 0 if all went well, else returns appropriate error value.
 542 */
 543static int ti_sci_set_device_state_no_wait(const struct ti_sci_handle *handle,
 544                                           u32 id, u32 flags, u8 state)
 545{
 546        struct ti_sci_msg_req_set_device_state req;
 547        struct ti_sci_info *info;
 548        struct ti_sci_xfer *xfer;
 549        int ret = 0;
 550
 551        if (IS_ERR(handle))
 552                return PTR_ERR(handle);
 553        if (!handle)
 554                return -EINVAL;
 555
 556        info = handle_to_ti_sci_info(handle);
 557
 558        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
 559                                     flags | TI_SCI_FLAG_REQ_GENERIC_NORESPONSE,
 560                                     (u32 *)&req, sizeof(req), 0);
 561        if (IS_ERR(xfer)) {
 562                ret = PTR_ERR(xfer);
 563                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
 564                return ret;
 565        }
 566        req.id = id;
 567        req.state = state;
 568
 569        ret = ti_sci_do_xfer(info, xfer);
 570        if (ret)
 571                dev_err(info->dev, "Mbox send fail %d\n", ret);
 572
 573        return ret;
 574}
 575
 576/**
 577 * ti_sci_get_device_state() - Get device state helper
 578 * @handle:     Handle to the device
 579 * @id:         Device Identifier
 580 * @clcnt:      Pointer to Context Loss Count
 581 * @resets:     pointer to resets
 582 * @p_state:    pointer to p_state
 583 * @c_state:    pointer to c_state
 584 *
 585 * Return: 0 if all went fine, else return appropriate error.
 586 */
 587static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
 588                                   u32 id,  u32 *clcnt,  u32 *resets,
 589                                   u8 *p_state,  u8 *c_state)
 590{
 591        struct ti_sci_msg_resp_get_device_state *resp;
 592        struct ti_sci_msg_req_get_device_state req;
 593        struct ti_sci_info *info;
 594        struct ti_sci_xfer *xfer;
 595        int ret = 0;
 596
 597        if (IS_ERR(handle))
 598                return PTR_ERR(handle);
 599        if (!handle)
 600                return -EINVAL;
 601
 602        if (!clcnt && !resets && !p_state && !c_state)
 603                return -EINVAL;
 604
 605        info = handle_to_ti_sci_info(handle);
 606
 607        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE,
 608                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
 609                                     (u32 *)&req, sizeof(req), sizeof(*resp));
 610        if (IS_ERR(xfer)) {
 611                ret = PTR_ERR(xfer);
 612                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
 613                return ret;
 614        }
 615        req.id = id;
 616
 617        ret = ti_sci_do_xfer(info, xfer);
 618        if (ret) {
 619                dev_err(dev, "Mbox send fail %d\n", ret);
 620                return ret;
 621        }
 622
 623        resp = (struct ti_sci_msg_resp_get_device_state *)xfer->tx_message.buf;
 624        if (!ti_sci_is_response_ack(resp))
 625                return -ENODEV;
 626
 627        if (clcnt)
 628                *clcnt = resp->context_loss_count;
 629        if (resets)
 630                *resets = resp->resets;
 631        if (p_state)
 632                *p_state = resp->programmed_state;
 633        if (c_state)
 634                *c_state = resp->current_state;
 635
 636        return ret;
 637}
 638
 639/**
 640 * ti_sci_cmd_get_device() - command to request for device managed by TISCI
 641 * @handle:     Pointer to TISCI handle as retrieved by *ti_sci_get_handle
 642 * @id:         Device Identifier
 643 *
 644 * Request for the device - NOTE: the client MUST maintain integrity of
 645 * usage count by balancing get_device with put_device. No refcounting is
 646 * managed by driver for that purpose.
 647 *
 648 * NOTE: The request is for exclusive access for the processor.
 649 *
 650 * Return: 0 if all went fine, else return appropriate error.
 651 */
 652static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
 653{
 654        return ti_sci_set_device_state(handle, id, 0,
 655                                       MSG_DEVICE_SW_STATE_ON);
 656}
 657
 658static int ti_sci_cmd_get_device_exclusive(const struct ti_sci_handle *handle,
 659                                           u32 id)
 660{
 661        return ti_sci_set_device_state(handle, id, MSG_FLAG_DEVICE_EXCLUSIVE,
 662                                       MSG_DEVICE_SW_STATE_ON);
 663}
 664
 665/**
 666 * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI
 667 * @handle:     Pointer to TISCI handle as retrieved by *ti_sci_get_handle
 668 * @id:         Device Identifier
 669 *
 670 * Request for the device - NOTE: the client MUST maintain integrity of
 671 * usage count by balancing get_device with put_device. No refcounting is
 672 * managed by driver for that purpose.
 673 *
 674 * Return: 0 if all went fine, else return appropriate error.
 675 */
 676static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
 677{
 678        return ti_sci_set_device_state(handle, id,
 679                                       0,
 680                                       MSG_DEVICE_SW_STATE_RETENTION);
 681}
 682
 683static int ti_sci_cmd_idle_device_exclusive(const struct ti_sci_handle *handle,
 684                                            u32 id)
 685{
 686        return ti_sci_set_device_state(handle, id, MSG_FLAG_DEVICE_EXCLUSIVE,
 687                                       MSG_DEVICE_SW_STATE_RETENTION);
 688}
 689
 690/**
 691 * ti_sci_cmd_put_device() - command to release a device managed by TISCI
 692 * @handle:     Pointer to TISCI handle as retrieved by *ti_sci_get_handle
 693 * @id:         Device Identifier
 694 *
 695 * Request for the device - NOTE: the client MUST maintain integrity of
 696 * usage count by balancing get_device with put_device. No refcounting is
 697 * managed by driver for that purpose.
 698 *
 699 * Return: 0 if all went fine, else return appropriate error.
 700 */
 701static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id)
 702{
 703        return ti_sci_set_device_state(handle, id, 0,
 704                                       MSG_DEVICE_SW_STATE_AUTO_OFF);
 705}
 706
 707static
 708int ti_sci_cmd_release_exclusive_devices(const struct ti_sci_handle *handle)
 709{
 710        struct ti_sci_exclusive_dev *dev, *tmp;
 711        struct ti_sci_info *info;
 712        int i, cnt;
 713
 714        info = handle_to_ti_sci_info(handle);
 715
 716        list_for_each_entry_safe(dev, tmp, &info->dev_list, list) {
 717                cnt = dev->count;
 718                debug("%s: id = %d, cnt = %d\n", __func__, dev->id, cnt);
 719                for (i = 0; i < cnt; i++)
 720                        ti_sci_cmd_put_device(handle, dev->id);
 721        }
 722
 723        return 0;
 724}
 725
 726/**
 727 * ti_sci_cmd_dev_is_valid() - Is the device valid
 728 * @handle:     Pointer to TISCI handle as retrieved by *ti_sci_get_handle
 729 * @id:         Device Identifier
 730 *
 731 * Return: 0 if all went fine and the device ID is valid, else return
 732 * appropriate error.
 733 */
 734static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id)
 735{
 736        u8 unused;
 737
 738        /* check the device state which will also tell us if the ID is valid */
 739        return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused);
 740}
 741
 742/**
 743 * ti_sci_cmd_dev_get_clcnt() - Get context loss counter
 744 * @handle:     Pointer to TISCI handle
 745 * @id:         Device Identifier
 746 * @count:      Pointer to Context Loss counter to populate
 747 *
 748 * Return: 0 if all went fine, else return appropriate error.
 749 */
 750static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id,
 751                                    u32 *count)
 752{
 753        return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL);
 754}
 755
 756/**
 757 * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle
 758 * @handle:     Pointer to TISCI handle
 759 * @id:         Device Identifier
 760 * @r_state:    true if requested to be idle
 761 *
 762 * Return: 0 if all went fine, else return appropriate error.
 763 */
 764static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id,
 765                                  bool *r_state)
 766{
 767        int ret;
 768        u8 state;
 769
 770        if (!r_state)
 771                return -EINVAL;
 772
 773        ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL);
 774        if (ret)
 775                return ret;
 776
 777        *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
 778
 779        return 0;
 780}
 781
 782/**
 783 * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped
 784 * @handle:     Pointer to TISCI handle
 785 * @id:         Device Identifier
 786 * @r_state:    true if requested to be stopped
 787 * @curr_state: true if currently stopped.
 788 *
 789 * Return: 0 if all went fine, else return appropriate error.
 790 */
 791static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id,
 792                                  bool *r_state,  bool *curr_state)
 793{
 794        int ret;
 795        u8 p_state, c_state;
 796
 797        if (!r_state && !curr_state)
 798                return -EINVAL;
 799
 800        ret =
 801            ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
 802        if (ret)
 803                return ret;
 804
 805        if (r_state)
 806                *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
 807        if (curr_state)
 808                *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
 809
 810        return 0;
 811}
 812
 813/**
 814 * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON
 815 * @handle:     Pointer to TISCI handle
 816 * @id:         Device Identifier
 817 * @r_state:    true if requested to be ON
 818 * @curr_state: true if currently ON and active
 819 *
 820 * Return: 0 if all went fine, else return appropriate error.
 821 */
 822static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id,
 823                                bool *r_state,  bool *curr_state)
 824{
 825        int ret;
 826        u8 p_state, c_state;
 827
 828        if (!r_state && !curr_state)
 829                return -EINVAL;
 830
 831        ret =
 832            ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
 833        if (ret)
 834                return ret;
 835
 836        if (r_state)
 837                *r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
 838        if (curr_state)
 839                *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
 840
 841        return 0;
 842}
 843
 844/**
 845 * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning
 846 * @handle:     Pointer to TISCI handle
 847 * @id:         Device Identifier
 848 * @curr_state: true if currently transitioning.
 849 *
 850 * Return: 0 if all went fine, else return appropriate error.
 851 */
 852static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id,
 853                                   bool *curr_state)
 854{
 855        int ret;
 856        u8 state;
 857
 858        if (!curr_state)
 859                return -EINVAL;
 860
 861        ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state);
 862        if (ret)
 863                return ret;
 864
 865        *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
 866
 867        return 0;
 868}
 869
 870/**
 871 * ti_sci_cmd_set_device_resets() - command to set resets for device managed
 872 *                                  by TISCI
 873 * @handle:     Pointer to TISCI handle as retrieved by *ti_sci_get_handle
 874 * @id:         Device Identifier
 875 * @reset_state: Device specific reset bit field
 876 *
 877 * Return: 0 if all went fine, else return appropriate error.
 878 */
 879static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle,
 880                                        u32 id, u32 reset_state)
 881{
 882        struct ti_sci_msg_req_set_device_resets req;
 883        struct ti_sci_msg_hdr *resp;
 884        struct ti_sci_info *info;
 885        struct ti_sci_xfer *xfer;
 886        int ret = 0;
 887
 888        if (IS_ERR(handle))
 889                return PTR_ERR(handle);
 890        if (!handle)
 891                return -EINVAL;
 892
 893        info = handle_to_ti_sci_info(handle);
 894
 895        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS,
 896                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
 897                                     (u32 *)&req, sizeof(req), sizeof(*resp));
 898        if (IS_ERR(xfer)) {
 899                ret = PTR_ERR(xfer);
 900                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
 901                return ret;
 902        }
 903        req.id = id;
 904        req.resets = reset_state;
 905
 906        ret = ti_sci_do_xfer(info, xfer);
 907        if (ret) {
 908                dev_err(info->dev, "Mbox send fail %d\n", ret);
 909                return ret;
 910        }
 911
 912        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
 913
 914        if (!ti_sci_is_response_ack(resp))
 915                return -ENODEV;
 916
 917        return ret;
 918}
 919
 920/**
 921 * ti_sci_cmd_get_device_resets() - Get reset state for device managed
 922 *                                  by TISCI
 923 * @handle:             Pointer to TISCI handle
 924 * @id:                 Device Identifier
 925 * @reset_state:        Pointer to reset state to populate
 926 *
 927 * Return: 0 if all went fine, else return appropriate error.
 928 */
 929static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle,
 930                                        u32 id, u32 *reset_state)
 931{
 932        return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL,
 933                                       NULL);
 934}
 935
 936/**
 937 * ti_sci_set_clock_state() - Set clock state helper
 938 * @handle:     pointer to TI SCI handle
 939 * @dev_id:     Device identifier this request is for
 940 * @clk_id:     Clock identifier for the device for this request.
 941 *              Each device has it's own set of clock inputs. This indexes
 942 *              which clock input to modify.
 943 * @flags:      Header flags as needed
 944 * @state:      State to request for the clock.
 945 *
 946 * Return: 0 if all went well, else returns appropriate error value.
 947 */
 948static int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
 949                                  u32 dev_id, u8 clk_id,
 950                                  u32 flags, u8 state)
 951{
 952        struct ti_sci_msg_req_set_clock_state req;
 953        struct ti_sci_msg_hdr *resp;
 954        struct ti_sci_info *info;
 955        struct ti_sci_xfer *xfer;
 956        int ret = 0;
 957
 958        if (IS_ERR(handle))
 959                return PTR_ERR(handle);
 960        if (!handle)
 961                return -EINVAL;
 962
 963        info = handle_to_ti_sci_info(handle);
 964
 965        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
 966                                     flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
 967                                     (u32 *)&req, sizeof(req), sizeof(*resp));
 968        if (IS_ERR(xfer)) {
 969                ret = PTR_ERR(xfer);
 970                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
 971                return ret;
 972        }
 973        req.dev_id = dev_id;
 974        req.clk_id = clk_id;
 975        req.request_state = state;
 976
 977        ret = ti_sci_do_xfer(info, xfer);
 978        if (ret) {
 979                dev_err(info->dev, "Mbox send fail %d\n", ret);
 980                return ret;
 981        }
 982
 983        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
 984
 985        if (!ti_sci_is_response_ack(resp))
 986                return -ENODEV;
 987
 988        return ret;
 989}
 990
 991/**
 992 * ti_sci_cmd_get_clock_state() - Get clock state helper
 993 * @handle:     pointer to TI SCI handle
 994 * @dev_id:     Device identifier this request is for
 995 * @clk_id:     Clock identifier for the device for this request.
 996 *              Each device has it's own set of clock inputs. This indexes
 997 *              which clock input to modify.
 998 * @programmed_state:   State requested for clock to move to
 999 * @current_state:      State that the clock is currently in
1000 *
1001 * Return: 0 if all went well, else returns appropriate error value.
1002 */
1003static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
1004                                      u32 dev_id, u8 clk_id,
1005                                      u8 *programmed_state, u8 *current_state)
1006{
1007        struct ti_sci_msg_resp_get_clock_state *resp;
1008        struct ti_sci_msg_req_get_clock_state req;
1009        struct ti_sci_info *info;
1010        struct ti_sci_xfer *xfer;
1011        int ret = 0;
1012
1013        if (IS_ERR(handle))
1014                return PTR_ERR(handle);
1015        if (!handle)
1016                return -EINVAL;
1017
1018        if (!programmed_state && !current_state)
1019                return -EINVAL;
1020
1021        info = handle_to_ti_sci_info(handle);
1022
1023        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
1024                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1025                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1026        if (IS_ERR(xfer)) {
1027                ret = PTR_ERR(xfer);
1028                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1029                return ret;
1030        }
1031        req.dev_id = dev_id;
1032        req.clk_id = clk_id;
1033
1034        ret = ti_sci_do_xfer(info, xfer);
1035        if (ret) {
1036                dev_err(info->dev, "Mbox send fail %d\n", ret);
1037                return ret;
1038        }
1039
1040        resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->tx_message.buf;
1041
1042        if (!ti_sci_is_response_ack(resp))
1043                return -ENODEV;
1044
1045        if (programmed_state)
1046                *programmed_state = resp->programmed_state;
1047        if (current_state)
1048                *current_state = resp->current_state;
1049
1050        return ret;
1051}
1052
1053/**
1054 * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
1055 * @handle:     pointer to TI SCI handle
1056 * @dev_id:     Device identifier this request is for
1057 * @clk_id:     Clock identifier for the device for this request.
1058 *              Each device has it's own set of clock inputs. This indexes
1059 *              which clock input to modify.
1060 * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
1061 * @can_change_freq: 'true' if frequency change is desired, else 'false'
1062 * @enable_input_term: 'true' if input termination is desired, else 'false'
1063 *
1064 * Return: 0 if all went well, else returns appropriate error value.
1065 */
1066static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
1067                                u8 clk_id, bool needs_ssc, bool can_change_freq,
1068                                bool enable_input_term)
1069{
1070        u32 flags = 0;
1071
1072        flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
1073        flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
1074        flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
1075
1076        return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
1077                                      MSG_CLOCK_SW_STATE_REQ);
1078}
1079
1080/**
1081 * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
1082 * @handle:     pointer to TI SCI handle
1083 * @dev_id:     Device identifier this request is for
1084 * @clk_id:     Clock identifier for the device for this request.
1085 *              Each device has it's own set of clock inputs. This indexes
1086 *              which clock input to modify.
1087 *
1088 * NOTE: This clock must have been requested by get_clock previously.
1089 *
1090 * Return: 0 if all went well, else returns appropriate error value.
1091 */
1092static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
1093                                 u32 dev_id, u8 clk_id)
1094{
1095        return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
1096                                      MSG_CLOCK_SW_STATE_UNREQ);
1097}
1098
1099/**
1100 * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
1101 * @handle:     pointer to TI SCI handle
1102 * @dev_id:     Device identifier this request is for
1103 * @clk_id:     Clock identifier for the device for this request.
1104 *              Each device has it's own set of clock inputs. This indexes
1105 *              which clock input to modify.
1106 *
1107 * NOTE: This clock must have been requested by get_clock previously.
1108 *
1109 * Return: 0 if all went well, else returns appropriate error value.
1110 */
1111static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
1112                                u32 dev_id, u8 clk_id)
1113{
1114        return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
1115                                      MSG_CLOCK_SW_STATE_AUTO);
1116}
1117
1118/**
1119 * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
1120 * @handle:     pointer to TI SCI handle
1121 * @dev_id:     Device identifier this request is for
1122 * @clk_id:     Clock identifier for the device for this request.
1123 *              Each device has it's own set of clock inputs. This indexes
1124 *              which clock input to modify.
1125 * @req_state: state indicating if the clock is auto managed
1126 *
1127 * Return: 0 if all went well, else returns appropriate error value.
1128 */
1129static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
1130                                  u32 dev_id, u8 clk_id, bool *req_state)
1131{
1132        u8 state = 0;
1133        int ret;
1134
1135        if (!req_state)
1136                return -EINVAL;
1137
1138        ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
1139        if (ret)
1140                return ret;
1141
1142        *req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
1143        return 0;
1144}
1145
1146/**
1147 * ti_sci_cmd_clk_is_on() - Is the clock ON
1148 * @handle:     pointer to TI SCI handle
1149 * @dev_id:     Device identifier this request is for
1150 * @clk_id:     Clock identifier for the device for this request.
1151 *              Each device has it's own set of clock inputs. This indexes
1152 *              which clock input to modify.
1153 * @req_state: state indicating if the clock is managed by us and enabled
1154 * @curr_state: state indicating if the clock is ready for operation
1155 *
1156 * Return: 0 if all went well, else returns appropriate error value.
1157 */
1158static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
1159                                u8 clk_id, bool *req_state, bool *curr_state)
1160{
1161        u8 c_state = 0, r_state = 0;
1162        int ret;
1163
1164        if (!req_state && !curr_state)
1165                return -EINVAL;
1166
1167        ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1168                                         &r_state, &c_state);
1169        if (ret)
1170                return ret;
1171
1172        if (req_state)
1173                *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
1174        if (curr_state)
1175                *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
1176        return 0;
1177}
1178
1179/**
1180 * ti_sci_cmd_clk_is_off() - Is the clock OFF
1181 * @handle:     pointer to TI SCI handle
1182 * @dev_id:     Device identifier this request is for
1183 * @clk_id:     Clock identifier for the device for this request.
1184 *              Each device has it's own set of clock inputs. This indexes
1185 *              which clock input to modify.
1186 * @req_state: state indicating if the clock is managed by us and disabled
1187 * @curr_state: state indicating if the clock is NOT ready for operation
1188 *
1189 * Return: 0 if all went well, else returns appropriate error value.
1190 */
1191static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
1192                                 u8 clk_id, bool *req_state, bool *curr_state)
1193{
1194        u8 c_state = 0, r_state = 0;
1195        int ret;
1196
1197        if (!req_state && !curr_state)
1198                return -EINVAL;
1199
1200        ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1201                                         &r_state, &c_state);
1202        if (ret)
1203                return ret;
1204
1205        if (req_state)
1206                *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
1207        if (curr_state)
1208                *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
1209        return 0;
1210}
1211
1212/**
1213 * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
1214 * @handle:     pointer to TI SCI handle
1215 * @dev_id:     Device identifier this request is for
1216 * @clk_id:     Clock identifier for the device for this request.
1217 *              Each device has it's own set of clock inputs. This indexes
1218 *              which clock input to modify.
1219 * @parent_id:  Parent clock identifier to set
1220 *
1221 * Return: 0 if all went well, else returns appropriate error value.
1222 */
1223static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
1224                                     u32 dev_id, u8 clk_id, u8 parent_id)
1225{
1226        struct ti_sci_msg_req_set_clock_parent req;
1227        struct ti_sci_msg_hdr *resp;
1228        struct ti_sci_info *info;
1229        struct ti_sci_xfer *xfer;
1230        int ret = 0;
1231
1232        if (IS_ERR(handle))
1233                return PTR_ERR(handle);
1234        if (!handle)
1235                return -EINVAL;
1236
1237        info = handle_to_ti_sci_info(handle);
1238
1239        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
1240                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1241                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1242        if (IS_ERR(xfer)) {
1243                ret = PTR_ERR(xfer);
1244                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1245                return ret;
1246        }
1247        req.dev_id = dev_id;
1248        req.clk_id = clk_id;
1249        req.parent_id = parent_id;
1250
1251        ret = ti_sci_do_xfer(info, xfer);
1252        if (ret) {
1253                dev_err(info->dev, "Mbox send fail %d\n", ret);
1254                return ret;
1255        }
1256
1257        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1258
1259        if (!ti_sci_is_response_ack(resp))
1260                return -ENODEV;
1261
1262        return ret;
1263}
1264
1265/**
1266 * ti_sci_cmd_clk_get_parent() - Get current parent clock source
1267 * @handle:     pointer to TI SCI handle
1268 * @dev_id:     Device identifier this request is for
1269 * @clk_id:     Clock identifier for the device for this request.
1270 *              Each device has it's own set of clock inputs. This indexes
1271 *              which clock input to modify.
1272 * @parent_id:  Current clock parent
1273 *
1274 * Return: 0 if all went well, else returns appropriate error value.
1275 */
1276static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
1277                                     u32 dev_id, u8 clk_id, u8 *parent_id)
1278{
1279        struct ti_sci_msg_resp_get_clock_parent *resp;
1280        struct ti_sci_msg_req_get_clock_parent req;
1281        struct ti_sci_info *info;
1282        struct ti_sci_xfer *xfer;
1283        int ret = 0;
1284
1285        if (IS_ERR(handle))
1286                return PTR_ERR(handle);
1287        if (!handle || !parent_id)
1288                return -EINVAL;
1289
1290        info = handle_to_ti_sci_info(handle);
1291
1292        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
1293                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1294                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1295        if (IS_ERR(xfer)) {
1296                ret = PTR_ERR(xfer);
1297                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1298                return ret;
1299        }
1300        req.dev_id = dev_id;
1301        req.clk_id = clk_id;
1302
1303        ret = ti_sci_do_xfer(info, xfer);
1304        if (ret) {
1305                dev_err(info->dev, "Mbox send fail %d\n", ret);
1306                return ret;
1307        }
1308
1309        resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->tx_message.buf;
1310
1311        if (!ti_sci_is_response_ack(resp))
1312                ret = -ENODEV;
1313        else
1314                *parent_id = resp->parent_id;
1315
1316        return ret;
1317}
1318
1319/**
1320 * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source
1321 * @handle:     pointer to TI SCI handle
1322 * @dev_id:     Device identifier this request is for
1323 * @clk_id:     Clock identifier for the device for this request.
1324 *              Each device has it's own set of clock inputs. This indexes
1325 *              which clock input to modify.
1326 * @num_parents: Returns he number of parents to the current clock.
1327 *
1328 * Return: 0 if all went well, else returns appropriate error value.
1329 */
1330static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
1331                                          u32 dev_id, u8 clk_id,
1332                                          u8 *num_parents)
1333{
1334        struct ti_sci_msg_resp_get_clock_num_parents *resp;
1335        struct ti_sci_msg_req_get_clock_num_parents req;
1336        struct ti_sci_info *info;
1337        struct ti_sci_xfer *xfer;
1338        int ret = 0;
1339
1340        if (IS_ERR(handle))
1341                return PTR_ERR(handle);
1342        if (!handle || !num_parents)
1343                return -EINVAL;
1344
1345        info = handle_to_ti_sci_info(handle);
1346
1347        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
1348                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1349                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1350        if (IS_ERR(xfer)) {
1351                ret = PTR_ERR(xfer);
1352                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1353                return ret;
1354        }
1355        req.dev_id = dev_id;
1356        req.clk_id = clk_id;
1357
1358        ret = ti_sci_do_xfer(info, xfer);
1359        if (ret) {
1360                dev_err(info->dev, "Mbox send fail %d\n", ret);
1361                return ret;
1362        }
1363
1364        resp = (struct ti_sci_msg_resp_get_clock_num_parents *)
1365                                                        xfer->tx_message.buf;
1366
1367        if (!ti_sci_is_response_ack(resp))
1368                ret = -ENODEV;
1369        else
1370                *num_parents = resp->num_parents;
1371
1372        return ret;
1373}
1374
1375/**
1376 * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
1377 * @handle:     pointer to TI SCI handle
1378 * @dev_id:     Device identifier this request is for
1379 * @clk_id:     Clock identifier for the device for this request.
1380 *              Each device has it's own set of clock inputs. This indexes
1381 *              which clock input to modify.
1382 * @min_freq:   The minimum allowable frequency in Hz. This is the minimum
1383 *              allowable programmed frequency and does not account for clock
1384 *              tolerances and jitter.
1385 * @target_freq: The target clock frequency in Hz. A frequency will be
1386 *              processed as close to this target frequency as possible.
1387 * @max_freq:   The maximum allowable frequency in Hz. This is the maximum
1388 *              allowable programmed frequency and does not account for clock
1389 *              tolerances and jitter.
1390 * @match_freq: Frequency match in Hz response.
1391 *
1392 * Return: 0 if all went well, else returns appropriate error value.
1393 */
1394static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
1395                                         u32 dev_id, u8 clk_id, u64 min_freq,
1396                                         u64 target_freq, u64 max_freq,
1397                                         u64 *match_freq)
1398{
1399        struct ti_sci_msg_resp_query_clock_freq *resp;
1400        struct ti_sci_msg_req_query_clock_freq req;
1401        struct ti_sci_info *info;
1402        struct ti_sci_xfer *xfer;
1403        int ret = 0;
1404
1405        if (IS_ERR(handle))
1406                return PTR_ERR(handle);
1407        if (!handle || !match_freq)
1408                return -EINVAL;
1409
1410        info = handle_to_ti_sci_info(handle);
1411
1412        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
1413                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1414                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1415        if (IS_ERR(xfer)) {
1416                ret = PTR_ERR(xfer);
1417                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1418                return ret;
1419        }
1420        req.dev_id = dev_id;
1421        req.clk_id = clk_id;
1422        req.min_freq_hz = min_freq;
1423        req.target_freq_hz = target_freq;
1424        req.max_freq_hz = max_freq;
1425
1426        ret = ti_sci_do_xfer(info, xfer);
1427        if (ret) {
1428                dev_err(info->dev, "Mbox send fail %d\n", ret);
1429                return ret;
1430        }
1431
1432        resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->tx_message.buf;
1433
1434        if (!ti_sci_is_response_ack(resp))
1435                ret = -ENODEV;
1436        else
1437                *match_freq = resp->freq_hz;
1438
1439        return ret;
1440}
1441
1442/**
1443 * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
1444 * @handle:     pointer to TI SCI handle
1445 * @dev_id:     Device identifier this request is for
1446 * @clk_id:     Clock identifier for the device for this request.
1447 *              Each device has it's own set of clock inputs. This indexes
1448 *              which clock input to modify.
1449 * @min_freq:   The minimum allowable frequency in Hz. This is the minimum
1450 *              allowable programmed frequency and does not account for clock
1451 *              tolerances and jitter.
1452 * @target_freq: The target clock frequency in Hz. A frequency will be
1453 *              processed as close to this target frequency as possible.
1454 * @max_freq:   The maximum allowable frequency in Hz. This is the maximum
1455 *              allowable programmed frequency and does not account for clock
1456 *              tolerances and jitter.
1457 *
1458 * Return: 0 if all went well, else returns appropriate error value.
1459 */
1460static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
1461                                   u32 dev_id, u8 clk_id, u64 min_freq,
1462                                   u64 target_freq, u64 max_freq)
1463{
1464        struct ti_sci_msg_req_set_clock_freq req;
1465        struct ti_sci_msg_hdr *resp;
1466        struct ti_sci_info *info;
1467        struct ti_sci_xfer *xfer;
1468        int ret = 0;
1469
1470        if (IS_ERR(handle))
1471                return PTR_ERR(handle);
1472        if (!handle)
1473                return -EINVAL;
1474
1475        info = handle_to_ti_sci_info(handle);
1476
1477        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
1478                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1479                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1480        if (IS_ERR(xfer)) {
1481                ret = PTR_ERR(xfer);
1482                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1483                return ret;
1484        }
1485        req.dev_id = dev_id;
1486        req.clk_id = clk_id;
1487        req.min_freq_hz = min_freq;
1488        req.target_freq_hz = target_freq;
1489        req.max_freq_hz = max_freq;
1490
1491        ret = ti_sci_do_xfer(info, xfer);
1492        if (ret) {
1493                dev_err(info->dev, "Mbox send fail %d\n", ret);
1494                return ret;
1495        }
1496
1497        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1498
1499        if (!ti_sci_is_response_ack(resp))
1500                return -ENODEV;
1501
1502        return ret;
1503}
1504
1505/**
1506 * ti_sci_cmd_clk_get_freq() - Get current frequency
1507 * @handle:     pointer to TI SCI handle
1508 * @dev_id:     Device identifier this request is for
1509 * @clk_id:     Clock identifier for the device for this request.
1510 *              Each device has it's own set of clock inputs. This indexes
1511 *              which clock input to modify.
1512 * @freq:       Currently frequency in Hz
1513 *
1514 * Return: 0 if all went well, else returns appropriate error value.
1515 */
1516static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
1517                                   u32 dev_id, u8 clk_id, u64 *freq)
1518{
1519        struct ti_sci_msg_resp_get_clock_freq *resp;
1520        struct ti_sci_msg_req_get_clock_freq req;
1521        struct ti_sci_info *info;
1522        struct ti_sci_xfer *xfer;
1523        int ret = 0;
1524
1525        if (IS_ERR(handle))
1526                return PTR_ERR(handle);
1527        if (!handle || !freq)
1528                return -EINVAL;
1529
1530        info = handle_to_ti_sci_info(handle);
1531
1532        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
1533                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1534                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1535        if (IS_ERR(xfer)) {
1536                ret = PTR_ERR(xfer);
1537                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1538                return ret;
1539        }
1540        req.dev_id = dev_id;
1541        req.clk_id = clk_id;
1542
1543        ret = ti_sci_do_xfer(info, xfer);
1544        if (ret) {
1545                dev_err(info->dev, "Mbox send fail %d\n", ret);
1546                return ret;
1547        }
1548
1549        resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->tx_message.buf;
1550
1551        if (!ti_sci_is_response_ack(resp))
1552                ret = -ENODEV;
1553        else
1554                *freq = resp->freq_hz;
1555
1556        return ret;
1557}
1558
1559/**
1560 * ti_sci_cmd_core_reboot() - Command to request system reset
1561 * @handle:     pointer to TI SCI handle
1562 *
1563 * Return: 0 if all went well, else returns appropriate error value.
1564 */
1565static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
1566{
1567        struct ti_sci_msg_req_reboot req;
1568        struct ti_sci_msg_hdr *resp;
1569        struct ti_sci_info *info;
1570        struct ti_sci_xfer *xfer;
1571        int ret = 0;
1572
1573        if (IS_ERR(handle))
1574                return PTR_ERR(handle);
1575        if (!handle)
1576                return -EINVAL;
1577
1578        info = handle_to_ti_sci_info(handle);
1579
1580        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SYS_RESET,
1581                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1582                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1583        if (IS_ERR(xfer)) {
1584                ret = PTR_ERR(xfer);
1585                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1586                return ret;
1587        }
1588
1589        ret = ti_sci_do_xfer(info, xfer);
1590        if (ret) {
1591                dev_err(dev, "Mbox send fail %d\n", ret);
1592                return ret;
1593        }
1594
1595        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1596
1597        if (!ti_sci_is_response_ack(resp))
1598                return -ENODEV;
1599
1600        return ret;
1601}
1602
1603static int ti_sci_get_resource_type(struct ti_sci_info *info, u16 dev_id,
1604                                    u16 *type)
1605{
1606        struct ti_sci_rm_type_map *rm_type_map = info->desc->rm_type_map;
1607        bool found = false;
1608        int i;
1609
1610        /* If map is not provided then assume dev_id is used as type */
1611        if (!rm_type_map) {
1612                *type = dev_id;
1613                return 0;
1614        }
1615
1616        for (i = 0; rm_type_map[i].dev_id; i++) {
1617                if (rm_type_map[i].dev_id == dev_id) {
1618                        *type = rm_type_map[i].type;
1619                        found = true;
1620                        break;
1621                }
1622        }
1623
1624        if (!found)
1625                return -EINVAL;
1626
1627        return 0;
1628}
1629
1630/**
1631 * ti_sci_get_resource_range - Helper to get a range of resources assigned
1632 *                             to a host. Resource is uniquely identified by
1633 *                             type and subtype.
1634 * @handle:             Pointer to TISCI handle.
1635 * @dev_id:             TISCI device ID.
1636 * @subtype:            Resource assignment subtype that is being requested
1637 *                      from the given device.
1638 * @s_host:             Host processor ID to which the resources are allocated
1639 * @range_start:        Start index of the resource range
1640 * @range_num:          Number of resources in the range
1641 *
1642 * Return: 0 if all went fine, else return appropriate error.
1643 */
1644static int ti_sci_get_resource_range(const struct ti_sci_handle *handle,
1645                                     u32 dev_id, u8 subtype, u8 s_host,
1646                                     u16 *range_start, u16 *range_num)
1647{
1648        struct ti_sci_msg_resp_get_resource_range *resp;
1649        struct ti_sci_msg_req_get_resource_range req;
1650        struct ti_sci_xfer *xfer;
1651        struct ti_sci_info *info;
1652        u16 type;
1653        int ret = 0;
1654
1655        if (IS_ERR(handle))
1656                return PTR_ERR(handle);
1657        if (!handle)
1658                return -EINVAL;
1659
1660        info = handle_to_ti_sci_info(handle);
1661
1662        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_RESOURCE_RANGE,
1663                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1664                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1665        if (IS_ERR(xfer)) {
1666                ret = PTR_ERR(xfer);
1667                dev_err(dev, "Message alloc failed(%d)\n", ret);
1668                return ret;
1669        }
1670
1671        ret = ti_sci_get_resource_type(info, dev_id, &type);
1672        if (ret) {
1673                dev_err(dev, "rm type lookup failed for %u\n", dev_id);
1674                goto fail;
1675        }
1676
1677        req.secondary_host = s_host;
1678        req.type = type & MSG_RM_RESOURCE_TYPE_MASK;
1679        req.subtype = subtype & MSG_RM_RESOURCE_SUBTYPE_MASK;
1680
1681        ret = ti_sci_do_xfer(info, xfer);
1682        if (ret) {
1683                dev_err(dev, "Mbox send fail %d\n", ret);
1684                goto fail;
1685        }
1686
1687        resp = (struct ti_sci_msg_resp_get_resource_range *)xfer->tx_message.buf;
1688        if (!ti_sci_is_response_ack(resp)) {
1689                ret = -ENODEV;
1690        } else if (!resp->range_start && !resp->range_num) {
1691                ret = -ENODEV;
1692        } else {
1693                *range_start = resp->range_start;
1694                *range_num = resp->range_num;
1695        };
1696
1697fail:
1698        return ret;
1699}
1700
1701/**
1702 * ti_sci_cmd_get_resource_range - Get a range of resources assigned to host
1703 *                                 that is same as ti sci interface host.
1704 * @handle:             Pointer to TISCI handle.
1705 * @dev_id:             TISCI device ID.
1706 * @subtype:            Resource assignment subtype that is being requested
1707 *                      from the given device.
1708 * @range_start:        Start index of the resource range
1709 * @range_num:          Number of resources in the range
1710 *
1711 * Return: 0 if all went fine, else return appropriate error.
1712 */
1713static int ti_sci_cmd_get_resource_range(const struct ti_sci_handle *handle,
1714                                         u32 dev_id, u8 subtype,
1715                                         u16 *range_start, u16 *range_num)
1716{
1717        return ti_sci_get_resource_range(handle, dev_id, subtype,
1718                                         TI_SCI_IRQ_SECONDARY_HOST_INVALID,
1719                                         range_start, range_num);
1720}
1721
1722/**
1723 * ti_sci_cmd_get_resource_range_from_shost - Get a range of resources
1724 *                                            assigned to a specified host.
1725 * @handle:             Pointer to TISCI handle.
1726 * @dev_id:             TISCI device ID.
1727 * @subtype:            Resource assignment subtype that is being requested
1728 *                      from the given device.
1729 * @s_host:             Host processor ID to which the resources are allocated
1730 * @range_start:        Start index of the resource range
1731 * @range_num:          Number of resources in the range
1732 *
1733 * Return: 0 if all went fine, else return appropriate error.
1734 */
1735static
1736int ti_sci_cmd_get_resource_range_from_shost(const struct ti_sci_handle *handle,
1737                                             u32 dev_id, u8 subtype, u8 s_host,
1738                                             u16 *range_start, u16 *range_num)
1739{
1740        return ti_sci_get_resource_range(handle, dev_id, subtype, s_host,
1741                                         range_start, range_num);
1742}
1743
1744/**
1745 * ti_sci_cmd_query_msmc() - Command to query currently available msmc memory
1746 * @handle:             pointer to TI SCI handle
1747 * @msms_start:         MSMC start as returned by tisci
1748 * @msmc_end:           MSMC end as returned by tisci
1749 *
1750 * Return: 0 if all went well, else returns appropriate error value.
1751 */
1752static int ti_sci_cmd_query_msmc(const struct ti_sci_handle *handle,
1753                                 u64 *msmc_start, u64 *msmc_end)
1754{
1755        struct ti_sci_msg_resp_query_msmc *resp;
1756        struct ti_sci_msg_hdr req;
1757        struct ti_sci_info *info;
1758        struct ti_sci_xfer *xfer;
1759        int ret = 0;
1760
1761        if (IS_ERR(handle))
1762                return PTR_ERR(handle);
1763        if (!handle)
1764                return -EINVAL;
1765
1766        info = handle_to_ti_sci_info(handle);
1767
1768        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_QUERY_MSMC,
1769                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1770                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1771        if (IS_ERR(xfer)) {
1772                ret = PTR_ERR(xfer);
1773                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1774                return ret;
1775        }
1776
1777        ret = ti_sci_do_xfer(info, xfer);
1778        if (ret) {
1779                dev_err(dev, "Mbox send fail %d\n", ret);
1780                return ret;
1781        }
1782
1783        resp = (struct ti_sci_msg_resp_query_msmc *)xfer->tx_message.buf;
1784
1785        if (!ti_sci_is_response_ack(resp))
1786                return -ENODEV;
1787
1788        *msmc_start = ((u64)resp->msmc_start_high << TISCI_ADDR_HIGH_SHIFT) |
1789                        resp->msmc_start_low;
1790        *msmc_end = ((u64)resp->msmc_end_high << TISCI_ADDR_HIGH_SHIFT) |
1791                        resp->msmc_end_low;
1792
1793        return ret;
1794}
1795
1796/**
1797 * ti_sci_cmd_proc_request() - Command to request a physical processor control
1798 * @handle:     Pointer to TI SCI handle
1799 * @proc_id:    Processor ID this request is for
1800 *
1801 * Return: 0 if all went well, else returns appropriate error value.
1802 */
1803static int ti_sci_cmd_proc_request(const struct ti_sci_handle *handle,
1804                                   u8 proc_id)
1805{
1806        struct ti_sci_msg_req_proc_request req;
1807        struct ti_sci_msg_hdr *resp;
1808        struct ti_sci_info *info;
1809        struct ti_sci_xfer *xfer;
1810        int ret = 0;
1811
1812        if (IS_ERR(handle))
1813                return PTR_ERR(handle);
1814        if (!handle)
1815                return -EINVAL;
1816
1817        info = handle_to_ti_sci_info(handle);
1818
1819        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_REQUEST,
1820                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1821                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1822        if (IS_ERR(xfer)) {
1823                ret = PTR_ERR(xfer);
1824                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1825                return ret;
1826        }
1827        req.processor_id = proc_id;
1828
1829        ret = ti_sci_do_xfer(info, xfer);
1830        if (ret) {
1831                dev_err(info->dev, "Mbox send fail %d\n", ret);
1832                return ret;
1833        }
1834
1835        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1836
1837        if (!ti_sci_is_response_ack(resp))
1838                ret = -ENODEV;
1839
1840        return ret;
1841}
1842
1843/**
1844 * ti_sci_cmd_proc_release() - Command to release a physical processor control
1845 * @handle:     Pointer to TI SCI handle
1846 * @proc_id:    Processor ID this request is for
1847 *
1848 * Return: 0 if all went well, else returns appropriate error value.
1849 */
1850static int ti_sci_cmd_proc_release(const struct ti_sci_handle *handle,
1851                                   u8 proc_id)
1852{
1853        struct ti_sci_msg_req_proc_release req;
1854        struct ti_sci_msg_hdr *resp;
1855        struct ti_sci_info *info;
1856        struct ti_sci_xfer *xfer;
1857        int ret = 0;
1858
1859        if (IS_ERR(handle))
1860                return PTR_ERR(handle);
1861        if (!handle)
1862                return -EINVAL;
1863
1864        info = handle_to_ti_sci_info(handle);
1865
1866        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_RELEASE,
1867                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1868                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1869        if (IS_ERR(xfer)) {
1870                ret = PTR_ERR(xfer);
1871                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1872                return ret;
1873        }
1874        req.processor_id = proc_id;
1875
1876        ret = ti_sci_do_xfer(info, xfer);
1877        if (ret) {
1878                dev_err(info->dev, "Mbox send fail %d\n", ret);
1879                return ret;
1880        }
1881
1882        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1883
1884        if (!ti_sci_is_response_ack(resp))
1885                ret = -ENODEV;
1886
1887        return ret;
1888}
1889
1890/**
1891 * ti_sci_cmd_proc_handover() - Command to handover a physical processor
1892 *                              control to a host in the processor's access
1893 *                              control list.
1894 * @handle:     Pointer to TI SCI handle
1895 * @proc_id:    Processor ID this request is for
1896 * @host_id:    Host ID to get the control of the processor
1897 *
1898 * Return: 0 if all went well, else returns appropriate error value.
1899 */
1900static int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle,
1901                                    u8 proc_id, u8 host_id)
1902{
1903        struct ti_sci_msg_req_proc_handover req;
1904        struct ti_sci_msg_hdr *resp;
1905        struct ti_sci_info *info;
1906        struct ti_sci_xfer *xfer;
1907        int ret = 0;
1908
1909        if (IS_ERR(handle))
1910                return PTR_ERR(handle);
1911        if (!handle)
1912                return -EINVAL;
1913
1914        info = handle_to_ti_sci_info(handle);
1915
1916        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_HANDOVER,
1917                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1918                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1919        if (IS_ERR(xfer)) {
1920                ret = PTR_ERR(xfer);
1921                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1922                return ret;
1923        }
1924        req.processor_id = proc_id;
1925        req.host_id = host_id;
1926
1927        ret = ti_sci_do_xfer(info, xfer);
1928        if (ret) {
1929                dev_err(info->dev, "Mbox send fail %d\n", ret);
1930                return ret;
1931        }
1932
1933        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1934
1935        if (!ti_sci_is_response_ack(resp))
1936                ret = -ENODEV;
1937
1938        return ret;
1939}
1940
1941/**
1942 * ti_sci_cmd_set_proc_boot_cfg() - Command to set the processor boot
1943 *                                  configuration flags
1944 * @handle:             Pointer to TI SCI handle
1945 * @proc_id:            Processor ID this request is for
1946 * @config_flags_set:   Configuration flags to be set
1947 * @config_flags_clear: Configuration flags to be cleared.
1948 *
1949 * Return: 0 if all went well, else returns appropriate error value.
1950 */
1951static int ti_sci_cmd_set_proc_boot_cfg(const struct ti_sci_handle *handle,
1952                                        u8 proc_id, u64 bootvector,
1953                                        u32 config_flags_set,
1954                                        u32 config_flags_clear)
1955{
1956        struct ti_sci_msg_req_set_proc_boot_config req;
1957        struct ti_sci_msg_hdr *resp;
1958        struct ti_sci_info *info;
1959        struct ti_sci_xfer *xfer;
1960        int ret = 0;
1961
1962        if (IS_ERR(handle))
1963                return PTR_ERR(handle);
1964        if (!handle)
1965                return -EINVAL;
1966
1967        info = handle_to_ti_sci_info(handle);
1968
1969        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CONFIG,
1970                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1971                                     (u32 *)&req, sizeof(req), sizeof(*resp));
1972        if (IS_ERR(xfer)) {
1973                ret = PTR_ERR(xfer);
1974                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
1975                return ret;
1976        }
1977        req.processor_id = proc_id;
1978        req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
1979        req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
1980                                TISCI_ADDR_HIGH_SHIFT;
1981        req.config_flags_set = config_flags_set;
1982        req.config_flags_clear = config_flags_clear;
1983
1984        ret = ti_sci_do_xfer(info, xfer);
1985        if (ret) {
1986                dev_err(info->dev, "Mbox send fail %d\n", ret);
1987                return ret;
1988        }
1989
1990        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
1991
1992        if (!ti_sci_is_response_ack(resp))
1993                ret = -ENODEV;
1994
1995        return ret;
1996}
1997
1998/**
1999 * ti_sci_cmd_set_proc_boot_ctrl() - Command to set the processor boot
2000 *                                   control flags
2001 * @handle:                     Pointer to TI SCI handle
2002 * @proc_id:                    Processor ID this request is for
2003 * @control_flags_set:          Control flags to be set
2004 * @control_flags_clear:        Control flags to be cleared
2005 *
2006 * Return: 0 if all went well, else returns appropriate error value.
2007 */
2008static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle,
2009                                         u8 proc_id, u32 control_flags_set,
2010                                         u32 control_flags_clear)
2011{
2012        struct ti_sci_msg_req_set_proc_boot_ctrl req;
2013        struct ti_sci_msg_hdr *resp;
2014        struct ti_sci_info *info;
2015        struct ti_sci_xfer *xfer;
2016        int ret = 0;
2017
2018        if (IS_ERR(handle))
2019                return PTR_ERR(handle);
2020        if (!handle)
2021                return -EINVAL;
2022
2023        info = handle_to_ti_sci_info(handle);
2024
2025        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CTRL,
2026                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2027                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2028        if (IS_ERR(xfer)) {
2029                ret = PTR_ERR(xfer);
2030                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
2031                return ret;
2032        }
2033        req.processor_id = proc_id;
2034        req.control_flags_set = control_flags_set;
2035        req.control_flags_clear = control_flags_clear;
2036
2037        ret = ti_sci_do_xfer(info, xfer);
2038        if (ret) {
2039                dev_err(info->dev, "Mbox send fail %d\n", ret);
2040                return ret;
2041        }
2042
2043        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
2044
2045        if (!ti_sci_is_response_ack(resp))
2046                ret = -ENODEV;
2047
2048        return ret;
2049}
2050
2051/**
2052 * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the
2053 *                      image and then set the processor configuration flags.
2054 * @handle:     Pointer to TI SCI handle
2055 * @image_addr: Memory address at which payload image and certificate is
2056 *              located in memory, this is updated if the image data is
2057 *              moved during authentication.
2058 * @image_size: This is updated with the final size of the image after
2059 *              authentication.
2060 *
2061 * Return: 0 if all went well, else returns appropriate error value.
2062 */
2063static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle,
2064                                           u64 *image_addr, u32 *image_size)
2065{
2066        struct ti_sci_msg_req_proc_auth_boot_image req;
2067        struct ti_sci_msg_resp_proc_auth_boot_image *resp;
2068        struct ti_sci_info *info;
2069        struct ti_sci_xfer *xfer;
2070        int ret = 0;
2071
2072        if (IS_ERR(handle))
2073                return PTR_ERR(handle);
2074        if (!handle)
2075                return -EINVAL;
2076
2077        info = handle_to_ti_sci_info(handle);
2078
2079        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_BOOT_IMIAGE,
2080                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2081                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2082        if (IS_ERR(xfer)) {
2083                ret = PTR_ERR(xfer);
2084                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
2085                return ret;
2086        }
2087        req.cert_addr_low = *image_addr & TISCI_ADDR_LOW_MASK;
2088        req.cert_addr_high = (*image_addr & TISCI_ADDR_HIGH_MASK) >>
2089                                TISCI_ADDR_HIGH_SHIFT;
2090
2091        ret = ti_sci_do_xfer(info, xfer);
2092        if (ret) {
2093                dev_err(info->dev, "Mbox send fail %d\n", ret);
2094                return ret;
2095        }
2096
2097        resp = (struct ti_sci_msg_resp_proc_auth_boot_image *)xfer->tx_message.buf;
2098
2099        if (!ti_sci_is_response_ack(resp))
2100                return -ENODEV;
2101
2102        *image_addr = (resp->image_addr_low & TISCI_ADDR_LOW_MASK) |
2103                        (((u64)resp->image_addr_high <<
2104                          TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
2105        *image_size = resp->image_size;
2106
2107        return ret;
2108}
2109
2110/**
2111 * ti_sci_cmd_get_proc_boot_status() - Command to get the processor boot status
2112 * @handle:     Pointer to TI SCI handle
2113 * @proc_id:    Processor ID this request is for
2114 *
2115 * Return: 0 if all went well, else returns appropriate error value.
2116 */
2117static int ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle *handle,
2118                                           u8 proc_id, u64 *bv, u32 *cfg_flags,
2119                                           u32 *ctrl_flags, u32 *sts_flags)
2120{
2121        struct ti_sci_msg_resp_get_proc_boot_status *resp;
2122        struct ti_sci_msg_req_get_proc_boot_status req;
2123        struct ti_sci_info *info;
2124        struct ti_sci_xfer *xfer;
2125        int ret = 0;
2126
2127        if (IS_ERR(handle))
2128                return PTR_ERR(handle);
2129        if (!handle)
2130                return -EINVAL;
2131
2132        info = handle_to_ti_sci_info(handle);
2133
2134        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_GET_PROC_BOOT_STATUS,
2135                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2136                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2137        if (IS_ERR(xfer)) {
2138                ret = PTR_ERR(xfer);
2139                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
2140                return ret;
2141        }
2142        req.processor_id = proc_id;
2143
2144        ret = ti_sci_do_xfer(info, xfer);
2145        if (ret) {
2146                dev_err(info->dev, "Mbox send fail %d\n", ret);
2147                return ret;
2148        }
2149
2150        resp = (struct ti_sci_msg_resp_get_proc_boot_status *)
2151                                                        xfer->tx_message.buf;
2152
2153        if (!ti_sci_is_response_ack(resp))
2154                return -ENODEV;
2155        *bv = (resp->bootvector_low & TISCI_ADDR_LOW_MASK) |
2156                        (((u64)resp->bootvector_high  <<
2157                          TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
2158        *cfg_flags = resp->config_flags;
2159        *ctrl_flags = resp->control_flags;
2160        *sts_flags = resp->status_flags;
2161
2162        return ret;
2163}
2164
2165/**
2166 * ti_sci_proc_wait_boot_status_no_wait() - Helper function to wait for a
2167 *                              processor boot status without requesting or
2168 *                              waiting for a response.
2169 * @proc_id:                    Processor ID this request is for
2170 * @num_wait_iterations:        Total number of iterations we will check before
2171 *                              we will timeout and give up
2172 * @num_match_iterations:       How many iterations should we have continued
2173 *                              status to account for status bits glitching.
2174 *                              This is to make sure that match occurs for
2175 *                              consecutive checks. This implies that the
2176 *                              worst case should consider that the stable
2177 *                              time should at the worst be num_wait_iterations
2178 *                              num_match_iterations to prevent timeout.
2179 * @delay_per_iteration_us:     Specifies how long to wait (in micro seconds)
2180 *                              between each status checks. This is the minimum
2181 *                              duration, and overhead of register reads and
2182 *                              checks are on top of this and can vary based on
2183 *                              varied conditions.
2184 * @delay_before_iterations_us: Specifies how long to wait (in micro seconds)
2185 *                              before the very first check in the first
2186 *                              iteration of status check loop. This is the
2187 *                              minimum duration, and overhead of register
2188 *                              reads and checks are.
2189 * @status_flags_1_set_all_wait:If non-zero, Specifies that all bits of the
2190 *                              status matching this field requested MUST be 1.
2191 * @status_flags_1_set_any_wait:If non-zero, Specifies that at least one of the
2192 *                              bits matching this field requested MUST be 1.
2193 * @status_flags_1_clr_all_wait:If non-zero, Specifies that all bits of the
2194 *                              status matching this field requested MUST be 0.
2195 * @status_flags_1_clr_any_wait:If non-zero, Specifies that at least one of the
2196 *                              bits matching this field requested MUST be 0.
2197 *
2198 * Return: 0 if all goes well, else appropriate error message
2199 */
2200static int
2201ti_sci_proc_wait_boot_status_no_wait(const struct ti_sci_handle *handle,
2202                                     u8 proc_id,
2203                                     u8 num_wait_iterations,
2204                                     u8 num_match_iterations,
2205                                     u8 delay_per_iteration_us,
2206                                     u8 delay_before_iterations_us,
2207                                     u32 status_flags_1_set_all_wait,
2208                                     u32 status_flags_1_set_any_wait,
2209                                     u32 status_flags_1_clr_all_wait,
2210                                     u32 status_flags_1_clr_any_wait)
2211{
2212        struct ti_sci_msg_req_wait_proc_boot_status req;
2213        struct ti_sci_info *info;
2214        struct ti_sci_xfer *xfer;
2215        int ret = 0;
2216
2217        if (IS_ERR(handle))
2218                return PTR_ERR(handle);
2219        if (!handle)
2220                return -EINVAL;
2221
2222        info = handle_to_ti_sci_info(handle);
2223
2224        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_WAIT_PROC_BOOT_STATUS,
2225                                     TI_SCI_FLAG_REQ_GENERIC_NORESPONSE,
2226                                     (u32 *)&req, sizeof(req), 0);
2227        if (IS_ERR(xfer)) {
2228                ret = PTR_ERR(xfer);
2229                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
2230                return ret;
2231        }
2232        req.processor_id = proc_id;
2233        req.num_wait_iterations = num_wait_iterations;
2234        req.num_match_iterations = num_match_iterations;
2235        req.delay_per_iteration_us = delay_per_iteration_us;
2236        req.delay_before_iterations_us = delay_before_iterations_us;
2237        req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
2238        req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
2239        req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
2240        req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
2241
2242        ret = ti_sci_do_xfer(info, xfer);
2243        if (ret)
2244                dev_err(info->dev, "Mbox send fail %d\n", ret);
2245
2246        return ret;
2247}
2248
2249/**
2250 * ti_sci_cmd_proc_shutdown_no_wait() - Command to shutdown a core without
2251 *              requesting or waiting for a response. Note that this API call
2252 *              should be followed by placing the respective processor into
2253 *              either WFE or WFI mode.
2254 * @handle:     Pointer to TI SCI handle
2255 * @proc_id:    Processor ID this request is for
2256 *
2257 * Return: 0 if all went well, else returns appropriate error value.
2258 */
2259static int ti_sci_cmd_proc_shutdown_no_wait(const struct ti_sci_handle *handle,
2260                                            u8 proc_id)
2261{
2262        int ret;
2263
2264        /*
2265         * Send the core boot status wait message waiting for either WFE or
2266         * WFI without requesting or waiting for a TISCI response with the
2267         * maximum wait time to give us the best chance to get to the WFE/WFI
2268         * command that should follow the invocation of this API before the
2269         * DMSC-internal processing of this command times out. Note that
2270         * waiting for the R5 WFE/WFI flags will also work on an ARMV8 type
2271         * core as the related flag bit positions are the same.
2272         */
2273        ret = ti_sci_proc_wait_boot_status_no_wait(handle, proc_id,
2274                U8_MAX, 100, U8_MAX, U8_MAX,
2275                0, PROC_BOOT_STATUS_FLAG_R5_WFE | PROC_BOOT_STATUS_FLAG_R5_WFI,
2276                0, 0);
2277        if (ret) {
2278                dev_err(info->dev, "Sending core %u wait message fail %d\n",
2279                        proc_id, ret);
2280                return ret;
2281        }
2282
2283        /*
2284         * Release a processor managed by TISCI without requesting or waiting
2285         * for a response.
2286         */
2287        ret = ti_sci_set_device_state_no_wait(handle, proc_id, 0,
2288                                              MSG_DEVICE_SW_STATE_AUTO_OFF);
2289        if (ret)
2290                dev_err(info->dev, "Sending core %u shutdown message fail %d\n",
2291                        proc_id, ret);
2292
2293        return ret;
2294}
2295
2296/**
2297 * ti_sci_cmd_ring_config() - configure RA ring
2298 * @handle:     pointer to TI SCI handle
2299 * @valid_params: Bitfield defining validity of ring configuration parameters.
2300 * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated
2301 * @index: Ring index.
2302 * @addr_lo: The ring base address lo 32 bits
2303 * @addr_hi: The ring base address hi 32 bits
2304 * @count: Number of ring elements.
2305 * @mode: The mode of the ring
2306 * @size: The ring element size.
2307 * @order_id: Specifies the ring's bus order ID.
2308 *
2309 * Return: 0 if all went well, else returns appropriate error value.
2310 *
2311 * See @ti_sci_msg_rm_ring_cfg_req for more info.
2312 */
2313static int ti_sci_cmd_ring_config(const struct ti_sci_handle *handle,
2314                                  u32 valid_params, u16 nav_id, u16 index,
2315                                  u32 addr_lo, u32 addr_hi, u32 count,
2316                                  u8 mode, u8 size, u8 order_id)
2317{
2318        struct ti_sci_msg_rm_ring_cfg_resp *resp;
2319        struct ti_sci_msg_rm_ring_cfg_req req;
2320        struct ti_sci_xfer *xfer;
2321        struct ti_sci_info *info;
2322        int ret = 0;
2323
2324        if (IS_ERR(handle))
2325                return PTR_ERR(handle);
2326        if (!handle)
2327                return -EINVAL;
2328
2329        info = handle_to_ti_sci_info(handle);
2330
2331        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_RING_CFG,
2332                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2333                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2334        if (IS_ERR(xfer)) {
2335                ret = PTR_ERR(xfer);
2336                dev_err(info->dev, "RM_RA:Message config failed(%d)\n", ret);
2337                return ret;
2338        }
2339        req.valid_params = valid_params;
2340        req.nav_id = nav_id;
2341        req.index = index;
2342        req.addr_lo = addr_lo;
2343        req.addr_hi = addr_hi;
2344        req.count = count;
2345        req.mode = mode;
2346        req.size = size;
2347        req.order_id = order_id;
2348
2349        ret = ti_sci_do_xfer(info, xfer);
2350        if (ret) {
2351                dev_err(info->dev, "RM_RA:Mbox config send fail %d\n", ret);
2352                goto fail;
2353        }
2354
2355        resp = (struct ti_sci_msg_rm_ring_cfg_resp *)xfer->tx_message.buf;
2356
2357        ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
2358
2359fail:
2360        dev_dbg(info->dev, "RM_RA:config ring %u ret:%d\n", index, ret);
2361        return ret;
2362}
2363
2364/**
2365 * ti_sci_cmd_ring_get_config() - get RA ring configuration
2366 * @handle:     pointer to TI SCI handle
2367 * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated
2368 * @index: Ring index.
2369 * @addr_lo: returns ring's base address lo 32 bits
2370 * @addr_hi: returns ring's base address hi 32 bits
2371 * @count: returns number of ring elements.
2372 * @mode: returns mode of the ring
2373 * @size: returns ring element size.
2374 * @order_id: returns ring's bus order ID.
2375 *
2376 * Return: 0 if all went well, else returns appropriate error value.
2377 *
2378 * See @ti_sci_msg_rm_ring_get_cfg_req for more info.
2379 */
2380static int ti_sci_cmd_ring_get_config(const struct ti_sci_handle *handle,
2381                                      u32 nav_id, u32 index, u8 *mode,
2382                                      u32 *addr_lo, u32 *addr_hi,
2383                                      u32 *count, u8 *size, u8 *order_id)
2384{
2385        struct ti_sci_msg_rm_ring_get_cfg_resp *resp;
2386        struct ti_sci_msg_rm_ring_get_cfg_req req;
2387        struct ti_sci_xfer *xfer;
2388        struct ti_sci_info *info;
2389        int ret = 0;
2390
2391        if (IS_ERR(handle))
2392                return PTR_ERR(handle);
2393        if (!handle)
2394                return -EINVAL;
2395
2396        info = handle_to_ti_sci_info(handle);
2397
2398        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_RING_GET_CFG,
2399                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2400                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2401        if (IS_ERR(xfer)) {
2402                ret = PTR_ERR(xfer);
2403                dev_err(info->dev,
2404                        "RM_RA:Message get config failed(%d)\n", ret);
2405                return ret;
2406        }
2407        req.nav_id = nav_id;
2408        req.index = index;
2409
2410        ret = ti_sci_do_xfer(info, xfer);
2411        if (ret) {
2412                dev_err(info->dev, "RM_RA:Mbox get config send fail %d\n", ret);
2413                goto fail;
2414        }
2415
2416        resp = (struct ti_sci_msg_rm_ring_get_cfg_resp *)xfer->tx_message.buf;
2417
2418        if (!ti_sci_is_response_ack(resp)) {
2419                ret = -ENODEV;
2420        } else {
2421                if (mode)
2422                        *mode = resp->mode;
2423                if (addr_lo)
2424                        *addr_lo = resp->addr_lo;
2425                if (addr_hi)
2426                        *addr_hi = resp->addr_hi;
2427                if (count)
2428                        *count = resp->count;
2429                if (size)
2430                        *size = resp->size;
2431                if (order_id)
2432                        *order_id = resp->order_id;
2433        };
2434
2435fail:
2436        dev_dbg(info->dev, "RM_RA:get config ring %u ret:%d\n", index, ret);
2437        return ret;
2438}
2439
2440static int ti_sci_cmd_rm_psil_pair(const struct ti_sci_handle *handle,
2441                                   u32 nav_id, u32 src_thread, u32 dst_thread)
2442{
2443        struct ti_sci_msg_hdr *resp;
2444        struct ti_sci_msg_psil_pair req;
2445        struct ti_sci_xfer *xfer;
2446        struct ti_sci_info *info;
2447        int ret = 0;
2448
2449        if (IS_ERR(handle))
2450                return PTR_ERR(handle);
2451        if (!handle)
2452                return -EINVAL;
2453
2454        info = handle_to_ti_sci_info(handle);
2455
2456        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_PSIL_PAIR,
2457                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2458                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2459        if (IS_ERR(xfer)) {
2460                ret = PTR_ERR(xfer);
2461                dev_err(info->dev, "RM_PSIL:Message alloc failed(%d)\n", ret);
2462                return ret;
2463        }
2464        req.nav_id = nav_id;
2465        req.src_thread = src_thread;
2466        req.dst_thread = dst_thread;
2467
2468        ret = ti_sci_do_xfer(info, xfer);
2469        if (ret) {
2470                dev_err(info->dev, "RM_PSIL:Mbox send fail %d\n", ret);
2471                goto fail;
2472        }
2473
2474        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
2475        ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
2476
2477fail:
2478        dev_dbg(info->dev, "RM_PSIL: nav: %u link pair %u->%u ret:%u\n",
2479                nav_id, src_thread, dst_thread, ret);
2480        return ret;
2481}
2482
2483static int ti_sci_cmd_rm_psil_unpair(const struct ti_sci_handle *handle,
2484                                     u32 nav_id, u32 src_thread, u32 dst_thread)
2485{
2486        struct ti_sci_msg_hdr *resp;
2487        struct ti_sci_msg_psil_unpair req;
2488        struct ti_sci_xfer *xfer;
2489        struct ti_sci_info *info;
2490        int ret = 0;
2491
2492        if (IS_ERR(handle))
2493                return PTR_ERR(handle);
2494        if (!handle)
2495                return -EINVAL;
2496
2497        info = handle_to_ti_sci_info(handle);
2498
2499        xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_PSIL_UNPAIR,
2500                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2501                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2502        if (IS_ERR(xfer)) {
2503                ret = PTR_ERR(xfer);
2504                dev_err(info->dev, "RM_PSIL:Message alloc failed(%d)\n", ret);
2505                return ret;
2506        }
2507        req.nav_id = nav_id;
2508        req.src_thread = src_thread;
2509        req.dst_thread = dst_thread;
2510
2511        ret = ti_sci_do_xfer(info, xfer);
2512        if (ret) {
2513                dev_err(info->dev, "RM_PSIL:Mbox send fail %d\n", ret);
2514                goto fail;
2515        }
2516
2517        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
2518        ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
2519
2520fail:
2521        dev_dbg(info->dev, "RM_PSIL: link unpair %u->%u ret:%u\n",
2522                src_thread, dst_thread, ret);
2523        return ret;
2524}
2525
2526static int ti_sci_cmd_rm_udmap_tx_ch_cfg(
2527                        const struct ti_sci_handle *handle,
2528                        const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params)
2529{
2530        struct ti_sci_msg_rm_udmap_tx_ch_cfg_resp *resp;
2531        struct ti_sci_msg_rm_udmap_tx_ch_cfg_req req;
2532        struct ti_sci_xfer *xfer;
2533        struct ti_sci_info *info;
2534        int ret = 0;
2535
2536        if (IS_ERR(handle))
2537                return PTR_ERR(handle);
2538        if (!handle)
2539                return -EINVAL;
2540
2541        info = handle_to_ti_sci_info(handle);
2542
2543        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_TX_CH_CFG,
2544                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2545                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2546        if (IS_ERR(xfer)) {
2547                ret = PTR_ERR(xfer);
2548                dev_err(info->dev, "Message TX_CH_CFG alloc failed(%d)\n", ret);
2549                return ret;
2550        }
2551        req.valid_params = params->valid_params;
2552        req.nav_id = params->nav_id;
2553        req.index = params->index;
2554        req.tx_pause_on_err = params->tx_pause_on_err;
2555        req.tx_filt_einfo = params->tx_filt_einfo;
2556        req.tx_filt_pswords = params->tx_filt_pswords;
2557        req.tx_atype = params->tx_atype;
2558        req.tx_chan_type = params->tx_chan_type;
2559        req.tx_supr_tdpkt = params->tx_supr_tdpkt;
2560        req.tx_fetch_size = params->tx_fetch_size;
2561        req.tx_credit_count = params->tx_credit_count;
2562        req.txcq_qnum = params->txcq_qnum;
2563        req.tx_priority = params->tx_priority;
2564        req.tx_qos = params->tx_qos;
2565        req.tx_orderid = params->tx_orderid;
2566        req.fdepth = params->fdepth;
2567        req.tx_sched_priority = params->tx_sched_priority;
2568
2569        ret = ti_sci_do_xfer(info, xfer);
2570        if (ret) {
2571                dev_err(info->dev, "Mbox send TX_CH_CFG fail %d\n", ret);
2572                goto fail;
2573        }
2574
2575        resp =
2576              (struct ti_sci_msg_rm_udmap_tx_ch_cfg_resp *)xfer->tx_message.buf;
2577        ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
2578
2579fail:
2580        dev_dbg(info->dev, "TX_CH_CFG: chn %u ret:%u\n", params->index, ret);
2581        return ret;
2582}
2583
2584static int ti_sci_cmd_rm_udmap_rx_ch_cfg(
2585                        const struct ti_sci_handle *handle,
2586                        const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params)
2587{
2588        struct ti_sci_msg_rm_udmap_rx_ch_cfg_resp *resp;
2589        struct ti_sci_msg_rm_udmap_rx_ch_cfg_req req;
2590        struct ti_sci_xfer *xfer;
2591        struct ti_sci_info *info;
2592        int ret = 0;
2593
2594        if (IS_ERR(handle))
2595                return PTR_ERR(handle);
2596        if (!handle)
2597                return -EINVAL;
2598
2599        info = handle_to_ti_sci_info(handle);
2600
2601        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_RX_CH_CFG,
2602                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2603                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2604        if (IS_ERR(xfer)) {
2605                ret = PTR_ERR(xfer);
2606                dev_err(info->dev, "Message RX_CH_CFG alloc failed(%d)\n", ret);
2607                return ret;
2608        }
2609
2610        req.valid_params = params->valid_params;
2611        req.nav_id = params->nav_id;
2612        req.index = params->index;
2613        req.rx_fetch_size = params->rx_fetch_size;
2614        req.rxcq_qnum = params->rxcq_qnum;
2615        req.rx_priority = params->rx_priority;
2616        req.rx_qos = params->rx_qos;
2617        req.rx_orderid = params->rx_orderid;
2618        req.rx_sched_priority = params->rx_sched_priority;
2619        req.flowid_start = params->flowid_start;
2620        req.flowid_cnt = params->flowid_cnt;
2621        req.rx_pause_on_err = params->rx_pause_on_err;
2622        req.rx_atype = params->rx_atype;
2623        req.rx_chan_type = params->rx_chan_type;
2624        req.rx_ignore_short = params->rx_ignore_short;
2625        req.rx_ignore_long = params->rx_ignore_long;
2626
2627        ret = ti_sci_do_xfer(info, xfer);
2628        if (ret) {
2629                dev_err(info->dev, "Mbox send RX_CH_CFG fail %d\n", ret);
2630                goto fail;
2631        }
2632
2633        resp =
2634              (struct ti_sci_msg_rm_udmap_rx_ch_cfg_resp *)xfer->tx_message.buf;
2635        ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
2636
2637fail:
2638        dev_dbg(info->dev, "RX_CH_CFG: chn %u ret:%d\n", params->index, ret);
2639        return ret;
2640}
2641
2642static int ti_sci_cmd_rm_udmap_rx_flow_cfg(
2643                        const struct ti_sci_handle *handle,
2644                        const struct ti_sci_msg_rm_udmap_flow_cfg *params)
2645{
2646        struct ti_sci_msg_rm_udmap_flow_cfg_resp *resp;
2647        struct ti_sci_msg_rm_udmap_flow_cfg_req req;
2648        struct ti_sci_xfer *xfer;
2649        struct ti_sci_info *info;
2650        int ret = 0;
2651
2652        if (IS_ERR(handle))
2653                return PTR_ERR(handle);
2654        if (!handle)
2655                return -EINVAL;
2656
2657        info = handle_to_ti_sci_info(handle);
2658
2659        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_FLOW_CFG,
2660                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2661                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2662        if (IS_ERR(xfer)) {
2663                ret = PTR_ERR(xfer);
2664                dev_err(dev, "RX_FL_CFG: Message alloc failed(%d)\n", ret);
2665                return ret;
2666        }
2667
2668        req.valid_params = params->valid_params;
2669        req.nav_id = params->nav_id;
2670        req.flow_index = params->flow_index;
2671        req.rx_einfo_present = params->rx_einfo_present;
2672        req.rx_psinfo_present = params->rx_psinfo_present;
2673        req.rx_error_handling = params->rx_error_handling;
2674        req.rx_desc_type = params->rx_desc_type;
2675        req.rx_sop_offset = params->rx_sop_offset;
2676        req.rx_dest_qnum = params->rx_dest_qnum;
2677        req.rx_src_tag_hi = params->rx_src_tag_hi;
2678        req.rx_src_tag_lo = params->rx_src_tag_lo;
2679        req.rx_dest_tag_hi = params->rx_dest_tag_hi;
2680        req.rx_dest_tag_lo = params->rx_dest_tag_lo;
2681        req.rx_src_tag_hi_sel = params->rx_src_tag_hi_sel;
2682        req.rx_src_tag_lo_sel = params->rx_src_tag_lo_sel;
2683        req.rx_dest_tag_hi_sel = params->rx_dest_tag_hi_sel;
2684        req.rx_dest_tag_lo_sel = params->rx_dest_tag_lo_sel;
2685        req.rx_fdq0_sz0_qnum = params->rx_fdq0_sz0_qnum;
2686        req.rx_fdq1_qnum = params->rx_fdq1_qnum;
2687        req.rx_fdq2_qnum = params->rx_fdq2_qnum;
2688        req.rx_fdq3_qnum = params->rx_fdq3_qnum;
2689        req.rx_ps_location = params->rx_ps_location;
2690
2691        ret = ti_sci_do_xfer(info, xfer);
2692        if (ret) {
2693                dev_err(dev, "RX_FL_CFG: Mbox send fail %d\n", ret);
2694                goto fail;
2695        }
2696
2697        resp =
2698               (struct ti_sci_msg_rm_udmap_flow_cfg_resp *)xfer->tx_message.buf;
2699        ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
2700
2701fail:
2702        dev_dbg(info->dev, "RX_FL_CFG: %u ret:%d\n", params->flow_index, ret);
2703        return ret;
2704}
2705
2706/**
2707 * ti_sci_cmd_set_fwl_region() - Request for configuring a firewall region
2708 * @handle:    pointer to TI SCI handle
2709 * @region:    region configuration parameters
2710 *
2711 * Return: 0 if all went well, else returns appropriate error value.
2712 */
2713static int ti_sci_cmd_set_fwl_region(const struct ti_sci_handle *handle,
2714                                     const struct ti_sci_msg_fwl_region *region)
2715{
2716        struct ti_sci_msg_fwl_set_firewall_region_req req;
2717        struct ti_sci_msg_hdr *resp;
2718        struct ti_sci_info *info;
2719        struct ti_sci_xfer *xfer;
2720        int ret = 0;
2721
2722        if (IS_ERR(handle))
2723                return PTR_ERR(handle);
2724        if (!handle)
2725                return -EINVAL;
2726
2727        info = handle_to_ti_sci_info(handle);
2728
2729        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_SET,
2730                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2731                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2732        if (IS_ERR(xfer)) {
2733                ret = PTR_ERR(xfer);
2734                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
2735                return ret;
2736        }
2737
2738        req.fwl_id = region->fwl_id;
2739        req.region = region->region;
2740        req.n_permission_regs = region->n_permission_regs;
2741        req.control = region->control;
2742        req.permissions[0] = region->permissions[0];
2743        req.permissions[1] = region->permissions[1];
2744        req.permissions[2] = region->permissions[2];
2745        req.start_address = region->start_address;
2746        req.end_address = region->end_address;
2747
2748        ret = ti_sci_do_xfer(info, xfer);
2749        if (ret) {
2750                dev_err(info->dev, "Mbox send fail %d\n", ret);
2751                return ret;
2752        }
2753
2754        resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
2755
2756        if (!ti_sci_is_response_ack(resp))
2757                return -ENODEV;
2758
2759        return 0;
2760}
2761
2762/**
2763 * ti_sci_cmd_get_fwl_region() - Request for getting a firewall region
2764 * @handle:    pointer to TI SCI handle
2765 * @region:    region configuration parameters
2766 *
2767 * Return: 0 if all went well, else returns appropriate error value.
2768 */
2769static int ti_sci_cmd_get_fwl_region(const struct ti_sci_handle *handle,
2770                                     struct ti_sci_msg_fwl_region *region)
2771{
2772        struct ti_sci_msg_fwl_get_firewall_region_req req;
2773        struct ti_sci_msg_fwl_get_firewall_region_resp *resp;
2774        struct ti_sci_info *info;
2775        struct ti_sci_xfer *xfer;
2776        int ret = 0;
2777
2778        if (IS_ERR(handle))
2779                return PTR_ERR(handle);
2780        if (!handle)
2781                return -EINVAL;
2782
2783        info = handle_to_ti_sci_info(handle);
2784
2785        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_GET,
2786                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2787                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2788        if (IS_ERR(xfer)) {
2789                ret = PTR_ERR(xfer);
2790                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
2791                return ret;
2792        }
2793
2794        req.fwl_id = region->fwl_id;
2795        req.region = region->region;
2796        req.n_permission_regs = region->n_permission_regs;
2797
2798        ret = ti_sci_do_xfer(info, xfer);
2799        if (ret) {
2800                dev_err(info->dev, "Mbox send fail %d\n", ret);
2801                return ret;
2802        }
2803
2804        resp = (struct ti_sci_msg_fwl_get_firewall_region_resp *)xfer->tx_message.buf;
2805
2806        if (!ti_sci_is_response_ack(resp))
2807                return -ENODEV;
2808
2809        region->fwl_id = resp->fwl_id;
2810        region->region = resp->region;
2811        region->n_permission_regs = resp->n_permission_regs;
2812        region->control = resp->control;
2813        region->permissions[0] = resp->permissions[0];
2814        region->permissions[1] = resp->permissions[1];
2815        region->permissions[2] = resp->permissions[2];
2816        region->start_address = resp->start_address;
2817        region->end_address = resp->end_address;
2818
2819        return 0;
2820}
2821
2822/**
2823 * ti_sci_cmd_change_fwl_owner() - Request for changing a firewall owner
2824 * @handle:    pointer to TI SCI handle
2825 * @region:    region configuration parameters
2826 *
2827 * Return: 0 if all went well, else returns appropriate error value.
2828 */
2829static int ti_sci_cmd_change_fwl_owner(const struct ti_sci_handle *handle,
2830                                       struct ti_sci_msg_fwl_owner *owner)
2831{
2832        struct ti_sci_msg_fwl_change_owner_info_req req;
2833        struct ti_sci_msg_fwl_change_owner_info_resp *resp;
2834        struct ti_sci_info *info;
2835        struct ti_sci_xfer *xfer;
2836        int ret = 0;
2837
2838        if (IS_ERR(handle))
2839                return PTR_ERR(handle);
2840        if (!handle)
2841                return -EINVAL;
2842
2843        info = handle_to_ti_sci_info(handle);
2844
2845        xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_CHANGE_OWNER,
2846                                     TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2847                                     (u32 *)&req, sizeof(req), sizeof(*resp));
2848        if (IS_ERR(xfer)) {
2849                ret = PTR_ERR(xfer);
2850                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
2851                return ret;
2852        }
2853
2854        req.fwl_id = owner->fwl_id;
2855        req.region = owner->region;
2856        req.owner_index = owner->owner_index;
2857
2858        ret = ti_sci_do_xfer(info, xfer);
2859        if (ret) {
2860                dev_err(info->dev, "Mbox send fail %d\n", ret);
2861                return ret;
2862        }
2863
2864        resp = (struct ti_sci_msg_fwl_change_owner_info_resp *)xfer->tx_message.buf;
2865
2866        if (!ti_sci_is_response_ack(resp))
2867                return -ENODEV;
2868
2869        owner->fwl_id = resp->fwl_id;
2870        owner->region = resp->region;
2871        owner->owner_index = resp->owner_index;
2872        owner->owner_privid = resp->owner_privid;
2873        owner->owner_permission_bits = resp->owner_permission_bits;
2874
2875        return ret;
2876}
2877
2878/*
2879 * ti_sci_setup_ops() - Setup the operations structures
2880 * @info:       pointer to TISCI pointer
2881 */
2882static void ti_sci_setup_ops(struct ti_sci_info *info)
2883{
2884        struct ti_sci_ops *ops = &info->handle.ops;
2885        struct ti_sci_board_ops *bops = &ops->board_ops;
2886        struct ti_sci_dev_ops *dops = &ops->dev_ops;
2887        struct ti_sci_clk_ops *cops = &ops->clk_ops;
2888        struct ti_sci_core_ops *core_ops = &ops->core_ops;
2889        struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
2890        struct ti_sci_proc_ops *pops = &ops->proc_ops;
2891        struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
2892        struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops;
2893        struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops;
2894        struct ti_sci_fwl_ops *fwl_ops = &ops->fwl_ops;
2895
2896        bops->board_config = ti_sci_cmd_set_board_config;
2897        bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
2898        bops->board_config_security = ti_sci_cmd_set_board_config_security;
2899        bops->board_config_pm = ti_sci_cmd_set_board_config_pm;
2900
2901        dops->get_device = ti_sci_cmd_get_device;
2902        dops->get_device_exclusive = ti_sci_cmd_get_device_exclusive;
2903        dops->idle_device = ti_sci_cmd_idle_device;
2904        dops->idle_device_exclusive = ti_sci_cmd_idle_device_exclusive;
2905        dops->put_device = ti_sci_cmd_put_device;
2906        dops->is_valid = ti_sci_cmd_dev_is_valid;
2907        dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
2908        dops->is_idle = ti_sci_cmd_dev_is_idle;
2909        dops->is_stop = ti_sci_cmd_dev_is_stop;
2910        dops->is_on = ti_sci_cmd_dev_is_on;
2911        dops->is_transitioning = ti_sci_cmd_dev_is_trans;
2912        dops->set_device_resets = ti_sci_cmd_set_device_resets;
2913        dops->get_device_resets = ti_sci_cmd_get_device_resets;
2914        dops->release_exclusive_devices = ti_sci_cmd_release_exclusive_devices;
2915
2916        cops->get_clock = ti_sci_cmd_get_clock;
2917        cops->idle_clock = ti_sci_cmd_idle_clock;
2918        cops->put_clock = ti_sci_cmd_put_clock;
2919        cops->is_auto = ti_sci_cmd_clk_is_auto;
2920        cops->is_on = ti_sci_cmd_clk_is_on;
2921        cops->is_off = ti_sci_cmd_clk_is_off;
2922
2923        cops->set_parent = ti_sci_cmd_clk_set_parent;
2924        cops->get_parent = ti_sci_cmd_clk_get_parent;
2925        cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
2926
2927        cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
2928        cops->set_freq = ti_sci_cmd_clk_set_freq;
2929        cops->get_freq = ti_sci_cmd_clk_get_freq;
2930
2931        core_ops->reboot_device = ti_sci_cmd_core_reboot;
2932        core_ops->query_msmc = ti_sci_cmd_query_msmc;
2933
2934        rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
2935        rm_core_ops->get_range_from_shost =
2936                ti_sci_cmd_get_resource_range_from_shost;
2937
2938        pops->proc_request = ti_sci_cmd_proc_request;
2939        pops->proc_release = ti_sci_cmd_proc_release;
2940        pops->proc_handover = ti_sci_cmd_proc_handover;
2941        pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg;
2942        pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl;
2943        pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image;
2944        pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status;
2945        pops->proc_shutdown_no_wait = ti_sci_cmd_proc_shutdown_no_wait;
2946
2947        rops->config = ti_sci_cmd_ring_config;
2948        rops->get_config = ti_sci_cmd_ring_get_config;
2949
2950        psilops->pair = ti_sci_cmd_rm_psil_pair;
2951        psilops->unpair = ti_sci_cmd_rm_psil_unpair;
2952
2953        udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg;
2954        udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg;
2955        udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg;
2956
2957        fwl_ops->set_fwl_region = ti_sci_cmd_set_fwl_region;
2958        fwl_ops->get_fwl_region = ti_sci_cmd_get_fwl_region;
2959        fwl_ops->change_fwl_owner = ti_sci_cmd_change_fwl_owner;
2960}
2961
2962/**
2963 * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW
2964 * @dev:        Pointer to the SYSFW device
2965 *
2966 * Return: pointer to handle if successful, else EINVAL if invalid conditions
2967 *         are encountered.
2968 */
2969const
2970struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev)
2971{
2972        if (!sci_dev)
2973                return ERR_PTR(-EINVAL);
2974
2975        struct ti_sci_info *info = dev_get_priv(sci_dev);
2976
2977        if (!info)
2978                return ERR_PTR(-EINVAL);
2979
2980        struct ti_sci_handle *handle = &info->handle;
2981
2982        if (!handle)
2983                return ERR_PTR(-EINVAL);
2984
2985        return handle;
2986}
2987
2988/**
2989 * ti_sci_get_handle() - Get the TI SCI handle for a device
2990 * @dev:        Pointer to device for which we want SCI handle
2991 *
2992 * Return: pointer to handle if successful, else EINVAL if invalid conditions
2993 *         are encountered.
2994 */
2995const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev)
2996{
2997        if (!dev)
2998                return ERR_PTR(-EINVAL);
2999
3000        struct udevice *sci_dev = dev_get_parent(dev);
3001
3002        return ti_sci_get_handle_from_sysfw(sci_dev);
3003}
3004
3005/**
3006 * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
3007 * @dev:        device node
3008 * @propname:   property name containing phandle on TISCI node
3009 *
3010 * Return: pointer to handle if successful, else appropriate error value.
3011 */
3012const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev,
3013                                                  const char *property)
3014{
3015        struct ti_sci_info *entry, *info = NULL;
3016        u32 phandle, err;
3017        ofnode node;
3018
3019        err = ofnode_read_u32(dev_ofnode(dev), property, &phandle);
3020        if (err)
3021                return ERR_PTR(err);
3022
3023        node = ofnode_get_by_phandle(phandle);
3024        if (!ofnode_valid(node))
3025                return ERR_PTR(-EINVAL);
3026
3027        list_for_each_entry(entry, &ti_sci_list, list)
3028                if (ofnode_equal(dev_ofnode(entry->dev), node)) {
3029                        info = entry;
3030                        break;
3031                }
3032
3033        if (!info)
3034                return ERR_PTR(-ENODEV);
3035
3036        return &info->handle;
3037}
3038
3039/**
3040 * ti_sci_of_to_info() - generate private data from device tree
3041 * @dev:        corresponding system controller interface device
3042 * @info:       pointer to driver specific private data
3043 *
3044 * Return: 0 if all goes good, else appropriate error message.
3045 */
3046static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info)
3047{
3048        int ret;
3049
3050        ret = mbox_get_by_name(dev, "tx", &info->chan_tx);
3051        if (ret) {
3052                dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n",
3053                        __func__, ret);
3054                return ret;
3055        }
3056
3057        ret = mbox_get_by_name(dev, "rx", &info->chan_rx);
3058        if (ret) {
3059                dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n",
3060                        __func__, ret);
3061                return ret;
3062        }
3063
3064        /* Notify channel is optional. Enable only if populated */
3065        ret = mbox_get_by_name(dev, "notify", &info->chan_notify);
3066        if (ret) {
3067                dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n",
3068                        __func__, ret);
3069        }
3070
3071        info->host_id = dev_read_u32_default(dev, "ti,host-id",
3072                                             info->desc->default_host_id);
3073
3074        info->is_secure = dev_read_bool(dev, "ti,secure-host");
3075
3076        return 0;
3077}
3078
3079/**
3080 * ti_sci_probe() - Basic probe
3081 * @dev:        corresponding system controller interface device
3082 *
3083 * Return: 0 if all goes good, else appropriate error message.
3084 */
3085static int ti_sci_probe(struct udevice *dev)
3086{
3087        struct ti_sci_info *info;
3088        int ret;
3089
3090        debug("%s(dev=%p)\n", __func__, dev);
3091
3092        info = dev_get_priv(dev);
3093        info->desc = (void *)dev_get_driver_data(dev);
3094
3095        ret = ti_sci_of_to_info(dev, info);
3096        if (ret) {
3097                dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
3098                return ret;
3099        }
3100
3101        info->dev = dev;
3102        info->seq = 0xA;
3103
3104        list_add_tail(&info->list, &ti_sci_list);
3105        ti_sci_setup_ops(info);
3106
3107        ret = ti_sci_cmd_get_revision(&info->handle);
3108
3109        INIT_LIST_HEAD(&info->dev_list);
3110
3111        return ret;
3112}
3113
3114/*
3115 * ti_sci_get_free_resource() - Get a free resource from TISCI resource.
3116 * @res:        Pointer to the TISCI resource
3117 *
3118 * Return: resource num if all went ok else TI_SCI_RESOURCE_NULL.
3119 */
3120u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
3121{
3122        u16 set, free_bit;
3123
3124        for (set = 0; set < res->sets; set++) {
3125                free_bit = find_first_zero_bit(res->desc[set].res_map,
3126                                               res->desc[set].num);
3127                if (free_bit != res->desc[set].num) {
3128                        set_bit(free_bit, res->desc[set].res_map);
3129                        return res->desc[set].start + free_bit;
3130                }
3131        }
3132
3133        return TI_SCI_RESOURCE_NULL;
3134}
3135
3136/**
3137 * ti_sci_release_resource() - Release a resource from TISCI resource.
3138 * @res:        Pointer to the TISCI resource
3139 */
3140void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
3141{
3142        u16 set;
3143
3144        for (set = 0; set < res->sets; set++) {
3145                if (res->desc[set].start <= id &&
3146                    (res->desc[set].num + res->desc[set].start) > id)
3147                        clear_bit(id - res->desc[set].start,
3148                                  res->desc[set].res_map);
3149        }
3150}
3151
3152/**
3153 * devm_ti_sci_get_of_resource() - Get a TISCI resource assigned to a device
3154 * @handle:     TISCI handle
3155 * @dev:        Device pointer to which the resource is assigned
3156 * @of_prop:    property name by which the resource are represented
3157 *
3158 * Note: This function expects of_prop to be in the form of tuples
3159 *      <type, subtype>. Allocates and initializes ti_sci_resource structure
3160 *      for each of_prop. Client driver can directly call
3161 *      ti_sci_(get_free, release)_resource apis for handling the resource.
3162 *
3163 * Return: Pointer to ti_sci_resource if all went well else appropriate
3164 *         error pointer.
3165 */
3166struct ti_sci_resource *
3167devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
3168                            struct udevice *dev, u32 dev_id, char *of_prop)
3169{
3170        u32 resource_subtype;
3171        u16 resource_type;
3172        struct ti_sci_resource *res;
3173        bool valid_set = false;
3174        int sets, i, ret;
3175        u32 *temp;
3176
3177        res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
3178        if (!res)
3179                return ERR_PTR(-ENOMEM);
3180
3181        sets = dev_read_size(dev, of_prop);
3182        if (sets < 0) {
3183                dev_err(dev, "%s resource type ids not available\n", of_prop);
3184                return ERR_PTR(sets);
3185        }
3186        temp = malloc(sets);
3187        sets /= sizeof(u32);
3188        res->sets = sets;
3189
3190        res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc),
3191                                 GFP_KERNEL);
3192        if (!res->desc)
3193                return ERR_PTR(-ENOMEM);
3194
3195        ret = ti_sci_get_resource_type(handle_to_ti_sci_info(handle), dev_id,
3196                                       &resource_type);
3197        if (ret) {
3198                dev_err(dev, "No valid resource type for %u\n", dev_id);
3199                return ERR_PTR(-EINVAL);
3200        }
3201
3202        ret = dev_read_u32_array(dev, of_prop, temp, res->sets);
3203        if (ret)
3204                return ERR_PTR(-EINVAL);
3205
3206        for (i = 0; i < res->sets; i++) {
3207                resource_subtype = temp[i];
3208                ret = handle->ops.rm_core_ops.get_range(handle, dev_id,
3209                                                        resource_subtype,
3210                                                        &res->desc[i].start,
3211                                                        &res->desc[i].num);
3212                if (ret) {
3213                        dev_dbg(dev, "type %d subtype %d not allocated for host %d\n",
3214                                resource_type, resource_subtype,
3215                                handle_to_ti_sci_info(handle)->host_id);
3216                        res->desc[i].start = 0;
3217                        res->desc[i].num = 0;
3218                        continue;
3219                }
3220
3221                valid_set = true;
3222                dev_dbg(dev, "res type = %d, subtype = %d, start = %d, num = %d\n",
3223                        resource_type, resource_subtype, res->desc[i].start,
3224                        res->desc[i].num);
3225
3226                res->desc[i].res_map =
3227                        devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) *
3228                                     sizeof(*res->desc[i].res_map), GFP_KERNEL);
3229                if (!res->desc[i].res_map)
3230                        return ERR_PTR(-ENOMEM);
3231        }
3232
3233        if (valid_set)
3234                return res;
3235
3236        return ERR_PTR(-EINVAL);
3237}
3238
3239/* Description for K2G */
3240static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
3241        .default_host_id = 2,
3242        /* Conservative duration */
3243        .max_rx_timeout_ms = 10000,
3244        /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
3245        .max_msgs = 20,
3246        .max_msg_size = 64,
3247        .rm_type_map = NULL,
3248};
3249
3250static struct ti_sci_rm_type_map ti_sci_am654_rm_type_map[] = {
3251        {.dev_id = 56, .type = 0x00b}, /* GIC_IRQ */
3252        {.dev_id = 179, .type = 0x000}, /* MAIN_NAV_UDMASS_IA0 */
3253        {.dev_id = 187, .type = 0x009}, /* MAIN_NAV_RA */
3254        {.dev_id = 188, .type = 0x006}, /* MAIN_NAV_UDMAP */
3255        {.dev_id = 194, .type = 0x007}, /* MCU_NAV_UDMAP */
3256        {.dev_id = 195, .type = 0x00a}, /* MCU_NAV_RA */
3257        {.dev_id = 0, .type = 0x000}, /* end of table */
3258};
3259
3260/* Description for AM654 */
3261static const struct ti_sci_desc ti_sci_pmmc_am654_desc = {
3262        .default_host_id = 12,
3263        /* Conservative duration */
3264        .max_rx_timeout_ms = 10000,
3265        /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
3266        .max_msgs = 20,
3267        .max_msg_size = 60,
3268        .rm_type_map = ti_sci_am654_rm_type_map,
3269};
3270
3271static const struct udevice_id ti_sci_ids[] = {
3272        {
3273                .compatible = "ti,k2g-sci",
3274                .data = (ulong)&ti_sci_pmmc_k2g_desc
3275        },
3276        {
3277                .compatible = "ti,am654-sci",
3278                .data = (ulong)&ti_sci_pmmc_am654_desc
3279        },
3280        { /* Sentinel */ },
3281};
3282
3283U_BOOT_DRIVER(ti_sci) = {
3284        .name = "ti_sci",
3285        .id = UCLASS_FIRMWARE,
3286        .of_match = ti_sci_ids,
3287        .probe = ti_sci_probe,
3288        .priv_auto_alloc_size = sizeof(struct ti_sci_info),
3289};
3290