|
|
@@ -2636,6 +2636,348 @@ fail:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * ti_sci_cmd_proc_request() - Command to request a physical processor control
|
|
|
+ * @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_request(const struct ti_sci_handle *handle,
|
|
|
+ u8 proc_id)
|
|
|
+{
|
|
|
+ struct ti_sci_msg_req_proc_request *req;
|
|
|
+ struct ti_sci_msg_hdr *resp;
|
|
|
+ struct ti_sci_info *info;
|
|
|
+ struct ti_sci_xfer *xfer;
|
|
|
+ struct device *dev;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!handle)
|
|
|
+ return -EINVAL;
|
|
|
+ if (IS_ERR(handle))
|
|
|
+ return PTR_ERR(handle);
|
|
|
+
|
|
|
+ info = handle_to_ti_sci_info(handle);
|
|
|
+ dev = info->dev;
|
|
|
+
|
|
|
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_REQUEST,
|
|
|
+ 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_proc_request *)xfer->xfer_buf;
|
|
|
+ req->processor_id = proc_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->tx_message.buf;
|
|
|
+
|
|
|
+ ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
|
|
|
+
|
|
|
+fail:
|
|
|
+ ti_sci_put_one_xfer(&info->minfo, xfer);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ti_sci_cmd_proc_release() - Command to release a physical processor control
|
|
|
+ * @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_release(const struct ti_sci_handle *handle,
|
|
|
+ u8 proc_id)
|
|
|
+{
|
|
|
+ struct ti_sci_msg_req_proc_release *req;
|
|
|
+ struct ti_sci_msg_hdr *resp;
|
|
|
+ struct ti_sci_info *info;
|
|
|
+ struct ti_sci_xfer *xfer;
|
|
|
+ struct device *dev;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!handle)
|
|
|
+ return -EINVAL;
|
|
|
+ if (IS_ERR(handle))
|
|
|
+ return PTR_ERR(handle);
|
|
|
+
|
|
|
+ info = handle_to_ti_sci_info(handle);
|
|
|
+ dev = info->dev;
|
|
|
+
|
|
|
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_RELEASE,
|
|
|
+ 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_proc_release *)xfer->xfer_buf;
|
|
|
+ req->processor_id = proc_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->tx_message.buf;
|
|
|
+
|
|
|
+ ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
|
|
|
+
|
|
|
+fail:
|
|
|
+ ti_sci_put_one_xfer(&info->minfo, xfer);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ti_sci_cmd_proc_handover() - Command to handover a physical processor
|
|
|
+ * control to a host in the processor's access
|
|
|
+ * control list.
|
|
|
+ * @handle: Pointer to TI SCI handle
|
|
|
+ * @proc_id: Processor ID this request is for
|
|
|
+ * @host_id: Host ID to get the control of the processor
|
|
|
+ *
|
|
|
+ * Return: 0 if all went well, else returns appropriate error value.
|
|
|
+ */
|
|
|
+static int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle,
|
|
|
+ u8 proc_id, u8 host_id)
|
|
|
+{
|
|
|
+ struct ti_sci_msg_req_proc_handover *req;
|
|
|
+ struct ti_sci_msg_hdr *resp;
|
|
|
+ struct ti_sci_info *info;
|
|
|
+ struct ti_sci_xfer *xfer;
|
|
|
+ struct device *dev;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!handle)
|
|
|
+ return -EINVAL;
|
|
|
+ if (IS_ERR(handle))
|
|
|
+ return PTR_ERR(handle);
|
|
|
+
|
|
|
+ info = handle_to_ti_sci_info(handle);
|
|
|
+ dev = info->dev;
|
|
|
+
|
|
|
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_HANDOVER,
|
|
|
+ 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_proc_handover *)xfer->xfer_buf;
|
|
|
+ req->processor_id = proc_id;
|
|
|
+ req->host_id = host_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->tx_message.buf;
|
|
|
+
|
|
|
+ ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
|
|
|
+
|
|
|
+fail:
|
|
|
+ ti_sci_put_one_xfer(&info->minfo, xfer);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ti_sci_cmd_proc_set_config() - Command to set the processor boot
|
|
|
+ * configuration flags
|
|
|
+ * @handle: Pointer to TI SCI handle
|
|
|
+ * @proc_id: Processor ID this request is for
|
|
|
+ * @config_flags_set: Configuration flags to be set
|
|
|
+ * @config_flags_clear: Configuration flags to be cleared.
|
|
|
+ *
|
|
|
+ * Return: 0 if all went well, else returns appropriate error value.
|
|
|
+ */
|
|
|
+static int ti_sci_cmd_proc_set_config(const struct ti_sci_handle *handle,
|
|
|
+ u8 proc_id, u64 bootvector,
|
|
|
+ u32 config_flags_set,
|
|
|
+ u32 config_flags_clear)
|
|
|
+{
|
|
|
+ struct ti_sci_msg_req_set_config *req;
|
|
|
+ struct ti_sci_msg_hdr *resp;
|
|
|
+ struct ti_sci_info *info;
|
|
|
+ struct ti_sci_xfer *xfer;
|
|
|
+ struct device *dev;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!handle)
|
|
|
+ return -EINVAL;
|
|
|
+ if (IS_ERR(handle))
|
|
|
+ return PTR_ERR(handle);
|
|
|
+
|
|
|
+ info = handle_to_ti_sci_info(handle);
|
|
|
+ dev = info->dev;
|
|
|
+
|
|
|
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CONFIG,
|
|
|
+ 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_config *)xfer->xfer_buf;
|
|
|
+ req->processor_id = proc_id;
|
|
|
+ req->bootvector_low = bootvector & TI_SCI_ADDR_LOW_MASK;
|
|
|
+ req->bootvector_high = (bootvector & TI_SCI_ADDR_HIGH_MASK) >>
|
|
|
+ TI_SCI_ADDR_HIGH_SHIFT;
|
|
|
+ req->config_flags_set = config_flags_set;
|
|
|
+ req->config_flags_clear = config_flags_clear;
|
|
|
+
|
|
|
+ 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->tx_message.buf;
|
|
|
+
|
|
|
+ ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
|
|
|
+
|
|
|
+fail:
|
|
|
+ ti_sci_put_one_xfer(&info->minfo, xfer);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ti_sci_cmd_proc_set_control() - Command to set the processor boot
|
|
|
+ * control flags
|
|
|
+ * @handle: Pointer to TI SCI handle
|
|
|
+ * @proc_id: Processor ID this request is for
|
|
|
+ * @control_flags_set: Control flags to be set
|
|
|
+ * @control_flags_clear: Control flags to be cleared
|
|
|
+ *
|
|
|
+ * Return: 0 if all went well, else returns appropriate error value.
|
|
|
+ */
|
|
|
+static int ti_sci_cmd_proc_set_control(const struct ti_sci_handle *handle,
|
|
|
+ u8 proc_id, u32 control_flags_set,
|
|
|
+ u32 control_flags_clear)
|
|
|
+{
|
|
|
+ struct ti_sci_msg_req_set_ctrl *req;
|
|
|
+ struct ti_sci_msg_hdr *resp;
|
|
|
+ struct ti_sci_info *info;
|
|
|
+ struct ti_sci_xfer *xfer;
|
|
|
+ struct device *dev;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!handle)
|
|
|
+ return -EINVAL;
|
|
|
+ if (IS_ERR(handle))
|
|
|
+ return PTR_ERR(handle);
|
|
|
+
|
|
|
+ info = handle_to_ti_sci_info(handle);
|
|
|
+ dev = info->dev;
|
|
|
+
|
|
|
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CTRL,
|
|
|
+ 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_ctrl *)xfer->xfer_buf;
|
|
|
+ req->processor_id = proc_id;
|
|
|
+ req->control_flags_set = control_flags_set;
|
|
|
+ req->control_flags_clear = control_flags_clear;
|
|
|
+
|
|
|
+ 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->tx_message.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_boot_status() - Command to get the processor boot status
|
|
|
+ * @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_get_status(const struct ti_sci_handle *handle,
|
|
|
+ u8 proc_id, u64 *bv, u32 *cfg_flags,
|
|
|
+ u32 *ctrl_flags, u32 *sts_flags)
|
|
|
+{
|
|
|
+ struct ti_sci_msg_resp_get_status *resp;
|
|
|
+ struct ti_sci_msg_req_get_status *req;
|
|
|
+ struct ti_sci_info *info;
|
|
|
+ struct ti_sci_xfer *xfer;
|
|
|
+ struct device *dev;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (!handle)
|
|
|
+ return -EINVAL;
|
|
|
+ if (IS_ERR(handle))
|
|
|
+ return PTR_ERR(handle);
|
|
|
+
|
|
|
+ info = handle_to_ti_sci_info(handle);
|
|
|
+ dev = info->dev;
|
|
|
+
|
|
|
+ xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_STATUS,
|
|
|
+ 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_status *)xfer->xfer_buf;
|
|
|
+ req->processor_id = proc_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_status *)xfer->tx_message.buf;
|
|
|
+
|
|
|
+ if (!ti_sci_is_response_ack(resp)) {
|
|
|
+ ret = -ENODEV;
|
|
|
+ } else {
|
|
|
+ *bv = (resp->bootvector_low & TI_SCI_ADDR_LOW_MASK) |
|
|
|
+ (((u64)resp->bootvector_high << TI_SCI_ADDR_HIGH_SHIFT) &
|
|
|
+ TI_SCI_ADDR_HIGH_MASK);
|
|
|
+ *cfg_flags = resp->config_flags;
|
|
|
+ *ctrl_flags = resp->control_flags;
|
|
|
+ *sts_flags = resp->status_flags;
|
|
|
+ }
|
|
|
+
|
|
|
+fail:
|
|
|
+ ti_sci_put_one_xfer(&info->minfo, xfer);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* ti_sci_setup_ops() - Setup the operations structures
|
|
|
* @info: pointer to TISCI pointer
|
|
|
@@ -2648,6 +2990,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
|
|
|
struct ti_sci_clk_ops *cops = &ops->clk_ops;
|
|
|
struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
|
|
|
struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_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;
|
|
|
@@ -2698,6 +3041,13 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
|
|
|
iops->free_event_irq_from_shost = ti_sci_cmd_free_event_irq_from_shost;
|
|
|
iops->free_event_irq_to_poll = ti_sci_cmd_free_event_irq_to_poll;
|
|
|
|
|
|
+ pops->request = ti_sci_cmd_proc_request;
|
|
|
+ pops->release = ti_sci_cmd_proc_release;
|
|
|
+ pops->handover = ti_sci_cmd_proc_handover;
|
|
|
+ pops->set_config = ti_sci_cmd_proc_set_config;
|
|
|
+ pops->set_control = ti_sci_cmd_proc_set_control;
|
|
|
+ pops->get_status = ti_sci_cmd_proc_get_status;
|
|
|
+
|
|
|
rops->config = ti_sci_cmd_ring_config;
|
|
|
rops->get_config = ti_sci_cmd_ring_get_config;
|
|
|
|