firmware: ti_sci: Add support for processor control
Texas Instrument's System Control Interface (TI-SCI) Message Protocol is used in Texas Instrument's System on Chip (SoC) such as those in K3 family AM654 SoC to communicate between various compute processors with a central system controller entity. The system controller provides various services including the control of other compute processors within the SoC. Extend the TI-SCI protocol support to add various TI-SCI commands to invoke services associated with power and reset control, and boot vector management of the various compute processors from the Linux kernel. Signed-off-by: Suman Anna <s-anna@ti.com> Signed-off-by: Tero Kristo <t-kristo@ti.com> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
This commit is contained in:

committed by
Santosh Shilimkar

parent
68608b5e50
commit
1e407f337f
@@ -2479,6 +2479,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
|
||||
@@ -2494,6 +2836,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
|
||||
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_proc_ops *pops = &ops->proc_ops;
|
||||
|
||||
core_ops->reboot_device = ti_sci_cmd_core_reboot;
|
||||
|
||||
@@ -2543,6 +2886,13 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user