2525#define SPX5_SERDES_25G_START 25
2626#define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START
2727
28+ #define LAN969X_SERDES_10G_CNT 10
29+
2830/* Optimal power settings from GUC */
2931#define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c
3032
@@ -36,6 +38,13 @@ const unsigned int sparx5_serdes_tsize[TSIZE_LAST] = {
3638 [TC_SD_LANE ] = 25 ,
3739};
3840
41+ const unsigned int lan969x_serdes_tsize [TSIZE_LAST ] = {
42+ [TC_SD10G_LANE ] = 10 ,
43+ [TC_SD_CMU ] = 6 ,
44+ [TC_SD_CMU_CFG ] = 6 ,
45+ [TC_SD_LANE ] = 10 ,
46+ };
47+
3948/* Pointer to the register target size table */
4049const unsigned int * tsize ;
4150
@@ -1096,6 +1105,24 @@ static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
10961105 return sparx5_serdes_cmu_map [mode ][sd_index ];
10971106}
10981107
1108+ /* Map of 6G/10G serdes mode and index to CMU index. */
1109+ static const int
1110+ lan969x_serdes_cmu_map [SPX5_SD10G28_CMU_MAX ][LAN969X_SERDES_10G_CNT ] = {
1111+ [SPX5_SD10G28_CMU_MAIN ] = { 2 , 2 , 2 , 2 , 2 ,
1112+ 2 , 2 , 2 , 5 , 5 },
1113+ [SPX5_SD10G28_CMU_AUX1 ] = { 0 , 0 , 3 , 3 , 3 ,
1114+ 3 , 3 , 3 , 3 , 3 },
1115+ [SPX5_SD10G28_CMU_AUX2 ] = { 1 , 1 , 1 , 1 , 4 ,
1116+ 4 , 4 , 4 , 4 , 4 },
1117+ [SPX5_SD10G28_CMU_NONE ] = { 1 , 1 , 1 , 1 , 4 ,
1118+ 4 , 4 , 4 , 4 , 4 },
1119+ };
1120+
1121+ static int lan969x_serdes_cmu_get (enum sparx5_10g28cmu_mode mode , int sd_index )
1122+ {
1123+ return lan969x_serdes_cmu_map [mode ][sd_index ];
1124+ }
1125+
10991126static void sparx5_serdes_cmu_power_off (struct sparx5_serdes_private * priv )
11001127{
11011128 void __iomem * cmu_inst , * cmu_cfg_inst ;
@@ -2184,6 +2211,10 @@ static int sparx5_serdes_clock_config(struct sparx5_serdes_macro *macro)
21842211{
21852212 struct sparx5_serdes_private * priv = macro -> priv ;
21862213
2214+ /* Clock is auto-detected in 100Base-FX mode on lan969x */
2215+ if (priv -> data -> type == SPX5_TARGET_LAN969X )
2216+ return 0 ;
2217+
21872218 if (macro -> serdesmode == SPX5_SD_MODE_100FX ) {
21882219 u32 freq = priv -> coreclock == 250000000 ? 2 :
21892220 priv -> coreclock == 500000000 ? 1 : 0 ;
@@ -2395,6 +2426,12 @@ static void sparx5_serdes_type_set(struct sparx5_serdes_macro *macro, int sidx)
23952426 }
23962427}
23972428
2429+ static void lan969x_serdes_type_set (struct sparx5_serdes_macro * macro , int sidx )
2430+ {
2431+ macro -> serdestype = SPX5_SDT_10G ;
2432+ macro -> stpidx = macro -> sidx ;
2433+ }
2434+
23982435static int sparx5_phy_create (struct sparx5_serdes_private * priv ,
23992436 int idx , struct phy * * phy )
24002437{
@@ -2519,6 +2556,41 @@ static struct sparx5_serdes_io_resource sparx5_serdes_iomap[] = {
25192556 { TARGET_SD_LANE_25G + 7 , 0x5c8000 }, /* 0x610dd0000: sd_lane_25g_32 */
25202557};
25212558
2559+ static const struct sparx5_serdes_io_resource lan969x_serdes_iomap [] = {
2560+ { TARGET_SD_CMU , 0x0 }, /* 0xe3410000 */
2561+ { TARGET_SD_CMU + 1 , 0x8000 }, /* 0xe3418000 */
2562+ { TARGET_SD_CMU + 2 , 0x10000 }, /* 0xe3420000 */
2563+ { TARGET_SD_CMU + 3 , 0x18000 }, /* 0xe3428000 */
2564+ { TARGET_SD_CMU + 4 , 0x20000 }, /* 0xe3430000 */
2565+ { TARGET_SD_CMU + 5 , 0x28000 }, /* 0xe3438000 */
2566+ { TARGET_SD_CMU_CFG , 0x30000 }, /* 0xe3440000 */
2567+ { TARGET_SD_CMU_CFG + 1 , 0x38000 }, /* 0xe3448000 */
2568+ { TARGET_SD_CMU_CFG + 2 , 0x40000 }, /* 0xe3450000 */
2569+ { TARGET_SD_CMU_CFG + 3 , 0x48000 }, /* 0xe3458000 */
2570+ { TARGET_SD_CMU_CFG + 4 , 0x50000 }, /* 0xe3460000 */
2571+ { TARGET_SD_CMU_CFG + 5 , 0x58000 }, /* 0xe3468000 */
2572+ { TARGET_SD10G_LANE , 0x60000 }, /* 0xe3470000 */
2573+ { TARGET_SD10G_LANE + 1 , 0x68000 }, /* 0xe3478000 */
2574+ { TARGET_SD10G_LANE + 2 , 0x70000 }, /* 0xe3480000 */
2575+ { TARGET_SD10G_LANE + 3 , 0x78000 }, /* 0xe3488000 */
2576+ { TARGET_SD10G_LANE + 4 , 0x80000 }, /* 0xe3490000 */
2577+ { TARGET_SD10G_LANE + 5 , 0x88000 }, /* 0xe3498000 */
2578+ { TARGET_SD10G_LANE + 6 , 0x90000 }, /* 0xe34a0000 */
2579+ { TARGET_SD10G_LANE + 7 , 0x98000 }, /* 0xe34a8000 */
2580+ { TARGET_SD10G_LANE + 8 , 0xa0000 }, /* 0xe34b0000 */
2581+ { TARGET_SD10G_LANE + 9 , 0xa8000 }, /* 0xe34b8000 */
2582+ { TARGET_SD_LANE , 0x100000 }, /* 0xe3510000 */
2583+ { TARGET_SD_LANE + 1 , 0x108000 }, /* 0xe3518000 */
2584+ { TARGET_SD_LANE + 2 , 0x110000 }, /* 0xe3520000 */
2585+ { TARGET_SD_LANE + 3 , 0x118000 }, /* 0xe3528000 */
2586+ { TARGET_SD_LANE + 4 , 0x120000 }, /* 0xe3530000 */
2587+ { TARGET_SD_LANE + 5 , 0x128000 }, /* 0xe3538000 */
2588+ { TARGET_SD_LANE + 6 , 0x130000 }, /* 0xe3540000 */
2589+ { TARGET_SD_LANE + 7 , 0x138000 }, /* 0xe3548000 */
2590+ { TARGET_SD_LANE + 8 , 0x140000 }, /* 0xe3550000 */
2591+ { TARGET_SD_LANE + 9 , 0x148000 }, /* 0xe3558000 */
2592+ };
2593+
25222594static const struct sparx5_serdes_match_data sparx5_desc = {
25232595 .type = SPX5_TARGET_SPARX5 ,
25242596 .iomap = sparx5_serdes_iomap ,
@@ -2534,6 +2606,21 @@ static const struct sparx5_serdes_match_data sparx5_desc = {
25342606 },
25352607};
25362608
2609+ static const struct sparx5_serdes_match_data lan969x_desc = {
2610+ .type = SPX5_TARGET_LAN969X ,
2611+ .iomap = lan969x_serdes_iomap ,
2612+ .iomap_size = ARRAY_SIZE (lan969x_serdes_iomap ),
2613+ .tsize = lan969x_serdes_tsize ,
2614+ .consts = {
2615+ .sd_max = 10 ,
2616+ .cmu_max = 6 ,
2617+ },
2618+ .ops = {
2619+ .serdes_type_set = & lan969x_serdes_type_set ,
2620+ .serdes_cmu_get = & lan969x_serdes_cmu_get ,
2621+ }
2622+ };
2623+
25372624/* Client lookup function, uses serdes index */
25382625static struct phy * sparx5_serdes_xlate (struct device * dev ,
25392626 const struct of_phandle_args * args )
@@ -2635,6 +2722,7 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
26352722
26362723static const struct of_device_id sparx5_serdes_match [] = {
26372724 { .compatible = "microchip,sparx5-serdes" , .data = & sparx5_desc },
2725+ { .compatible = "microchip,lan9691-serdes" , .data = & lan969x_desc },
26382726 { }
26392727};
26402728MODULE_DEVICE_TABLE (of , sparx5_serdes_match );
0 commit comments