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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAl/NtZwACgkQfBQHDyUj g0fXVw//ewFAHbj6dDWZEvI46mvlqQkvmYk6oViSN/tLdLu3Ay0ggDpMWht5vzf/ IfhxgassigWEY0aFxBrhj/TxOVJuuJpMVGWg0xyLZIngyrDmghRYqt+Ssk6AAX9t dN9mr5mxR0EI6CY0/jX62WRHvy/NVk9FFXuRRpsFF6HEDQcIKCEfXxl/5mhFnMuL D52wyxfgn8jOJ11sR5uOn8QPpA9ZGjRsw52LlZKTqNn07kclEcE0r+B30+7GvEYV HlWh6BGR4BoAygJwfTjTwU0WA3fBSccpFAfmDojY32qncrVzYRq8amYe5DxPKK17 E7dZMWGZY4KWy9O8GG+ENuDtHQk8G30tcf+9kDbhLL7Izrrnf3de6aRbRmHx73i1 4mWcFld5Eq0IaDjlYBcxuanJ6fKxPambEVVihA90rhCfXszNu27sron5AmYwKwk+ FA417GDbM9VBLSif4qrq+LrCRrIO3ixhPgmMcpakuo+m9y0KvzEJiT5MZiSFZjMG UnEOKKAC6M04NxnttxmXLS1MQRxp4n9gOwjN/slSvrCIakBur64hurzdh/7BUO3Q cW4naYGkBhyQ1XMjtOyg+gj7u+btt9bqOVghWiixXkvahQsjq8dsMPN85ghA9M2P K9/kyBvyJUoGPd5nUgbbKXSnPF6KFP2CdrSeucR9v/6v9pg58Qs= =cDZP -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
6e559fe128
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -359,6 +359,7 @@ struct sdw_dpn_prop {
|
|||
* @sink_dpn_prop: Sink Data Port N properties
|
||||
* @scp_int1_mask: SCP_INT1_MASK desired settings
|
||||
* @quirks: bitmask identifying deltas from the MIPI specification
|
||||
* @is_sdca: the Slave supports the SDCA specification
|
||||
*/
|
||||
struct sdw_slave_prop {
|
||||
u32 mipi_revision;
|
||||
|
@ -382,6 +383,7 @@ struct sdw_slave_prop {
|
|||
struct sdw_dpn_prop *sink_dpn_prop;
|
||||
u8 scp_int1_mask;
|
||||
u32 quirks;
|
||||
bool is_sdca;
|
||||
};
|
||||
|
||||
#define SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY BIT(0)
|
||||
|
@ -479,10 +481,12 @@ struct sdw_slave_id {
|
|||
|
||||
/**
|
||||
* struct sdw_slave_intr_status - Slave interrupt status
|
||||
* @sdca_cascade: set if the Slave device reports an SDCA interrupt
|
||||
* @control_port: control port status
|
||||
* @port: data port status
|
||||
*/
|
||||
struct sdw_slave_intr_status {
|
||||
bool sdca_cascade;
|
||||
u8 control_port;
|
||||
u8 port[15];
|
||||
};
|
||||
|
|
|
@ -41,6 +41,12 @@
|
|||
#define SDW_DP0_INT_IMPDEF1 BIT(5)
|
||||
#define SDW_DP0_INT_IMPDEF2 BIT(6)
|
||||
#define SDW_DP0_INT_IMPDEF3 BIT(7)
|
||||
#define SDW_DP0_INTERRUPTS (SDW_DP0_INT_TEST_FAIL | \
|
||||
SDW_DP0_INT_PORT_READY | \
|
||||
SDW_DP0_INT_BRA_FAILURE | \
|
||||
SDW_DP0_INT_IMPDEF1 | \
|
||||
SDW_DP0_INT_IMPDEF2 | \
|
||||
SDW_DP0_INT_IMPDEF3)
|
||||
|
||||
#define SDW_DP0_PORTCTRL_DATAMODE GENMASK(3, 2)
|
||||
#define SDW_DP0_PORTCTRL_NXTINVBANK BIT(4)
|
||||
|
@ -241,6 +247,11 @@
|
|||
#define SDW_DPN_INT_IMPDEF1 BIT(5)
|
||||
#define SDW_DPN_INT_IMPDEF2 BIT(6)
|
||||
#define SDW_DPN_INT_IMPDEF3 BIT(7)
|
||||
#define SDW_DPN_INTERRUPTS (SDW_DPN_INT_TEST_FAIL | \
|
||||
SDW_DPN_INT_PORT_READY | \
|
||||
SDW_DPN_INT_IMPDEF1 | \
|
||||
SDW_DPN_INT_IMPDEF2 | \
|
||||
SDW_DPN_INT_IMPDEF3)
|
||||
|
||||
#define SDW_DPN_PORTCTRL_FLOWMODE GENMASK(1, 0)
|
||||
#define SDW_DPN_PORTCTRL_DATAMODE GENMASK(3, 2)
|
||||
|
|
Loading…
Reference in New Issue