NULL);
 }
 
+/**
+ * ti_sci_set_clock_state() - Set clock state helper
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @flags:     Header flags as needed
+ * @state:     State to request for the clock.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
+                                 u32 dev_id, u8 clk_id,
+                                 u32 flags, u8 state)
+{
+       struct ti_sci_info *info;
+       struct ti_sci_msg_req_set_clock_state *req;
+       struct ti_sci_msg_hdr *resp;
+       struct ti_sci_xfer *xfer;
+       struct device *dev;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+       dev = info->dev;
+
+       xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
+                                  flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                  sizeof(*req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req = (struct ti_sci_msg_req_set_clock_state *)xfer->xfer_buf;
+       req->dev_id = dev_id;
+       req->clk_id = clk_id;
+       req->request_state = state;
+
+       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_hdr *)xfer->xfer_buf;
+
+       ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+       ti_sci_put_one_xfer(&info->minfo, xfer);
+
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_get_clock_state() - Get clock state helper
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @programmed_state:  State requested for clock to move to
+ * @current_state:     State that the clock is currently in
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
+                                     u32 dev_id, u8 clk_id,
+                                     u8 *programmed_state, u8 *current_state)
+{
+       struct ti_sci_info *info;
+       struct ti_sci_msg_req_get_clock_state *req;
+       struct ti_sci_msg_resp_get_clock_state *resp;
+       struct ti_sci_xfer *xfer;
+       struct device *dev;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       if (!programmed_state && !current_state)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+       dev = info->dev;
+
+       xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
+                                  TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                  sizeof(*req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req = (struct ti_sci_msg_req_get_clock_state *)xfer->xfer_buf;
+       req->dev_id = dev_id;
+       req->clk_id = clk_id;
+
+       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_clock_state *)xfer->xfer_buf;
+
+       if (!ti_sci_is_response_ack(resp)) {
+               ret = -ENODEV;
+               goto fail;
+       }
+
+       if (programmed_state)
+               *programmed_state = resp->programmed_state;
+       if (current_state)
+               *current_state = resp->current_state;
+
+fail:
+       ti_sci_put_one_xfer(&info->minfo, xfer);
+
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
+ * @can_change_freq: 'true' if frequency change is desired, else 'false'
+ * @enable_input_term: 'true' if input termination is desired, else 'false'
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
+                               u8 clk_id, bool needs_ssc, bool can_change_freq,
+                               bool enable_input_term)
+{
+       u32 flags = 0;
+
+       flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
+       flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
+       flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
+
+       return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
+                                     MSG_CLOCK_SW_STATE_REQ);
+}
+
+/**
+ * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ *
+ * NOTE: This clock must have been requested by get_clock previously.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
+                                u32 dev_id, u8 clk_id)
+{
+       return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
+                                     MSG_CLOCK_SW_STATE_UNREQ);
+}
+
+/**
+ * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ *
+ * NOTE: This clock must have been requested by get_clock previously.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
+                               u32 dev_id, u8 clk_id)
+{
+       return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
+                                     MSG_CLOCK_SW_STATE_AUTO);
+}
+
+/**
+ * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @req_state: state indicating if the clock is auto managed
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
+                                 u32 dev_id, u8 clk_id, bool *req_state)
+{
+       u8 state = 0;
+       int ret;
+
+       if (!req_state)
+               return -EINVAL;
+
+       ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
+       if (ret)
+               return ret;
+
+       *req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
+       return 0;
+}
+
+/**
+ * ti_sci_cmd_clk_is_on() - Is the clock ON
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @req_state: state indicating if the clock is managed by us and enabled
+ * @curr_state: state indicating if the clock is ready for operation
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
+                               u8 clk_id, bool *req_state, bool *curr_state)
+{
+       u8 c_state = 0, r_state = 0;
+       int ret;
+
+       if (!req_state && !curr_state)
+               return -EINVAL;
+
+       ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
+                                        &r_state, &c_state);
+       if (ret)
+               return ret;
+
+       if (req_state)
+               *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
+       if (curr_state)
+               *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
+       return 0;
+}
+
+/**
+ * ti_sci_cmd_clk_is_off() - Is the clock OFF
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @req_state: state indicating if the clock is managed by us and disabled
+ * @curr_state: state indicating if the clock is NOT ready for operation
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
+                                u8 clk_id, bool *req_state, bool *curr_state)
+{
+       u8 c_state = 0, r_state = 0;
+       int ret;
+
+       if (!req_state && !curr_state)
+               return -EINVAL;
+
+       ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
+                                        &r_state, &c_state);
+       if (ret)
+               return ret;
+
+       if (req_state)
+               *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
+       if (curr_state)
+               *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
+       return 0;
+}
+
+/**
+ * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @parent_id: Parent clock identifier to set
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
+                                    u32 dev_id, u8 clk_id, u8 parent_id)
+{
+       struct ti_sci_info *info;
+       struct ti_sci_msg_req_set_clock_parent *req;
+       struct ti_sci_msg_hdr *resp;
+       struct ti_sci_xfer *xfer;
+       struct device *dev;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+       dev = info->dev;
+
+       xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
+                                  TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                  sizeof(*req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req = (struct ti_sci_msg_req_set_clock_parent *)xfer->xfer_buf;
+       req->dev_id = dev_id;
+       req->clk_id = clk_id;
+       req->parent_id = parent_id;
+
+       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_hdr *)xfer->xfer_buf;
+
+       ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+       ti_sci_put_one_xfer(&info->minfo, xfer);
+
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_get_parent() - Get current parent clock source
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @parent_id: Current clock parent
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
+                                    u32 dev_id, u8 clk_id, u8 *parent_id)
+{
+       struct ti_sci_info *info;
+       struct ti_sci_msg_req_get_clock_parent *req;
+       struct ti_sci_msg_resp_get_clock_parent *resp;
+       struct ti_sci_xfer *xfer;
+       struct device *dev;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle || !parent_id)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+       dev = info->dev;
+
+       xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
+                                  TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                  sizeof(*req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req = (struct ti_sci_msg_req_get_clock_parent *)xfer->xfer_buf;
+       req->dev_id = dev_id;
+       req->clk_id = clk_id;
+
+       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_clock_parent *)xfer->xfer_buf;
+
+       if (!ti_sci_is_response_ack(resp))
+               ret = -ENODEV;
+       else
+               *parent_id = resp->parent_id;
+
+fail:
+       ti_sci_put_one_xfer(&info->minfo, xfer);
+
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @num_parents: Returns he number of parents to the current clock.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
+                                         u32 dev_id, u8 clk_id,
+                                         u8 *num_parents)
+{
+       struct ti_sci_info *info;
+       struct ti_sci_msg_req_get_clock_num_parents *req;
+       struct ti_sci_msg_resp_get_clock_num_parents *resp;
+       struct ti_sci_xfer *xfer;
+       struct device *dev;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle || !num_parents)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+       dev = info->dev;
+
+       xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
+                                  TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                  sizeof(*req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req = (struct ti_sci_msg_req_get_clock_num_parents *)xfer->xfer_buf;
+       req->dev_id = dev_id;
+       req->clk_id = clk_id;
+
+       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_clock_num_parents *)xfer->xfer_buf;
+
+       if (!ti_sci_is_response_ack(resp))
+               ret = -ENODEV;
+       else
+               *num_parents = resp->num_parents;
+
+fail:
+       ti_sci_put_one_xfer(&info->minfo, xfer);
+
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @min_freq:  The minimum allowable frequency in Hz. This is the minimum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ * @target_freq: The target clock frequency in Hz. A frequency will be
+ *             processed as close to this target frequency as possible.
+ * @max_freq:  The maximum allowable frequency in Hz. This is the maximum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ * @match_freq:        Frequency match in Hz response.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
+                                        u32 dev_id, u8 clk_id, u64 min_freq,
+                                        u64 target_freq, u64 max_freq,
+                                        u64 *match_freq)
+{
+       struct ti_sci_info *info;
+       struct ti_sci_msg_req_query_clock_freq *req;
+       struct ti_sci_msg_resp_query_clock_freq *resp;
+       struct ti_sci_xfer *xfer;
+       struct device *dev;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle || !match_freq)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+       dev = info->dev;
+
+       xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
+                                  TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                  sizeof(*req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req = (struct ti_sci_msg_req_query_clock_freq *)xfer->xfer_buf;
+       req->dev_id = dev_id;
+       req->clk_id = clk_id;
+       req->min_freq_hz = min_freq;
+       req->target_freq_hz = target_freq;
+       req->max_freq_hz = max_freq;
+
+       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_query_clock_freq *)xfer->xfer_buf;
+
+       if (!ti_sci_is_response_ack(resp))
+               ret = -ENODEV;
+       else
+               *match_freq = resp->freq_hz;
+
+fail:
+       ti_sci_put_one_xfer(&info->minfo, xfer);
+
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @min_freq:  The minimum allowable frequency in Hz. This is the minimum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ * @target_freq: The target clock frequency in Hz. A frequency will be
+ *             processed as close to this target frequency as possible.
+ * @max_freq:  The maximum allowable frequency in Hz. This is the maximum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
+                                  u32 dev_id, u8 clk_id, u64 min_freq,
+                                  u64 target_freq, u64 max_freq)
+{
+       struct ti_sci_info *info;
+       struct ti_sci_msg_req_set_clock_freq *req;
+       struct ti_sci_msg_hdr *resp;
+       struct ti_sci_xfer *xfer;
+       struct device *dev;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+       dev = info->dev;
+
+       xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
+                                  TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                  sizeof(*req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req = (struct ti_sci_msg_req_set_clock_freq *)xfer->xfer_buf;
+       req->dev_id = dev_id;
+       req->clk_id = clk_id;
+       req->min_freq_hz = min_freq;
+       req->target_freq_hz = target_freq;
+       req->max_freq_hz = max_freq;
+
+       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_hdr *)xfer->xfer_buf;
+
+       ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+       ti_sci_put_one_xfer(&info->minfo, xfer);
+
+       return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_get_freq() - Get current frequency
+ * @handle:    pointer to TI SCI handle
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @freq:      Currently frequency in Hz
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
+                                  u32 dev_id, u8 clk_id, u64 *freq)
+{
+       struct ti_sci_info *info;
+       struct ti_sci_msg_req_get_clock_freq *req;
+       struct ti_sci_msg_resp_get_clock_freq *resp;
+       struct ti_sci_xfer *xfer;
+       struct device *dev;
+       int ret = 0;
+
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
+       if (!handle || !freq)
+               return -EINVAL;
+
+       info = handle_to_ti_sci_info(handle);
+       dev = info->dev;
+
+       xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
+                                  TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+                                  sizeof(*req), sizeof(*resp));
+       if (IS_ERR(xfer)) {
+               ret = PTR_ERR(xfer);
+               dev_err(dev, "Message alloc failed(%d)\n", ret);
+               return ret;
+       }
+       req = (struct ti_sci_msg_req_get_clock_freq *)xfer->xfer_buf;
+       req->dev_id = dev_id;
+       req->clk_id = clk_id;
+
+       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_clock_freq *)xfer->xfer_buf;
+
+       if (!ti_sci_is_response_ack(resp))
+               ret = -ENODEV;
+       else
+               *freq = resp->freq_hz;
+
+fail:
+       ti_sci_put_one_xfer(&info->minfo, xfer);
+
+       return ret;
+}
+
 /*
  * ti_sci_setup_ops() - Setup the operations structures
  * @info:      pointer to TISCI pointer
 {
        struct ti_sci_ops *ops = &info->handle.ops;
        struct ti_sci_dev_ops *dops = &ops->dev_ops;
+       struct ti_sci_clk_ops *cops = &ops->clk_ops;
 
        dops->get_device = ti_sci_cmd_get_device;
        dops->idle_device = ti_sci_cmd_idle_device;
        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;
+
+       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;
 }
 
 /**
 
 #define TI_SCI_MSG_GET_DEVICE_STATE    0x0201
 #define TI_SCI_MSG_SET_DEVICE_RESETS   0x0202
 
+/* Clock requests */
+#define TI_SCI_MSG_SET_CLOCK_STATE     0x0100
+#define TI_SCI_MSG_GET_CLOCK_STATE     0x0101
+#define TI_SCI_MSG_SET_CLOCK_PARENT    0x0102
+#define TI_SCI_MSG_GET_CLOCK_PARENT    0x0103
+#define TI_SCI_MSG_GET_NUM_CLOCK_PARENTS 0x0104
+#define TI_SCI_MSG_SET_CLOCK_FREQ      0x010c
+#define TI_SCI_MSG_QUERY_CLOCK_FREQ    0x010d
+#define TI_SCI_MSG_GET_CLOCK_FREQ      0x010e
+
 /**
  * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
  * @type:      Type of messages: One of TI_SCI_MSG* values
        u32 resets;
 } __packed;
 
+/**
+ * struct ti_sci_msg_req_set_clock_state - Request to setup a Clock state
+ * @hdr:       Generic Header, Certain flags can be set specific to the clocks:
+ *             MSG_FLAG_CLOCK_ALLOW_SSC: Allow this clock to be modified
+ *             via spread spectrum clocking.
+ *             MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE: Allow this clock's
+ *             frequency to be changed while it is running so long as it
+ *             is within the min/max limits.
+ *             MSG_FLAG_CLOCK_INPUT_TERM: Enable input termination, this
+ *             is only applicable to clock inputs on the SoC pseudo-device.
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @request_state: Request the state for the clock to be set to.
+ *             MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock,
+ *             it can be disabled, regardless of the state of the device
+ *             MSG_CLOCK_SW_STATE_AUTO: Allow the System Controller to
+ *             automatically manage the state of this clock. If the device
+ *             is enabled, then the clock is enabled. If the device is set
+ *             to off or retention, then the clock is internally set as not
+ *             being required by the device.(default)
+ *             MSG_CLOCK_SW_STATE_REQ:  Configure the clock to be enabled,
+ *             regardless of the state of the device.
+ *
+ * Normally, all required clocks are managed by TISCI entity, this is used
+ * only for specific control *IF* required. Auto managed state is
+ * MSG_CLOCK_SW_STATE_AUTO, in other states, TISCI entity assume remote
+ * will explicitly control.
+ *
+ * Request type is TI_SCI_MSG_SET_CLOCK_STATE, response is a generic
+ * ACK or NACK message.
+ */
+struct ti_sci_msg_req_set_clock_state {
+       /* Additional hdr->flags options */
+#define MSG_FLAG_CLOCK_ALLOW_SSC               TI_SCI_MSG_FLAG(8)
+#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE       TI_SCI_MSG_FLAG(9)
+#define MSG_FLAG_CLOCK_INPUT_TERM              TI_SCI_MSG_FLAG(10)
+       struct ti_sci_msg_hdr hdr;
+       u32 dev_id;
+       u8 clk_id;
+#define MSG_CLOCK_SW_STATE_UNREQ       0
+#define MSG_CLOCK_SW_STATE_AUTO                1
+#define MSG_CLOCK_SW_STATE_REQ         2
+       u8 request_state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_state - Request for clock state
+ * @hdr:       Generic Header
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to get state of.
+ *
+ * Request type is TI_SCI_MSG_GET_CLOCK_STATE, response is state
+ * of the clock
+ */
+struct ti_sci_msg_req_get_clock_state {
+       struct ti_sci_msg_hdr hdr;
+       u32 dev_id;
+       u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_state - Response to get clock state
+ * @hdr:       Generic Header
+ * @programmed_state: Any programmed state of the clock. This is one of
+ *             MSG_CLOCK_SW_STATE* values.
+ * @current_state: Current state of the clock. This is one of:
+ *             MSG_CLOCK_HW_STATE_NOT_READY: Clock is not ready
+ *             MSG_CLOCK_HW_STATE_READY: Clock is ready
+ *
+ * Response to TI_SCI_MSG_GET_CLOCK_STATE.
+ */
+struct ti_sci_msg_resp_get_clock_state {
+       struct ti_sci_msg_hdr hdr;
+       u8 programmed_state;
+#define MSG_CLOCK_HW_STATE_NOT_READY   0
+#define MSG_CLOCK_HW_STATE_READY       1
+       u8 current_state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_clock_parent - Set the clock parent
+ * @hdr:       Generic Header
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * @parent_id: The new clock parent is selectable by an index via this
+ *             parameter.
+ *
+ * Request type is TI_SCI_MSG_SET_CLOCK_PARENT, response is generic
+ * ACK / NACK message.
+ */
+struct ti_sci_msg_req_set_clock_parent {
+       struct ti_sci_msg_hdr hdr;
+       u32 dev_id;
+       u8 clk_id;
+       u8 parent_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_parent - Get the clock parent
+ * @hdr:       Generic Header
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to get the parent for.
+ *
+ * Request type is TI_SCI_MSG_GET_CLOCK_PARENT, response is parent information
+ */
+struct ti_sci_msg_req_get_clock_parent {
+       struct ti_sci_msg_hdr hdr;
+       u32 dev_id;
+       u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_parent - Response with clock parent
+ * @hdr:       Generic Header
+ * @parent_id: The current clock parent
+ *
+ * Response to TI_SCI_MSG_GET_CLOCK_PARENT.
+ */
+struct ti_sci_msg_resp_get_clock_parent {
+       struct ti_sci_msg_hdr hdr;
+       u8 parent_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_num_parents - Request to get clock parents
+ * @hdr:       Generic header
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *
+ * This request provides information about how many clock parent options
+ * are available for a given clock to a device. This is typically used
+ * for input clocks.
+ *
+ * Request type is TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, response is appropriate
+ * message, or NACK in case of inability to satisfy request.
+ */
+struct ti_sci_msg_req_get_clock_num_parents {
+       struct ti_sci_msg_hdr hdr;
+       u32 dev_id;
+       u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_num_parents - Response for get clk parents
+ * @hdr:               Generic header
+ * @num_parents:       Number of clock parents
+ *
+ * Response to TI_SCI_MSG_GET_NUM_CLOCK_PARENTS
+ */
+struct ti_sci_msg_resp_get_clock_num_parents {
+       struct ti_sci_msg_hdr hdr;
+       u8 num_parents;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_query_clock_freq - Request to query a frequency
+ * @hdr:       Generic Header
+ * @dev_id:    Device identifier this request is for
+ * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ * @target_freq_hz: The target clock frequency. A frequency will be found
+ *             as close to this target frequency as possible.
+ * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ * @clk_id:    Clock identifier for the device for this request.
+ *
+ * NOTE: Normally clock frequency management is automatically done by TISCI
+ * entity. In case of specific requests, TISCI evaluates capability to achieve
+ * requested frequency within provided range and responds with
+ * result message.
+ *
+ * Request type is TI_SCI_MSG_QUERY_CLOCK_FREQ, response is appropriate message,
+ * or NACK in case of inability to satisfy request.
+ */
+struct ti_sci_msg_req_query_clock_freq {
+       struct ti_sci_msg_hdr hdr;
+       u32 dev_id;
+       u64 min_freq_hz;
+       u64 target_freq_hz;
+       u64 max_freq_hz;
+       u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_query_clock_freq - Response to a clock frequency query
+ * @hdr:       Generic Header
+ * @freq_hz:   Frequency that is the best match in Hz.
+ *
+ * Response to request type TI_SCI_MSG_QUERY_CLOCK_FREQ. NOTE: if the request
+ * cannot be satisfied, the message will be of type NACK.
+ */
+struct ti_sci_msg_resp_query_clock_freq {
+       struct ti_sci_msg_hdr hdr;
+       u64 freq_hz;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_clock_freq - Request to setup a clock frequency
+ * @hdr:       Generic Header
+ * @dev_id:    Device identifier this request is for
+ * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ * @target_freq_hz: The target clock frequency. The clock will be programmed
+ *             at a rate as close to this target frequency as possible.
+ * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ * @clk_id:    Clock identifier for the device for this request.
+ *
+ * NOTE: Normally clock frequency management is automatically done by TISCI
+ * entity. In case of specific requests, TISCI evaluates capability to achieve
+ * requested range and responds with success/failure message.
+ *
+ * This sets the desired frequency for a clock within an allowable
+ * range. This message will fail on an enabled clock unless
+ * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally,
+ * if other clocks have their frequency modified due to this message,
+ * they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled.
+ *
+ * Calling set frequency on a clock input to the SoC pseudo-device will
+ * inform the PMMC of that clock's frequency. Setting a frequency of
+ * zero will indicate the clock is disabled.
+ *
+ * Calling set frequency on clock outputs from the SoC pseudo-device will
+ * function similarly to setting the clock frequency on a device.
+ *
+ * Request type is TI_SCI_MSG_SET_CLOCK_FREQ, response is a generic ACK/NACK
+ * message.
+ */
+struct ti_sci_msg_req_set_clock_freq {
+       struct ti_sci_msg_hdr hdr;
+       u32 dev_id;
+       u64 min_freq_hz;
+       u64 target_freq_hz;
+       u64 max_freq_hz;
+       u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_freq - Request to get the clock frequency
+ * @hdr:       Generic Header
+ * @dev_id:    Device identifier this request is for
+ * @clk_id:    Clock identifier for the device for this request.
+ *
+ * NOTE: Normally clock frequency management is automatically done by TISCI
+ * entity. In some cases, clock frequencies are configured by host.
+ *
+ * Request type is TI_SCI_MSG_GET_CLOCK_FREQ, responded with clock frequency
+ * that the clock is currently at.
+ */
+struct ti_sci_msg_req_get_clock_freq {
+       struct ti_sci_msg_hdr hdr;
+       u32 dev_id;
+       u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_freq - Response of clock frequency request
+ * @hdr:       Generic Header
+ * @freq_hz:   Frequency that the clock is currently on, in Hz.
+ *
+ * Response to request type TI_SCI_MSG_GET_CLOCK_FREQ.
+ */
+struct ti_sci_msg_resp_get_clock_freq {
+       struct ti_sci_msg_hdr hdr;
+       u64 freq_hz;
+} __packed;
+
 #endif /* __TI_SCI_H */
 
                                 u32 *reset_state);
 };
 
+/**
+ * struct ti_sci_clk_ops - Clock control operations
+ * @get_clock: Request for activation of clock and manage by processor
+ *             - needs_ssc: 'true' if Spread Spectrum clock is desired.
+ *             - can_change_freq: 'true' if frequency change is desired.
+ *             - enable_input_term: 'true' if input termination is desired.
+ * @idle_clock:        Request for Idling a clock managed by processor
+ * @put_clock: Release the clock to be auto managed by TISCI
+ * @is_auto:   Is the clock being auto managed
+ *             - req_state: state indicating if the clock is auto managed
+ * @is_on:     Is the clock ON
+ *             - req_state: if the clock is requested to be forced ON
+ *             - current_state: if the clock is currently ON
+ * @is_off:    Is the clock OFF
+ *             - req_state: if the clock is requested to be forced OFF
+ *             - current_state: if the clock is currently Gated
+ * @set_parent:        Set the clock source of a specific device clock
+ *             - parent_id: Parent clock identifier to set.
+ * @get_parent:        Get the current clock source of a specific device clock
+ *             - parent_id: Parent clock identifier which is the parent.
+ * @get_num_parents: Get the number of parents of the current clock source
+ *             - num_parents: returns the number of parent clocks.
+ * @get_best_match_freq: Find a best matching frequency for a frequency
+ *             range.
+ *             - match_freq: Best matching frequency in Hz.
+ * @set_freq:  Set the Clock frequency
+ * @get_freq:  Get the Clock frequency
+ *             - current_freq: Frequency in Hz that the clock is at.
+ *
+ * NOTE: for all these functions, the following parameters are generic in
+ * nature:
+ * -handle:    Pointer to TISCI handle as retrieved by *ti_sci_get_handle
+ * -did:       Device identifier this request is for
+ * -cid:       Clock identifier for the device for this request.
+ *             Each device has it's own set of clock inputs. This indexes
+ *             which clock input to modify.
+ * -min_freq:  The minimum allowable frequency in Hz. This is the minimum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ * -target_freq: The target clock frequency in Hz. A frequency will be
+ *             processed as close to this target frequency as possible.
+ * -max_freq:  The maximum allowable frequency in Hz. This is the maximum
+ *             allowable programmed frequency and does not account for clock
+ *             tolerances and jitter.
+ *
+ * Request for the clock - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_clock with put_clock. No refcounting is
+ * managed by driver for that purpose.
+ */
+struct ti_sci_clk_ops {
+       int (*get_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid,
+                        bool needs_ssc, bool can_change_freq,
+                        bool enable_input_term);
+       int (*idle_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid);
+       int (*put_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid);
+       int (*is_auto)(const struct ti_sci_handle *handle, u32 did, u8 cid,
+                      bool *req_state);
+       int (*is_on)(const struct ti_sci_handle *handle, u32 did, u8 cid,
+                    bool *req_state, bool *current_state);
+       int (*is_off)(const struct ti_sci_handle *handle, u32 did, u8 cid,
+                     bool *req_state, bool *current_state);
+       int (*set_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid,
+                         u8 parent_id);
+       int (*get_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid,
+                         u8 *parent_id);
+       int (*get_num_parents)(const struct ti_sci_handle *handle, u32 did,
+                              u8 cid, u8 *num_parents);
+       int (*get_best_match_freq)(const struct ti_sci_handle *handle, u32 did,
+                                  u8 cid, u64 min_freq, u64 target_freq,
+                                  u64 max_freq, u64 *match_freq);
+       int (*set_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid,
+                       u64 min_freq, u64 target_freq, u64 max_freq);
+       int (*get_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid,
+                       u64 *current_freq);
+};
+
 /**
  * struct ti_sci_ops - Function support for TI SCI
  * @dev_ops:   Device specific operations
+ * @clk_ops:   Clock specific operations
  */
 struct ti_sci_ops {
        struct ti_sci_dev_ops dev_ops;
+       struct ti_sci_clk_ops clk_ops;
 };
 
 /**