@@ -393,6 +393,74 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral,
393393 return 0 ;
394394}
395395
396+ static int cs35l63_sdw_kick_divider (struct cs35l56_private * cs35l56 ,
397+ struct sdw_slave * peripheral )
398+ {
399+ unsigned int curr_scale_reg , next_scale_reg ;
400+ int curr_scale , next_scale , ret ;
401+
402+ if (!cs35l56 -> base .init_done )
403+ return 0 ;
404+
405+ if (peripheral -> bus -> params .curr_bank ) {
406+ curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1 ;
407+ next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0 ;
408+ } else {
409+ curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0 ;
410+ next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1 ;
411+ }
412+
413+ /*
414+ * Current clock scale value must be different to new value.
415+ * Modify current to guarantee this. If next still has the dummy
416+ * value we wrote when it was current, the core code has not set
417+ * a new scale so restore its original good value
418+ */
419+ curr_scale = sdw_read_no_pm (peripheral , curr_scale_reg );
420+ if (curr_scale < 0 ) {
421+ dev_err (cs35l56 -> base .dev , "Failed to read current clock scale: %d\n" , curr_scale );
422+ return curr_scale ;
423+ }
424+
425+ next_scale = sdw_read_no_pm (peripheral , next_scale_reg );
426+ if (next_scale < 0 ) {
427+ dev_err (cs35l56 -> base .dev , "Failed to read next clock scale: %d\n" , next_scale );
428+ return next_scale ;
429+ }
430+
431+ if (next_scale == CS35L56_SDW_INVALID_BUS_SCALE ) {
432+ next_scale = cs35l56 -> old_sdw_clock_scale ;
433+ ret = sdw_write_no_pm (peripheral , next_scale_reg , next_scale );
434+ if (ret < 0 ) {
435+ dev_err (cs35l56 -> base .dev , "Failed to modify current clock scale: %d\n" ,
436+ ret );
437+ return ret ;
438+ }
439+ }
440+
441+ cs35l56 -> old_sdw_clock_scale = curr_scale ;
442+ ret = sdw_write_no_pm (peripheral , curr_scale_reg , CS35L56_SDW_INVALID_BUS_SCALE );
443+ if (ret < 0 ) {
444+ dev_err (cs35l56 -> base .dev , "Failed to modify current clock scale: %d\n" , ret );
445+ return ret ;
446+ }
447+
448+ dev_dbg (cs35l56 -> base .dev , "Next bus scale: %#x\n" , next_scale );
449+
450+ return 0 ;
451+ }
452+
453+ static int cs35l56_sdw_bus_config (struct sdw_slave * peripheral ,
454+ struct sdw_bus_params * params )
455+ {
456+ struct cs35l56_private * cs35l56 = dev_get_drvdata (& peripheral -> dev );
457+
458+ if ((cs35l56 -> base .type == 0x63 ) && (cs35l56 -> base .rev < 0xa1 ))
459+ return cs35l63_sdw_kick_divider (cs35l56 , peripheral );
460+
461+ return 0 ;
462+ }
463+
396464static int __maybe_unused cs35l56_sdw_clk_stop (struct sdw_slave * peripheral ,
397465 enum sdw_clk_stop_mode mode ,
398466 enum sdw_clk_stop_type type )
@@ -408,6 +476,7 @@ static const struct sdw_slave_ops cs35l56_sdw_ops = {
408476 .read_prop = cs35l56_sdw_read_prop ,
409477 .interrupt_callback = cs35l56_sdw_interrupt ,
410478 .update_status = cs35l56_sdw_update_status ,
479+ .bus_config = cs35l56_sdw_bus_config ,
411480#ifdef DEBUG
412481 .clk_stop = cs35l56_sdw_clk_stop ,
413482#endif
@@ -509,6 +578,7 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi
509578{
510579 struct device * dev = & peripheral -> dev ;
511580 struct cs35l56_private * cs35l56 ;
581+ const struct regmap_config * regmap_config ;
512582 int ret ;
513583
514584 cs35l56 = devm_kzalloc (dev , sizeof (* cs35l56 ), GFP_KERNEL );
@@ -521,8 +591,22 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi
521591
522592 dev_set_drvdata (dev , cs35l56 );
523593
594+ switch ((unsigned int )id -> driver_data ) {
595+ case 0x3556 :
596+ case 0x3557 :
597+ regmap_config = & cs35l56_regmap_sdw ;
598+ cs35l56 -> base .fw_reg = & cs35l56_fw_reg ;
599+ break ;
600+ case 0x3563 :
601+ regmap_config = & cs35l63_regmap_sdw ;
602+ cs35l56 -> base .fw_reg = & cs35l63_fw_reg ;
603+ break ;
604+ default :
605+ return - ENODEV ;
606+ }
607+
524608 cs35l56 -> base .regmap = devm_regmap_init (dev , & cs35l56_regmap_bus_sdw ,
525- peripheral , & cs35l56_regmap_sdw );
609+ peripheral , regmap_config );
526610 if (IS_ERR (cs35l56 -> base .regmap )) {
527611 ret = PTR_ERR (cs35l56 -> base .regmap );
528612 return dev_err_probe (dev , ret , "Failed to allocate register map\n" );
@@ -562,8 +646,9 @@ static const struct dev_pm_ops cs35l56_sdw_pm = {
562646};
563647
564648static const struct sdw_device_id cs35l56_sdw_id [] = {
565- SDW_SLAVE_ENTRY (0x01FA , 0x3556 , 0 ),
566- SDW_SLAVE_ENTRY (0x01FA , 0x3557 , 0 ),
649+ SDW_SLAVE_ENTRY (0x01FA , 0x3556 , 0x3556 ),
650+ SDW_SLAVE_ENTRY (0x01FA , 0x3557 , 0x3557 ),
651+ SDW_SLAVE_ENTRY (0x01FA , 0x3563 , 0x3563 ),
567652 {},
568653};
569654MODULE_DEVICE_TABLE (sdw , cs35l56_sdw_id );
0 commit comments