diff mbox series

[V6,2/4] firmware: ti_sci: Add support for querying the firmware caps

Message ID 20230803064247.503036-3-d-gole@ti.com (mailing list archive)
State New, archived
Headers show
Series firmware: ti_sci: Introduce system suspend support | expand

Commit Message

Dhruva Gole Aug. 3, 2023, 6:42 a.m. UTC
From: Georgi Vlaev <g-vlaev@ti.com>

This patch adds support for the TISCI_MSG_QUERY_FW_CAPS
message, used to retrieve the firmware capabilities of the
currently running system firmware. The message belongs to
the TISCI general core message API [1] and is available in
SysFW version 08.04.03 and above. Currently, the message is
supported on devices with split architecture of the system
firmware (DM + TIFS) like AM62x. Old revisions or not yet
supported platforms will NACK this request.

We're using this message locally in ti_sci.c to get the low
power featutes of the FW/SoC. As there's no other kernel
consumers yet, this is not added to struct ti_sci_core_ops.

[1] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/general/core.html

Signed-off-by: Georgi Vlaev <g-vlaev@ti.com>
---
 drivers/firmware/ti_sci.c | 56 +++++++++++++++++++++++++++++++++++++++
 drivers/firmware/ti_sci.h | 26 ++++++++++++++++++
 2 files changed, 82 insertions(+)

Comments

Andrew Davis Aug. 3, 2023, 3:21 p.m. UTC | #1
On 8/3/23 1:42 AM, Dhruva Gole wrote:
> From: Georgi Vlaev <g-vlaev@ti.com>
> 
> This patch adds support for the TISCI_MSG_QUERY_FW_CAPS
> message, used to retrieve the firmware capabilities of the
> currently running system firmware. The message belongs to
> the TISCI general core message API [1] and is available in
> SysFW version 08.04.03 and above. Currently, the message is
> supported on devices with split architecture of the system
> firmware (DM + TIFS) like AM62x. Old revisions or not yet
> supported platforms will NACK this request.

The API is also buggy on SYSFW 9.00 and below, maybe we should
check the firmware version in this function and return "not
supported" or all 0s, instead of returning known bad values.

Andrew

> 
> We're using this message locally in ti_sci.c to get the low
> power featutes of the FW/SoC. As there's no other kernel
> consumers yet, this is not added to struct ti_sci_core_ops.
> 
> [1] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/general/core.html
> 
> Signed-off-by: Georgi Vlaev <g-vlaev@ti.com>
> ---
>   drivers/firmware/ti_sci.c | 56 +++++++++++++++++++++++++++++++++++++++
>   drivers/firmware/ti_sci.h | 26 ++++++++++++++++++
>   2 files changed, 82 insertions(+)
> 
> diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
> index 31a71613ca54..3b40f9336b3f 100644
> --- a/drivers/firmware/ti_sci.c
> +++ b/drivers/firmware/ti_sci.c
> @@ -1723,6 +1723,62 @@ static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode,
>   	return ret;
>   }
>   
> +/**
> + * ti_sci_msg_cmd_query_fw_caps() - Get the FW/SoC capabilities
> + * @handle:		Pointer to TI SCI handle
> + * @fw_caps:		Each bit in fw_caps indicating one FW/SOC capability
> + *
> + * Return: 0 if all went well, else returns appropriate error value.
> + */
> +static int ti_sci_msg_cmd_query_fw_caps(const struct ti_sci_handle *handle,
> +					u64 *fw_caps)
> +{
> +	struct ti_sci_info *info;
> +	struct ti_sci_xfer *xfer;
> +	struct ti_sci_msg_resp_query_fw_caps *resp;
> +	struct device *dev;
> +	int ret = 0;
> +
> +	if (IS_ERR(handle))
> +		return PTR_ERR(handle);
> +	if (!handle)
> +		return -EINVAL;
> +
> +	info = handle_to_ti_sci_info(handle);
> +	dev = info->dev;
> +
> +	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_FW_CAPS,
> +				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
> +				   sizeof(struct ti_sci_msg_hdr),
> +				   sizeof(*resp));
> +	if (IS_ERR(xfer)) {
> +		ret = PTR_ERR(xfer);
> +		dev_err(dev, "Message alloc failed(%d)\n", ret);
> +		return ret;
> +	}
> +
> +	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_query_fw_caps *)xfer->xfer_buf;
> +
> +	if (!ti_sci_is_response_ack(resp)) {
> +		ret = -ENODEV;
> +		goto fail;
> +	}
> +
> +	if (fw_caps)
> +		*fw_caps = resp->fw_caps;
> +
> +fail:
> +	ti_sci_put_one_xfer(&info->minfo, xfer);
> +
> +	return ret;
> +}
> +
>   /**
>    * ti_sci_msg_cmd_lpm_wake_reason() - Get the wakeup source from LPM
>    * @handle:		Pointer to TI SCI handle
> diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
> index e4bfe146c43d..d5b23d91b9b9 100644
> --- a/drivers/firmware/ti_sci.h
> +++ b/drivers/firmware/ti_sci.h
> @@ -19,6 +19,7 @@
>   #define TI_SCI_MSG_WAKE_REASON	0x0003
>   #define TI_SCI_MSG_GOODBYE	0x0004
>   #define TI_SCI_MSG_SYS_RESET	0x0005
> +#define TI_SCI_MSG_QUERY_FW_CAPS	0x0022
>   
>   /* Device requests */
>   #define TI_SCI_MSG_SET_DEVICE_STATE	0x0200
> @@ -137,6 +138,31 @@ struct ti_sci_msg_req_reboot {
>   	struct ti_sci_msg_hdr hdr;
>   } __packed;
>   
> +/**
> + * struct ti_sci_msg_resp_query_fw_caps - Response for query firmware caps
> + * @hdr:	Generic header
> + * @fw_caps:	Each bit in fw_caps indicating one FW/SOC capability
> + *		MSG_FLAG_CAPS_GENERIC: Generic capability (LPM not supported)
> + *		MSG_FLAG_CAPS_LPM_DEEP_SLEEP: Deep Sleep LPM
> + *		MSG_FLAG_CAPS_LPM_MCU_ONLY: MCU only LPM
> + *		MSG_FLAG_CAPS_LPM_STANDBY: Standby LPM
> + *		MSG_FLAG_CAPS_LPM_PARTIAL_IO: Partial IO in LPM
> + *
> + * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS
> + * providing currently available SOC/firmware capabilities. SoC that don't
> + * support low power modes return only MSG_FLAG_CAPS_GENERIC capability.
> + */
> +struct ti_sci_msg_resp_query_fw_caps {
> +	struct ti_sci_msg_hdr hdr;
> +#define MSG_FLAG_CAPS_GENERIC		TI_SCI_MSG_FLAG(0)
> +#define MSG_FLAG_CAPS_LPM_DEEP_SLEEP	TI_SCI_MSG_FLAG(1)
> +#define MSG_FLAG_CAPS_LPM_MCU_ONLY	TI_SCI_MSG_FLAG(2)
> +#define MSG_FLAG_CAPS_LPM_STANDBY	TI_SCI_MSG_FLAG(3)
> +#define MSG_FLAG_CAPS_LPM_PARTIAL_IO	TI_SCI_MSG_FLAG(4)
> +#define MSG_MASK_CAPS_LPM		GENMASK_ULL(4, 1)
> +	u64 fw_caps;
> +} __packed;
> +
>   /**
>    * struct ti_sci_msg_req_set_device_state - Set the desired state of the device
>    * @hdr:		Generic header
diff mbox series

Patch

diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 31a71613ca54..3b40f9336b3f 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -1723,6 +1723,62 @@  static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode,
 	return ret;
 }
 
+/**
+ * ti_sci_msg_cmd_query_fw_caps() - Get the FW/SoC capabilities
+ * @handle:		Pointer to TI SCI handle
+ * @fw_caps:		Each bit in fw_caps indicating one FW/SOC capability
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_msg_cmd_query_fw_caps(const struct ti_sci_handle *handle,
+					u64 *fw_caps)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_xfer *xfer;
+	struct ti_sci_msg_resp_query_fw_caps *resp;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_FW_CAPS,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(struct ti_sci_msg_hdr),
+				   sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+
+	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_query_fw_caps *)xfer->xfer_buf;
+
+	if (!ti_sci_is_response_ack(resp)) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	if (fw_caps)
+		*fw_caps = resp->fw_caps;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
 /**
  * ti_sci_msg_cmd_lpm_wake_reason() - Get the wakeup source from LPM
  * @handle:		Pointer to TI SCI handle
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index e4bfe146c43d..d5b23d91b9b9 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -19,6 +19,7 @@ 
 #define TI_SCI_MSG_WAKE_REASON	0x0003
 #define TI_SCI_MSG_GOODBYE	0x0004
 #define TI_SCI_MSG_SYS_RESET	0x0005
+#define TI_SCI_MSG_QUERY_FW_CAPS	0x0022
 
 /* Device requests */
 #define TI_SCI_MSG_SET_DEVICE_STATE	0x0200
@@ -137,6 +138,31 @@  struct ti_sci_msg_req_reboot {
 	struct ti_sci_msg_hdr hdr;
 } __packed;
 
+/**
+ * struct ti_sci_msg_resp_query_fw_caps - Response for query firmware caps
+ * @hdr:	Generic header
+ * @fw_caps:	Each bit in fw_caps indicating one FW/SOC capability
+ *		MSG_FLAG_CAPS_GENERIC: Generic capability (LPM not supported)
+ *		MSG_FLAG_CAPS_LPM_DEEP_SLEEP: Deep Sleep LPM
+ *		MSG_FLAG_CAPS_LPM_MCU_ONLY: MCU only LPM
+ *		MSG_FLAG_CAPS_LPM_STANDBY: Standby LPM
+ *		MSG_FLAG_CAPS_LPM_PARTIAL_IO: Partial IO in LPM
+ *
+ * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS
+ * providing currently available SOC/firmware capabilities. SoC that don't
+ * support low power modes return only MSG_FLAG_CAPS_GENERIC capability.
+ */
+struct ti_sci_msg_resp_query_fw_caps {
+	struct ti_sci_msg_hdr hdr;
+#define MSG_FLAG_CAPS_GENERIC		TI_SCI_MSG_FLAG(0)
+#define MSG_FLAG_CAPS_LPM_DEEP_SLEEP	TI_SCI_MSG_FLAG(1)
+#define MSG_FLAG_CAPS_LPM_MCU_ONLY	TI_SCI_MSG_FLAG(2)
+#define MSG_FLAG_CAPS_LPM_STANDBY	TI_SCI_MSG_FLAG(3)
+#define MSG_FLAG_CAPS_LPM_PARTIAL_IO	TI_SCI_MSG_FLAG(4)
+#define MSG_MASK_CAPS_LPM		GENMASK_ULL(4, 1)
+	u64 fw_caps;
+} __packed;
+
 /**
  * struct ti_sci_msg_req_set_device_state - Set the desired state of the device
  * @hdr:		Generic header