@@ -351,6 +351,7 @@ struct cdns_torrent_phy {
351351 void __iomem * sd_base ; /* SD0801 registers base */
352352 u32 max_bit_rate ; /* Maximum link bit rate to use (in Mbps) */
353353 u32 dp_pll ;
354+ u32 protocol_bitmask ;
354355 struct reset_control * phy_rst ;
355356 struct reset_control * apb_rst ;
356357 struct device * dev ;
@@ -2473,156 +2474,206 @@ int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy)
24732474 enum cdns_torrent_phy_type phy_t1 , phy_t2 ;
24742475 const struct cdns_reg_pairs * reg_pairs ;
24752476 int i , j , node , mlane , num_lanes , ret ;
2477+ struct device * dev = cdns_phy -> dev ;
24762478 enum cdns_torrent_ssc_mode ssc ;
24772479 struct regmap * regmap ;
2478- u32 num_regs ;
2480+ u32 num_regs , num_protocols , protocol ;
24792481
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" );
24822486 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+ }
24832510
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+ }
24862514
24872515 /**
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.
24902528 */
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 ) {
24932538 /**
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.
24962541 * Get the array values as [phy_t2][phy_t1][ssc].
24972542 */
24982543 swap (phy_t1 , phy_t2 );
24992544 swap (ref_clk , ref_clk1 );
25002545 }
25012546
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 ;
25052550
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 ;
25232554
25242555 /**
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.
25272564 */
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+ }
25302584
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+ }
25352598
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 );
25472610 }
2548- }
25492611
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+ }
25622625
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+ }
25752638
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+ }
25882653
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+ }
26012667 }
2602- }
26032668
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 ;
26162673 }
2617- }
26182674
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 );
26232676 }
2624-
2625- reset_control_deassert (cdns_phy -> phys [node ].lnk_rst );
26262677 }
26272678
26282679 /* Take the PHY out of reset */
@@ -2826,6 +2877,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
28262877 dev_set_drvdata (dev , cdns_phy );
28272878 cdns_phy -> dev = dev ;
28282879 cdns_phy -> init_data = data ;
2880+ cdns_phy -> protocol_bitmask = 0 ;
28292881
28302882 cdns_phy -> sd_base = devm_platform_ioremap_resource (pdev , 0 );
28312883 if (IS_ERR (cdns_phy -> sd_base ))
@@ -3010,6 +3062,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
30103062 }
30113063
30123064 cdns_phy -> phys [node ].phy = gphy ;
3065+ cdns_phy -> protocol_bitmask |= BIT (cdns_phy -> phys [node ].phy_type );
30133066 phy_set_drvdata (gphy , & cdns_phy -> phys [node ]);
30143067
30153068 node ++ ;
0 commit comments