Skip to content

Commit 6035799

Browse files
dgerlachnmenon
authored andcommitted
firmware: ti_sci: Introduce Power Management Ops
Introduce power management ops supported by the TISCI Low Power Mode API [1]. 1) 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. 2) TISCI_MSG_LPM_SET_DEVICE_CONSTRAINT Set LPM constraint on behalf of a device. By setting a constraint, the device ensures that it will not be powered off or reset in the selected mode. 3) TISCI_MSG_LPM_SET_LATENCY_CONSTRAINT Set LPM resume latency constraint. By setting a constraint, the host ensures that the resume time from selected mode will be less than the constraint value. [1] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html Signed-off-by: Dave Gerlach <[email protected]> [[email protected]: LPM_WAKE_REASON and IO_ISOLATION support] Signed-off-by: Georgi Vlaev <[email protected]> [[email protected]: SET_DEVICE_CONSTRAINT support] Signed-off-by: Akashdeep Kaur <[email protected]> [[email protected]: SET_LATENCY_CONSTRAINT support] Signed-off-by: Vibhore Vardhan <[email protected]> Signed-off-by: Kevin Hilman <[email protected]> Reviewed-by: Akashdeep Kaur <[email protected]> Tested-by: Dhruva Gole <[email protected]> Signed-off-by: Markus Schneider-Pargmann <[email protected]> Tested-by: Kevin Hilman <[email protected]> Tested-by: Roger Quadros <[email protected]> Acked-by: Dhruva Gole <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Nishanth Menon <[email protected]>
1 parent ec24643 commit 6035799

File tree

3 files changed

+300
-0
lines changed

3 files changed

+300
-0
lines changed

drivers/firmware/ti_sci.c

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,6 +1833,186 @@ static int ti_sci_cmd_set_io_isolation(const struct ti_sci_handle *handle,
18331833
return ret;
18341834
}
18351835

1836+
/**
1837+
* ti_sci_msg_cmd_lpm_wake_reason() - Get the wakeup source from LPM
1838+
* @handle: Pointer to TI SCI handle
1839+
* @source: The wakeup source that woke the SoC from LPM
1840+
* @timestamp: Timestamp of the wakeup event
1841+
* @pin: The pin that has triggered wake up
1842+
* @mode: The last entered low power mode
1843+
*
1844+
* Return: 0 if all went well, else returns appropriate error value.
1845+
*/
1846+
static int ti_sci_msg_cmd_lpm_wake_reason(const struct ti_sci_handle *handle,
1847+
u32 *source, u64 *timestamp, u8 *pin, u8 *mode)
1848+
{
1849+
struct ti_sci_info *info;
1850+
struct ti_sci_xfer *xfer;
1851+
struct ti_sci_msg_resp_lpm_wake_reason *resp;
1852+
struct device *dev;
1853+
int ret = 0;
1854+
1855+
if (IS_ERR(handle))
1856+
return PTR_ERR(handle);
1857+
if (!handle)
1858+
return -EINVAL;
1859+
1860+
info = handle_to_ti_sci_info(handle);
1861+
dev = info->dev;
1862+
1863+
xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_WAKE_REASON,
1864+
TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1865+
sizeof(struct ti_sci_msg_hdr),
1866+
sizeof(*resp));
1867+
if (IS_ERR(xfer)) {
1868+
ret = PTR_ERR(xfer);
1869+
dev_err(dev, "Message alloc failed(%d)\n", ret);
1870+
return ret;
1871+
}
1872+
1873+
ret = ti_sci_do_xfer(info, xfer);
1874+
if (ret) {
1875+
dev_err(dev, "Mbox send fail %d\n", ret);
1876+
goto fail;
1877+
}
1878+
1879+
resp = (struct ti_sci_msg_resp_lpm_wake_reason *)xfer->xfer_buf;
1880+
1881+
if (!ti_sci_is_response_ack(resp)) {
1882+
dev_err(dev, "Failed to get wake reason\n");
1883+
ret = -ENODEV;
1884+
goto fail;
1885+
}
1886+
1887+
if (source)
1888+
*source = resp->wake_source;
1889+
if (timestamp)
1890+
*timestamp = resp->wake_timestamp;
1891+
if (pin)
1892+
*pin = resp->wake_pin;
1893+
if (mode)
1894+
*mode = resp->mode;
1895+
1896+
fail:
1897+
ti_sci_put_one_xfer(&info->minfo, xfer);
1898+
1899+
return ret;
1900+
}
1901+
1902+
/**
1903+
* ti_sci_cmd_set_device_constraint() - Set LPM constraint on behalf of a device
1904+
* @handle: pointer to TI SCI handle
1905+
* @id: Device identifier
1906+
* @state: The desired state of device constraint: set or clear
1907+
*
1908+
* Return: 0 if all went well, else returns appropriate error value.
1909+
*/
1910+
static int ti_sci_cmd_set_device_constraint(const struct ti_sci_handle *handle,
1911+
u32 id, u8 state)
1912+
{
1913+
struct ti_sci_info *info;
1914+
struct ti_sci_msg_req_lpm_set_device_constraint *req;
1915+
struct ti_sci_msg_hdr *resp;
1916+
struct ti_sci_xfer *xfer;
1917+
struct device *dev;
1918+
int ret = 0;
1919+
1920+
if (IS_ERR(handle))
1921+
return PTR_ERR(handle);
1922+
if (!handle)
1923+
return -EINVAL;
1924+
1925+
info = handle_to_ti_sci_info(handle);
1926+
dev = info->dev;
1927+
1928+
xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_SET_DEVICE_CONSTRAINT,
1929+
TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1930+
sizeof(*req), sizeof(*resp));
1931+
if (IS_ERR(xfer)) {
1932+
ret = PTR_ERR(xfer);
1933+
dev_err(dev, "Message alloc failed(%d)\n", ret);
1934+
return ret;
1935+
}
1936+
req = (struct ti_sci_msg_req_lpm_set_device_constraint *)xfer->xfer_buf;
1937+
req->id = id;
1938+
req->state = state;
1939+
1940+
ret = ti_sci_do_xfer(info, xfer);
1941+
if (ret) {
1942+
dev_err(dev, "Mbox send fail %d\n", ret);
1943+
goto fail;
1944+
}
1945+
1946+
resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
1947+
1948+
if (!ti_sci_is_response_ack(resp)) {
1949+
dev_err(dev, "Failed to set device constraint\n");
1950+
ret = -ENODEV;
1951+
}
1952+
1953+
fail:
1954+
ti_sci_put_one_xfer(&info->minfo, xfer);
1955+
1956+
return ret;
1957+
}
1958+
1959+
/**
1960+
* ti_sci_cmd_set_latency_constraint() - Set LPM resume latency constraint
1961+
* @handle: pointer to TI SCI handle
1962+
* @latency: maximum acceptable latency (in ms) to wake up from LPM
1963+
* @state: The desired state of latency constraint: set or clear
1964+
*
1965+
* Return: 0 if all went well, else returns appropriate error value.
1966+
*/
1967+
static int ti_sci_cmd_set_latency_constraint(const struct ti_sci_handle *handle,
1968+
u16 latency, u8 state)
1969+
{
1970+
struct ti_sci_info *info;
1971+
struct ti_sci_msg_req_lpm_set_latency_constraint *req;
1972+
struct ti_sci_msg_hdr *resp;
1973+
struct ti_sci_xfer *xfer;
1974+
struct device *dev;
1975+
int ret = 0;
1976+
1977+
if (IS_ERR(handle))
1978+
return PTR_ERR(handle);
1979+
if (!handle)
1980+
return -EINVAL;
1981+
1982+
info = handle_to_ti_sci_info(handle);
1983+
dev = info->dev;
1984+
1985+
xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_SET_LATENCY_CONSTRAINT,
1986+
TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1987+
sizeof(*req), sizeof(*resp));
1988+
if (IS_ERR(xfer)) {
1989+
ret = PTR_ERR(xfer);
1990+
dev_err(dev, "Message alloc failed(%d)\n", ret);
1991+
return ret;
1992+
}
1993+
req = (struct ti_sci_msg_req_lpm_set_latency_constraint *)xfer->xfer_buf;
1994+
req->latency = latency;
1995+
req->state = state;
1996+
1997+
ret = ti_sci_do_xfer(info, xfer);
1998+
if (ret) {
1999+
dev_err(dev, "Mbox send fail %d\n", ret);
2000+
goto fail;
2001+
}
2002+
2003+
resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
2004+
2005+
if (!ti_sci_is_response_ack(resp)) {
2006+
dev_err(dev, "Failed to set device constraint\n");
2007+
ret = -ENODEV;
2008+
}
2009+
2010+
fail:
2011+
ti_sci_put_one_xfer(&info->minfo, xfer);
2012+
2013+
return ret;
2014+
}
2015+
18362016
static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
18372017
{
18382018
struct ti_sci_info *info;
@@ -2975,6 +3155,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
29753155
struct ti_sci_core_ops *core_ops = &ops->core_ops;
29763156
struct ti_sci_dev_ops *dops = &ops->dev_ops;
29773157
struct ti_sci_clk_ops *cops = &ops->clk_ops;
3158+
struct ti_sci_pm_ops *pmops = &ops->pm_ops;
29783159
struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
29793160
struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops;
29803161
struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
@@ -3014,6 +3195,13 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
30143195
cops->set_freq = ti_sci_cmd_clk_set_freq;
30153196
cops->get_freq = ti_sci_cmd_clk_get_freq;
30163197

3198+
if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) {
3199+
pr_debug("detected DM managed LPM in fw_caps\n");
3200+
pmops->lpm_wake_reason = ti_sci_msg_cmd_lpm_wake_reason;
3201+
pmops->set_device_constraint = ti_sci_cmd_set_device_constraint;
3202+
pmops->set_latency_constraint = ti_sci_cmd_set_latency_constraint;
3203+
}
3204+
30173205
rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
30183206
rm_core_ops->get_range_from_shost =
30193207
ti_sci_cmd_get_resource_range_from_shost;
@@ -3503,11 +3691,21 @@ static int __maybe_unused ti_sci_resume_noirq(struct device *dev)
35033691
{
35043692
struct ti_sci_info *info = dev_get_drvdata(dev);
35053693
int ret = 0;
3694+
u32 source;
3695+
u64 time;
3696+
u8 pin;
3697+
u8 mode;
35063698

35073699
ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_DISABLE);
35083700
if (ret)
35093701
return ret;
35103702

3703+
ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode);
3704+
/* Do not fail to resume on error as the wake reason is not critical */
3705+
if (!ret)
3706+
dev_info(dev, "ti_sci: wakeup source:0x%x, pin:0x%x, mode:0x%x\n",
3707+
source, pin, mode);
3708+
35113709
return 0;
35123710
}
35133711

drivers/firmware/ti_sci.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@
3838

3939
/* Low Power Mode Requests */
4040
#define TI_SCI_MSG_PREPARE_SLEEP 0x0300
41+
#define TI_SCI_MSG_LPM_WAKE_REASON 0x0306
4142
#define TI_SCI_MSG_SET_IO_ISOLATION 0x0307
43+
#define TI_SCI_MSG_LPM_SET_DEVICE_CONSTRAINT 0x0309
44+
#define TI_SCI_MSG_LPM_SET_LATENCY_CONSTRAINT 0x030A
4245

4346
/* Resource Management Requests */
4447
#define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500
@@ -610,6 +613,79 @@ struct ti_sci_msg_req_set_io_isolation {
610613
u8 state;
611614
} __packed;
612615

616+
/**
617+
* struct ti_sci_msg_resp_lpm_wake_reason - Response for TI_SCI_MSG_LPM_WAKE_REASON.
618+
*
619+
* @hdr: Generic header.
620+
* @wake_source: The wake up source that woke soc from LPM.
621+
* @wake_timestamp: Timestamp at which soc woke.
622+
* @wake_pin: The pin that has triggered wake up.
623+
* @mode: The last entered low power mode.
624+
* @rsvd: Reserved for future use.
625+
*
626+
* Response to a generic message with message type TI_SCI_MSG_LPM_WAKE_REASON,
627+
* used to query the wake up source, pin and entered low power mode.
628+
*/
629+
struct ti_sci_msg_resp_lpm_wake_reason {
630+
struct ti_sci_msg_hdr hdr;
631+
u32 wake_source;
632+
u64 wake_timestamp;
633+
u8 wake_pin;
634+
u8 mode;
635+
u32 rsvd[2];
636+
} __packed;
637+
638+
/**
639+
* struct ti_sci_msg_req_lpm_set_device_constraint - Request for
640+
* TISCI_MSG_LPM_SET_DEVICE_CONSTRAINT.
641+
*
642+
* @hdr: TISCI header to provide ACK/NAK flags to the host.
643+
* @id: Device ID of device whose constraint has to be modified.
644+
* @state: The desired state of device constraint: set or clear.
645+
* @rsvd: Reserved for future use.
646+
*
647+
* This message is used by host to set constraint on the device. This can be
648+
* sent anytime after boot before prepare sleep message. Any device can set a
649+
* constraint on the low power mode that the SoC can enter. It allows
650+
* configurable information to be easily shared from the application, as this
651+
* is a non-secure message and therefore can be sent by anyone. By setting a
652+
* constraint, the device ensures that it will not be powered off or reset in
653+
* the selected mode. Note: Access Restriction: Exclusivity flag of Device will
654+
* be honored. If some other host already has constraint on this device ID,
655+
* NACK will be returned.
656+
*/
657+
struct ti_sci_msg_req_lpm_set_device_constraint {
658+
struct ti_sci_msg_hdr hdr;
659+
u32 id;
660+
u8 state;
661+
u32 rsvd[2];
662+
} __packed;
663+
664+
/**
665+
* struct ti_sci_msg_req_lpm_set_latency_constraint - Request for
666+
* TISCI_MSG_LPM_SET_LATENCY_CONSTRAINT.
667+
*
668+
* @hdr: TISCI header to provide ACK/NAK flags to the host.
669+
* @wkup_latency: The maximum acceptable latency to wake up from low power mode
670+
* in milliseconds. The deeper the state, the higher the latency.
671+
* @state: The desired state of wakeup latency constraint: set or clear.
672+
* @rsvd: Reserved for future use.
673+
*
674+
* This message is used by host to set wakeup latency from low power mode. This can
675+
* be sent anytime after boot before prepare sleep message, and can be sent after
676+
* current low power mode is exited. Any device can set a constraint on the low power
677+
* mode that the SoC can enter. It allows configurable information to be easily shared
678+
* from the application, as this is a non-secure message and therefore can be sent by
679+
* anyone. By setting a wakeup latency constraint, the host ensures that the resume time
680+
* from selected low power mode will be less than the constraint value.
681+
*/
682+
struct ti_sci_msg_req_lpm_set_latency_constraint {
683+
struct ti_sci_msg_hdr hdr;
684+
u16 latency;
685+
u8 state;
686+
u32 rsvd;
687+
} __packed;
688+
613689
#define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff
614690

615691
/**

include/linux/soc/ti/ti_sci_protocol.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,31 @@ struct ti_sci_clk_ops {
199199
#define TISCI_MSG_VALUE_IO_ENABLE 1
200200
#define TISCI_MSG_VALUE_IO_DISABLE 0
201201

202+
/* TISCI LPM constraint state values */
203+
#define TISCI_MSG_CONSTRAINT_SET 1
204+
#define TISCI_MSG_CONSTRAINT_CLR 0
205+
206+
/**
207+
* struct ti_sci_pm_ops - Low Power Mode (LPM) control operations
208+
* @lpm_wake_reason: Get the wake up source that woke the SoC from LPM
209+
* - source: The wake up source that woke soc from LPM.
210+
* - timestamp: Timestamp at which soc woke.
211+
* @set_device_constraint: Set LPM constraint on behalf of a device
212+
* - id: Device Identifier
213+
* - state: The desired state of device constraint: set or clear.
214+
* @set_latency_constraint: Set LPM resume latency constraint
215+
* - latency: maximum acceptable latency to wake up from low power mode
216+
* - state: The desired state of latency constraint: set or clear.
217+
*/
218+
struct ti_sci_pm_ops {
219+
int (*lpm_wake_reason)(const struct ti_sci_handle *handle,
220+
u32 *source, u64 *timestamp, u8 *pin, u8 *mode);
221+
int (*set_device_constraint)(const struct ti_sci_handle *handle,
222+
u32 id, u8 state);
223+
int (*set_latency_constraint)(const struct ti_sci_handle *handle,
224+
u16 latency, u8 state);
225+
};
226+
202227
/**
203228
* struct ti_sci_resource_desc - Description of TI SCI resource instance range.
204229
* @start: Start index of the first resource range.
@@ -543,6 +568,7 @@ struct ti_sci_ops {
543568
struct ti_sci_core_ops core_ops;
544569
struct ti_sci_dev_ops dev_ops;
545570
struct ti_sci_clk_ops clk_ops;
571+
struct ti_sci_pm_ops pm_ops;
546572
struct ti_sci_rm_core_ops rm_core_ops;
547573
struct ti_sci_rm_irq_ops rm_irq_ops;
548574
struct ti_sci_rm_ringacc_ops rm_ring_ops;

0 commit comments

Comments
 (0)