From: Dave Gerlach <[email protected]>
Introduce power management ops supported by the TISCI
Low Power Mode API [1]. These messages are currently
supported only on AM62x platforms.
1) TISCI_MSG_PREPARE_SLEEP
Prepare the SOC for entering into a low power mode and
provide details to firmware about the state being entered.
2) TISCI_MSG_LPM_WAKE_REASON
Get which wake up source woke the SoC from Low Power Mode.
The wake up source IDs will be common for all K3 platforms.
3) TISCI_MSG_SET_IO_ISOLATION
Control the IO isolation for Low Power Mode.
[1] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html
Signed-off-by: Dave Gerlach <[email protected]>
Signed-off-by: Vibhore Vardhan <[email protected]>
[[email protected]: LPM_WAKE_REASON and IO_ISOLATION support]
Signed-off-by: Georgi Vlaev <[email protected]>
Tested-by: Roger Quadros <[email protected]>
---
drivers/firmware/ti_sci.c | 175 +++++++++++++++++++++++++
drivers/firmware/ti_sci.h | 64 ++++++++-
include/linux/soc/ti/ti_sci_protocol.h | 44 +++++++
3 files changed, 282 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 26a37f47f4ca..31a71613ca54 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -1664,6 +1664,176 @@ static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
return ret;
}
+/**
+ * ti_sci_cmd_prepare_sleep() - Prepare system for system suspend
+ * @handle: pointer to TI SCI handle
+ * @mode: Device identifier
+ * @ctx_lo: Low part of address for context save
+ * @ctx_hi: High part of address for context save
+ * @debug_flags: Debug flags to pass to firmware
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode,
+ u32 ctx_lo, u32 ctx_hi, u32 debug_flags)
+{
+ struct ti_sci_info *info;
+ struct ti_sci_msg_req_prepare_sleep *req;
+ struct ti_sci_msg_hdr *resp;
+ struct ti_sci_xfer *xfer;
+ 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_PREPARE_SLEEP,
+ 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_prepare_sleep *)xfer->xfer_buf;
+ req->mode = mode;
+ req->ctx_lo = ctx_lo;
+ req->ctx_hi = ctx_hi;
+ req->debug_flags = debug_flags;
+
+ 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->xfer_buf;
+
+ ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+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
+ * @source: The wakeup source that woke the SoC from LPM
+ * @timestamp: Timestamp of the wakeup event
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_msg_cmd_lpm_wake_reason(const struct ti_sci_handle *handle,
+ u32 *source, u64 *timestamp)
+{
+ struct ti_sci_info *info;
+ struct ti_sci_xfer *xfer;
+ struct ti_sci_msg_resp_lpm_wake_reason *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_LPM_WAKE_REASON,
+ 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_lpm_wake_reason *)xfer->xfer_buf;
+
+ if (!ti_sci_is_response_ack(resp)) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ if (source)
+ *source = resp->wake_source;
+ if (timestamp)
+ *timestamp = resp->wake_timestamp;
+
+fail:
+ ti_sci_put_one_xfer(&info->minfo, xfer);
+
+ return ret;
+}
+
+/**
+ * ti_sci_cmd_set_io_isolation() - Enable IO isolation in LPM
+ * @handle: Pointer to TI SCI handle
+ * @state: The desired state of the IO isolation
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_set_io_isolation(const struct ti_sci_handle *handle,
+ u8 state)
+{
+ struct ti_sci_info *info;
+ struct ti_sci_msg_req_set_io_isolation *req;
+ struct ti_sci_msg_hdr *resp;
+ struct ti_sci_xfer *xfer;
+ 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_SET_IO_ISOLATION,
+ 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_io_isolation *)xfer->xfer_buf;
+ req->state = state;
+
+ 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->xfer_buf;
+
+ ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+ ti_sci_put_one_xfer(&info->minfo, xfer);
+
+ return ret;
+}
+
static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
{
struct ti_sci_info *info;
@@ -2806,6 +2976,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
struct ti_sci_core_ops *core_ops = &ops->core_ops;
struct ti_sci_dev_ops *dops = &ops->dev_ops;
struct ti_sci_clk_ops *cops = &ops->clk_ops;
+ struct ti_sci_pm_ops *pmops = &ops->pm_ops;
struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops;
struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
@@ -2845,6 +3016,10 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
cops->set_freq = ti_sci_cmd_clk_set_freq;
cops->get_freq = ti_sci_cmd_clk_get_freq;
+ pmops->prepare_sleep = ti_sci_cmd_prepare_sleep;
+ pmops->lpm_wake_reason = ti_sci_msg_cmd_lpm_wake_reason;
+ pmops->set_io_isolation = ti_sci_cmd_set_io_isolation;
+
rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
rm_core_ops->get_range_from_shost =
ti_sci_cmd_get_resource_range_from_shost;
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index ef3a8214d002..e4bfe146c43d 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -6,7 +6,7 @@
* The system works in a message response protocol
* See: http://processors.wiki.ti.com/index.php/TISCI for details
*
- * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com/
*/
#ifndef __TI_SCI_H
@@ -35,6 +35,11 @@
#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d
#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e
+/* Low Power Mode Requests */
+#define TI_SCI_MSG_PREPARE_SLEEP 0x0300
+#define TI_SCI_MSG_LPM_WAKE_REASON 0x0306
+#define TI_SCI_MSG_SET_IO_ISOLATION 0x0307
+
/* Resource Management Requests */
#define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500
@@ -545,6 +550,63 @@ struct ti_sci_msg_resp_get_clock_freq {
u64 freq_hz;
} __packed;
+#define TISCI_MSG_VALUE_SLEEP_MODE_DEEP_SLEEP 0x0
+#define TISCI_MSG_VALUE_SLEEP_MODE_MCU_ONLY 0x1
+#define TISCI_MSG_VALUE_SLEEP_MODE_STANDBY 0x2
+
+/**
+ * struct tisci_msg_prepare_sleep_req - Request for TISCI_MSG_PREPARE_SLEEP.
+ *
+ * @hdr TISCI header to provide ACK/NAK flags to the host.
+ * @mode Low power mode to enter.
+ * @ctx_lo Low 32-bits of physical pointer to address to use for context save.
+ * @ctx_hi High 32-bits of physical pointer to address to use for context save.
+ * @debug_flags Flags that can be set to halt the sequence during suspend or
+ * resume to allow JTAG connection and debug.
+ *
+ * This message is used as the first step of entering a low power mode. It
+ * allows configurable information, including which state to enter to be
+ * easily shared from the application, as this is a non-secure message and
+ * therefore can be sent by anyone.
+ */
+struct ti_sci_msg_req_prepare_sleep {
+ struct ti_sci_msg_hdr hdr;
+ u8 mode;
+ u32 ctx_lo;
+ u32 ctx_hi;
+ u32 debug_flags;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_lpm_wake_reason - Response for TI_SCI_MSG_LPM_WAKE_REASON.
+ *
+ * @hdr: Generic header.
+ * @wake_source: The wake up source that woke soc from LPM.
+ * @wake_timestamp: Timestamp at which soc woke.
+ *
+ * Response to a generic message with message type TI_SCI_MSG_LPM_WAKE_REASON,
+ * used to query the wake up source from low power mode.
+ */
+struct ti_sci_msg_resp_lpm_wake_reason {
+ struct ti_sci_msg_hdr hdr;
+ u32 wake_source;
+ u64 wake_timestamp;
+} __packed;
+
+/**
+ * struct tisci_msg_set_io_isolation_req - Request for TI_SCI_MSG_SET_IO_ISOLATION.
+ *
+ * @hdr: Generic header
+ * @state: The deseared state of the IO isolation.
+ *
+ * This message is used to enable/disable IO isolation for low power modes.
+ * Response is generic ACK / NACK message.
+ */
+struct ti_sci_msg_req_set_io_isolation {
+ struct ti_sci_msg_hdr hdr;
+ u8 state;
+} __packed;
+
#define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff
/**
diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
index bd0d11af76c5..f2d1d74ab8fc 100644
--- a/include/linux/soc/ti/ti_sci_protocol.h
+++ b/include/linux/soc/ti/ti_sci_protocol.h
@@ -195,6 +195,49 @@ struct ti_sci_clk_ops {
u64 *current_freq);
};
+/* TISCI LPM wake up sources */
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_I2C0 0x00
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_UART0 0x10
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_GPIO0 0x20
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_ICEMELTER0 0x30
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER0 0x40
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER1 0x41
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_RTC0 0x50
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_RESET 0x60
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB0 0x70
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB1 0x71
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MAIN_IO 0x80
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_IO 0x81
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_CAN_IO 0x82
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_INVALID 0xFF
+
+/* TISCI LPM IO isolation control values */
+#define TISCI_MSG_VALUE_IO_ENABLE 1
+#define TISCI_MSG_VALUE_IO_DISABLE 0
+
+/**
+ * struct ti_sci_pm_ops - Low Power Mode (LPM) control operations
+ * @prepare_sleep: Prepare to enter low power mode
+ * - mode: Low power mode to enter.
+ * - ctx_lo: Low 32-bits of physical address for context save.
+ * - ctx_hi: High 32-bits of physical address for context save.
+ * - ctx_lo: 'true' if frequency change is desired.
+ * - debug_flags: JTAG control flags for debug.
+ * @lpm_wake_reason: Get the wake up source that woke the SoC from LPM
+ * - source: The wake up source that woke soc from LPM.
+ * - timestamp: Timestamp at which soc woke.
+ * @set_io_isolation: Enable or disable IO isolation
+ * - state: The desired state of the IO isolation.
+ */
+struct ti_sci_pm_ops {
+ int (*prepare_sleep)(const struct ti_sci_handle *handle, u8 mode,
+ u32 ctx_lo, u32 ctx_hi, u32 flags);
+ int (*lpm_wake_reason)(const struct ti_sci_handle *handle,
+ u32 *source, u64 *timestamp);
+ int (*set_io_isolation)(const struct ti_sci_handle *handle,
+ u8 state);
+};
+
/**
* struct ti_sci_resource_desc - Description of TI SCI resource instance range.
* @start: Start index of the first resource range.
@@ -539,6 +582,7 @@ struct ti_sci_ops {
struct ti_sci_core_ops core_ops;
struct ti_sci_dev_ops dev_ops;
struct ti_sci_clk_ops clk_ops;
+ struct ti_sci_pm_ops pm_ops;
struct ti_sci_rm_core_ops rm_core_ops;
struct ti_sci_rm_irq_ops rm_irq_ops;
struct ti_sci_rm_ringacc_ops rm_ring_ops;
--
2.34.1
On 8/3/23 1:42 AM, Dhruva Gole wrote:
> From: Dave Gerlach <[email protected]>
>
> Introduce power management ops supported by the TISCI
> Low Power Mode API [1]. These messages are currently
> supported only on AM62x platforms.
>
> 1) TISCI_MSG_PREPARE_SLEEP
> Prepare the SOC for entering into a low power mode and
> provide details to firmware about the state being entered.
>
> 2) TISCI_MSG_LPM_WAKE_REASON
> Get which wake up source woke the SoC from Low Power Mode.
> The wake up source IDs will be common for all K3 platforms.
>
> 3) TISCI_MSG_SET_IO_ISOLATION
> Control the IO isolation for Low Power Mode.
>
> [1] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html
>
> Signed-off-by: Dave Gerlach <[email protected]>
> Signed-off-by: Vibhore Vardhan <[email protected]>
> [[email protected]: LPM_WAKE_REASON and IO_ISOLATION support]
> Signed-off-by: Georgi Vlaev <[email protected]>
> Tested-by: Roger Quadros <[email protected]>
> ---
> drivers/firmware/ti_sci.c | 175 +++++++++++++++++++++++++
> drivers/firmware/ti_sci.h | 64 ++++++++-
> include/linux/soc/ti/ti_sci_protocol.h | 44 +++++++
> 3 files changed, 282 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
> index 26a37f47f4ca..31a71613ca54 100644
> --- a/drivers/firmware/ti_sci.c
> +++ b/drivers/firmware/ti_sci.c
> @@ -1664,6 +1664,176 @@ static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
> return ret;
> }
>
> +/**
> + * ti_sci_cmd_prepare_sleep() - Prepare system for system suspend
> + * @handle: pointer to TI SCI handle
> + * @mode: Device identifier
> + * @ctx_lo: Low part of address for context save
> + * @ctx_hi: High part of address for context save
> + * @debug_flags: Debug flags to pass to firmware
> + *
> + * Return: 0 if all went well, else returns appropriate error value.
> + */
> +static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode,
> + u32 ctx_lo, u32 ctx_hi, u32 debug_flags)
> +{
> + struct ti_sci_info *info;
> + struct ti_sci_msg_req_prepare_sleep *req;
> + struct ti_sci_msg_hdr *resp;
> + struct ti_sci_xfer *xfer;
> + 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_PREPARE_SLEEP,
> + 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_prepare_sleep *)xfer->xfer_buf;
> + req->mode = mode;
> + req->ctx_lo = ctx_lo;
> + req->ctx_hi = ctx_hi;
> + req->debug_flags = debug_flags;
> +
> + 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->xfer_buf;
> +
> + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
> +
> +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
> + * @source: The wakeup source that woke the SoC from LPM
> + * @timestamp: Timestamp of the wakeup event
> + *
> + * Return: 0 if all went well, else returns appropriate error value.
> + */
> +static int ti_sci_msg_cmd_lpm_wake_reason(const struct ti_sci_handle *handle,
> + u32 *source, u64 *timestamp)
> +{
> + struct ti_sci_info *info;
> + struct ti_sci_xfer *xfer;
> + struct ti_sci_msg_resp_lpm_wake_reason *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_LPM_WAKE_REASON,
> + 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_lpm_wake_reason *)xfer->xfer_buf;
> +
> + if (!ti_sci_is_response_ack(resp)) {
> + ret = -ENODEV;
> + goto fail;
> + }
> +
> + if (source)
> + *source = resp->wake_source;
> + if (timestamp)
> + *timestamp = resp->wake_timestamp;
> +
> +fail:
> + ti_sci_put_one_xfer(&info->minfo, xfer);
> +
> + return ret;
> +}
> +
> +/**
> + * ti_sci_cmd_set_io_isolation() - Enable IO isolation in LPM
> + * @handle: Pointer to TI SCI handle
> + * @state: The desired state of the IO isolation
> + *
> + * Return: 0 if all went well, else returns appropriate error value.
> + */
> +static int ti_sci_cmd_set_io_isolation(const struct ti_sci_handle *handle,
> + u8 state)
> +{
> + struct ti_sci_info *info;
> + struct ti_sci_msg_req_set_io_isolation *req;
> + struct ti_sci_msg_hdr *resp;
> + struct ti_sci_xfer *xfer;
> + 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_SET_IO_ISOLATION,
> + 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_io_isolation *)xfer->xfer_buf;
> + req->state = state;
> +
> + 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->xfer_buf;
> +
> + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
> +
> +fail:
> + ti_sci_put_one_xfer(&info->minfo, xfer);
> +
> + return ret;
> +}
> +
> static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
> {
> struct ti_sci_info *info;
> @@ -2806,6 +2976,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
> struct ti_sci_core_ops *core_ops = &ops->core_ops;
> struct ti_sci_dev_ops *dops = &ops->dev_ops;
> struct ti_sci_clk_ops *cops = &ops->clk_ops;
> + struct ti_sci_pm_ops *pmops = &ops->pm_ops;
> struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
> struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops;
> struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
> @@ -2845,6 +3016,10 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
> cops->set_freq = ti_sci_cmd_clk_set_freq;
> cops->get_freq = ti_sci_cmd_clk_get_freq;
>
> + pmops->prepare_sleep = ti_sci_cmd_prepare_sleep;
> + pmops->lpm_wake_reason = ti_sci_msg_cmd_lpm_wake_reason;
> + pmops->set_io_isolation = ti_sci_cmd_set_io_isolation;
> +
> rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
> rm_core_ops->get_range_from_shost =
> ti_sci_cmd_get_resource_range_from_shost;
> diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
> index ef3a8214d002..e4bfe146c43d 100644
> --- a/drivers/firmware/ti_sci.h
> +++ b/drivers/firmware/ti_sci.h
> @@ -6,7 +6,7 @@
> * The system works in a message response protocol
> * See: http://processors.wiki.ti.com/index.php/TISCI for details
> *
> - * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
> + * Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com/
> */
>
> #ifndef __TI_SCI_H
> @@ -35,6 +35,11 @@
> #define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d
> #define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e
>
> +/* Low Power Mode Requests */
> +#define TI_SCI_MSG_PREPARE_SLEEP 0x0300
> +#define TI_SCI_MSG_LPM_WAKE_REASON 0x0306
> +#define TI_SCI_MSG_SET_IO_ISOLATION 0x0307
> +
> /* Resource Management Requests */
> #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500
>
> @@ -545,6 +550,63 @@ struct ti_sci_msg_resp_get_clock_freq {
> u64 freq_hz;
> } __packed;
>
> +#define TISCI_MSG_VALUE_SLEEP_MODE_DEEP_SLEEP 0x0
> +#define TISCI_MSG_VALUE_SLEEP_MODE_MCU_ONLY 0x1
> +#define TISCI_MSG_VALUE_SLEEP_MODE_STANDBY 0x2
Feels like excessive alignment tabs..
> +
> +/**
> + * struct tisci_msg_prepare_sleep_req - Request for TISCI_MSG_PREPARE_SLEEP.
> + *
> + * @hdr TISCI header to provide ACK/NAK flags to the host.
> + * @mode Low power mode to enter.
> + * @ctx_lo Low 32-bits of physical pointer to address to use for context save.
> + * @ctx_hi High 32-bits of physical pointer to address to use for context save.
> + * @debug_flags Flags that can be set to halt the sequence during suspend or
> + * resume to allow JTAG connection and debug.
> + *
> + * This message is used as the first step of entering a low power mode. It
> + * allows configurable information, including which state to enter to be
> + * easily shared from the application, as this is a non-secure message and
> + * therefore can be sent by anyone.
> + */
> +struct ti_sci_msg_req_prepare_sleep {
> + struct ti_sci_msg_hdr hdr;
> + u8 mode;
> + u32 ctx_lo;
> + u32 ctx_hi;
> + u32 debug_flags;
> +} __packed;
> +
> +/**
> + * struct ti_sci_msg_resp_lpm_wake_reason - Response for TI_SCI_MSG_LPM_WAKE_REASON.
> + *
> + * @hdr: Generic header.
> + * @wake_source: The wake up source that woke soc from LPM.
> + * @wake_timestamp: Timestamp at which soc woke.
> + *
> + * Response to a generic message with message type TI_SCI_MSG_LPM_WAKE_REASON,
> + * used to query the wake up source from low power mode.
> + */
> +struct ti_sci_msg_resp_lpm_wake_reason {
> + struct ti_sci_msg_hdr hdr;
> + u32 wake_source;
> + u64 wake_timestamp;
> +} __packed;
> +
> +/**
> + * struct tisci_msg_set_io_isolation_req - Request for TI_SCI_MSG_SET_IO_ISOLATION.
> + *
> + * @hdr: Generic header
> + * @state: The deseared state of the IO isolation.
> + *
> + * This message is used to enable/disable IO isolation for low power modes.
> + * Response is generic ACK / NACK message.
> + */
> +struct ti_sci_msg_req_set_io_isolation {
> + struct ti_sci_msg_hdr hdr;
> + u8 state;
> +} __packed;
> +
> #define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff
>
> /**
> diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
> index bd0d11af76c5..f2d1d74ab8fc 100644
> --- a/include/linux/soc/ti/ti_sci_protocol.h
> +++ b/include/linux/soc/ti/ti_sci_protocol.h
> @@ -195,6 +195,49 @@ struct ti_sci_clk_ops {
> u64 *current_freq);
> };
>
> +/* TISCI LPM wake up sources */
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_I2C0 0x00
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_UART0 0x10
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_GPIO0 0x20
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_ICEMELTER0 0x30
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER0 0x40
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER1 0x41
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_RTC0 0x50
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_RESET 0x60
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB0 0x70
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB1 0x71
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MAIN_IO 0x80
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_IO 0x81
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_CAN_IO 0x82
> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_INVALID 0xFF
I don't see these used in this series, do you need them? lpm_wake_reason()
doesn't seem used either and I'm not sure how you plan to use it, could
you detail that?
Andrew
> +
> +/* TISCI LPM IO isolation control values */
> +#define TISCI_MSG_VALUE_IO_ENABLE 1
> +#define TISCI_MSG_VALUE_IO_DISABLE 0
> +
> +/**
> + * struct ti_sci_pm_ops - Low Power Mode (LPM) control operations
> + * @prepare_sleep: Prepare to enter low power mode
> + * - mode: Low power mode to enter.
> + * - ctx_lo: Low 32-bits of physical address for context save.
> + * - ctx_hi: High 32-bits of physical address for context save.
> + * - ctx_lo: 'true' if frequency change is desired.
> + * - debug_flags: JTAG control flags for debug.
> + * @lpm_wake_reason: Get the wake up source that woke the SoC from LPM
> + * - source: The wake up source that woke soc from LPM.
> + * - timestamp: Timestamp at which soc woke.
> + * @set_io_isolation: Enable or disable IO isolation
> + * - state: The desired state of the IO isolation.
> + */
> +struct ti_sci_pm_ops {
> + int (*prepare_sleep)(const struct ti_sci_handle *handle, u8 mode,
> + u32 ctx_lo, u32 ctx_hi, u32 flags);
> + int (*lpm_wake_reason)(const struct ti_sci_handle *handle,
> + u32 *source, u64 *timestamp);
> + int (*set_io_isolation)(const struct ti_sci_handle *handle,
> + u8 state);
> +};
> +
> /**
> * struct ti_sci_resource_desc - Description of TI SCI resource instance range.
> * @start: Start index of the first resource range.
> @@ -539,6 +582,7 @@ struct ti_sci_ops {
> struct ti_sci_core_ops core_ops;
> struct ti_sci_dev_ops dev_ops;
> struct ti_sci_clk_ops clk_ops;
> + struct ti_sci_pm_ops pm_ops;
> struct ti_sci_rm_core_ops rm_core_ops;
> struct ti_sci_rm_irq_ops rm_irq_ops;
> struct ti_sci_rm_ringacc_ops rm_ring_ops;
On Aug 03, 2023 at 10:14:03 -0500, Andrew Davis wrote:
[..snip..]
> > #define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff
> > /**
> > diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
> > index bd0d11af76c5..f2d1d74ab8fc 100644
> > --- a/include/linux/soc/ti/ti_sci_protocol.h
> > +++ b/include/linux/soc/ti/ti_sci_protocol.h
> > @@ -195,6 +195,49 @@ struct ti_sci_clk_ops {
> > u64 *current_freq);
> > };
> > +/* TISCI LPM wake up sources */
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_I2C0 0x00
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_UART0 0x10
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_GPIO0 0x20
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_ICEMELTER0 0x30
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER0 0x40
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER1 0x41
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_RTC0 0x50
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_RESET 0x60
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB0 0x70
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB1 0x71
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MAIN_IO 0x80
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_IO 0x81
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_CAN_IO 0x82
> > +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_INVALID 0xFF
>
> I don't see these used in this series, do you need them? lpm_wake_reason()
True, we are not currently using these macros. They _maybe required in
future.
I can remove them if required?
> doesn't seem used either and I'm not sure how you plan to use it, could
> you detail that?
When the system wakes from suspend-to-mem we can check which
subsystem has woken us up with the TISCI LPM_WAKEUP_REASON message.
There's no hardware event generated and we have to ask the firmware
for the actual wake reason.
We may want to add support for a wake up interrupt controller that will
generate an interrupt for other subsystems. This might end up using this
lpm_wake_reason API, hence even though the function maybe unused today
it will be required for above described scenario.
However if you prefer that I remove it and then add it in future when we
finally write a working interrupt controller driver, then do let me
know.
>
> Andrew
>
> > +
> > +/* TISCI LPM IO isolation control values */
> > +#define TISCI_MSG_VALUE_IO_ENABLE 1
> > +#define TISCI_MSG_VALUE_IO_DISABLE 0
> > +
[..snip..]
--
Best regards,
Dhruva Gole <[email protected]>
On 8/3/23 10:42 AM, Dhruva Gole wrote:
> On Aug 03, 2023 at 10:14:03 -0500, Andrew Davis wrote:
> [..snip..]
>>> #define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff
>>> /**
>>> diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
>>> index bd0d11af76c5..f2d1d74ab8fc 100644
>>> --- a/include/linux/soc/ti/ti_sci_protocol.h
>>> +++ b/include/linux/soc/ti/ti_sci_protocol.h
>>> @@ -195,6 +195,49 @@ struct ti_sci_clk_ops {
>>> u64 *current_freq);
>>> };
>>> +/* TISCI LPM wake up sources */
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_I2C0 0x00
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_UART0 0x10
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_GPIO0 0x20
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_ICEMELTER0 0x30
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER0 0x40
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER1 0x41
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_RTC0 0x50
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_RESET 0x60
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB0 0x70
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB1 0x71
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MAIN_IO 0x80
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_IO 0x81
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_CAN_IO 0x82
>>> +#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_INVALID 0xFF
>>
>> I don't see these used in this series, do you need them? lpm_wake_reason()
>
> True, we are not currently using these macros. They _maybe required in
> future.
> I can remove them if required?
>
>> doesn't seem used either and I'm not sure how you plan to use it, could
>> you detail that?
>
> When the system wakes from suspend-to-mem we can check which
> subsystem has woken us up with the TISCI LPM_WAKEUP_REASON message.
> There's no hardware event generated and we have to ask the firmware
> for the actual wake reason.
>
> We may want to add support for a wake up interrupt controller that will
> generate an interrupt for other subsystems. This might end up using this
> lpm_wake_reason API, hence even though the function maybe unused today
> it will be required for above described scenario.
>
> However if you prefer that I remove it and then add it in future when we
> finally write a working interrupt controller driver, then do let me
> know.
>
It's easier to review code that is used. We may go with a
completely different approach by then, will be easier to unwind
this if you don't start with it, only add it when used.
Andrew
>>
>> Andrew
>>
>>> +
>>> +/* TISCI LPM IO isolation control values */
>>> +#define TISCI_MSG_VALUE_IO_ENABLE 1
>>> +#define TISCI_MSG_VALUE_IO_DISABLE 0
>>> +
> [..snip..]
>