Skip to content

Commit 8c61951

Browse files
committed
Merge tag 'soundwire-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire into char-misc-next
Vinod writes: soundwire updates for 5.15-rc1 - Core has updates to support SoundWire mockup device (includes tag from asoc), improved error handling and slave status. - Drivers has update on Intel driver for new quriks and better handling of errors and suspend routines * tag 'soundwire-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire: soundwire: cadence: do not extend reset delay soundwire: intel: conditionally exit clock stop mode on system suspend soundwire: intel: skip suspend/resume/wake when link was not started soundwire: intel: fix potential race condition during power down soundwire: cadence: override PDI configurations to create loopback soundwire: cadence: add debugfs interface for PDI loopbacks soundwire: stream: don't program mockup device ports soundwire: bus: squelch error returned by mockup devices soundwire: add flag to ignore all command/control for mockup devices soundwire: stream: don't abort bank switch on Command_Ignored/-ENODATA soundwire: cadence: add paranoid check on self-clearing bits soundwire: dmi-quirks: add quirk for Intel 'Bishop County' NUC M15 soundwire: bus: update Slave status in sdw_clear_slave_status soundwire: cadence: Remove ret variable from sdw_cdns_irq() soundwire: bus: filter out more -EDATA errors on clock stop soundwire: dmi-quirks: add ull suffix for SoundWire _ADR values ASoC: Intel: boards: sof_sdw: add SoundWire mockup codecs for tests ASoC: soc-acpi: tgl: add table for SoundWire mockup devices ASoC: soc-acpi: cnl: add table for SoundWire mockup devices ASoC: codecs: add SoundWire mockup device support
2 parents 96e9df3 + 2564a2d commit 8c61951

File tree

18 files changed

+966
-93
lines changed

18 files changed

+966
-93
lines changed

drivers/soundwire/bus.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,10 @@ sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val)
390390
if (ret < 0)
391391
return ret;
392392

393-
return sdw_transfer(slave->bus, &msg);
393+
ret = sdw_transfer(slave->bus, &msg);
394+
if (slave->is_mockup_device)
395+
ret = 0;
396+
return ret;
394397
}
395398

396399
static int
@@ -404,7 +407,10 @@ sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val)
404407
if (ret < 0)
405408
return ret;
406409

407-
return sdw_transfer(slave->bus, &msg);
410+
ret = sdw_transfer(slave->bus, &msg);
411+
if (slave->is_mockup_device)
412+
ret = 0;
413+
return ret;
408414
}
409415

410416
int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value)
@@ -896,7 +902,8 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num)
896902
do {
897903
val = sdw_bread_no_pm(bus, dev_num, SDW_SCP_STAT);
898904
if (val < 0) {
899-
dev_err(bus->dev, "SDW_SCP_STAT bread failed:%d\n", val);
905+
if (val != -ENODATA)
906+
dev_err(bus->dev, "SDW_SCP_STAT bread failed:%d\n", val);
900907
return val;
901908
}
902909
val &= SDW_SCP_STAT_CLK_STP_NF;
@@ -1853,6 +1860,7 @@ void sdw_clear_slave_status(struct sdw_bus *bus, u32 request)
18531860
if (slave->status != SDW_SLAVE_UNATTACHED) {
18541861
sdw_modify_slave_status(slave, SDW_SLAVE_UNATTACHED);
18551862
slave->first_interrupt_done = false;
1863+
sdw_update_slave_status(slave, SDW_SLAVE_UNATTACHED);
18561864
}
18571865

18581866
/* keep track of request, used in pm_runtime resume */

drivers/soundwire/cadence_master.c

Lines changed: 188 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,40 @@ static int cdns_parity_error_injection(void *data, u64 value)
450450
DEFINE_DEBUGFS_ATTRIBUTE(cdns_parity_error_fops, NULL,
451451
cdns_parity_error_injection, "%llu\n");
452452

453+
static int cdns_set_pdi_loopback_source(void *data, u64 value)
454+
{
455+
struct sdw_cdns *cdns = data;
456+
unsigned int pdi_out_num = cdns->pcm.num_bd + cdns->pcm.num_out;
457+
458+
if (value > pdi_out_num)
459+
return -EINVAL;
460+
461+
/* Userspace changed the hardware state behind the kernel's back */
462+
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
463+
464+
cdns->pdi_loopback_source = value;
465+
466+
return 0;
467+
}
468+
DEFINE_DEBUGFS_ATTRIBUTE(cdns_pdi_loopback_source_fops, NULL, cdns_set_pdi_loopback_source, "%llu\n");
469+
470+
static int cdns_set_pdi_loopback_target(void *data, u64 value)
471+
{
472+
struct sdw_cdns *cdns = data;
473+
unsigned int pdi_in_num = cdns->pcm.num_bd + cdns->pcm.num_in;
474+
475+
if (value > pdi_in_num)
476+
return -EINVAL;
477+
478+
/* Userspace changed the hardware state behind the kernel's back */
479+
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
480+
481+
cdns->pdi_loopback_target = value;
482+
483+
return 0;
484+
}
485+
DEFINE_DEBUGFS_ATTRIBUTE(cdns_pdi_loopback_target_fops, NULL, cdns_set_pdi_loopback_target, "%llu\n");
486+
453487
/**
454488
* sdw_cdns_debugfs_init() - Cadence debugfs init
455489
* @cdns: Cadence instance
@@ -464,6 +498,16 @@ void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root)
464498

465499
debugfs_create_file("cdns-parity-error-injection", 0200, root, cdns,
466500
&cdns_parity_error_fops);
501+
502+
cdns->pdi_loopback_source = -1;
503+
cdns->pdi_loopback_target = -1;
504+
505+
debugfs_create_file("cdns-pdi-loopback-source", 0200, root, cdns,
506+
&cdns_pdi_loopback_source_fops);
507+
508+
debugfs_create_file("cdns-pdi-loopback-target", 0200, root, cdns,
509+
&cdns_pdi_loopback_target_fops);
510+
467511
}
468512
EXPORT_SYMBOL_GPL(sdw_cdns_debugfs_init);
469513

@@ -822,7 +866,6 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
822866
{
823867
struct sdw_cdns *cdns = dev_id;
824868
u32 int_status;
825-
int ret = IRQ_HANDLED;
826869

827870
/* Check if the link is up */
828871
if (!cdns->link_up)
@@ -900,7 +943,7 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
900943
}
901944

902945
cdns_writel(cdns, CDNS_MCP_INTSTAT, int_status);
903-
return ret;
946+
return IRQ_HANDLED;
904947
}
905948
EXPORT_SYMBOL(sdw_cdns_irq);
906949

@@ -936,6 +979,49 @@ static void cdns_update_slave_status_work(struct work_struct *work)
936979

937980
}
938981

982+
/* paranoia check to make sure self-cleared bits are indeed cleared */
983+
void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string,
984+
bool initial_delay, int reset_iterations)
985+
{
986+
u32 mcp_control;
987+
u32 mcp_config_update;
988+
int i;
989+
990+
if (initial_delay)
991+
usleep_range(1000, 1500);
992+
993+
mcp_control = cdns_readl(cdns, CDNS_MCP_CONTROL);
994+
995+
/* the following bits should be cleared immediately */
996+
if (mcp_control & CDNS_MCP_CONTROL_CMD_RST)
997+
dev_err(cdns->dev, "%s failed: MCP_CONTROL_CMD_RST is not cleared\n", string);
998+
if (mcp_control & CDNS_MCP_CONTROL_SOFT_RST)
999+
dev_err(cdns->dev, "%s failed: MCP_CONTROL_SOFT_RST is not cleared\n", string);
1000+
if (mcp_control & CDNS_MCP_CONTROL_SW_RST)
1001+
dev_err(cdns->dev, "%s failed: MCP_CONTROL_SW_RST is not cleared\n", string);
1002+
if (mcp_control & CDNS_MCP_CONTROL_CLK_STOP_CLR)
1003+
dev_err(cdns->dev, "%s failed: MCP_CONTROL_CLK_STOP_CLR is not cleared\n", string);
1004+
mcp_config_update = cdns_readl(cdns, CDNS_MCP_CONFIG_UPDATE);
1005+
if (mcp_config_update & CDNS_MCP_CONFIG_UPDATE_BIT)
1006+
dev_err(cdns->dev, "%s failed: MCP_CONFIG_UPDATE_BIT is not cleared\n", string);
1007+
1008+
i = 0;
1009+
while (mcp_control & CDNS_MCP_CONTROL_HW_RST) {
1010+
if (i == reset_iterations) {
1011+
dev_err(cdns->dev, "%s failed: MCP_CONTROL_HW_RST is not cleared\n", string);
1012+
break;
1013+
}
1014+
1015+
dev_dbg(cdns->dev, "%s: MCP_CONTROL_HW_RST is not cleared at iteration %d\n", string, i);
1016+
i++;
1017+
1018+
usleep_range(1000, 1500);
1019+
mcp_control = cdns_readl(cdns, CDNS_MCP_CONTROL);
1020+
}
1021+
1022+
}
1023+
EXPORT_SYMBOL(sdw_cdns_check_self_clearing_bits);
1024+
9391025
/*
9401026
* init routines
9411027
*/
@@ -946,10 +1032,7 @@ static void cdns_update_slave_status_work(struct work_struct *work)
9461032
*/
9471033
int sdw_cdns_exit_reset(struct sdw_cdns *cdns)
9481034
{
949-
/* program maximum length reset to be safe */
950-
cdns_updatel(cdns, CDNS_MCP_CONTROL,
951-
CDNS_MCP_CONTROL_RST_DELAY,
952-
CDNS_MCP_CONTROL_RST_DELAY);
1035+
/* keep reset delay unchanged to 4096 cycles */
9531036

9541037
/* use hardware generated reset */
9551038
cdns_updatel(cdns, CDNS_MCP_CONTROL,
@@ -1213,6 +1296,8 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
12131296

12141297
cdns_init_clock_ctrl(cdns);
12151298

1299+
sdw_cdns_check_self_clearing_bits(cdns, __func__, false, 0);
1300+
12161301
/* reset msg_count to default value of FIFOLEVEL */
12171302
cdns->msg_count = cdns_readl(cdns, CDNS_MCP_FIFOLEVEL);
12181303

@@ -1286,20 +1371,37 @@ static int cdns_port_params(struct sdw_bus *bus,
12861371
struct sdw_port_params *p_params, unsigned int bank)
12871372
{
12881373
struct sdw_cdns *cdns = bus_to_cdns(bus);
1289-
int dpn_config = 0, dpn_config_off;
1374+
int dpn_config_off_source;
1375+
int dpn_config_off_target;
1376+
int target_num = p_params->num;
1377+
int source_num = p_params->num;
1378+
bool override = false;
1379+
int dpn_config;
1380+
1381+
if (target_num == cdns->pdi_loopback_target &&
1382+
cdns->pdi_loopback_source != -1) {
1383+
source_num = cdns->pdi_loopback_source;
1384+
override = true;
1385+
}
12901386

1291-
if (bank)
1292-
dpn_config_off = CDNS_DPN_B1_CONFIG(p_params->num);
1293-
else
1294-
dpn_config_off = CDNS_DPN_B0_CONFIG(p_params->num);
1387+
if (bank) {
1388+
dpn_config_off_source = CDNS_DPN_B1_CONFIG(source_num);
1389+
dpn_config_off_target = CDNS_DPN_B1_CONFIG(target_num);
1390+
} else {
1391+
dpn_config_off_source = CDNS_DPN_B0_CONFIG(source_num);
1392+
dpn_config_off_target = CDNS_DPN_B0_CONFIG(target_num);
1393+
}
12951394

1296-
dpn_config = cdns_readl(cdns, dpn_config_off);
1395+
dpn_config = cdns_readl(cdns, dpn_config_off_source);
12971396

1298-
u32p_replace_bits(&dpn_config, (p_params->bps - 1), CDNS_DPN_CONFIG_WL);
1299-
u32p_replace_bits(&dpn_config, p_params->flow_mode, CDNS_DPN_CONFIG_PORT_FLOW);
1300-
u32p_replace_bits(&dpn_config, p_params->data_mode, CDNS_DPN_CONFIG_PORT_DAT);
1397+
/* use port params if there is no loopback, otherwise use source as is */
1398+
if (!override) {
1399+
u32p_replace_bits(&dpn_config, p_params->bps - 1, CDNS_DPN_CONFIG_WL);
1400+
u32p_replace_bits(&dpn_config, p_params->flow_mode, CDNS_DPN_CONFIG_PORT_FLOW);
1401+
u32p_replace_bits(&dpn_config, p_params->data_mode, CDNS_DPN_CONFIG_PORT_DAT);
1402+
}
13011403

1302-
cdns_writel(cdns, dpn_config_off, dpn_config);
1404+
cdns_writel(cdns, dpn_config_off_target, dpn_config);
13031405

13041406
return 0;
13051407
}
@@ -1309,44 +1411,87 @@ static int cdns_transport_params(struct sdw_bus *bus,
13091411
enum sdw_reg_bank bank)
13101412
{
13111413
struct sdw_cdns *cdns = bus_to_cdns(bus);
1312-
int dpn_offsetctrl = 0, dpn_offsetctrl_off;
1313-
int dpn_config = 0, dpn_config_off;
1314-
int dpn_hctrl = 0, dpn_hctrl_off;
1315-
int num = t_params->port_num;
1316-
int dpn_samplectrl_off;
1414+
int dpn_config;
1415+
int dpn_config_off_source;
1416+
int dpn_config_off_target;
1417+
int dpn_hctrl;
1418+
int dpn_hctrl_off_source;
1419+
int dpn_hctrl_off_target;
1420+
int dpn_offsetctrl;
1421+
int dpn_offsetctrl_off_source;
1422+
int dpn_offsetctrl_off_target;
1423+
int dpn_samplectrl;
1424+
int dpn_samplectrl_off_source;
1425+
int dpn_samplectrl_off_target;
1426+
int source_num = t_params->port_num;
1427+
int target_num = t_params->port_num;
1428+
bool override = false;
1429+
1430+
if (target_num == cdns->pdi_loopback_target &&
1431+
cdns->pdi_loopback_source != -1) {
1432+
source_num = cdns->pdi_loopback_source;
1433+
override = true;
1434+
}
13171435

13181436
/*
13191437
* Note: Only full data port is supported on the Master side for
13201438
* both PCM and PDM ports.
13211439
*/
13221440

13231441
if (bank) {
1324-
dpn_config_off = CDNS_DPN_B1_CONFIG(num);
1325-
dpn_samplectrl_off = CDNS_DPN_B1_SAMPLE_CTRL(num);
1326-
dpn_hctrl_off = CDNS_DPN_B1_HCTRL(num);
1327-
dpn_offsetctrl_off = CDNS_DPN_B1_OFFSET_CTRL(num);
1442+
dpn_config_off_source = CDNS_DPN_B1_CONFIG(source_num);
1443+
dpn_hctrl_off_source = CDNS_DPN_B1_HCTRL(source_num);
1444+
dpn_offsetctrl_off_source = CDNS_DPN_B1_OFFSET_CTRL(source_num);
1445+
dpn_samplectrl_off_source = CDNS_DPN_B1_SAMPLE_CTRL(source_num);
1446+
1447+
dpn_config_off_target = CDNS_DPN_B1_CONFIG(target_num);
1448+
dpn_hctrl_off_target = CDNS_DPN_B1_HCTRL(target_num);
1449+
dpn_offsetctrl_off_target = CDNS_DPN_B1_OFFSET_CTRL(target_num);
1450+
dpn_samplectrl_off_target = CDNS_DPN_B1_SAMPLE_CTRL(target_num);
1451+
13281452
} else {
1329-
dpn_config_off = CDNS_DPN_B0_CONFIG(num);
1330-
dpn_samplectrl_off = CDNS_DPN_B0_SAMPLE_CTRL(num);
1331-
dpn_hctrl_off = CDNS_DPN_B0_HCTRL(num);
1332-
dpn_offsetctrl_off = CDNS_DPN_B0_OFFSET_CTRL(num);
1453+
dpn_config_off_source = CDNS_DPN_B0_CONFIG(source_num);
1454+
dpn_hctrl_off_source = CDNS_DPN_B0_HCTRL(source_num);
1455+
dpn_offsetctrl_off_source = CDNS_DPN_B0_OFFSET_CTRL(source_num);
1456+
dpn_samplectrl_off_source = CDNS_DPN_B0_SAMPLE_CTRL(source_num);
1457+
1458+
dpn_config_off_target = CDNS_DPN_B0_CONFIG(target_num);
1459+
dpn_hctrl_off_target = CDNS_DPN_B0_HCTRL(target_num);
1460+
dpn_offsetctrl_off_target = CDNS_DPN_B0_OFFSET_CTRL(target_num);
1461+
dpn_samplectrl_off_target = CDNS_DPN_B0_SAMPLE_CTRL(target_num);
13331462
}
13341463

1335-
dpn_config = cdns_readl(cdns, dpn_config_off);
1336-
u32p_replace_bits(&dpn_config, t_params->blk_grp_ctrl, CDNS_DPN_CONFIG_BGC);
1337-
u32p_replace_bits(&dpn_config, t_params->blk_pkg_mode, CDNS_DPN_CONFIG_BPM);
1338-
cdns_writel(cdns, dpn_config_off, dpn_config);
1464+
dpn_config = cdns_readl(cdns, dpn_config_off_source);
1465+
if (!override) {
1466+
u32p_replace_bits(&dpn_config, t_params->blk_grp_ctrl, CDNS_DPN_CONFIG_BGC);
1467+
u32p_replace_bits(&dpn_config, t_params->blk_pkg_mode, CDNS_DPN_CONFIG_BPM);
1468+
}
1469+
cdns_writel(cdns, dpn_config_off_target, dpn_config);
13391470

1340-
u32p_replace_bits(&dpn_offsetctrl, t_params->offset1, CDNS_DPN_OFFSET_CTRL_1);
1341-
u32p_replace_bits(&dpn_offsetctrl, t_params->offset2, CDNS_DPN_OFFSET_CTRL_2);
1342-
cdns_writel(cdns, dpn_offsetctrl_off, dpn_offsetctrl);
1471+
if (!override) {
1472+
dpn_offsetctrl = 0;
1473+
u32p_replace_bits(&dpn_offsetctrl, t_params->offset1, CDNS_DPN_OFFSET_CTRL_1);
1474+
u32p_replace_bits(&dpn_offsetctrl, t_params->offset2, CDNS_DPN_OFFSET_CTRL_2);
1475+
} else {
1476+
dpn_offsetctrl = cdns_readl(cdns, dpn_offsetctrl_off_source);
1477+
}
1478+
cdns_writel(cdns, dpn_offsetctrl_off_target, dpn_offsetctrl);
13431479

1344-
u32p_replace_bits(&dpn_hctrl, t_params->hstart, CDNS_DPN_HCTRL_HSTART);
1345-
u32p_replace_bits(&dpn_hctrl, t_params->hstop, CDNS_DPN_HCTRL_HSTOP);
1346-
u32p_replace_bits(&dpn_hctrl, t_params->lane_ctrl, CDNS_DPN_HCTRL_LCTRL);
1480+
if (!override) {
1481+
dpn_hctrl = 0;
1482+
u32p_replace_bits(&dpn_hctrl, t_params->hstart, CDNS_DPN_HCTRL_HSTART);
1483+
u32p_replace_bits(&dpn_hctrl, t_params->hstop, CDNS_DPN_HCTRL_HSTOP);
1484+
u32p_replace_bits(&dpn_hctrl, t_params->lane_ctrl, CDNS_DPN_HCTRL_LCTRL);
1485+
} else {
1486+
dpn_hctrl = cdns_readl(cdns, dpn_hctrl_off_source);
1487+
}
1488+
cdns_writel(cdns, dpn_hctrl_off_target, dpn_hctrl);
13471489

1348-
cdns_writel(cdns, dpn_hctrl_off, dpn_hctrl);
1349-
cdns_writel(cdns, dpn_samplectrl_off, (t_params->sample_interval - 1));
1490+
if (!override)
1491+
dpn_samplectrl = t_params->sample_interval - 1;
1492+
else
1493+
dpn_samplectrl = cdns_readl(cdns, dpn_samplectrl_off_source);
1494+
cdns_writel(cdns, dpn_samplectrl_off_target, dpn_samplectrl);
13501495

13511496
return 0;
13521497
}
@@ -1397,6 +1542,8 @@ int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake)
13971542
struct sdw_slave *slave;
13981543
int ret;
13991544

1545+
sdw_cdns_check_self_clearing_bits(cdns, __func__, false, 0);
1546+
14001547
/* Check suspend status */
14011548
if (sdw_cdns_is_clock_stop(cdns)) {
14021549
dev_dbg(cdns->dev, "Clock is already stopped\n");

drivers/soundwire/cadence_master.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ struct sdw_cdns {
129129
struct sdw_cdns_streams pcm;
130130
struct sdw_cdns_streams pdm;
131131

132+
int pdi_loopback_source;
133+
int pdi_loopback_target;
134+
132135
void __iomem *registers;
133136

134137
bool link_up;
@@ -184,4 +187,8 @@ int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params);
184187

185188
int cdns_set_sdw_stream(struct snd_soc_dai *dai,
186189
void *stream, bool pcm, int direction);
190+
191+
void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string,
192+
bool initial_delay, int reset_iterations);
193+
187194
#endif /* __SDW_CADENCE_H */

0 commit comments

Comments
 (0)