Unverified Commit ffca6779 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'ti-driver-soc-for-v6.13' of...

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: default avatarArnd Bergmann <arnd@arndb.de>
parents 7d6f7cfc a4c14f50
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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.
+487 −2
Original line number Diff line number Diff line
@@ -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);
+142 −1
Original line number Diff line number Diff line
@@ -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

/**
+2 −4
Original line number Diff line number Diff line
@@ -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,
		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);
+30 −0
Original line number Diff line number Diff line
@@ -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;