[U-Boot,v3,2/7] firmware: ti_sci: Add support for firewall management
diff mbox series

Message ID 20190412165448.1788-3-afd@ti.com
State Accepted
Delegated to: Tom Rini
Headers show
Series
  • AM65x HS device support
Related show

Commit Message

Andrew F. Davis April 12, 2019, 4:54 p.m. UTC
TI-SCI message protocol provides support for controlling the firewall
configurations available in SoC.

Introduce support for the set of TI-SCI message protocol APIs that
provide us with this capability of controlling firewalls.

Signed-off-by: Andrew F. Davis <afd@ti.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
Reviewed-by: Andreas Dannenberg <dannenberg@ti.com>
---
 drivers/firmware/ti_sci.c              | 177 +++++++++++++++++++++++++
 drivers/firmware/ti_sci.h              | 121 +++++++++++++++++
 include/linux/soc/ti/ti_sci_protocol.h |  64 +++++++++
 3 files changed, 362 insertions(+)

Comments

Tom Rini April 27, 2019, 2:45 p.m. UTC | #1
On Fri, Apr 12, 2019 at 12:54:43PM -0400, Andrew F. Davis wrote:

> TI-SCI message protocol provides support for controlling the firewall
> configurations available in SoC.
> 
> Introduce support for the set of TI-SCI message protocol APIs that
> provide us with this capability of controlling firewalls.
> 
> Signed-off-by: Andrew F. Davis <afd@ti.com>
> Reviewed-by: Tom Rini <trini@konsulko.com>
> Reviewed-by: Andreas Dannenberg <dannenberg@ti.com>

Applied to u-boot/master, thanks!

Patch
diff mbox series

diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index d47d22fff3..44bbeb66c2 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -2428,6 +2428,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 +2616,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 +2674,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..1b601ff01b 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
@@ -1338,4 +1342,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 */
diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
index 222cf66546..895cb1b911 100644
--- a/include/linux/soc/ti/ti_sci_protocol.h
+++ b/include/linux/soc/ti/ti_sci_protocol.h
@@ -510,6 +510,68 @@  struct ti_sci_rm_udmap_ops {
 		const struct ti_sci_msg_rm_udmap_flow_cfg *params);
 };
 
+/**
+ * struct ti_sci_msg_fwl_region_cfg - Request and Response for firewalls settings
+ *
+ * @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_region {
+	u16 fwl_id;
+	u16 region;
+	u32 n_permission_regs;
+	u32 control;
+	u32 permissions[3];
+	u64 start_address;
+	u64 end_address;
+} __packed;
+
+/**
+ * \brief Request and Response for firewall owner change
+ *
+ * @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 <= 3
+ * @control:		Control register value for this region
+ * @owner_index:	New owner index to change to. Owner indexes are setup in DMSC firmware boot configuration data
+ * @owner_privid:	New owner priv-id, used to lookup owner_index is not known, must be set to zero otherwise
+ * @owner_permission_bits: New owner permission bits
+ */
+struct ti_sci_msg_fwl_owner {
+	u16 fwl_id;
+	u16 region;
+	u8 owner_index;
+	u8 owner_privid;
+	u16 owner_permission_bits;
+} __packed;
+
+/**
+ * struct ti_sci_fwl_ops - Firewall specific operations
+ * @set_fwl_region: Request for configuring the firewall permissions.
+ * @get_fwl_region: Request for retrieving the firewall permissions.
+ * @change_fwl_owner: Request for a change of firewall owner.
+ */
+struct ti_sci_fwl_ops {
+	int (*set_fwl_region)(const struct ti_sci_handle *handle, const struct ti_sci_msg_fwl_region *region);
+	int (*get_fwl_region)(const struct ti_sci_handle *handle, struct ti_sci_msg_fwl_region *region);
+	int (*change_fwl_owner)(const struct ti_sci_handle *handle, struct ti_sci_msg_fwl_owner *owner);
+};
+
 /**
  * struct ti_sci_ops - Function support for TI SCI
  * @board_ops:	Miscellaneous operations
@@ -518,6 +580,7 @@  struct ti_sci_rm_udmap_ops {
  * @core_ops:	Core specific operations
  * @proc_ops:	Processor specific operations
  * @ring_ops: Ring Accelerator Management operations
+ * @fw_ops:	Firewall specific operations
  */
 struct ti_sci_ops {
 	struct ti_sci_board_ops board_ops;
@@ -529,6 +592,7 @@  struct ti_sci_ops {
 	struct ti_sci_rm_ringacc_ops rm_ring_ops;
 	struct ti_sci_rm_psil_ops rm_psil_ops;
 	struct ti_sci_rm_udmap_ops rm_udmap_ops;
+	struct ti_sci_fwl_ops fwl_ops;
 };
 
 /**