TI SoC driver updates for v6.13

- knav_qmss_queue: Cleanups around request_irq params and redundant code.
 - ti_sci: Power management ops in preperation for suspend/resume capability.
   Also includes dependency patch to export dev_pm_qos_read_value
   (acked by Rafael).
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE+KKGk1TrgjIXoxo03bWEnRc2JJ0FAmcrXIEACgkQ3bWEnRc2
 JJ0ZRhAAiJKWaG8TS3E9Bpy1HtgMvtn5mXC+72EFCqFWn7oUmuAmL5ivO7XDKbcO
 scAtdzkupgazD6h4lLwu7VQYEGRt/1+mTaQ1MfgnHlQiShLeJQ8tbkmv49MXGiH0
 OKNMlKYfxVvTmyQYVYStM1WoH54ab3vn6iMZT1uiDAAkHniGE+uBgX92+Y+AjV9p
 26rBct9aOHzfoEx339/mr3yElf6y74kuie2rpskJfCqT8dRqIw1glu6mFI8T2Bwp
 BFjjSny7rAg37Q9gzhhg623TznXhNxFEpDKE/thsgc9LU6OiMSTuONjXvCuPhANe
 OvAt8FTg691Op5Dkj+3e3AUp7cQ46BTQZdpLS7aEjjiT810zqsp0U+BL2ozyPgs8
 9BHNRDlsctj+92emzi8XujivmpariYaeTvFY4h2MvaIUJnubaoxN90568fS2orgb
 U/DykVczyau3VIUFft7DJ7VlPYz3pfbvutfEhKmRpF51HOlqSZyZXHOJByrIzMpt
 MFQCbjHWAJlvQfIemv7ybAMpKFyCjWlFxsKnMFJU1V6bjYei89IYTIGqegH6Yy4d
 hOLZJCM388T4RupGk3+Mbh3IlmZq5H33Pich1c1FC/EB2v0ni5qZunEIEaYXWMES
 ddLAo+2eeVCi1HSiMYWzX+DFCR1d4WU3TDJPU+eemgE/1UcJuDY=
 =xIlb
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmczbbYACgkQYKtH/8kJ
 UicSehAAwcjh2YgHkAzfSlXBzfCs3rai0YprsqrKspw4cA6VR2s3i7z47x5mX+DS
 7czKBAoR2pmWdbnQQqvp07DTR9h3VpG3PfVeXJXQf4b+ylzXU8qYycjcX7mIsh59
 fwNc0z3FDtCawmM3x/tZBSizr2I5Z7kfdDJcqBIyJVaLsPdknmB4pKXGFXoT7oK4
 aCDgNnTyCD4nWfK3WGC9Sn/uWUOYuoWnIBEwbLu7wrGcG0i2gKGlTc1AD8N8sR7O
 z4jfKcFm8CZF/KsmkV+dytctDP4U3iGG/OPvouTIWgCui3htQHr0dcZnZLAXuwJa
 EfEfis41M82osS2RjSudBRX+sYVrTjDNr1BME1ns/dZoyBBKWWOI4tc6Q+Q7MeQL
 VSPk/4nSKE9XqC8XnPvp1op26h4FfZlmvlzyWHqHTT+e4bPwm1b36LQNQFXBcpvp
 pETbYBSrAfjPrPGOyQd0H+ttef1Y8nN+SIe4QlMYUtLoJLwPMo3gAqC8C7PpFDmc
 jymtSxhN9BI9FfeFANvS0H/m7tL/dozazxRj1YlM7ZfKWJRzUp+bgmTajBRvPqyF
 3HkFFuxdke8QuenF8kevSHEphXQ2g1Wc6m6sww2fyTCqhrf9KPgfpCBm7QyUuv1o
 nE5sbmy0WK82NGjyRJbiOKk8fWYJ5KWuSrsVPyRDUmjNHlpaI0o=
 =Y17E
 -----END PGP SIGNATURE-----

Merge tag 'ti-driver-soc-for-v6.13' of https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux into soc/drivers

TI SoC driver updates for v6.13

- knav_qmss_queue: Cleanups around request_irq params and redundant code.
- ti_sci: Power management ops in preperation for suspend/resume capability.
  Also includes dependency patch to export dev_pm_qos_read_value
  (acked by Rafael).

* tag 'ti-driver-soc-for-v6.13' of https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux:
  firmware: ti_sci: Remove use of of_match_ptr() helper
  firmware: ti_sci: add CPU latency constraint management
  firmware: ti_sci: Introduce Power Management Ops
  firmware: ti_sci: Add system suspend and resume call
  firmware: ti_sci: Add support for querying the firmware caps
  PM: QoS: Export dev_pm_qos_read_value
  soc: ti: knav_qmss_queue: Drop redundant continue statement
  soc: ti: knav_qmss_queue: Use IRQF_NO_AUTOEN flag in request_irq()

Link: https://lore.kernel.org/r/20241106121708.rso5wvc7wbhfi6xk@maverick
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2024-11-12 16:01:09 +01:00
commit ffca677936
5 changed files with 662 additions and 7 deletions

View File

@ -137,6 +137,7 @@ s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_read_value);
/**
* apply_constraint - Add/modify/remove device PM QoS request.

View File

@ -2,13 +2,14 @@
/*
* Texas Instruments System Control Interface Protocol Driver
*
* Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com/
* Copyright (C) 2015-2024 Texas Instruments Incorporated - https://www.ti.com/
* Nishanth Menon
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/bitmap.h>
#include <linux/cpu.h>
#include <linux/debugfs.h>
#include <linux/export.h>
#include <linux/io.h>
@ -19,11 +20,14 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_qos.h>
#include <linux/property.h>
#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/soc/ti/ti-msgmgr.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#include <linux/suspend.h>
#include <linux/sys_soc.h>
#include <linux/reboot.h>
#include "ti_sci.h"
@ -98,6 +102,7 @@ struct ti_sci_desc {
* @minfo: Message info
* @node: list head
* @host_id: Host ID
* @fw_caps: FW/SoC low power capabilities
* @users: Number of users of this instance
*/
struct ti_sci_info {
@ -114,6 +119,7 @@ struct ti_sci_info {
struct ti_sci_xfers_info minfo;
struct list_head node;
u8 host_id;
u64 fw_caps;
/* protected by ti_sci_list_mutex */
int users;
};
@ -1651,6 +1657,364 @@ 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;
if (!ti_sci_is_response_ack(resp)) {
dev_err(dev, "Failed to prepare sleep\n");
ret = -ENODEV;
}
fail:
ti_sci_put_one_xfer(&info->minfo, xfer);
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
*
* Check if the firmware supports any optional low power modes.
* Old revisions of TIFS (< 08.04) will NACK the request which results in
* -ENODEV being returned.
*
* 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)) {
dev_err(dev, "Failed to get capabilities\n");
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_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;
if (!ti_sci_is_response_ack(resp)) {
dev_err(dev, "Failed to set IO isolation\n");
ret = -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
* @pin: The pin that has triggered wake up
* @mode: The last entered low power mode
*
* 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, u8 *pin, u8 *mode)
{
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)) {
dev_err(dev, "Failed to get wake reason\n");
ret = -ENODEV;
goto fail;
}
if (source)
*source = resp->wake_source;
if (timestamp)
*timestamp = resp->wake_timestamp;
if (pin)
*pin = resp->wake_pin;
if (mode)
*mode = resp->mode;
fail:
ti_sci_put_one_xfer(&info->minfo, xfer);
return ret;
}
/**
* ti_sci_cmd_set_device_constraint() - Set LPM constraint on behalf of a device
* @handle: pointer to TI SCI handle
* @id: Device identifier
* @state: The desired state of device constraint: set or clear
*
* Return: 0 if all went well, else returns appropriate error value.
*/
static int ti_sci_cmd_set_device_constraint(const struct ti_sci_handle *handle,
u32 id, u8 state)
{
struct ti_sci_info *info;
struct ti_sci_msg_req_lpm_set_device_constraint *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_LPM_SET_DEVICE_CONSTRAINT,
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_lpm_set_device_constraint *)xfer->xfer_buf;
req->id = id;
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;
if (!ti_sci_is_response_ack(resp)) {
dev_err(dev, "Failed to set device constraint\n");
ret = -ENODEV;
}
fail:
ti_sci_put_one_xfer(&info->minfo, xfer);
return ret;
}
/**
* ti_sci_cmd_set_latency_constraint() - Set LPM resume latency constraint
* @handle: pointer to TI SCI handle
* @latency: maximum acceptable latency (in ms) to wake up from LPM
* @state: The desired state of latency constraint: set or clear
*
* Return: 0 if all went well, else returns appropriate error value.
*/
static int ti_sci_cmd_set_latency_constraint(const struct ti_sci_handle *handle,
u16 latency, u8 state)
{
struct ti_sci_info *info;
struct ti_sci_msg_req_lpm_set_latency_constraint *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_LPM_SET_LATENCY_CONSTRAINT,
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_lpm_set_latency_constraint *)xfer->xfer_buf;
req->latency = latency;
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;
if (!ti_sci_is_response_ack(resp)) {
dev_err(dev, "Failed to set device constraint\n");
ret = -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;
@ -2793,6 +3157,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;
@ -2832,6 +3197,13 @@ 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;
if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) {
pr_debug("detected DM managed LPM in fw_caps\n");
pmops->lpm_wake_reason = ti_sci_msg_cmd_lpm_wake_reason;
pmops->set_device_constraint = ti_sci_cmd_set_device_constraint;
pmops->set_latency_constraint = ti_sci_cmd_set_latency_constraint;
}
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;
@ -3262,6 +3634,111 @@ static int tisci_reboot_handler(struct sys_off_data *data)
return NOTIFY_BAD;
}
static int ti_sci_prepare_system_suspend(struct ti_sci_info *info)
{
/*
* Map and validate the target Linux suspend state to TISCI LPM.
* Default is to let Device Manager select the low power mode.
*/
switch (pm_suspend_target_state) {
case PM_SUSPEND_MEM:
if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) {
/*
* For the DM_MANAGED mode the context is reserved for
* internal use and can be 0
*/
return ti_sci_cmd_prepare_sleep(&info->handle,
TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED,
0, 0, 0);
} else {
/* DM Managed is not supported by the firmware. */
dev_err(info->dev, "Suspend to memory is not supported by the firmware\n");
return -EOPNOTSUPP;
}
break;
default:
/*
* Do not fail if we don't have action to take for a
* specific suspend mode.
*/
return 0;
}
}
static int __maybe_unused ti_sci_suspend(struct device *dev)
{
struct ti_sci_info *info = dev_get_drvdata(dev);
struct device *cpu_dev, *cpu_dev_max = NULL;
s32 val, cpu_lat = 0;
int i, ret;
if (info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) {
for_each_possible_cpu(i) {
cpu_dev = get_cpu_device(i);
val = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_RESUME_LATENCY);
if (val != PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) {
cpu_lat = max(cpu_lat, val);
cpu_dev_max = cpu_dev;
}
}
if (cpu_dev_max) {
dev_dbg(cpu_dev_max, "%s: sending max CPU latency=%u\n", __func__, cpu_lat);
ret = ti_sci_cmd_set_latency_constraint(&info->handle,
cpu_lat, TISCI_MSG_CONSTRAINT_SET);
if (ret)
return ret;
}
}
ret = ti_sci_prepare_system_suspend(info);
if (ret)
return ret;
return 0;
}
static int __maybe_unused ti_sci_suspend_noirq(struct device *dev)
{
struct ti_sci_info *info = dev_get_drvdata(dev);
int ret = 0;
ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_ENABLE);
if (ret)
return ret;
return 0;
}
static int __maybe_unused ti_sci_resume_noirq(struct device *dev)
{
struct ti_sci_info *info = dev_get_drvdata(dev);
int ret = 0;
u32 source;
u64 time;
u8 pin;
u8 mode;
ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_DISABLE);
if (ret)
return ret;
ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode);
/* Do not fail to resume on error as the wake reason is not critical */
if (!ret)
dev_info(dev, "ti_sci: wakeup source:0x%x, pin:0x%x, mode:0x%x\n",
source, pin, mode);
return 0;
}
static const struct dev_pm_ops ti_sci_pm_ops = {
#ifdef CONFIG_PM_SLEEP
.suspend = ti_sci_suspend,
.suspend_noirq = ti_sci_suspend_noirq,
.resume_noirq = ti_sci_resume_noirq,
#endif
};
/* Description for K2G */
static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
.default_host_id = 2,
@ -3390,6 +3867,13 @@ static int ti_sci_probe(struct platform_device *pdev)
goto out;
}
ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps);
dev_dbg(dev, "Detected firmware capabilities: %s%s%s\n",
info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "",
info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "",
info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : ""
);
ti_sci_setup_ops(info);
ret = devm_register_restart_handler(dev, tisci_reboot_handler, info);
@ -3421,8 +3905,9 @@ static struct platform_driver ti_sci_driver = {
.probe = ti_sci_probe,
.driver = {
.name = "ti-sci",
.of_match_table = of_match_ptr(ti_sci_of_match),
.of_match_table = ti_sci_of_match,
.suppress_bind_attrs = true,
.pm = &ti_sci_pm_ops,
},
};
module_platform_driver(ti_sci_driver);

View File

@ -6,7 +6,7 @@
* The system works in a message response protocol
* See: https://software-dl.ti.com/tisci/esd/latest/index.html for details
*
* Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
* Copyright (C) 2015-2024 Texas Instruments Incorporated - https://www.ti.com/
*/
#ifndef __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
@ -35,6 +36,13 @@
#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
#define TI_SCI_MSG_LPM_SET_DEVICE_CONSTRAINT 0x0309
#define TI_SCI_MSG_LPM_SET_LATENCY_CONSTRAINT 0x030A
/* Resource Management Requests */
#define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500
@ -132,6 +140,27 @@ 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_PARTIAL_IO: Partial IO in LPM
* MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM
*
* 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_PARTIAL_IO TI_SCI_MSG_FLAG(4)
#define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5)
#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
@ -545,6 +574,118 @@ struct ti_sci_msg_resp_get_clock_freq {
u64 freq_hz;
} __packed;
/**
* struct tisci_msg_req_prepare_sleep - 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;
#define TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED 0xfd
u8 mode;
u32 ctx_lo;
u32 ctx_hi;
u32 debug_flags;
} __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;
/**
* 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.
* @wake_pin: The pin that has triggered wake up.
* @mode: The last entered low power mode.
* @rsvd: Reserved for future use.
*
* Response to a generic message with message type TI_SCI_MSG_LPM_WAKE_REASON,
* used to query the wake up source, pin and entered low power mode.
*/
struct ti_sci_msg_resp_lpm_wake_reason {
struct ti_sci_msg_hdr hdr;
u32 wake_source;
u64 wake_timestamp;
u8 wake_pin;
u8 mode;
u32 rsvd[2];
} __packed;
/**
* struct ti_sci_msg_req_lpm_set_device_constraint - Request for
* TISCI_MSG_LPM_SET_DEVICE_CONSTRAINT.
*
* @hdr: TISCI header to provide ACK/NAK flags to the host.
* @id: Device ID of device whose constraint has to be modified.
* @state: The desired state of device constraint: set or clear.
* @rsvd: Reserved for future use.
*
* This message is used by host to set constraint on the device. This can be
* sent anytime after boot before prepare sleep message. Any device can set a
* constraint on the low power mode that the SoC can enter. It allows
* configurable information to be easily shared from the application, as this
* is a non-secure message and therefore can be sent by anyone. By setting a
* constraint, the device ensures that it will not be powered off or reset in
* the selected mode. Note: Access Restriction: Exclusivity flag of Device will
* be honored. If some other host already has constraint on this device ID,
* NACK will be returned.
*/
struct ti_sci_msg_req_lpm_set_device_constraint {
struct ti_sci_msg_hdr hdr;
u32 id;
u8 state;
u32 rsvd[2];
} __packed;
/**
* struct ti_sci_msg_req_lpm_set_latency_constraint - Request for
* TISCI_MSG_LPM_SET_LATENCY_CONSTRAINT.
*
* @hdr: TISCI header to provide ACK/NAK flags to the host.
* @wkup_latency: The maximum acceptable latency to wake up from low power mode
* in milliseconds. The deeper the state, the higher the latency.
* @state: The desired state of wakeup latency constraint: set or clear.
* @rsvd: Reserved for future use.
*
* This message is used by host to set wakeup latency from low power mode. This can
* be sent anytime after boot before prepare sleep message, and can be sent after
* current low power mode is exited. Any device can set a constraint on the low power
* mode that the SoC can enter. It allows configurable information to be easily shared
* from the application, as this is a non-secure message and therefore can be sent by
* anyone. By setting a wakeup latency constraint, the host ensures that the resume time
* from selected low power mode will be less than the constraint value.
*/
struct ti_sci_msg_req_lpm_set_latency_constraint {
struct ti_sci_msg_hdr hdr;
u16 latency;
u8 state;
u32 rsvd;
} __packed;
#define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff
/**

View File

@ -119,11 +119,10 @@ static int knav_queue_setup_irq(struct knav_range_info *range,
if (range->flags & RANGE_HAS_IRQ) {
irq = range->irqs[queue].irq;
ret = request_irq(irq, knav_queue_int_handler, 0,
inst->irq_name, inst);
ret = request_irq(irq, knav_queue_int_handler, IRQF_NO_AUTOEN,
inst->irq_name, inst);
if (ret)
return ret;
disable_irq(irq);
if (range->irqs[queue].cpu_mask) {
ret = irq_set_affinity_hint(irq, range->irqs[queue].cpu_mask);
if (ret) {
@ -723,7 +722,6 @@ static void kdesc_empty_pool(struct knav_pool *pool)
if (!desc) {
dev_dbg(pool->kdev->dev,
"couldn't unmap desc, continuing\n");
continue;
}
}
WARN_ON(i != pool->num_desc);

View File

@ -195,6 +195,35 @@ struct ti_sci_clk_ops {
u64 *current_freq);
};
/* TISCI LPM IO isolation control values */
#define TISCI_MSG_VALUE_IO_ENABLE 1
#define TISCI_MSG_VALUE_IO_DISABLE 0
/* TISCI LPM constraint state values */
#define TISCI_MSG_CONSTRAINT_SET 1
#define TISCI_MSG_CONSTRAINT_CLR 0
/**
* struct ti_sci_pm_ops - Low Power Mode (LPM) control operations
* @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_device_constraint: Set LPM constraint on behalf of a device
* - id: Device Identifier
* - state: The desired state of device constraint: set or clear.
* @set_latency_constraint: Set LPM resume latency constraint
* - latency: maximum acceptable latency to wake up from low power mode
* - state: The desired state of latency constraint: set or clear.
*/
struct ti_sci_pm_ops {
int (*lpm_wake_reason)(const struct ti_sci_handle *handle,
u32 *source, u64 *timestamp, u8 *pin, u8 *mode);
int (*set_device_constraint)(const struct ti_sci_handle *handle,
u32 id, u8 state);
int (*set_latency_constraint)(const struct ti_sci_handle *handle,
u16 latency, u8 state);
};
/**
* struct ti_sci_resource_desc - Description of TI SCI resource instance range.
* @start: Start index of the first resource range.
@ -539,6 +568,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;