Commit 6e559fe1 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'soundwire-5.11-rc1' of...

Merge tag 'soundwire-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire into char-misc-next

Vinod writes:

soundwire updates for 5.11-rc1

Updates for last PR for this year contain:
- Improvements from Intel for port interrupt handling
- SDCA cascade interrupt support
- runtime pm for master device

* tag 'soundwire-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire:
  soundwire: intel: fix another unused-function warning
  soundwire: master: use pm_runtime_set_active() on add
  soundwire: qcom: Fix build failure when slimbus is module
  soundwire: bus: only clear valid DPN interrupts
  soundwire: bus: only clear valid DP0 interrupts
  soundwire: registers: add definitions for clearable interrupt fields
  soundwire: bus: reset slave_notify status at each loop
  soundwire: bus: add comments to explain interrupt loop filter
  soundwire: SDCA: detect sdca_cascade interrupt
  soundwire: Fix DEBUG_LOCKS_WARN_ON for uninitialized attribute
parents a3ab07c6 17e0da0b
Loading
Loading
Loading
Loading
+46 −9
Original line number Diff line number Diff line
@@ -1280,7 +1280,7 @@ static int sdw_initialize_slave(struct sdw_slave *slave)

static int sdw_handle_dp0_interrupt(struct sdw_slave *slave, u8 *slave_status)
{
	u8 clear = 0, impl_int_mask;
	u8 clear, impl_int_mask;
	int status, status2, ret, count = 0;

	status = sdw_read(slave, SDW_DP0_INT);
@@ -1291,6 +1291,8 @@ static int sdw_handle_dp0_interrupt(struct sdw_slave *slave, u8 *slave_status)
	}

	do {
		clear = status & ~SDW_DP0_INTERRUPTS;

		if (status & SDW_DP0_INT_TEST_FAIL) {
			dev_err(&slave->dev, "Test fail for port 0\n");
			clear |= SDW_DP0_INT_TEST_FAIL;
@@ -1319,7 +1321,7 @@ static int sdw_handle_dp0_interrupt(struct sdw_slave *slave, u8 *slave_status)
			*slave_status = clear;
		}

		/* clear the interrupt */
		/* clear the interrupts but don't touch reserved and SDCA_CASCADE fields */
		ret = sdw_write(slave, SDW_DP0_INT, clear);
		if (ret < 0) {
			dev_err(slave->bus->dev,
@@ -1334,12 +1336,13 @@ static int sdw_handle_dp0_interrupt(struct sdw_slave *slave, u8 *slave_status)
				"SDW_DP0_INT read failed:%d\n", status2);
			return status2;
		}
		/* filter to limit loop to interrupts identified in the first status read */
		status &= status2;

		count++;

		/* we can get alerts while processing so keep retrying */
	} while (status != 0 && count < SDW_READ_INTR_CLEAR_RETRY);
	} while ((status & SDW_DP0_INTERRUPTS) && (count < SDW_READ_INTR_CLEAR_RETRY));

	if (count == SDW_READ_INTR_CLEAR_RETRY)
		dev_warn(slave->bus->dev, "Reached MAX_RETRY on DP0 read\n");
@@ -1350,7 +1353,7 @@ static int sdw_handle_dp0_interrupt(struct sdw_slave *slave, u8 *slave_status)
static int sdw_handle_port_interrupt(struct sdw_slave *slave,
				     int port, u8 *slave_status)
{
	u8 clear = 0, impl_int_mask;
	u8 clear, impl_int_mask;
	int status, status2, ret, count = 0;
	u32 addr;

@@ -1367,6 +1370,8 @@ static int sdw_handle_port_interrupt(struct sdw_slave *slave,
	}

	do {
		clear = status & ~SDW_DPN_INTERRUPTS;

		if (status & SDW_DPN_INT_TEST_FAIL) {
			dev_err(&slave->dev, "Test fail for port:%d\n", port);
			clear |= SDW_DPN_INT_TEST_FAIL;
@@ -1389,7 +1394,7 @@ static int sdw_handle_port_interrupt(struct sdw_slave *slave,
			*slave_status = clear;
		}

		/* clear the interrupt */
		/* clear the interrupt but don't touch reserved fields */
		ret = sdw_write(slave, addr, clear);
		if (ret < 0) {
			dev_err(slave->bus->dev,
@@ -1404,12 +1409,13 @@ static int sdw_handle_port_interrupt(struct sdw_slave *slave,
				"SDW_DPN_INT read failed:%d\n", status2);
			return status2;
		}
		/* filter to limit loop to interrupts identified in the first status read */
		status &= status2;

		count++;

		/* we can get alerts while processing so keep retrying */
	} while (status != 0 && count < SDW_READ_INTR_CLEAR_RETRY);
	} while ((status & SDW_DPN_INTERRUPTS) && (count < SDW_READ_INTR_CLEAR_RETRY));

	if (count == SDW_READ_INTR_CLEAR_RETRY)
		dev_warn(slave->bus->dev, "Reached MAX_RETRY on port read");
@@ -1423,7 +1429,8 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
	u8 clear = 0, bit, port_status[15] = {0};
	int port_num, stat, ret, count = 0;
	unsigned long port;
	bool slave_notify = false;
	bool slave_notify;
	u8 sdca_cascade = 0;
	u8 buf, buf2[2], _buf, _buf2[2];
	bool parity_check;
	bool parity_quirk;
@@ -1453,7 +1460,19 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
		goto io_err;
	}

	if (slave->prop.is_sdca) {
		ret = sdw_read(slave, SDW_DP0_INT);
		if (ret < 0) {
			dev_err(slave->bus->dev,
				"SDW_DP0_INT read failed:%d\n", ret);
			goto io_err;
		}
		sdca_cascade = ret & SDW_DP0_SDCA_CASCADE;
	}

	do {
		slave_notify = false;

		/*
		 * Check parity, bus clash and Slave (impl defined)
		 * interrupt
@@ -1489,6 +1508,10 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
			clear |= SDW_SCP_INT1_IMPL_DEF;
		}

		/* the SDCA interrupts are cleared in the codec driver .interrupt_callback() */
		if (sdca_cascade)
			slave_notify = true;

		/* Check port 0 - 3 interrupts */
		port = buf & SDW_SCP_INT1_PORT0_3;

@@ -1526,6 +1549,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
		/* Update the Slave driver */
		if (slave_notify && slave->ops &&
		    slave->ops->interrupt_callback) {
			slave_intr.sdca_cascade = sdca_cascade;
			slave_intr.control_port = clear;
			memcpy(slave_intr.port, &port_status,
			       sizeof(slave_intr.port));
@@ -1563,11 +1587,24 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
			goto io_err;
		}

		/* Make sure no interrupts are pending */
		if (slave->prop.is_sdca) {
			ret = sdw_read(slave, SDW_DP0_INT);
			if (ret < 0) {
				dev_err(slave->bus->dev,
					"SDW_DP0_INT read failed:%d\n", ret);
				goto io_err;
			}
			sdca_cascade = ret & SDW_DP0_SDCA_CASCADE;
		}

		/*
		 * Make sure no interrupts are pending, but filter to limit loop
		 * to interrupts identified in the first status read
		 */
		buf &= _buf;
		buf2[0] &= _buf2[0];
		buf2[1] &= _buf2[1];
		stat = buf || buf2[0] || buf2[1];
		stat = buf || buf2[0] || buf2[1] || sdca_cascade;

		/*
		 * Exit loop if Slave is continuously in ALERT state even
+2 −6
Original line number Diff line number Diff line
@@ -1585,8 +1585,6 @@ int intel_master_process_wakeen_event(struct platform_device *pdev)
 * PM calls
 */

#ifdef CONFIG_PM

static int __maybe_unused intel_suspend(struct device *dev)
{
	struct sdw_cdns *cdns = dev_get_drvdata(dev);
@@ -1641,7 +1639,7 @@ static int __maybe_unused intel_suspend(struct device *dev)
	return 0;
}

static int intel_suspend_runtime(struct device *dev)
static int __maybe_unused intel_suspend_runtime(struct device *dev)
{
	struct sdw_cdns *cdns = dev_get_drvdata(dev);
	struct sdw_intel *sdw = cdns_to_intel(cdns);
@@ -1796,7 +1794,7 @@ static int __maybe_unused intel_resume(struct device *dev)
	return ret;
}

static int intel_resume_runtime(struct device *dev)
static int __maybe_unused intel_resume_runtime(struct device *dev)
{
	struct sdw_cdns *cdns = dev_get_drvdata(dev);
	struct sdw_intel *sdw = cdns_to_intel(cdns);
@@ -1969,8 +1967,6 @@ static int intel_resume_runtime(struct device *dev)
	return ret;
}

#endif

static const struct dev_pm_ops intel_pm = {
	SET_SYSTEM_SLEEP_PM_OPS(intel_suspend, intel_resume)
	SET_RUNTIME_PM_OPS(intel_suspend_runtime, intel_resume_runtime, NULL)
+14 −0
Original line number Diff line number Diff line
@@ -8,6 +8,15 @@
#include <linux/soundwire/sdw_type.h>
#include "bus.h"

/*
 * The 3s value for autosuspend will only be used if there are no
 * devices physically attached on a bus segment. In practice enabling
 * the bus operation will result in children devices become active and
 * the master device will only suspend when all its children are no
 * longer active.
 */
#define SDW_MASTER_SUSPEND_DELAY_MS 3000

/*
 * The sysfs for properties reflects the MIPI description as given
 * in the MIPI DisCo spec
@@ -154,7 +163,12 @@ int sdw_master_device_add(struct sdw_bus *bus, struct device *parent,
	bus->dev = &md->dev;
	bus->md = md;

	pm_runtime_set_autosuspend_delay(&bus->md->dev, SDW_MASTER_SUSPEND_DELAY_MS);
	pm_runtime_use_autosuspend(&bus->md->dev);
	pm_runtime_mark_last_busy(&bus->md->dev);
	pm_runtime_set_active(&bus->md->dev);
	pm_runtime_enable(&bus->md->dev);
	pm_runtime_idle(&bus->md->dev);
device_register_err:
	return ret;
}
+1 −1
Original line number Diff line number Diff line
@@ -799,7 +799,7 @@ static int qcom_swrm_probe(struct platform_device *pdev)
	data = of_device_get_match_data(dev);
	ctrl->rows_index = sdw_find_row_index(data->default_rows);
	ctrl->cols_index = sdw_find_col_index(data->default_cols);
#if IS_ENABLED(CONFIG_SLIMBUS)
#if IS_REACHABLE(CONFIG_SLIMBUS)
	if (dev->parent->bus == &slimbus_bus) {
#else
	if (false) {
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ static int field##_attribute_alloc(struct device *dev, \
		return -ENOMEM;						\
	dpn_attr->N = N;						\
	dpn_attr->dir = dir;						\
	sysfs_attr_init(&dpn_attr->dev_attr.attr);			\
	dpn_attr->format_string = format_string;			\
	dpn_attr->dev_attr.attr.name = __stringify(field);		\
	dpn_attr->dev_attr.attr.mode = 0444;				\
Loading