summaryrefslogtreecommitdiff
path: root/drivers/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/ti_sci.c202
-rw-r--r--drivers/firmware/ti_sci.h130
2 files changed, 321 insertions, 11 deletions
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index d47d22fff3..1196ce0712 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -1915,16 +1915,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;
@@ -1944,9 +1947,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);
@@ -1955,10 +1957,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;
}
@@ -2428,6 +2435,178 @@ fail:
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_GET,
+ TISCI_MSG_FWL_CHANGE_OWNER,
+ (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
@@ -2444,6 +2623,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_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;
@@ -2501,6 +2681,10 @@ 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;
+
+ 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;
}
/**
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index 2d87cdd2cf..a484b1fa40 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -79,6 +79,10 @@
#define TISCI_MSG_RM_UDMAP_FLOW_GET_CFG 0x1232
#define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_GET_CFG 0x1233
+#define TISCI_MSG_FWL_SET 0x9000
+#define TISCI_MSG_FWL_GET 0x9001
+#define TISCI_MSG_FWL_CHANGE_OWNER 0x9002
+
/**
* struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
* @type: Type of messages: One of TI_SCI_MSG* values
@@ -704,7 +708,6 @@ struct ti_sci_msg_req_set_proc_boot_ctrl {
/**
* struct ti_sci_msg_req_proc_auth_start_image - Authenticate and start image
* @hdr: Generic Header
- * @processor_id: ID of processor
* @cert_addr_low: Lower 32bit (Little Endian) of certificate
* @cert_addr_high: Higher 32bit (Little Endian) of certificate
*
@@ -713,11 +716,17 @@ struct ti_sci_msg_req_set_proc_boot_ctrl {
*/
struct ti_sci_msg_req_proc_auth_boot_image {
struct ti_sci_msg_hdr hdr;
- u8 processor_id;
u32 cert_addr_low;
u32 cert_addr_high;
} __packed;
+struct ti_sci_msg_resp_proc_auth_boot_image {
+ struct ti_sci_msg_hdr hdr;
+ u32 image_addr_low;
+ u32 image_addr_high;
+ u32 image_size;
+} __packed;
+
/**
* struct ti_sci_msg_req_get_proc_boot_status - Get processor boot status
* @hdr: Generic Header
@@ -1338,4 +1347,121 @@ struct ti_sci_msg_rm_udmap_flow_cfg_resp {
struct ti_sci_msg_hdr hdr;
} __packed;
+#define FWL_MAX_PRIVID_SLOTS 3U
+
+/**
+ * struct ti_sci_msg_fwl_set_firewall_region_req - Request for configuring the firewall permissions.
+ *
+ * @hdr: Generic Header
+ *
+ * @fwl_id: Firewall ID in question
+ * @region: Region or channel number to set config info
+ * This field is unused in case of a simple firewall and must be initialized
+ * to zero. In case of a region based firewall, this field indicates the
+ * region in question. (index starting from 0) In case of a channel based
+ * firewall, this field indicates the channel in question (index starting
+ * from 0)
+ * @n_permission_regs: Number of permission registers to set
+ * @control: Contents of the firewall CONTROL register to set
+ * @permissions: Contents of the firewall PERMISSION register to set
+ * @start_address: Contents of the firewall START_ADDRESS register to set
+ * @end_address: Contents of the firewall END_ADDRESS register to set
+ */
+
+struct ti_sci_msg_fwl_set_firewall_region_req {
+ struct ti_sci_msg_hdr hdr;
+ u16 fwl_id;
+ u16 region;
+ u32 n_permission_regs;
+ u32 control;
+ u32 permissions[FWL_MAX_PRIVID_SLOTS];
+ u64 start_address;
+ u64 end_address;
+} __packed;
+
+/**
+ * struct ti_sci_msg_fwl_get_firewall_region_req - Request for retrieving the firewall permissions
+ *
+ * @hdr: Generic Header
+ *
+ * @fwl_id: Firewall ID in question
+ * @region: Region or channel number to get config info
+ * This field is unused in case of a simple firewall and must be initialized
+ * to zero. In case of a region based firewall, this field indicates the
+ * region in question (index starting from 0). In case of a channel based
+ * firewall, this field indicates the channel in question (index starting
+ * from 0).
+ * @n_permission_regs: Number of permission registers to retrieve
+ */
+struct ti_sci_msg_fwl_get_firewall_region_req {
+ struct ti_sci_msg_hdr hdr;
+ u16 fwl_id;
+ u16 region;
+ u32 n_permission_regs;
+} __packed;
+
+/**
+ * struct ti_sci_msg_fwl_get_firewall_region_resp - Response for retrieving the firewall permissions
+ *
+ * @hdr: Generic Header
+ *
+ * @fwl_id: Firewall ID in question
+ * @region: Region or channel number to set config info This field is
+ * unused in case of a simple firewall and must be initialized to zero. In
+ * case of a region based firewall, this field indicates the region in
+ * question. (index starting from 0) In case of a channel based firewall, this
+ * field indicates the channel in question (index starting from 0)
+ * @n_permission_regs: Number of permission registers retrieved
+ * @control: Contents of the firewall CONTROL register
+ * @permissions: Contents of the firewall PERMISSION registers
+ * @start_address: Contents of the firewall START_ADDRESS register This is not applicable for channelized firewalls.
+ * @end_address: Contents of the firewall END_ADDRESS register This is not applicable for channelized firewalls.
+ */
+struct ti_sci_msg_fwl_get_firewall_region_resp {
+ struct ti_sci_msg_hdr hdr;
+ u16 fwl_id;
+ u16 region;
+ u32 n_permission_regs;
+ u32 control;
+ u32 permissions[FWL_MAX_PRIVID_SLOTS];
+ u64 start_address;
+ u64 end_address;
+} __packed;
+
+/**
+ * struct ti_sci_msg_fwl_change_owner_info_req - Request for a firewall owner change
+ *
+ * @hdr: Generic Header
+ *
+ * @fwl_id: Firewall ID in question
+ * @region: Region or channel number if applicable
+ * @owner_index: New owner index to transfer ownership to
+ */
+struct ti_sci_msg_fwl_change_owner_info_req {
+ struct ti_sci_msg_hdr hdr;
+ u16 fwl_id;
+ u16 region;
+ u8 owner_index;
+} __packed;
+
+/**
+ * struct ti_sci_msg_fwl_change_owner_info_resp - Response for a firewall owner change
+ *
+ * @hdr: Generic Header
+ *
+ * @fwl_id: Firewall ID specified in request
+ * @region: Region or channel number specified in request
+ * @owner_index: Owner index specified in request
+ * @owner_privid: New owner priv-ID returned by DMSC.
+ * @owner_permission_bits: New owner permission bits returned by DMSC.
+ */
+struct ti_sci_msg_fwl_change_owner_info_resp {
+ struct ti_sci_msg_hdr hdr;
+ u16 fwl_id;
+ u16 region;
+ u8 owner_index;
+ u8 owner_privid;
+ u16 owner_permission_bits;
+} __packed;
+
#endif /* __TI_SCI_H */