On 26-01-21, 16:37, Bard Liao wrote: > The SoundWire specification allows a Slave device to report a bus clash > with the in-band interrupt mechanism when it detects a conflict while > driving a bitSlot it owns. This can be a symptom of an electrical conflict > or a programming error, and it's vital to detect reliably. > > Unfortunately, on some platforms, bus clashes are randomly reported by > Slave devices after a bus reset, with an interrupt status set even before > the bus clash interrupt is enabled. These initial spurious interrupts are > not relevant and should optionally be filtered out, while leaving the > interrupt mechanism enabled to detect 'true' issues. > > This patch suggests the addition of a Master level quirk to discard such > interrupts. The quirk should in theory have been added at the Slave level, > but since the problem was detected with different generations of Slave > devices it's hard to point to a specific IP. The problem might also be > board-dependent and hence dealing with a Master quirk is simpler. > > Signed-off-by: Bard Liao <yung-chuan.liao@xxxxxxxxxxxxxxx> > Reviewed-by: Rander Wang <rander.wang@xxxxxxxxxxxxxxx> > Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@xxxxxxxxxxxxxxx> > --- > drivers/soundwire/bus.c | 10 ++++++++++ > include/linux/soundwire/sdw.h | 4 ++++ > 2 files changed, 14 insertions(+) > > diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c > index 6e1c988f3845..d394905936e4 100644 > --- a/drivers/soundwire/bus.c > +++ b/drivers/soundwire/bus.c > @@ -1240,6 +1240,7 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave) > static int sdw_initialize_slave(struct sdw_slave *slave) > { > struct sdw_slave_prop *prop = &slave->prop; > + int status; > int ret; > u8 val; > > @@ -1247,6 +1248,15 @@ static int sdw_initialize_slave(struct sdw_slave *slave) > if (ret < 0) > return ret; > > + if (slave->bus->prop.quirks & SDW_MASTER_QUIRKS_CLEAR_INITIAL_CLASH) { > + /* Clear bus clash interrupt before enabling interrupt mask */ > + status = sdw_read_no_pm(slave, SDW_SCP_INT1); > + if (status & SDW_SCP_INT1_BUS_CLASH) { > + dev_warn(&slave->dev, "Bus clash detected before INT mask is enabled\n"); > + sdw_write_no_pm(slave, SDW_SCP_INT1, SDW_SCP_INT1_BUS_CLASH); > + } > + } > + > /* > * Set SCP_INT1_MASK register, typically bus clash and > * implementation-defined interrupt mask. The Parity detection > diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h > index f0b01b728640..a2766c3b603d 100644 > --- a/include/linux/soundwire/sdw.h > +++ b/include/linux/soundwire/sdw.h > @@ -405,6 +405,7 @@ struct sdw_slave_prop { > * command > * @mclk_freq: clock reference passed to SoundWire Master, in Hz. > * @hw_disabled: if true, the Master is not functional, typically due to pin-mux > + * @quirks: bitmask identifying optional behavior beyond the scope of the MIPI specification > */ > struct sdw_master_prop { > u32 revision; > @@ -421,8 +422,11 @@ struct sdw_master_prop { > u32 err_threshold; > u32 mclk_freq; > bool hw_disabled; > + u32 quirks; Can we do u64 here please.. I dont know where we would end up.. but would hate if we start running out of space .. > }; > > +#define SDW_MASTER_QUIRKS_CLEAR_INITIAL_CLASH BIT(0) > + > int sdw_master_read_prop(struct sdw_bus *bus); > int sdw_slave_read_prop(struct sdw_slave *slave); > > -- > 2.17.1 -- ~Vinod