@@ -351,6 +351,7 @@ struct cdns_torrent_phy {
351
351
void __iomem * sd_base ; /* SD0801 registers base */
352
352
u32 max_bit_rate ; /* Maximum link bit rate to use (in Mbps) */
353
353
u32 dp_pll ;
354
+ u32 protocol_bitmask ;
354
355
struct reset_control * phy_rst ;
355
356
struct reset_control * apb_rst ;
356
357
struct device * dev ;
@@ -2473,156 +2474,206 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy)
2473
2474
enum cdns_torrent_phy_type phy_t1 , phy_t2 ;
2474
2475
const struct cdns_reg_pairs * reg_pairs ;
2475
2476
int i , j , node , mlane , num_lanes , ret ;
2477
+ struct device * dev = cdns_phy -> dev ;
2476
2478
enum cdns_torrent_ssc_mode ssc ;
2477
2479
struct regmap * regmap ;
2478
- u32 num_regs ;
2480
+ u32 num_regs , num_protocols , protocol ;
2479
2481
2480
- /* Maximum 2 links (subnodes) are supported */
2481
- if (cdns_phy -> nsubnodes != 2 )
2482
+ num_protocols = hweight32 (cdns_phy -> protocol_bitmask );
2483
+ /* Maximum 2 protocols are supported */
2484
+ if (num_protocols > 2 ) {
2485
+ dev_err (dev , "at most 2 protocols are supported\n" );
2482
2486
return - EINVAL ;
2487
+ }
2488
+
2489
+
2490
+ /**
2491
+ * Get PHY types directly from subnodes if only 2 subnodes exist.
2492
+ * It is possible for phy_t1 to be the same as phy_t2 for special
2493
+ * configurations such as PCIe Multilink.
2494
+ */
2495
+ if (cdns_phy -> nsubnodes == 2 ) {
2496
+ phy_t1 = cdns_phy -> phys [0 ].phy_type ;
2497
+ phy_t2 = cdns_phy -> phys [1 ].phy_type ;
2498
+ } else {
2499
+ /**
2500
+ * Both PHY types / protocols should be unique.
2501
+ * If they are the same, it should be expressed with either
2502
+ * a) Single-Link (1 Sub-node) - handled via PHY APIs
2503
+ * OR
2504
+ * b) Double-Link (2 Sub-nodes) - handled above
2505
+ */
2506
+ if (num_protocols != 2 ) {
2507
+ dev_err (dev , "incorrect representation of link\n" );
2508
+ return - EINVAL ;
2509
+ }
2483
2510
2484
- phy_t1 = cdns_phy -> phys [0 ].phy_type ;
2485
- phy_t2 = cdns_phy -> phys [1 ].phy_type ;
2511
+ phy_t1 = fns (cdns_phy -> protocol_bitmask , 0 );
2512
+ phy_t2 = fns (cdns_phy -> protocol_bitmask , 1 );
2513
+ }
2486
2514
2487
2515
/**
2488
- * First configure the PHY for first link with phy_t1. Get the array
2489
- * values as [phy_t1][phy_t2][ssc].
2516
+ * Configure all links with the protocol phy_t1 first followed by
2517
+ * configuring all links with the protocol phy_t2.
2518
+ *
2519
+ * When phy_t1 = phy_t2, it is a single protocol and configuration
2520
+ * is performed with a single iteration of the protocol and multiple
2521
+ * iterations over the sub-nodes (links).
2522
+ *
2523
+ * When phy_t1 != phy_t2, there are two protocols and configuration
2524
+ * is performed by iterating over all sub-nodes matching the first
2525
+ * protocol and configuring them first, followed by iterating over
2526
+ * all sub-nodes matching the second protocol and configuring them
2527
+ * next.
2490
2528
*/
2491
- for (node = 0 ; node < cdns_phy -> nsubnodes ; node ++ ) {
2492
- if (node == 1 ) {
2529
+ for (protocol = 0 ; protocol < num_protocols ; protocol ++ ) {
2530
+ /**
2531
+ * For the case where num_protocols is 1,
2532
+ * phy_t1 = phy_t2 and the swap is unnecessary.
2533
+ *
2534
+ * Swapping phy_t1 and phy_t2 is only required when the
2535
+ * number of protocols is 2 and there are 2 or more links.
2536
+ */
2537
+ if (protocol == 1 ) {
2493
2538
/**
2494
- * If first link with phy_t1 is configured, then
2495
- * configure the PHY for second link with phy_t2.
2539
+ * If first protocol with phy_t1 is configured, then
2540
+ * configure the PHY for second protocol with phy_t2.
2496
2541
* Get the array values as [phy_t2][phy_t1][ssc].
2497
2542
*/
2498
2543
swap (phy_t1 , phy_t2 );
2499
2544
swap (ref_clk , ref_clk1 );
2500
2545
}
2501
2546
2502
- mlane = cdns_phy -> phys [ node ]. mlane ;
2503
- ssc = cdns_phy -> phys [node ].ssc_mode ;
2504
- num_lanes = cdns_phy -> phys [ node ]. num_lanes ;
2547
+ for ( node = 0 ; node < cdns_phy -> nsubnodes ; node ++ ) {
2548
+ if ( cdns_phy -> phys [node ].phy_type != phy_t1 )
2549
+ continue ;
2505
2550
2506
- /**
2507
- * PHY configuration specific registers:
2508
- * link_cmn_vals depend on combination of PHY types being
2509
- * configured and are common for both PHY types, so array
2510
- * values should be same for [phy_t1][phy_t2][ssc] and
2511
- * [phy_t2][phy_t1][ssc].
2512
- * xcvr_diag_vals also depend on combination of PHY types
2513
- * being configured, but these can be different for particular
2514
- * PHY type and are per lane.
2515
- */
2516
- link_cmn_vals = cdns_torrent_get_tbl_vals (& init_data -> link_cmn_vals_tbl ,
2517
- CLK_ANY , CLK_ANY ,
2518
- phy_t1 , phy_t2 , ANY_SSC );
2519
- if (link_cmn_vals ) {
2520
- reg_pairs = link_cmn_vals -> reg_pairs ;
2521
- num_regs = link_cmn_vals -> num_regs ;
2522
- regmap = cdns_phy -> regmap_common_cdb ;
2551
+ mlane = cdns_phy -> phys [node ].mlane ;
2552
+ ssc = cdns_phy -> phys [node ].ssc_mode ;
2553
+ num_lanes = cdns_phy -> phys [node ].num_lanes ;
2523
2554
2524
2555
/**
2525
- * First array value in link_cmn_vals must be of
2526
- * PHY_PLL_CFG register
2556
+ * PHY configuration specific registers:
2557
+ * link_cmn_vals depend on combination of PHY types being
2558
+ * configured and are common for both PHY types, so array
2559
+ * values should be same for [phy_t1][phy_t2][ssc] and
2560
+ * [phy_t2][phy_t1][ssc].
2561
+ * xcvr_diag_vals also depend on combination of PHY types
2562
+ * being configured, but these can be different for particular
2563
+ * PHY type and are per lane.
2527
2564
*/
2528
- regmap_field_write (cdns_phy -> phy_pll_cfg ,
2529
- reg_pairs [0 ].val );
2565
+ link_cmn_vals = cdns_torrent_get_tbl_vals (& init_data -> link_cmn_vals_tbl ,
2566
+ CLK_ANY , CLK_ANY ,
2567
+ phy_t1 , phy_t2 , ANY_SSC );
2568
+ if (link_cmn_vals ) {
2569
+ reg_pairs = link_cmn_vals -> reg_pairs ;
2570
+ num_regs = link_cmn_vals -> num_regs ;
2571
+ regmap = cdns_phy -> regmap_common_cdb ;
2572
+
2573
+ /**
2574
+ * First array value in link_cmn_vals must be of
2575
+ * PHY_PLL_CFG register
2576
+ */
2577
+ regmap_field_write (cdns_phy -> phy_pll_cfg ,
2578
+ reg_pairs [0 ].val );
2579
+
2580
+ for (i = 1 ; i < num_regs ; i ++ )
2581
+ regmap_write (regmap , reg_pairs [i ].off ,
2582
+ reg_pairs [i ].val );
2583
+ }
2530
2584
2531
- for (i = 1 ; i < num_regs ; i ++ )
2532
- regmap_write (regmap , reg_pairs [i ].off ,
2533
- reg_pairs [i ].val );
2534
- }
2585
+ xcvr_diag_vals = cdns_torrent_get_tbl_vals (& init_data -> xcvr_diag_vals_tbl ,
2586
+ CLK_ANY , CLK_ANY ,
2587
+ phy_t1 , phy_t2 , ANY_SSC );
2588
+ if (xcvr_diag_vals ) {
2589
+ reg_pairs = xcvr_diag_vals -> reg_pairs ;
2590
+ num_regs = xcvr_diag_vals -> num_regs ;
2591
+ for (i = 0 ; i < num_lanes ; i ++ ) {
2592
+ regmap = cdns_phy -> regmap_tx_lane_cdb [i + mlane ];
2593
+ for (j = 0 ; j < num_regs ; j ++ )
2594
+ regmap_write (regmap , reg_pairs [j ].off ,
2595
+ reg_pairs [j ].val );
2596
+ }
2597
+ }
2535
2598
2536
- xcvr_diag_vals = cdns_torrent_get_tbl_vals ( & init_data -> xcvr_diag_vals_tbl ,
2537
- CLK_ANY , CLK_ANY ,
2538
- phy_t1 , phy_t2 , ANY_SSC );
2539
- if ( xcvr_diag_vals ) {
2540
- reg_pairs = xcvr_diag_vals -> reg_pairs ;
2541
- num_regs = xcvr_diag_vals -> num_regs ;
2542
- for ( i = 0 ; i < num_lanes ; i ++ ) {
2543
- regmap = cdns_phy -> regmap_tx_lane_cdb [ i + mlane ] ;
2544
- for (j = 0 ; j < num_regs ; j ++ )
2545
- regmap_write (regmap , reg_pairs [j ].off ,
2546
- reg_pairs [j ].val );
2599
+ /* PHY PCS common registers configurations */
2600
+ pcs_cmn_vals = cdns_torrent_get_tbl_vals ( & init_data -> pcs_cmn_vals_tbl ,
2601
+ CLK_ANY , CLK_ANY ,
2602
+ phy_t1 , phy_t2 , ANY_SSC );
2603
+ if ( pcs_cmn_vals ) {
2604
+ reg_pairs = pcs_cmn_vals -> reg_pairs ;
2605
+ num_regs = pcs_cmn_vals -> num_regs ;
2606
+ regmap = cdns_phy -> regmap_phy_pcs_common_cdb ;
2607
+ for (i = 0 ; i < num_regs ; i ++ )
2608
+ regmap_write (regmap , reg_pairs [i ].off ,
2609
+ reg_pairs [i ].val );
2547
2610
}
2548
- }
2549
2611
2550
- /* PHY PCS common registers configurations */
2551
- pcs_cmn_vals = cdns_torrent_get_tbl_vals (& init_data -> pcs_cmn_vals_tbl ,
2552
- CLK_ANY , CLK_ANY ,
2553
- phy_t1 , phy_t2 , ANY_SSC );
2554
- if (pcs_cmn_vals ) {
2555
- reg_pairs = pcs_cmn_vals -> reg_pairs ;
2556
- num_regs = pcs_cmn_vals -> num_regs ;
2557
- regmap = cdns_phy -> regmap_phy_pcs_common_cdb ;
2558
- for (i = 0 ; i < num_regs ; i ++ )
2559
- regmap_write (regmap , reg_pairs [i ].off ,
2560
- reg_pairs [i ].val );
2561
- }
2612
+ /* PHY PMA common registers configurations */
2613
+ phy_pma_cmn_vals =
2614
+ cdns_torrent_get_tbl_vals (& init_data -> phy_pma_cmn_vals_tbl ,
2615
+ CLK_ANY , CLK_ANY , phy_t1 , phy_t2 ,
2616
+ ANY_SSC );
2617
+ if (phy_pma_cmn_vals ) {
2618
+ reg_pairs = phy_pma_cmn_vals -> reg_pairs ;
2619
+ num_regs = phy_pma_cmn_vals -> num_regs ;
2620
+ regmap = cdns_phy -> regmap_phy_pma_common_cdb ;
2621
+ for (i = 0 ; i < num_regs ; i ++ )
2622
+ regmap_write (regmap , reg_pairs [i ].off ,
2623
+ reg_pairs [i ].val );
2624
+ }
2562
2625
2563
- /* PHY PMA common registers configurations */
2564
- phy_pma_cmn_vals = cdns_torrent_get_tbl_vals (& init_data -> phy_pma_cmn_vals_tbl ,
2565
- CLK_ANY , CLK_ANY ,
2566
- phy_t1 , phy_t2 , ANY_SSC );
2567
- if (phy_pma_cmn_vals ) {
2568
- reg_pairs = phy_pma_cmn_vals -> reg_pairs ;
2569
- num_regs = phy_pma_cmn_vals -> num_regs ;
2570
- regmap = cdns_phy -> regmap_phy_pma_common_cdb ;
2571
- for (i = 0 ; i < num_regs ; i ++ )
2572
- regmap_write (regmap , reg_pairs [i ].off ,
2573
- reg_pairs [i ].val );
2574
- }
2626
+ /* PMA common registers configurations */
2627
+ cmn_vals = cdns_torrent_get_tbl_vals (& init_data -> cmn_vals_tbl ,
2628
+ ref_clk , ref_clk1 ,
2629
+ phy_t1 , phy_t2 , ssc );
2630
+ if (cmn_vals ) {
2631
+ reg_pairs = cmn_vals -> reg_pairs ;
2632
+ num_regs = cmn_vals -> num_regs ;
2633
+ regmap = cdns_phy -> regmap_common_cdb ;
2634
+ for (i = 0 ; i < num_regs ; i ++ )
2635
+ regmap_write (regmap , reg_pairs [i ].off ,
2636
+ reg_pairs [i ].val );
2637
+ }
2575
2638
2576
- /* PMA common registers configurations */
2577
- cmn_vals = cdns_torrent_get_tbl_vals (& init_data -> cmn_vals_tbl ,
2578
- ref_clk , ref_clk1 ,
2579
- phy_t1 , phy_t2 , ssc );
2580
- if (cmn_vals ) {
2581
- reg_pairs = cmn_vals -> reg_pairs ;
2582
- num_regs = cmn_vals -> num_regs ;
2583
- regmap = cdns_phy -> regmap_common_cdb ;
2584
- for (i = 0 ; i < num_regs ; i ++ )
2585
- regmap_write (regmap , reg_pairs [i ].off ,
2586
- reg_pairs [i ].val );
2587
- }
2639
+ /* PMA TX lane registers configurations */
2640
+ tx_ln_vals = cdns_torrent_get_tbl_vals (& init_data -> tx_ln_vals_tbl ,
2641
+ ref_clk , ref_clk1 ,
2642
+ phy_t1 , phy_t2 , ssc );
2643
+ if (tx_ln_vals ) {
2644
+ reg_pairs = tx_ln_vals -> reg_pairs ;
2645
+ num_regs = tx_ln_vals -> num_regs ;
2646
+ for (i = 0 ; i < num_lanes ; i ++ ) {
2647
+ regmap = cdns_phy -> regmap_tx_lane_cdb [i + mlane ];
2648
+ for (j = 0 ; j < num_regs ; j ++ )
2649
+ regmap_write (regmap , reg_pairs [j ].off ,
2650
+ reg_pairs [j ].val );
2651
+ }
2652
+ }
2588
2653
2589
- /* PMA TX lane registers configurations */
2590
- tx_ln_vals = cdns_torrent_get_tbl_vals (& init_data -> tx_ln_vals_tbl ,
2591
- ref_clk , ref_clk1 ,
2592
- phy_t1 , phy_t2 , ssc );
2593
- if (tx_ln_vals ) {
2594
- reg_pairs = tx_ln_vals -> reg_pairs ;
2595
- num_regs = tx_ln_vals -> num_regs ;
2596
- for (i = 0 ; i < num_lanes ; i ++ ) {
2597
- regmap = cdns_phy -> regmap_tx_lane_cdb [i + mlane ];
2598
- for (j = 0 ; j < num_regs ; j ++ )
2599
- regmap_write (regmap , reg_pairs [j ].off ,
2600
- reg_pairs [j ].val );
2654
+ /* PMA RX lane registers configurations */
2655
+ rx_ln_vals = cdns_torrent_get_tbl_vals (& init_data -> rx_ln_vals_tbl ,
2656
+ ref_clk , ref_clk1 ,
2657
+ phy_t1 , phy_t2 , ssc );
2658
+ if (rx_ln_vals ) {
2659
+ reg_pairs = rx_ln_vals -> reg_pairs ;
2660
+ num_regs = rx_ln_vals -> num_regs ;
2661
+ for (i = 0 ; i < num_lanes ; i ++ ) {
2662
+ regmap = cdns_phy -> regmap_rx_lane_cdb [i + mlane ];
2663
+ for (j = 0 ; j < num_regs ; j ++ )
2664
+ regmap_write (regmap , reg_pairs [j ].off ,
2665
+ reg_pairs [j ].val );
2666
+ }
2601
2667
}
2602
- }
2603
2668
2604
- /* PMA RX lane registers configurations */
2605
- rx_ln_vals = cdns_torrent_get_tbl_vals (& init_data -> rx_ln_vals_tbl ,
2606
- ref_clk , ref_clk1 ,
2607
- phy_t1 , phy_t2 , ssc );
2608
- if (rx_ln_vals ) {
2609
- reg_pairs = rx_ln_vals -> reg_pairs ;
2610
- num_regs = rx_ln_vals -> num_regs ;
2611
- for (i = 0 ; i < num_lanes ; i ++ ) {
2612
- regmap = cdns_phy -> regmap_rx_lane_cdb [i + mlane ];
2613
- for (j = 0 ; j < num_regs ; j ++ )
2614
- regmap_write (regmap , reg_pairs [j ].off ,
2615
- reg_pairs [j ].val );
2669
+ if (phy_t1 == TYPE_DP ) {
2670
+ ret = cdns_torrent_dp_get_pll (cdns_phy , phy_t2 );
2671
+ if (ret )
2672
+ return ret ;
2616
2673
}
2617
- }
2618
2674
2619
- if (phy_t1 == TYPE_DP ) {
2620
- ret = cdns_torrent_dp_get_pll (cdns_phy , phy_t2 );
2621
- if (ret )
2622
- return ret ;
2675
+ reset_control_deassert (cdns_phy -> phys [node ].lnk_rst );
2623
2676
}
2624
-
2625
- reset_control_deassert (cdns_phy -> phys [node ].lnk_rst );
2626
2677
}
2627
2678
2628
2679
/* Take the PHY out of reset */
@@ -2826,6 +2877,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
2826
2877
dev_set_drvdata (dev , cdns_phy );
2827
2878
cdns_phy -> dev = dev ;
2828
2879
cdns_phy -> init_data = data ;
2880
+ cdns_phy -> protocol_bitmask = 0 ;
2829
2881
2830
2882
cdns_phy -> sd_base = devm_platform_ioremap_resource (pdev , 0 );
2831
2883
if (IS_ERR (cdns_phy -> sd_base ))
@@ -3010,6 +3062,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
3010
3062
}
3011
3063
3012
3064
cdns_phy -> phys [node ].phy = gphy ;
3065
+ cdns_phy -> protocol_bitmask |= BIT (cdns_phy -> phys [node ].phy_type );
3013
3066
phy_set_drvdata (gphy , & cdns_phy -> phys [node ]);
3014
3067
3015
3068
node ++ ;
0 commit comments