Merge branch 'next' of git://git.denx.de/u-boot-usb into next
[oweals/u-boot.git] / drivers / firmware / ti_sci.c
index 91481260411aa5a0b7f13ad823089f98a1da2236..c3f95b252f24f3969d7cf5838e6304f7fe36c805 100644 (file)
 #include <dm.h>
 #include <errno.h>
 #include <mailbox.h>
+#include <malloc.h>
 #include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <linux/compat.h>
 #include <linux/err.h>
 #include <linux/soc/ti/k3-sec-proxy.h>
 #include <linux/soc/ti/ti_sci_protocol.h>
@@ -31,16 +35,37 @@ struct ti_sci_xfer {
        u8 rx_len;
 };
 
+/**
+ * struct ti_sci_rm_type_map - Structure representing TISCI Resource
+ *                             management representation of dev_ids.
+ * @dev_id:    TISCI device ID
+ * @type:      Corresponding id as identified by TISCI RM.
+ *
+ * Note: This is used only as a work around for using RM range apis
+ *     for AM654 SoC. For future SoCs dev_id will be used as type
+ *     for RM range APIs. In order to maintain ABI backward compatibility
+ *     type is not being changed for AM654 SoC.
+ */
+struct ti_sci_rm_type_map {
+       u32 dev_id;
+       u16 type;
+};
+
 /**
  * struct ti_sci_desc - Description of SoC integration
- * @host_id:           Host identifier representing the compute entity
- * @max_rx_timeout_us: Timeout for communication with SoC (in Microseconds)
- * @max_msg_size:      Maximum size of data per message that can be handled.
+ * @default_host_id:   Host identifier representing the compute entity
+ * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
+ * @max_msgs: Maximum number of messages that can be pending
+ *               simultaneously in the system
+ * @max_msg_size: Maximum size of data per message that can be handled.
+ * @rm_type_map: RM resource type mapping structure.
  */
 struct ti_sci_desc {
-       u8 host_id;
-       int max_rx_timeout_us;
+       u8 default_host_id;
+       int max_rx_timeout_ms;
+       int max_msgs;
        int max_msg_size;
+       struct ti_sci_rm_type_map *rm_type_map;
 };
 
 /**
@@ -65,11 +90,18 @@ struct ti_sci_info {
        struct mbox_chan chan_notify;
        struct ti_sci_xfer xfer;
        struct list_head list;
+       struct list_head dev_list;
        bool is_secure;
        u8 host_id;
        u8 seq;
 };
 
+struct ti_sci_exclusive_dev {
+       u32 id;
+       u32 count;
+       struct list_head list;
+};
+
 #define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
 
 /**
@@ -79,7 +111,8 @@ struct ti_sci_info {
  * @msg_flags: Flag to set for the message
  * @buf:       Buffer to be send to mailbox channel
  * @tx_message_size: transmit message size
- * @rx_message_size: receive message size
+ * @rx_message_size: receive message size. may be set to zero for send-only
+ *                  transactions.
  *
  * Helper function which is used by various command functions that are
  * exposed to clients of this driver for allocating a message traffic event.
@@ -99,7 +132,8 @@ static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info,
        /* Ensure we have sane transfer sizes */
        if (rx_message_size > info->desc->max_msg_size ||
            tx_message_size > info->desc->max_msg_size ||
-           rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr))
+           (rx_message_size > 0 && rx_message_size < sizeof(*hdr)) ||
+           tx_message_size < sizeof(*hdr))
                return ERR_PTR(-ERANGE);
 
        info->seq = ~info->seq;
@@ -136,7 +170,7 @@ static inline int ti_sci_get_response(struct ti_sci_info *info,
        int ret;
 
        /* Receive the response */
-       ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_us);
+       ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_ms * 1000);
        if (ret) {
                dev_err(info->dev, "%s: Message receive failed. ret = %d\n",
                        __func__, ret);
@@ -197,7 +231,9 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info,
 
                xfer->tx_message.buf = (u32 *)secure_buf;
                xfer->tx_message.len += sizeof(secure_hdr);
-               xfer->rx_len += sizeof(secure_hdr);
+
+               if (xfer->rx_len)
+                       xfer->rx_len += sizeof(secure_hdr);
        }
 
        /* Send the message */
@@ -208,7 +244,11 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info,
                return ret;
        }
 
-       return ti_sci_get_response(info, xfer, &info->chan_rx);
+       /* Get response if requested */
+       if (xfer->rx_len)
+               ret = ti_sci_get_response(info, xfer, &info->chan_rx);
+
+       return ret;
 }
 
 /**
@@ -235,7 +275,8 @@ static int ti_sci_cmd_get_revision(struct ti_sci_handle *handle)
 
        info = handle_to_ti_sci_info(handle);
 
-       xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION, 0x0,
+       xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
                                     (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr),
                                     sizeof(*rev_info));
        if (IS_ERR(xfer)) {
@@ -396,6 +437,47 @@ static int ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle *handle,
                                              addr, size);
 }
 
+static struct ti_sci_exclusive_dev
+*ti_sci_get_exclusive_dev(struct list_head *dev_list, u32 id)
+{
+       struct ti_sci_exclusive_dev *dev;
+
+       list_for_each_entry(dev, dev_list, list)
+               if (dev->id == id)
+                       return dev;
+
+       return NULL;
+}
+
+static void ti_sci_add_exclusive_dev(struct ti_sci_info *info, u32 id)
+{
+       struct ti_sci_exclusive_dev *dev;
+
+       dev = ti_sci_get_exclusive_dev(&info->dev_list, id);
+       if (dev) {
+               dev->count++;
+               return;
+       }
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       dev->id = id;
+       dev->count = 1;
+       INIT_LIST_HEAD(&dev->list);
+       list_add_tail(&dev->list, &info->dev_list);
+}
+
+static void ti_sci_delete_exclusive_dev(struct ti_sci_info *info, u32 id)
+{
+       struct ti_sci_exclusive_dev *dev;
+
+       dev = ti_sci_get_exclusive_dev(&info->dev_list, id);
+       if (!dev)
+               return;
+
+       if (dev->count > 0)
+               dev->count--;
+}
+
 /**
  * ti_sci_set_device_state() - Set device state helper
  * @handle:    pointer to TI SCI handle
@@ -443,6 +525,54 @@ static int ti_sci_set_device_state(const struct ti_sci_handle *handle,
        if (!ti_sci_is_response_ack(resp))
                return -ENODEV;
 
+       if (state == MSG_DEVICE_SW_STATE_AUTO_OFF)
+               ti_sci_delete_exclusive_dev(info, id);
+       else if (flags & MSG_FLAG_DEVICE_EXCLUSIVE)
+               ti_sci_add_exclusive_dev(info, id);
+
+       return ret;
+}
+
+/**
+ * ti_sci_set_device_state_no_wait() - Set device state helper without
+ *                                    requesting or waiting for a response.
+ * @handle:    pointer to TI SCI handle
+ * @id:                Device identifier
+ * @flags:     flags to setup for the device
+ * @state:     State to move the device to
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_set_device_state_no_wait(const struct ti_sci_handle *handle,
+                                          u32 id, u32 flags, u8 state)
+{
+       struct ti_sci_msg_req_set_device_state req;
+       struct ti_sci_info *info;
+       struct ti_sci_xfer *xfer;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
+                                    flags | TI_SCI_FLAG_REQ_GENERIC_NORESPONSE,
+                                    (u32 *)&req, sizeof(req), 0);
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req.id = id;
+       req.state = state;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret)
+               dev_err(info->dev, "Mbox send fail %d\n", ret);
+
        return ret;
 }
 
@@ -477,8 +607,8 @@ static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
 
        info = handle_to_ti_sci_info(handle);
 
-       /* Response is expected, so need of any flags */
-       xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE, 0,
+       xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
                                     (u32 *)&req, sizeof(req), sizeof(*resp));
        if (IS_ERR(xfer)) {
                ret = PTR_ERR(xfer);
@@ -524,8 +654,14 @@ static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
  */
 static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
 {
-       return ti_sci_set_device_state(handle, id,
-                                      MSG_FLAG_DEVICE_EXCLUSIVE,
+       return ti_sci_set_device_state(handle, id, 0,
+                                      MSG_DEVICE_SW_STATE_ON);
+}
+
+static int ti_sci_cmd_get_device_exclusive(const struct ti_sci_handle *handle,
+                                          u32 id)
+{
+       return ti_sci_set_device_state(handle, id, MSG_FLAG_DEVICE_EXCLUSIVE,
                                       MSG_DEVICE_SW_STATE_ON);
 }
 
@@ -543,7 +679,14 @@ static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
 static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
 {
        return ti_sci_set_device_state(handle, id,
-                                      MSG_FLAG_DEVICE_EXCLUSIVE,
+                                      0,
+                                      MSG_DEVICE_SW_STATE_RETENTION);
+}
+
+static int ti_sci_cmd_idle_device_exclusive(const struct ti_sci_handle *handle,
+                                           u32 id)
+{
+       return ti_sci_set_device_state(handle, id, MSG_FLAG_DEVICE_EXCLUSIVE,
                                       MSG_DEVICE_SW_STATE_RETENTION);
 }
 
@@ -560,8 +703,27 @@ static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
  */
 static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id)
 {
-       return ti_sci_set_device_state(handle, id,
-                                      0, MSG_DEVICE_SW_STATE_AUTO_OFF);
+       return ti_sci_set_device_state(handle, id, 0,
+                                      MSG_DEVICE_SW_STATE_AUTO_OFF);
+}
+
+static
+int ti_sci_cmd_release_exclusive_devices(const struct ti_sci_handle *handle)
+{
+       struct ti_sci_exclusive_dev *dev, *tmp;
+       struct ti_sci_info *info;
+       int i, cnt;
+
+       info = handle_to_ti_sci_info(handle);
+
+       list_for_each_entry_safe(dev, tmp, &info->dev_list, list) {
+               cnt = dev->count;
+               debug("%s: id = %d, cnt = %d\n", __func__, dev->id, cnt);
+               for (i = 0; i < cnt; i++)
+                       ti_sci_cmd_put_device(handle, dev->id);
+       }
+
+       return 0;
 }
 
 /**
@@ -1441,6 +1603,199 @@ static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
        return ret;
 }
 
+static int ti_sci_get_resource_type(struct ti_sci_info *info, u16 dev_id,
+                                   u16 *type)
+{
+       struct ti_sci_rm_type_map *rm_type_map = info->desc->rm_type_map;
+       bool found = false;
+       int i;
+
+       /* If map is not provided then assume dev_id is used as type */
+       if (!rm_type_map) {
+               *type = dev_id;
+               return 0;
+       }
+
+       for (i = 0; rm_type_map[i].dev_id; i++) {
+               if (rm_type_map[i].dev_id == dev_id) {
+                       *type = rm_type_map[i].type;
+                       found = true;
+                       break;
+               }
+       }
+
+       if (!found)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ * ti_sci_get_resource_range - Helper to get a range of resources assigned
+ *                            to a host. Resource is uniquely identified by
+ *                            type and subtype.
+ * @handle:            Pointer to TISCI handle.
+ * @dev_id:            TISCI device ID.
+ * @subtype:           Resource assignment subtype that is being requested
+ *                     from the given device.
+ * @s_host:            Host processor ID to which the resources are allocated
+ * @range_start:       Start index of the resource range
+ * @range_num:         Number of resources in the range
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_get_resource_range(const struct ti_sci_handle *handle,
+                                    u32 dev_id, u8 subtype, u8 s_host,
+                                    u16 *range_start, u16 *range_num)
+{
+       struct ti_sci_msg_resp_get_resource_range *resp;
+       struct ti_sci_msg_req_get_resource_range req;
+       struct ti_sci_xfer *xfer;
+       struct ti_sci_info *info;
+       u16 type;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_RESOURCE_RANGE,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+
+       ret = ti_sci_get_resource_type(info, dev_id, &type);
+       if (ret) {
+               dev_err(dev, "rm type lookup failed for %u\n", dev_id);
+               goto fail;
+       }
+
+       req.secondary_host = s_host;
+       req.type = type & MSG_RM_RESOURCE_TYPE_MASK;
+       req.subtype = subtype & MSG_RM_RESOURCE_SUBTYPE_MASK;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(dev, "Mbox send fail %d\n", ret);
+               goto fail;
+       }
+
+       resp = (struct ti_sci_msg_resp_get_resource_range *)xfer->tx_message.buf;
+       if (!ti_sci_is_response_ack(resp)) {
+               ret = -ENODEV;
+       } else if (!resp->range_start && !resp->range_num) {
+               ret = -ENODEV;
+       } else {
+               *range_start = resp->range_start;
+               *range_num = resp->range_num;
+       };
+
+fail:
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_get_resource_range - Get a range of resources assigned to host
+ *                                that is same as ti sci interface host.
+ * @handle:            Pointer to TISCI handle.
+ * @dev_id:            TISCI device ID.
+ * @subtype:           Resource assignment subtype that is being requested
+ *                     from the given device.
+ * @range_start:       Start index of the resource range
+ * @range_num:         Number of resources in the range
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_get_resource_range(const struct ti_sci_handle *handle,
+                                        u32 dev_id, u8 subtype,
+                                        u16 *range_start, u16 *range_num)
+{
+       return ti_sci_get_resource_range(handle, dev_id, subtype,
+                                        TI_SCI_IRQ_SECONDARY_HOST_INVALID,
+                                        range_start, range_num);
+}
+
+/**
+ * ti_sci_cmd_get_resource_range_from_shost - Get a range of resources
+ *                                           assigned to a specified host.
+ * @handle:            Pointer to TISCI handle.
+ * @dev_id:            TISCI device ID.
+ * @subtype:           Resource assignment subtype that is being requested
+ *                     from the given device.
+ * @s_host:            Host processor ID to which the resources are allocated
+ * @range_start:       Start index of the resource range
+ * @range_num:         Number of resources in the range
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static
+int ti_sci_cmd_get_resource_range_from_shost(const struct ti_sci_handle *handle,
+                                            u32 dev_id, u8 subtype, u8 s_host,
+                                            u16 *range_start, u16 *range_num)
+{
+       return ti_sci_get_resource_range(handle, dev_id, subtype, s_host,
+                                        range_start, range_num);
+}
+
+/**
+ * ti_sci_cmd_query_msmc() - Command to query currently available msmc memory
+ * @handle:            pointer to TI SCI handle
+ * @msms_start:                MSMC start as returned by tisci
+ * @msmc_end:          MSMC end as returned by tisci
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_query_msmc(const struct ti_sci_handle *handle,
+                                u64 *msmc_start, u64 *msmc_end)
+{
+       struct ti_sci_msg_resp_query_msmc *resp;
+       struct ti_sci_msg_hdr req;
+       struct ti_sci_info *info;
+       struct ti_sci_xfer *xfer;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_QUERY_MSMC,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(dev, "Mbox send fail %d\n", ret);
+               return ret;
+       }
+
+       resp = (struct ti_sci_msg_resp_query_msmc *)xfer->tx_message.buf;
+
+       if (!ti_sci_is_response_ack(resp))
+               return -ENODEV;
+
+       *msmc_start = ((u64)resp->msmc_start_high << TISCI_ADDR_HIGH_SHIFT) |
+                       resp->msmc_start_low;
+       *msmc_end = ((u64)resp->msmc_end_high << TISCI_ADDR_HIGH_SHIFT) |
+                       resp->msmc_end_low;
+
+       return ret;
+}
+
 /**
  * ti_sci_cmd_proc_request() - Command to request a physical processor control
  * @handle:    Pointer to TI SCI handle
@@ -1700,16 +2055,19 @@ static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle,
  * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the
  *                     image and then set the processor configuration flags.
  * @handle:    Pointer to TI SCI handle
- * @proc_id:   Processor ID this request is for
- * @cert_addr: Memory address at which payload image certificate is located.
+ * @image_addr:        Memory address at which payload image and certificate is
+ *             located in memory, this is updated if the image data is
+ *             moved during authentication.
+ * @image_size: This is updated with the final size of the image after
+ *             authentication.
  *
  * Return: 0 if all went well, else returns appropriate error value.
  */
 static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle,
-                                          u8 proc_id, u64 cert_addr)
+                                          u64 *image_addr, u32 *image_size)
 {
        struct ti_sci_msg_req_proc_auth_boot_image req;
-       struct ti_sci_msg_hdr *resp;
+       struct ti_sci_msg_resp_proc_auth_boot_image *resp;
        struct ti_sci_info *info;
        struct ti_sci_xfer *xfer;
        int ret = 0;
@@ -1729,9 +2087,8 @@ static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle,
                dev_err(info->dev, "Message alloc failed(%d)\n", ret);
                return ret;
        }
-       req.processor_id = proc_id;
-       req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
-       req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
+       req.cert_addr_low = *image_addr & TISCI_ADDR_LOW_MASK;
+       req.cert_addr_high = (*image_addr & TISCI_ADDR_HIGH_MASK) >>
                                TISCI_ADDR_HIGH_SHIFT;
 
        ret = ti_sci_do_xfer(info, xfer);
@@ -1740,10 +2097,15 @@ static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle,
                return ret;
        }
 
-       resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
+       resp = (struct ti_sci_msg_resp_proc_auth_boot_image *)xfer->tx_message.buf;
 
        if (!ti_sci_is_response_ack(resp))
-               ret = -ENODEV;
+               return -ENODEV;
+
+       *image_addr = (resp->image_addr_low & TISCI_ADDR_LOW_MASK) |
+                       (((u64)resp->image_addr_high <<
+                         TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
+       *image_size = resp->image_size;
 
        return ret;
 }
@@ -1803,52 +2165,702 @@ static int ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle *handle,
        return ret;
 }
 
-/*
- * ti_sci_setup_ops() - Setup the operations structures
- * @info:      pointer to TISCI pointer
+/**
+ * ti_sci_proc_wait_boot_status_no_wait() - Helper function to wait for a
+ *                             processor boot status without requesting or
+ *                             waiting for a response.
+ * @proc_id:                   Processor ID this request is for
+ * @num_wait_iterations:       Total number of iterations we will check before
+ *                             we will timeout and give up
+ * @num_match_iterations:      How many iterations should we have continued
+ *                             status to account for status bits glitching.
+ *                             This is to make sure that match occurs for
+ *                             consecutive checks. This implies that the
+ *                             worst case should consider that the stable
+ *                             time should at the worst be num_wait_iterations
+ *                             num_match_iterations to prevent timeout.
+ * @delay_per_iteration_us:    Specifies how long to wait (in micro seconds)
+ *                             between each status checks. This is the minimum
+ *                             duration, and overhead of register reads and
+ *                             checks are on top of this and can vary based on
+ *                             varied conditions.
+ * @delay_before_iterations_us:        Specifies how long to wait (in micro seconds)
+ *                             before the very first check in the first
+ *                             iteration of status check loop. This is the
+ *                             minimum duration, and overhead of register
+ *                             reads and checks are.
+ * @status_flags_1_set_all_wait:If non-zero, Specifies that all bits of the
+ *                             status matching this field requested MUST be 1.
+ * @status_flags_1_set_any_wait:If non-zero, Specifies that at least one of the
+ *                             bits matching this field requested MUST be 1.
+ * @status_flags_1_clr_all_wait:If non-zero, Specifies that all bits of the
+ *                             status matching this field requested MUST be 0.
+ * @status_flags_1_clr_any_wait:If non-zero, Specifies that at least one of the
+ *                             bits matching this field requested MUST be 0.
+ *
+ * Return: 0 if all goes well, else appropriate error message
  */
-static void ti_sci_setup_ops(struct ti_sci_info *info)
+static int
+ti_sci_proc_wait_boot_status_no_wait(const struct ti_sci_handle *handle,
+                                    u8 proc_id,
+                                    u8 num_wait_iterations,
+                                    u8 num_match_iterations,
+                                    u8 delay_per_iteration_us,
+                                    u8 delay_before_iterations_us,
+                                    u32 status_flags_1_set_all_wait,
+                                    u32 status_flags_1_set_any_wait,
+                                    u32 status_flags_1_clr_all_wait,
+                                    u32 status_flags_1_clr_any_wait)
 {
-       struct ti_sci_ops *ops = &info->handle.ops;
-       struct ti_sci_board_ops *bops = &ops->board_ops;
-       struct ti_sci_dev_ops *dops = &ops->dev_ops;
-       struct ti_sci_clk_ops *cops = &ops->clk_ops;
-       struct ti_sci_core_ops *core_ops = &ops->core_ops;
-       struct ti_sci_proc_ops *pops = &ops->proc_ops;
+       struct ti_sci_msg_req_wait_proc_boot_status req;
+       struct ti_sci_info *info;
+       struct ti_sci_xfer *xfer;
+       int ret = 0;
 
-       bops->board_config = ti_sci_cmd_set_board_config;
-       bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
-       bops->board_config_security = ti_sci_cmd_set_board_config_security;
-       bops->board_config_pm = ti_sci_cmd_set_board_config_pm;
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
 
-       dops->get_device = ti_sci_cmd_get_device;
-       dops->idle_device = ti_sci_cmd_idle_device;
-       dops->put_device = ti_sci_cmd_put_device;
-       dops->is_valid = ti_sci_cmd_dev_is_valid;
-       dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
-       dops->is_idle = ti_sci_cmd_dev_is_idle;
-       dops->is_stop = ti_sci_cmd_dev_is_stop;
-       dops->is_on = ti_sci_cmd_dev_is_on;
-       dops->is_transitioning = ti_sci_cmd_dev_is_trans;
-       dops->set_device_resets = ti_sci_cmd_set_device_resets;
-       dops->get_device_resets = ti_sci_cmd_get_device_resets;
+       info = handle_to_ti_sci_info(handle);
 
-       cops->get_clock = ti_sci_cmd_get_clock;
-       cops->idle_clock = ti_sci_cmd_idle_clock;
-       cops->put_clock = ti_sci_cmd_put_clock;
-       cops->is_auto = ti_sci_cmd_clk_is_auto;
-       cops->is_on = ti_sci_cmd_clk_is_on;
-       cops->is_off = ti_sci_cmd_clk_is_off;
+       xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_WAIT_PROC_BOOT_STATUS,
+                                    TI_SCI_FLAG_REQ_GENERIC_NORESPONSE,
+                                    (u32 *)&req, sizeof(req), 0);
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req.processor_id = proc_id;
+       req.num_wait_iterations = num_wait_iterations;
+       req.num_match_iterations = num_match_iterations;
+       req.delay_per_iteration_us = delay_per_iteration_us;
+       req.delay_before_iterations_us = delay_before_iterations_us;
+       req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
+       req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
+       req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
+       req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
 
-       cops->set_parent = ti_sci_cmd_clk_set_parent;
-       cops->get_parent = ti_sci_cmd_clk_get_parent;
-       cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret)
+               dev_err(info->dev, "Mbox send fail %d\n", ret);
 
-       cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_proc_shutdown_no_wait() - Command to shutdown a core without
+ *             requesting or waiting for a response. Note that this API call
+ *             should be followed by placing the respective processor into
+ *             either WFE or WFI mode.
+ * @handle:    Pointer to TI SCI handle
+ * @proc_id:   Processor ID this request is for
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_proc_shutdown_no_wait(const struct ti_sci_handle *handle,
+                                           u8 proc_id)
+{
+       int ret;
+
+       /*
+        * Send the core boot status wait message waiting for either WFE or
+        * WFI without requesting or waiting for a TISCI response with the
+        * maximum wait time to give us the best chance to get to the WFE/WFI
+        * command that should follow the invocation of this API before the
+        * DMSC-internal processing of this command times out. Note that
+        * waiting for the R5 WFE/WFI flags will also work on an ARMV8 type
+        * core as the related flag bit positions are the same.
+        */
+       ret = ti_sci_proc_wait_boot_status_no_wait(handle, proc_id,
+               U8_MAX, 100, U8_MAX, U8_MAX,
+               0, PROC_BOOT_STATUS_FLAG_R5_WFE | PROC_BOOT_STATUS_FLAG_R5_WFI,
+               0, 0);
+       if (ret) {
+               dev_err(info->dev, "Sending core %u wait message fail %d\n",
+                       proc_id, ret);
+               return ret;
+       }
+
+       /*
+        * Release a processor managed by TISCI without requesting or waiting
+        * for a response.
+        */
+       ret = ti_sci_set_device_state_no_wait(handle, proc_id, 0,
+                                             MSG_DEVICE_SW_STATE_AUTO_OFF);
+       if (ret)
+               dev_err(info->dev, "Sending core %u shutdown message fail %d\n",
+                       proc_id, ret);
+
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_ring_config() - configure RA ring
+ * @handle:    pointer to TI SCI handle
+ * @valid_params: Bitfield defining validity of ring configuration parameters.
+ * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated
+ * @index: Ring index.
+ * @addr_lo: The ring base address lo 32 bits
+ * @addr_hi: The ring base address hi 32 bits
+ * @count: Number of ring elements.
+ * @mode: The mode of the ring
+ * @size: The ring element size.
+ * @order_id: Specifies the ring's bus order ID.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ *
+ * See @ti_sci_msg_rm_ring_cfg_req for more info.
+ */
+static int ti_sci_cmd_ring_config(const struct ti_sci_handle *handle,
+                                 u32 valid_params, u16 nav_id, u16 index,
+                                 u32 addr_lo, u32 addr_hi, u32 count,
+                                 u8 mode, u8 size, u8 order_id)
+{
+       struct ti_sci_msg_rm_ring_cfg_resp *resp;
+       struct ti_sci_msg_rm_ring_cfg_req req;
+       struct ti_sci_xfer *xfer;
+       struct ti_sci_info *info;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_RING_CFG,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "RM_RA:Message config failed(%d)\n", ret);
+               return ret;
+       }
+       req.valid_params = valid_params;
+       req.nav_id = nav_id;
+       req.index = index;
+       req.addr_lo = addr_lo;
+       req.addr_hi = addr_hi;
+       req.count = count;
+       req.mode = mode;
+       req.size = size;
+       req.order_id = order_id;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(info->dev, "RM_RA:Mbox config send fail %d\n", ret);
+               goto fail;
+       }
+
+       resp = (struct ti_sci_msg_rm_ring_cfg_resp *)xfer->tx_message.buf;
+
+       ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+       dev_dbg(info->dev, "RM_RA:config ring %u ret:%d\n", index, ret);
+       return ret;
+}
+
+static int ti_sci_cmd_rm_psil_pair(const struct ti_sci_handle *handle,
+                                  u32 nav_id, u32 src_thread, u32 dst_thread)
+{
+       struct ti_sci_msg_hdr *resp;
+       struct ti_sci_msg_psil_pair req;
+       struct ti_sci_xfer *xfer;
+       struct ti_sci_info *info;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_PSIL_PAIR,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "RM_PSIL:Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req.nav_id = nav_id;
+       req.src_thread = src_thread;
+       req.dst_thread = dst_thread;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(info->dev, "RM_PSIL:Mbox send fail %d\n", ret);
+               goto fail;
+       }
+
+       resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
+       ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+       dev_dbg(info->dev, "RM_PSIL: nav: %u link pair %u->%u ret:%u\n",
+               nav_id, src_thread, dst_thread, ret);
+       return ret;
+}
+
+static int ti_sci_cmd_rm_psil_unpair(const struct ti_sci_handle *handle,
+                                    u32 nav_id, u32 src_thread, u32 dst_thread)
+{
+       struct ti_sci_msg_hdr *resp;
+       struct ti_sci_msg_psil_unpair req;
+       struct ti_sci_xfer *xfer;
+       struct ti_sci_info *info;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_PSIL_UNPAIR,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "RM_PSIL:Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req.nav_id = nav_id;
+       req.src_thread = src_thread;
+       req.dst_thread = dst_thread;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(info->dev, "RM_PSIL:Mbox send fail %d\n", ret);
+               goto fail;
+       }
+
+       resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
+       ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+       dev_dbg(info->dev, "RM_PSIL: link unpair %u->%u ret:%u\n",
+               src_thread, dst_thread, ret);
+       return ret;
+}
+
+static int ti_sci_cmd_rm_udmap_tx_ch_cfg(
+                       const struct ti_sci_handle *handle,
+                       const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params)
+{
+       struct ti_sci_msg_rm_udmap_tx_ch_cfg_resp *resp;
+       struct ti_sci_msg_rm_udmap_tx_ch_cfg_req req;
+       struct ti_sci_xfer *xfer;
+       struct ti_sci_info *info;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_TX_CH_CFG,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "Message TX_CH_CFG alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req.valid_params = params->valid_params;
+       req.nav_id = params->nav_id;
+       req.index = params->index;
+       req.tx_pause_on_err = params->tx_pause_on_err;
+       req.tx_filt_einfo = params->tx_filt_einfo;
+       req.tx_filt_pswords = params->tx_filt_pswords;
+       req.tx_atype = params->tx_atype;
+       req.tx_chan_type = params->tx_chan_type;
+       req.tx_supr_tdpkt = params->tx_supr_tdpkt;
+       req.tx_fetch_size = params->tx_fetch_size;
+       req.tx_credit_count = params->tx_credit_count;
+       req.txcq_qnum = params->txcq_qnum;
+       req.tx_priority = params->tx_priority;
+       req.tx_qos = params->tx_qos;
+       req.tx_orderid = params->tx_orderid;
+       req.fdepth = params->fdepth;
+       req.tx_sched_priority = params->tx_sched_priority;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(info->dev, "Mbox send TX_CH_CFG fail %d\n", ret);
+               goto fail;
+       }
+
+       resp =
+             (struct ti_sci_msg_rm_udmap_tx_ch_cfg_resp *)xfer->tx_message.buf;
+       ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
+
+fail:
+       dev_dbg(info->dev, "TX_CH_CFG: chn %u ret:%u\n", params->index, ret);
+       return ret;
+}
+
+static int ti_sci_cmd_rm_udmap_rx_ch_cfg(
+                       const struct ti_sci_handle *handle,
+                       const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params)
+{
+       struct ti_sci_msg_rm_udmap_rx_ch_cfg_resp *resp;
+       struct ti_sci_msg_rm_udmap_rx_ch_cfg_req req;
+       struct ti_sci_xfer *xfer;
+       struct ti_sci_info *info;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_RX_CH_CFG,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "Message RX_CH_CFG alloc failed(%d)\n", ret);
+               return ret;
+       }
+
+       req.valid_params = params->valid_params;
+       req.nav_id = params->nav_id;
+       req.index = params->index;
+       req.rx_fetch_size = params->rx_fetch_size;
+       req.rxcq_qnum = params->rxcq_qnum;
+       req.rx_priority = params->rx_priority;
+       req.rx_qos = params->rx_qos;
+       req.rx_orderid = params->rx_orderid;
+       req.rx_sched_priority = params->rx_sched_priority;
+       req.flowid_start = params->flowid_start;
+       req.flowid_cnt = params->flowid_cnt;
+       req.rx_pause_on_err = params->rx_pause_on_err;
+       req.rx_atype = params->rx_atype;
+       req.rx_chan_type = params->rx_chan_type;
+       req.rx_ignore_short = params->rx_ignore_short;
+       req.rx_ignore_long = params->rx_ignore_long;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(info->dev, "Mbox send RX_CH_CFG fail %d\n", ret);
+               goto fail;
+       }
+
+       resp =
+             (struct ti_sci_msg_rm_udmap_rx_ch_cfg_resp *)xfer->tx_message.buf;
+       ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
+
+fail:
+       dev_dbg(info->dev, "RX_CH_CFG: chn %u ret:%d\n", params->index, ret);
+       return ret;
+}
+
+static int ti_sci_cmd_rm_udmap_rx_flow_cfg(
+                       const struct ti_sci_handle *handle,
+                       const struct ti_sci_msg_rm_udmap_flow_cfg *params)
+{
+       struct ti_sci_msg_rm_udmap_flow_cfg_resp *resp;
+       struct ti_sci_msg_rm_udmap_flow_cfg_req req;
+       struct ti_sci_xfer *xfer;
+       struct ti_sci_info *info;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_FLOW_CFG,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "RX_FL_CFG: Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+
+       req.valid_params = params->valid_params;
+       req.nav_id = params->nav_id;
+       req.flow_index = params->flow_index;
+       req.rx_einfo_present = params->rx_einfo_present;
+       req.rx_psinfo_present = params->rx_psinfo_present;
+       req.rx_error_handling = params->rx_error_handling;
+       req.rx_desc_type = params->rx_desc_type;
+       req.rx_sop_offset = params->rx_sop_offset;
+       req.rx_dest_qnum = params->rx_dest_qnum;
+       req.rx_src_tag_hi = params->rx_src_tag_hi;
+       req.rx_src_tag_lo = params->rx_src_tag_lo;
+       req.rx_dest_tag_hi = params->rx_dest_tag_hi;
+       req.rx_dest_tag_lo = params->rx_dest_tag_lo;
+       req.rx_src_tag_hi_sel = params->rx_src_tag_hi_sel;
+       req.rx_src_tag_lo_sel = params->rx_src_tag_lo_sel;
+       req.rx_dest_tag_hi_sel = params->rx_dest_tag_hi_sel;
+       req.rx_dest_tag_lo_sel = params->rx_dest_tag_lo_sel;
+       req.rx_fdq0_sz0_qnum = params->rx_fdq0_sz0_qnum;
+       req.rx_fdq1_qnum = params->rx_fdq1_qnum;
+       req.rx_fdq2_qnum = params->rx_fdq2_qnum;
+       req.rx_fdq3_qnum = params->rx_fdq3_qnum;
+       req.rx_ps_location = params->rx_ps_location;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(dev, "RX_FL_CFG: Mbox send fail %d\n", ret);
+               goto fail;
+       }
+
+       resp =
+              (struct ti_sci_msg_rm_udmap_flow_cfg_resp *)xfer->tx_message.buf;
+       ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
+
+fail:
+       dev_dbg(info->dev, "RX_FL_CFG: %u ret:%d\n", params->flow_index, ret);
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_set_fwl_region() - Request for configuring a firewall region
+ * @handle:    pointer to TI SCI handle
+ * @region:    region configuration parameters
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_set_fwl_region(const struct ti_sci_handle *handle,
+                                    const struct ti_sci_msg_fwl_region *region)
+{
+       struct ti_sci_msg_fwl_set_firewall_region_req req;
+       struct ti_sci_msg_hdr *resp;
+       struct ti_sci_info *info;
+       struct ti_sci_xfer *xfer;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_SET,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+
+       req.fwl_id = region->fwl_id;
+       req.region = region->region;
+       req.n_permission_regs = region->n_permission_regs;
+       req.control = region->control;
+       req.permissions[0] = region->permissions[0];
+       req.permissions[1] = region->permissions[1];
+       req.permissions[2] = region->permissions[2];
+       req.start_address = region->start_address;
+       req.end_address = region->end_address;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(info->dev, "Mbox send fail %d\n", ret);
+               return ret;
+       }
+
+       resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
+
+       if (!ti_sci_is_response_ack(resp))
+               return -ENODEV;
+
+       return 0;
+}
+
+/**
+ * ti_sci_cmd_get_fwl_region() - Request for getting a firewall region
+ * @handle:    pointer to TI SCI handle
+ * @region:    region configuration parameters
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_get_fwl_region(const struct ti_sci_handle *handle,
+                                    struct ti_sci_msg_fwl_region *region)
+{
+       struct ti_sci_msg_fwl_get_firewall_region_req req;
+       struct ti_sci_msg_fwl_get_firewall_region_resp *resp;
+       struct ti_sci_info *info;
+       struct ti_sci_xfer *xfer;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_GET,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+
+       req.fwl_id = region->fwl_id;
+       req.region = region->region;
+       req.n_permission_regs = region->n_permission_regs;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(info->dev, "Mbox send fail %d\n", ret);
+               return ret;
+       }
+
+       resp = (struct ti_sci_msg_fwl_get_firewall_region_resp *)xfer->tx_message.buf;
+
+       if (!ti_sci_is_response_ack(resp))
+               return -ENODEV;
+
+       region->fwl_id = resp->fwl_id;
+       region->region = resp->region;
+       region->n_permission_regs = resp->n_permission_regs;
+       region->control = resp->control;
+       region->permissions[0] = resp->permissions[0];
+       region->permissions[1] = resp->permissions[1];
+       region->permissions[2] = resp->permissions[2];
+       region->start_address = resp->start_address;
+       region->end_address = resp->end_address;
+
+       return 0;
+}
+
+/**
+ * ti_sci_cmd_change_fwl_owner() - Request for changing a firewall owner
+ * @handle:    pointer to TI SCI handle
+ * @region:    region configuration parameters
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_change_fwl_owner(const struct ti_sci_handle *handle,
+                                      struct ti_sci_msg_fwl_owner *owner)
+{
+       struct ti_sci_msg_fwl_change_owner_info_req req;
+       struct ti_sci_msg_fwl_change_owner_info_resp *resp;
+       struct ti_sci_info *info;
+       struct ti_sci_xfer *xfer;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+
+       xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_CHANGE_OWNER,
+                                    TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                    (u32 *)&req, sizeof(req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(info->dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+
+       req.fwl_id = owner->fwl_id;
+       req.region = owner->region;
+       req.owner_index = owner->owner_index;
+
+       ret = ti_sci_do_xfer(info, xfer);
+       if (ret) {
+               dev_err(info->dev, "Mbox send fail %d\n", ret);
+               return ret;
+       }
+
+       resp = (struct ti_sci_msg_fwl_change_owner_info_resp *)xfer->tx_message.buf;
+
+       if (!ti_sci_is_response_ack(resp))
+               return -ENODEV;
+
+       owner->fwl_id = resp->fwl_id;
+       owner->region = resp->region;
+       owner->owner_index = resp->owner_index;
+       owner->owner_privid = resp->owner_privid;
+       owner->owner_permission_bits = resp->owner_permission_bits;
+
+       return ret;
+}
+
+/*
+ * ti_sci_setup_ops() - Setup the operations structures
+ * @info:      pointer to TISCI pointer
+ */
+static void ti_sci_setup_ops(struct ti_sci_info *info)
+{
+       struct ti_sci_ops *ops = &info->handle.ops;
+       struct ti_sci_board_ops *bops = &ops->board_ops;
+       struct ti_sci_dev_ops *dops = &ops->dev_ops;
+       struct ti_sci_clk_ops *cops = &ops->clk_ops;
+       struct ti_sci_core_ops *core_ops = &ops->core_ops;
+       struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
+       struct ti_sci_proc_ops *pops = &ops->proc_ops;
+       struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
+       struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops;
+       struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops;
+       struct ti_sci_fwl_ops *fwl_ops = &ops->fwl_ops;
+
+       bops->board_config = ti_sci_cmd_set_board_config;
+       bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
+       bops->board_config_security = ti_sci_cmd_set_board_config_security;
+       bops->board_config_pm = ti_sci_cmd_set_board_config_pm;
+
+       dops->get_device = ti_sci_cmd_get_device;
+       dops->get_device_exclusive = ti_sci_cmd_get_device_exclusive;
+       dops->idle_device = ti_sci_cmd_idle_device;
+       dops->idle_device_exclusive = ti_sci_cmd_idle_device_exclusive;
+       dops->put_device = ti_sci_cmd_put_device;
+       dops->is_valid = ti_sci_cmd_dev_is_valid;
+       dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
+       dops->is_idle = ti_sci_cmd_dev_is_idle;
+       dops->is_stop = ti_sci_cmd_dev_is_stop;
+       dops->is_on = ti_sci_cmd_dev_is_on;
+       dops->is_transitioning = ti_sci_cmd_dev_is_trans;
+       dops->set_device_resets = ti_sci_cmd_set_device_resets;
+       dops->get_device_resets = ti_sci_cmd_get_device_resets;
+       dops->release_exclusive_devices = ti_sci_cmd_release_exclusive_devices;
+
+       cops->get_clock = ti_sci_cmd_get_clock;
+       cops->idle_clock = ti_sci_cmd_idle_clock;
+       cops->put_clock = ti_sci_cmd_put_clock;
+       cops->is_auto = ti_sci_cmd_clk_is_auto;
+       cops->is_on = ti_sci_cmd_clk_is_on;
+       cops->is_off = ti_sci_cmd_clk_is_off;
+
+       cops->set_parent = ti_sci_cmd_clk_set_parent;
+       cops->get_parent = ti_sci_cmd_clk_get_parent;
+       cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
+
+       cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
        cops->set_freq = ti_sci_cmd_clk_set_freq;
        cops->get_freq = ti_sci_cmd_clk_get_freq;
 
        core_ops->reboot_device = ti_sci_cmd_core_reboot;
+       core_ops->query_msmc = ti_sci_cmd_query_msmc;
+
+       rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
+       rm_core_ops->get_range_from_shost =
+               ti_sci_cmd_get_resource_range_from_shost;
 
        pops->proc_request = ti_sci_cmd_proc_request;
        pops->proc_release = ti_sci_cmd_proc_release;
@@ -1857,6 +2869,20 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
        pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl;
        pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image;
        pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status;
+       pops->proc_shutdown_no_wait = ti_sci_cmd_proc_shutdown_no_wait;
+
+       rops->config = ti_sci_cmd_ring_config;
+
+       psilops->pair = ti_sci_cmd_rm_psil_pair;
+       psilops->unpair = ti_sci_cmd_rm_psil_unpair;
+
+       udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg;
+       udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg;
+       udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg;
+
+       fwl_ops->set_fwl_region = ti_sci_cmd_set_fwl_region;
+       fwl_ops->get_fwl_region = ti_sci_cmd_get_fwl_region;
+       fwl_ops->change_fwl_owner = ti_sci_cmd_change_fwl_owner;
 }
 
 /**
@@ -1969,7 +2995,7 @@ static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info)
        }
 
        info->host_id = dev_read_u32_default(dev, "ti,host-id",
-                                            info->desc->host_id);
+                                            info->desc->default_host_id);
 
        info->is_secure = dev_read_bool(dev, "ti,secure-host");
 
@@ -2006,20 +3032,176 @@ static int ti_sci_probe(struct udevice *dev)
 
        ret = ti_sci_cmd_get_revision(&info->handle);
 
+       INIT_LIST_HEAD(&info->dev_list);
+
        return ret;
 }
 
+/*
+ * ti_sci_get_free_resource() - Get a free resource from TISCI resource.
+ * @res:       Pointer to the TISCI resource
+ *
+ * Return: resource num if all went ok else TI_SCI_RESOURCE_NULL.
+ */
+u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
+{
+       u16 set, free_bit;
+
+       for (set = 0; set < res->sets; set++) {
+               free_bit = find_first_zero_bit(res->desc[set].res_map,
+                                              res->desc[set].num);
+               if (free_bit != res->desc[set].num) {
+                       set_bit(free_bit, res->desc[set].res_map);
+                       return res->desc[set].start + free_bit;
+               }
+       }
+
+       return TI_SCI_RESOURCE_NULL;
+}
+
+/**
+ * ti_sci_release_resource() - Release a resource from TISCI resource.
+ * @res:       Pointer to the TISCI resource
+ */
+void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
+{
+       u16 set;
+
+       for (set = 0; set < res->sets; set++) {
+               if (res->desc[set].start <= id &&
+                   (res->desc[set].num + res->desc[set].start) > id)
+                       clear_bit(id - res->desc[set].start,
+                                 res->desc[set].res_map);
+       }
+}
+
+/**
+ * devm_ti_sci_get_of_resource() - Get a TISCI resource assigned to a device
+ * @handle:    TISCI handle
+ * @dev:       Device pointer to which the resource is assigned
+ * @of_prop:   property name by which the resource are represented
+ *
+ * Note: This function expects of_prop to be in the form of tuples
+ *     <type, subtype>. Allocates and initializes ti_sci_resource structure
+ *     for each of_prop. Client driver can directly call
+ *     ti_sci_(get_free, release)_resource apis for handling the resource.
+ *
+ * Return: Pointer to ti_sci_resource if all went well else appropriate
+ *        error pointer.
+ */
+struct ti_sci_resource *
+devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
+                           struct udevice *dev, u32 dev_id, char *of_prop)
+{
+       u32 resource_subtype;
+       u16 resource_type;
+       struct ti_sci_resource *res;
+       bool valid_set = false;
+       int sets, i, ret;
+       u32 *temp;
+
+       res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
+       if (!res)
+               return ERR_PTR(-ENOMEM);
+
+       sets = dev_read_size(dev, of_prop);
+       if (sets < 0) {
+               dev_err(dev, "%s resource type ids not available\n", of_prop);
+               return ERR_PTR(sets);
+       }
+       temp = malloc(sets);
+       sets /= sizeof(u32);
+       res->sets = sets;
+
+       res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc),
+                                GFP_KERNEL);
+       if (!res->desc)
+               return ERR_PTR(-ENOMEM);
+
+       ret = ti_sci_get_resource_type(handle_to_ti_sci_info(handle), dev_id,
+                                      &resource_type);
+       if (ret) {
+               dev_err(dev, "No valid resource type for %u\n", dev_id);
+               return ERR_PTR(-EINVAL);
+       }
+
+       ret = dev_read_u32_array(dev, of_prop, temp, res->sets);
+       if (ret)
+               return ERR_PTR(-EINVAL);
+
+       for (i = 0; i < res->sets; i++) {
+               resource_subtype = temp[i];
+               ret = handle->ops.rm_core_ops.get_range(handle, dev_id,
+                                                       resource_subtype,
+                                                       &res->desc[i].start,
+                                                       &res->desc[i].num);
+               if (ret) {
+                       dev_dbg(dev, "type %d subtype %d not allocated for host %d\n",
+                               resource_type, resource_subtype,
+                               handle_to_ti_sci_info(handle)->host_id);
+                       res->desc[i].start = 0;
+                       res->desc[i].num = 0;
+                       continue;
+               }
+
+               valid_set = true;
+               dev_dbg(dev, "res type = %d, subtype = %d, start = %d, num = %d\n",
+                       resource_type, resource_subtype, res->desc[i].start,
+                       res->desc[i].num);
+
+               res->desc[i].res_map =
+                       devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) *
+                                    sizeof(*res->desc[i].res_map), GFP_KERNEL);
+               if (!res->desc[i].res_map)
+                       return ERR_PTR(-ENOMEM);
+       }
+
+       if (valid_set)
+               return res;
+
+       return ERR_PTR(-EINVAL);
+}
+
+/* Description for K2G */
+static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
+       .default_host_id = 2,
+       /* Conservative duration */
+       .max_rx_timeout_ms = 10000,
+       /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
+       .max_msgs = 20,
+       .max_msg_size = 64,
+       .rm_type_map = NULL,
+};
+
+static struct ti_sci_rm_type_map ti_sci_am654_rm_type_map[] = {
+       {.dev_id = 56, .type = 0x00b}, /* GIC_IRQ */
+       {.dev_id = 179, .type = 0x000}, /* MAIN_NAV_UDMASS_IA0 */
+       {.dev_id = 187, .type = 0x009}, /* MAIN_NAV_RA */
+       {.dev_id = 188, .type = 0x006}, /* MAIN_NAV_UDMAP */
+       {.dev_id = 194, .type = 0x007}, /* MCU_NAV_UDMAP */
+       {.dev_id = 195, .type = 0x00a}, /* MCU_NAV_RA */
+       {.dev_id = 0, .type = 0x000}, /* end of table */
+};
+
 /* Description for AM654 */
-static const struct ti_sci_desc ti_sci_sysfw_am654_desc = {
-       .host_id = 4,
-       .max_rx_timeout_us = 1000000,
+static const struct ti_sci_desc ti_sci_pmmc_am654_desc = {
+       .default_host_id = 12,
+       /* Conservative duration */
+       .max_rx_timeout_ms = 10000,
+       /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
+       .max_msgs = 20,
        .max_msg_size = 60,
+       .rm_type_map = ti_sci_am654_rm_type_map,
 };
 
 static const struct udevice_id ti_sci_ids[] = {
        {
                .compatible = "ti,k2g-sci",
-               .data = (ulong)&ti_sci_sysfw_am654_desc
+               .data = (ulong)&ti_sci_pmmc_k2g_desc
+       },
+       {
+               .compatible = "ti,am654-sci",
+               .data = (ulong)&ti_sci_pmmc_am654_desc
        },
        { /* Sentinel */ },
 };