@@ -450,6 +450,40 @@ static int cdns_parity_error_injection(void *data, u64 value)
450
450
DEFINE_DEBUGFS_ATTRIBUTE (cdns_parity_error_fops , NULL ,
451
451
cdns_parity_error_injection , "%llu\n" );
452
452
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
+
453
487
/**
454
488
* sdw_cdns_debugfs_init() - Cadence debugfs init
455
489
* @cdns: Cadence instance
@@ -464,6 +498,16 @@ void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root)
464
498
465
499
debugfs_create_file ("cdns-parity-error-injection" , 0200 , root , cdns ,
466
500
& 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
+
467
511
}
468
512
EXPORT_SYMBOL_GPL (sdw_cdns_debugfs_init );
469
513
@@ -822,7 +866,6 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
822
866
{
823
867
struct sdw_cdns * cdns = dev_id ;
824
868
u32 int_status ;
825
- int ret = IRQ_HANDLED ;
826
869
827
870
/* Check if the link is up */
828
871
if (!cdns -> link_up )
@@ -900,7 +943,7 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
900
943
}
901
944
902
945
cdns_writel (cdns , CDNS_MCP_INTSTAT , int_status );
903
- return ret ;
946
+ return IRQ_HANDLED ;
904
947
}
905
948
EXPORT_SYMBOL (sdw_cdns_irq );
906
949
@@ -936,6 +979,49 @@ static void cdns_update_slave_status_work(struct work_struct *work)
936
979
937
980
}
938
981
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
+
939
1025
/*
940
1026
* init routines
941
1027
*/
@@ -946,10 +1032,7 @@ static void cdns_update_slave_status_work(struct work_struct *work)
946
1032
*/
947
1033
int sdw_cdns_exit_reset (struct sdw_cdns * cdns )
948
1034
{
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 */
953
1036
954
1037
/* use hardware generated reset */
955
1038
cdns_updatel (cdns , CDNS_MCP_CONTROL ,
@@ -1213,6 +1296,8 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
1213
1296
1214
1297
cdns_init_clock_ctrl (cdns );
1215
1298
1299
+ sdw_cdns_check_self_clearing_bits (cdns , __func__ , false, 0 );
1300
+
1216
1301
/* reset msg_count to default value of FIFOLEVEL */
1217
1302
cdns -> msg_count = cdns_readl (cdns , CDNS_MCP_FIFOLEVEL );
1218
1303
@@ -1286,20 +1371,37 @@ static int cdns_port_params(struct sdw_bus *bus,
1286
1371
struct sdw_port_params * p_params , unsigned int bank )
1287
1372
{
1288
1373
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
+ }
1290
1386
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
+ }
1295
1394
1296
- dpn_config = cdns_readl (cdns , dpn_config_off );
1395
+ dpn_config = cdns_readl (cdns , dpn_config_off_source );
1297
1396
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
+ }
1301
1403
1302
- cdns_writel (cdns , dpn_config_off , dpn_config );
1404
+ cdns_writel (cdns , dpn_config_off_target , dpn_config );
1303
1405
1304
1406
return 0 ;
1305
1407
}
@@ -1309,44 +1411,87 @@ static int cdns_transport_params(struct sdw_bus *bus,
1309
1411
enum sdw_reg_bank bank )
1310
1412
{
1311
1413
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
+ }
1317
1435
1318
1436
/*
1319
1437
* Note: Only full data port is supported on the Master side for
1320
1438
* both PCM and PDM ports.
1321
1439
*/
1322
1440
1323
1441
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
+
1328
1452
} 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 );
1333
1462
}
1334
1463
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 );
1339
1470
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 );
1343
1479
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 );
1347
1489
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 );
1350
1495
1351
1496
return 0 ;
1352
1497
}
@@ -1397,6 +1542,8 @@ int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake)
1397
1542
struct sdw_slave * slave ;
1398
1543
int ret ;
1399
1544
1545
+ sdw_cdns_check_self_clearing_bits (cdns , __func__ , false, 0 );
1546
+
1400
1547
/* Check suspend status */
1401
1548
if (sdw_cdns_is_clock_stop (cdns )) {
1402
1549
dev_dbg (cdns -> dev , "Clock is already stopped\n" );
0 commit comments