diff options
author | Lokesh Vutla <lokeshvutla@ti.com> | 2018-08-27 15:57:37 +0530 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2018-09-11 08:32:55 -0400 |
commit | ccbc8b2fddc59f9ec5f487b704195227e4360c29 (patch) | |
tree | ffb57516d6984ec0328645f9505659c0b19368e5 /drivers/firmware/ti_sci.c | |
parent | f369b0f26cf77921e2a3b8c5ad7dab7e82b246ee (diff) |
firmware: ti_sci: Add support for processor control services
TI-SCI message protocol provides support for controlling of various
physical cores available in SoC. In order to control which host is
capable of controlling a physical processor core, there is a processor
access control list that needs to be populated as part of the board
configuration data.
Introduce support for the set of TI-SCI message protocol apis that
provide us with this capability of controlling physical cores.
Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Diffstat (limited to 'drivers/firmware/ti_sci.c')
-rw-r--r-- | drivers/firmware/ti_sci.c | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 1a78b7d0dc..9148126041 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -1441,6 +1441,368 @@ static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) 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; + 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_PROC_REQUEST, + 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.processor_id = proc_id; + + 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)) + ret = -ENODEV; + + 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; + 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_PROC_RELEASE, + 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.processor_id = proc_id; + + 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)) + ret = -ENODEV; + + 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; + 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_PROC_HANDOVER, + 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.processor_id = proc_id; + req.host_id = host_id; + + 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)) + ret = -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_set_proc_boot_cfg() - 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_set_proc_boot_cfg(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_proc_boot_config 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_SET_PROC_BOOT_CONFIG, + 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.processor_id = proc_id; + req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK; + req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >> + TISCI_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(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)) + ret = -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_set_proc_boot_ctrl() - 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_set_proc_boot_ctrl(const struct ti_sci_handle *handle, + u8 proc_id, u32 control_flags_set, + u32 control_flags_clear) +{ + struct ti_sci_msg_req_set_proc_boot_ctrl 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_SET_PROC_BOOT_CTRL, + 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.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(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)) + ret = -ENODEV; + + return ret; +} + +/** + * 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. + * + * 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) +{ + struct ti_sci_msg_req_proc_auth_boot_image 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_PROC_AUTH_BOOT_IMIAGE, + 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.processor_id = proc_id; + req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK; + req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >> + TISCI_ADDR_HIGH_SHIFT; + + 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)) + ret = -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_get_proc_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_get_proc_boot_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_proc_boot_status *resp; + struct ti_sci_msg_req_get_proc_boot_status 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_GET_PROC_BOOT_STATUS, + 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.processor_id = proc_id; + + 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_resp_get_proc_boot_status *) + xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + *bv = (resp->bootvector_low & TISCI_ADDR_LOW_MASK) | + (((u64)resp->bootvector_high << + TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK); + *cfg_flags = resp->config_flags; + *ctrl_flags = resp->control_flags; + *sts_flags = resp->status_flags; + + return ret; +} + /* * ti_sci_setup_ops() - Setup the operations structures * @info: pointer to TISCI pointer @@ -1452,6 +1814,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) 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; bops->board_config = ti_sci_cmd_set_board_config; bops->board_config_rm = ti_sci_cmd_set_board_config_rm; @@ -1486,6 +1849,14 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) cops->get_freq = ti_sci_cmd_clk_get_freq; core_ops->reboot_device = ti_sci_cmd_core_reboot; + + pops->proc_request = ti_sci_cmd_proc_request; + pops->proc_release = ti_sci_cmd_proc_release; + pops->proc_handover = ti_sci_cmd_proc_handover; + pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg; + 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; } /** |