Skip to content

Commit 0363169

Browse files
committed
Merge tag 'ti-driver-soc-for-v6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux into soc/drivers
TI SoC driver updates for v6.19 - ti_sci: Add Partial-IO poweroff support and sys_off handler integration - ti_sci: Gate IO isolation programming on firmware capability flag - ti_sci: cleanup by replacing ifdeffery in PM ops with pm_sleep_ptr() macro * tag 'ti-driver-soc-for-v6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux: firmware: ti_sci: Partial-IO support firmware: ti_sci: Support transfers without response firmware: ti_sci: Set IO Isolation only if the firmware is capable firmware: ti_sci: Replace ifdeffery by pm_sleep_ptr() macro Signed-off-by: Arnd Bergmann <arnd@arndb.de>
2 parents 16e8af6 + e0431ff commit 0363169

2 files changed

Lines changed: 135 additions & 27 deletions

File tree

drivers/firmware/ti_sci.c

Lines changed: 128 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@ static void ti_sci_put_one_xfer(struct ti_sci_xfers_info *minfo,
398398
static inline int ti_sci_do_xfer(struct ti_sci_info *info,
399399
struct ti_sci_xfer *xfer)
400400
{
401+
struct ti_sci_msg_hdr *hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
402+
bool response_expected = !!(hdr->flags & (TI_SCI_FLAG_REQ_ACK_ON_PROCESSED |
403+
TI_SCI_FLAG_REQ_ACK_ON_RECEIVED));
401404
int ret;
402405
int timeout;
403406
struct device *dev = info->dev;
@@ -409,12 +412,12 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info,
409412

410413
ret = 0;
411414

412-
if (system_state <= SYSTEM_RUNNING) {
415+
if (response_expected && system_state <= SYSTEM_RUNNING) {
413416
/* And we wait for the response. */
414417
timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
415418
if (!wait_for_completion_timeout(&xfer->done, timeout))
416419
ret = -ETIMEDOUT;
417-
} else {
420+
} else if (response_expected) {
418421
/*
419422
* If we are !running, we cannot use wait_for_completion_timeout
420423
* during noirq phase, so we must manually poll the completion.
@@ -1670,6 +1673,9 @@ static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
16701673
static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode,
16711674
u32 ctx_lo, u32 ctx_hi, u32 debug_flags)
16721675
{
1676+
u32 msg_flags = mode == TISCI_MSG_VALUE_SLEEP_MODE_PARTIAL_IO ?
1677+
TI_SCI_FLAG_REQ_GENERIC_NORESPONSE :
1678+
TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;
16731679
struct ti_sci_info *info;
16741680
struct ti_sci_msg_req_prepare_sleep *req;
16751681
struct ti_sci_msg_hdr *resp;
@@ -1686,7 +1692,7 @@ static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode,
16861692
dev = info->dev;
16871693

16881694
xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PREPARE_SLEEP,
1689-
TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1695+
msg_flags,
16901696
sizeof(*req), sizeof(*resp));
16911697
if (IS_ERR(xfer)) {
16921698
ret = PTR_ERR(xfer);
@@ -1706,11 +1712,12 @@ static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode,
17061712
goto fail;
17071713
}
17081714

1709-
resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
1710-
1711-
if (!ti_sci_is_response_ack(resp)) {
1712-
dev_err(dev, "Failed to prepare sleep\n");
1713-
ret = -ENODEV;
1715+
if (msg_flags == TI_SCI_FLAG_REQ_ACK_ON_PROCESSED) {
1716+
resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
1717+
if (!ti_sci_is_response_ack(resp)) {
1718+
dev_err(dev, "Failed to prepare sleep\n");
1719+
ret = -ENODEV;
1720+
}
17141721
}
17151722

17161723
fail:
@@ -3664,6 +3671,78 @@ devm_ti_sci_get_resource(const struct ti_sci_handle *handle, struct device *dev,
36643671
}
36653672
EXPORT_SYMBOL_GPL(devm_ti_sci_get_resource);
36663673

3674+
/*
3675+
* Iterate all device nodes that have a wakeup-source property and check if one
3676+
* of the possible phandles points to a Partial-IO system state. If it
3677+
* does resolve the device node to an actual device and check if wakeup is
3678+
* enabled.
3679+
*/
3680+
static bool ti_sci_partial_io_wakeup_enabled(struct ti_sci_info *info)
3681+
{
3682+
struct device_node *wakeup_node = NULL;
3683+
3684+
for_each_node_with_property(wakeup_node, "wakeup-source") {
3685+
struct of_phandle_iterator it;
3686+
int err;
3687+
3688+
of_for_each_phandle(&it, err, wakeup_node, "wakeup-source", NULL, 0) {
3689+
struct platform_device *pdev;
3690+
bool may_wakeup;
3691+
3692+
/*
3693+
* Continue if idle-state-name is not off-wake. Return
3694+
* value is the index of the string which should be 0 if
3695+
* off-wake is present.
3696+
*/
3697+
if (of_property_match_string(it.node, "idle-state-name", "off-wake"))
3698+
continue;
3699+
3700+
pdev = of_find_device_by_node(wakeup_node);
3701+
if (!pdev)
3702+
continue;
3703+
3704+
may_wakeup = device_may_wakeup(&pdev->dev);
3705+
put_device(&pdev->dev);
3706+
3707+
if (may_wakeup) {
3708+
dev_dbg(info->dev, "%pOF identified as wakeup source for Partial-IO\n",
3709+
wakeup_node);
3710+
of_node_put(it.node);
3711+
of_node_put(wakeup_node);
3712+
return true;
3713+
}
3714+
}
3715+
}
3716+
3717+
return false;
3718+
}
3719+
3720+
static int ti_sci_sys_off_handler(struct sys_off_data *data)
3721+
{
3722+
struct ti_sci_info *info = data->cb_data;
3723+
const struct ti_sci_handle *handle = &info->handle;
3724+
bool enter_partial_io = ti_sci_partial_io_wakeup_enabled(info);
3725+
int ret;
3726+
3727+
if (!enter_partial_io)
3728+
return NOTIFY_DONE;
3729+
3730+
dev_info(info->dev, "Entering Partial-IO because a powered wakeup-enabled device was found.\n");
3731+
3732+
ret = ti_sci_cmd_prepare_sleep(handle, TISCI_MSG_VALUE_SLEEP_MODE_PARTIAL_IO, 0, 0, 0);
3733+
if (ret) {
3734+
dev_err(info->dev,
3735+
"Failed to enter Partial-IO %pe, trying to do an emergency restart\n",
3736+
ERR_PTR(ret));
3737+
emergency_restart();
3738+
}
3739+
3740+
mdelay(5000);
3741+
emergency_restart();
3742+
3743+
return NOTIFY_DONE;
3744+
}
3745+
36673746
static int tisci_reboot_handler(struct sys_off_data *data)
36683747
{
36693748
struct ti_sci_info *info = data->cb_data;
@@ -3706,7 +3785,7 @@ static int ti_sci_prepare_system_suspend(struct ti_sci_info *info)
37063785
}
37073786
}
37083787

3709-
static int __maybe_unused ti_sci_suspend(struct device *dev)
3788+
static int ti_sci_suspend(struct device *dev)
37103789
{
37113790
struct ti_sci_info *info = dev_get_drvdata(dev);
37123791
struct device *cpu_dev, *cpu_dev_max = NULL;
@@ -3746,19 +3825,21 @@ static int __maybe_unused ti_sci_suspend(struct device *dev)
37463825
return 0;
37473826
}
37483827

3749-
static int __maybe_unused ti_sci_suspend_noirq(struct device *dev)
3828+
static int ti_sci_suspend_noirq(struct device *dev)
37503829
{
37513830
struct ti_sci_info *info = dev_get_drvdata(dev);
37523831
int ret = 0;
37533832

3754-
ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_ENABLE);
3755-
if (ret)
3756-
return ret;
3833+
if (info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION) {
3834+
ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_ENABLE);
3835+
if (ret)
3836+
return ret;
3837+
}
37573838

37583839
return 0;
37593840
}
37603841

3761-
static int __maybe_unused ti_sci_resume_noirq(struct device *dev)
3842+
static int ti_sci_resume_noirq(struct device *dev)
37623843
{
37633844
struct ti_sci_info *info = dev_get_drvdata(dev);
37643845
int ret = 0;
@@ -3767,9 +3848,11 @@ static int __maybe_unused ti_sci_resume_noirq(struct device *dev)
37673848
u8 pin;
37683849
u8 mode;
37693850

3770-
ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_DISABLE);
3771-
if (ret)
3772-
return ret;
3851+
if (info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION) {
3852+
ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_DISABLE);
3853+
if (ret)
3854+
return ret;
3855+
}
37733856

37743857
ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode);
37753858
/* Do not fail to resume on error as the wake reason is not critical */
@@ -3780,7 +3863,7 @@ static int __maybe_unused ti_sci_resume_noirq(struct device *dev)
37803863
return 0;
37813864
}
37823865

3783-
static void __maybe_unused ti_sci_pm_complete(struct device *dev)
3866+
static void ti_sci_pm_complete(struct device *dev)
37843867
{
37853868
struct ti_sci_info *info = dev_get_drvdata(dev);
37863869

@@ -3791,12 +3874,10 @@ static void __maybe_unused ti_sci_pm_complete(struct device *dev)
37913874
}
37923875

37933876
static const struct dev_pm_ops ti_sci_pm_ops = {
3794-
#ifdef CONFIG_PM_SLEEP
3795-
.suspend = ti_sci_suspend,
3796-
.suspend_noirq = ti_sci_suspend_noirq,
3797-
.resume_noirq = ti_sci_resume_noirq,
3798-
.complete = ti_sci_pm_complete,
3799-
#endif
3877+
.suspend = pm_sleep_ptr(ti_sci_suspend),
3878+
.suspend_noirq = pm_sleep_ptr(ti_sci_suspend_noirq),
3879+
.resume_noirq = pm_sleep_ptr(ti_sci_resume_noirq),
3880+
.complete = pm_sleep_ptr(ti_sci_pm_complete),
38003881
};
38013882

38023883
/* Description for K2G */
@@ -3928,11 +4009,12 @@ static int ti_sci_probe(struct platform_device *pdev)
39284009
}
39294010

39304011
ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps);
3931-
dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s\n",
4012+
dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s\n",
39324013
info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "",
39334014
info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "",
39344015
info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "",
3935-
info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : ""
4016+
info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "",
4017+
info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : ""
39364018
);
39374019

39384020
ti_sci_setup_ops(info);
@@ -3943,6 +4025,19 @@ static int ti_sci_probe(struct platform_device *pdev)
39434025
goto out;
39444026
}
39454027

4028+
if (info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO) {
4029+
ret = devm_register_sys_off_handler(dev,
4030+
SYS_OFF_MODE_POWER_OFF,
4031+
SYS_OFF_PRIO_FIRMWARE,
4032+
ti_sci_sys_off_handler,
4033+
info);
4034+
if (ret) {
4035+
dev_err(dev, "Failed to register sys_off_handler %pe\n",
4036+
ERR_PTR(ret));
4037+
goto out;
4038+
}
4039+
}
4040+
39464041
dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n",
39474042
info->handle.version.abi_major, info->handle.version.abi_minor,
39484043
info->handle.version.firmware_revision,
@@ -3952,7 +4047,13 @@ static int ti_sci_probe(struct platform_device *pdev)
39524047
list_add_tail(&info->node, &ti_sci_list);
39534048
mutex_unlock(&ti_sci_list_mutex);
39544049

3955-
return of_platform_populate(dev->of_node, NULL, NULL, dev);
4050+
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
4051+
if (ret) {
4052+
dev_err(dev, "platform_populate failed %pe\n", ERR_PTR(ret));
4053+
goto out;
4054+
}
4055+
return 0;
4056+
39564057
out:
39574058
if (!IS_ERR(info->chan_tx))
39584059
mbox_free_channel(info->chan_tx);

drivers/firmware/ti_sci.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ struct ti_sci_msg_req_reboot {
149149
* MSG_FLAG_CAPS_LPM_PARTIAL_IO: Partial IO in LPM
150150
* MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM
151151
* MSG_FLAG_CAPS_LPM_ABORT: Abort entry to LPM
152+
* MSG_FLAG_CAPS_IO_ISOLATION: IO Isolation support
152153
*
153154
* Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS
154155
* providing currently available SOC/firmware capabilities. SoC that don't
@@ -160,6 +161,7 @@ struct ti_sci_msg_resp_query_fw_caps {
160161
#define MSG_FLAG_CAPS_LPM_PARTIAL_IO TI_SCI_MSG_FLAG(4)
161162
#define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5)
162163
#define MSG_FLAG_CAPS_LPM_ABORT TI_SCI_MSG_FLAG(9)
164+
#define MSG_FLAG_CAPS_IO_ISOLATION TI_SCI_MSG_FLAG(7)
163165
#define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1)
164166
u64 fw_caps;
165167
} __packed;
@@ -595,6 +597,11 @@ struct ti_sci_msg_resp_get_clock_freq {
595597
struct ti_sci_msg_req_prepare_sleep {
596598
struct ti_sci_msg_hdr hdr;
597599

600+
/*
601+
* When sending prepare_sleep with MODE_PARTIAL_IO no response will be sent,
602+
* no further steps are required.
603+
*/
604+
#define TISCI_MSG_VALUE_SLEEP_MODE_PARTIAL_IO 0x03
598605
#define TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED 0xfd
599606
u8 mode;
600607
u32 ctx_lo;

0 commit comments

Comments
 (0)