1010#include <linux/kernel.h>
1111#include <linux/module.h>
1212#include <linux/phy.h>
13+ #include <linux/of.h>
1314
1415#define PHY_ID_YT8511 0x0000010a
1516#define PHY_ID_YT8521 0x0000011a
187188 * 1b1 use inverted tx_clk_rgmii.
188189 */
189190#define YT8521_RC1R_TX_CLK_SEL_INVERTED BIT(14)
190- /* TX Gig-E Delay is bits 3:0, default 0x1
191- * TX Fast-E Delay is bits 7:4, default 0xf
192- * RX Delay is bits 13:10, default 0x0
193- * Delay = 150ps * N
194- * On = 2250ps, off = 0ps
195- */
196191#define YT8521_RC1R_RX_DELAY_MASK GENMASK(13, 10)
197- #define YT8521_RC1R_RX_DELAY_EN (0xF << 10)
198- #define YT8521_RC1R_RX_DELAY_DIS (0x0 << 10)
199192#define YT8521_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4)
200- #define YT8521_RC1R_FE_TX_DELAY_EN (0xF << 4)
201- #define YT8521_RC1R_FE_TX_DELAY_DIS (0x0 << 4)
202193#define YT8521_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0)
203- #define YT8521_RC1R_GE_TX_DELAY_EN (0xF << 0)
204- #define YT8521_RC1R_GE_TX_DELAY_DIS (0x0 << 0)
205194#define YT8521_RC1R_RGMII_0_000_NS 0
206195#define YT8521_RC1R_RGMII_0_150_NS 1
207196#define YT8521_RC1R_RGMII_0_300_NS 2
274263
275264/* Extended Register end */
276265
266+ #define YTPHY_DTS_OUTPUT_CLK_DIS 0
267+ #define YTPHY_DTS_OUTPUT_CLK_25M 25000000
268+ #define YTPHY_DTS_OUTPUT_CLK_125M 125000000
269+
277270struct yt8521_priv {
278271 /* combo_advertising is used for case of YT8521 in combo mode,
279272 * this means that yt8521 may work in utp or fiber mode which depends
@@ -640,6 +633,142 @@ static int yt8521_write_page(struct phy_device *phydev, int page)
640633 return ytphy_modify_ext (phydev , YT8521_REG_SPACE_SELECT_REG , mask , set );
641634};
642635
636+ /**
637+ * struct ytphy_cfg_reg_map - map a config value to a register value
638+ * @cfg: value in device configuration
639+ * @reg: value in the register
640+ */
641+ struct ytphy_cfg_reg_map {
642+ u32 cfg ;
643+ u32 reg ;
644+ };
645+
646+ static const struct ytphy_cfg_reg_map ytphy_rgmii_delays [] = {
647+ /* for tx delay / rx delay with YT8521_CCR_RXC_DLY_EN is not set. */
648+ { 0 , YT8521_RC1R_RGMII_0_000_NS },
649+ { 150 , YT8521_RC1R_RGMII_0_150_NS },
650+ { 300 , YT8521_RC1R_RGMII_0_300_NS },
651+ { 450 , YT8521_RC1R_RGMII_0_450_NS },
652+ { 600 , YT8521_RC1R_RGMII_0_600_NS },
653+ { 750 , YT8521_RC1R_RGMII_0_750_NS },
654+ { 900 , YT8521_RC1R_RGMII_0_900_NS },
655+ { 1050 , YT8521_RC1R_RGMII_1_050_NS },
656+ { 1200 , YT8521_RC1R_RGMII_1_200_NS },
657+ { 1350 , YT8521_RC1R_RGMII_1_350_NS },
658+ { 1500 , YT8521_RC1R_RGMII_1_500_NS },
659+ { 1650 , YT8521_RC1R_RGMII_1_650_NS },
660+ { 1800 , YT8521_RC1R_RGMII_1_800_NS },
661+ { 1950 , YT8521_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */
662+ { 2100 , YT8521_RC1R_RGMII_2_100_NS },
663+ { 2250 , YT8521_RC1R_RGMII_2_250_NS },
664+
665+ /* only for rx delay with YT8521_CCR_RXC_DLY_EN is set. */
666+ { 0 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_0_000_NS },
667+ { 150 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_0_150_NS },
668+ { 300 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_0_300_NS },
669+ { 450 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_0_450_NS },
670+ { 600 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_0_600_NS },
671+ { 750 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_0_750_NS },
672+ { 900 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_0_900_NS },
673+ { 1050 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_1_050_NS },
674+ { 1200 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_1_200_NS },
675+ { 1350 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_1_350_NS },
676+ { 1500 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_1_500_NS },
677+ { 1650 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_1_650_NS },
678+ { 1800 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_1_800_NS },
679+ { 1950 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_1_950_NS },
680+ { 2100 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_2_100_NS },
681+ { 2250 + YT8521_CCR_RXC_DLY_1_900_NS , YT8521_RC1R_RGMII_2_250_NS }
682+ };
683+
684+ static u32 ytphy_get_delay_reg_value (struct phy_device * phydev ,
685+ const char * prop_name ,
686+ const struct ytphy_cfg_reg_map * tbl ,
687+ int tb_size ,
688+ u16 * rxc_dly_en ,
689+ u32 dflt )
690+ {
691+ struct device_node * node = phydev -> mdio .dev .of_node ;
692+ int tb_size_half = tb_size / 2 ;
693+ u32 val ;
694+ int i ;
695+
696+ if (of_property_read_u32 (node , prop_name , & val ))
697+ goto err_dts_val ;
698+
699+ /* when rxc_dly_en is NULL, it is get the delay for tx, only half of
700+ * tb_size is valid.
701+ */
702+ if (!rxc_dly_en )
703+ tb_size = tb_size_half ;
704+
705+ for (i = 0 ; i < tb_size ; i ++ ) {
706+ if (tbl [i ].cfg == val ) {
707+ if (rxc_dly_en && i < tb_size_half )
708+ * rxc_dly_en = 0 ;
709+ return tbl [i ].reg ;
710+ }
711+ }
712+
713+ phydev_warn (phydev , "Unsupported value %d for %s using default (%u)\n" ,
714+ val , prop_name , dflt );
715+
716+ err_dts_val :
717+ /* when rxc_dly_en is not NULL, it is get the delay for rx.
718+ * The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps,
719+ * so YT8521_CCR_RXC_DLY_EN should not be set.
720+ */
721+ if (rxc_dly_en )
722+ * rxc_dly_en = 0 ;
723+
724+ return dflt ;
725+ }
726+
727+ static int ytphy_rgmii_clk_delay_config (struct phy_device * phydev )
728+ {
729+ int tb_size = ARRAY_SIZE (ytphy_rgmii_delays );
730+ u16 rxc_dly_en = YT8521_CCR_RXC_DLY_EN ;
731+ u32 rx_reg , tx_reg ;
732+ u16 mask , val = 0 ;
733+ int ret ;
734+
735+ rx_reg = ytphy_get_delay_reg_value (phydev , "rx-internal-delay-ps" ,
736+ ytphy_rgmii_delays , tb_size ,
737+ & rxc_dly_en ,
738+ YT8521_RC1R_RGMII_1_950_NS );
739+ tx_reg = ytphy_get_delay_reg_value (phydev , "tx-internal-delay-ps" ,
740+ ytphy_rgmii_delays , tb_size , NULL ,
741+ YT8521_RC1R_RGMII_1_950_NS );
742+
743+ switch (phydev -> interface ) {
744+ case PHY_INTERFACE_MODE_RGMII :
745+ rxc_dly_en = 0 ;
746+ break ;
747+ case PHY_INTERFACE_MODE_RGMII_RXID :
748+ val |= FIELD_PREP (YT8521_RC1R_RX_DELAY_MASK , rx_reg );
749+ break ;
750+ case PHY_INTERFACE_MODE_RGMII_TXID :
751+ rxc_dly_en = 0 ;
752+ val |= FIELD_PREP (YT8521_RC1R_GE_TX_DELAY_MASK , tx_reg );
753+ break ;
754+ case PHY_INTERFACE_MODE_RGMII_ID :
755+ val |= FIELD_PREP (YT8521_RC1R_RX_DELAY_MASK , rx_reg ) |
756+ FIELD_PREP (YT8521_RC1R_GE_TX_DELAY_MASK , tx_reg );
757+ break ;
758+ default : /* do not support other modes */
759+ return - EOPNOTSUPP ;
760+ }
761+
762+ ret = ytphy_modify_ext (phydev , YT8521_CHIP_CONFIG_REG ,
763+ YT8521_CCR_RXC_DLY_EN , rxc_dly_en );
764+ if (ret < 0 )
765+ return ret ;
766+
767+ /* Generally, it is not necessary to adjust YT8521_RC1R_FE_TX_DELAY */
768+ mask = YT8521_RC1R_RX_DELAY_MASK | YT8521_RC1R_GE_TX_DELAY_MASK ;
769+ return ytphy_modify_ext (phydev , YT8521_RGMII_CONFIG1_REG , mask , val );
770+ }
771+
643772/**
644773 * yt8521_probe() - read chip config then set suitable polling_mode
645774 * @phydev: a pointer to a &struct phy_device
@@ -648,9 +777,12 @@ static int yt8521_write_page(struct phy_device *phydev, int page)
648777 */
649778static int yt8521_probe (struct phy_device * phydev )
650779{
780+ struct device_node * node = phydev -> mdio .dev .of_node ;
651781 struct device * dev = & phydev -> mdio .dev ;
652782 struct yt8521_priv * priv ;
653783 int chip_config ;
784+ u16 mask , val ;
785+ u32 freq ;
654786 int ret ;
655787
656788 priv = devm_kzalloc (dev , sizeof (* priv ), GFP_KERNEL );
@@ -695,7 +827,45 @@ static int yt8521_probe(struct phy_device *phydev)
695827 return ret ;
696828 }
697829
698- return 0 ;
830+ if (of_property_read_u32 (node , "motorcomm,clk-out-frequency-hz" , & freq ))
831+ freq = YTPHY_DTS_OUTPUT_CLK_DIS ;
832+
833+ if (phydev -> drv -> phy_id == PHY_ID_YT8521 ) {
834+ switch (freq ) {
835+ case YTPHY_DTS_OUTPUT_CLK_DIS :
836+ mask = YT8521_SCR_SYNCE_ENABLE ;
837+ val = 0 ;
838+ break ;
839+ case YTPHY_DTS_OUTPUT_CLK_25M :
840+ mask = YT8521_SCR_SYNCE_ENABLE |
841+ YT8521_SCR_CLK_SRC_MASK |
842+ YT8521_SCR_CLK_FRE_SEL_125M ;
843+ val = YT8521_SCR_SYNCE_ENABLE |
844+ FIELD_PREP (YT8521_SCR_CLK_SRC_MASK ,
845+ YT8521_SCR_CLK_SRC_REF_25M );
846+ break ;
847+ case YTPHY_DTS_OUTPUT_CLK_125M :
848+ mask = YT8521_SCR_SYNCE_ENABLE |
849+ YT8521_SCR_CLK_SRC_MASK |
850+ YT8521_SCR_CLK_FRE_SEL_125M ;
851+ val = YT8521_SCR_SYNCE_ENABLE |
852+ YT8521_SCR_CLK_FRE_SEL_125M |
853+ FIELD_PREP (YT8521_SCR_CLK_SRC_MASK ,
854+ YT8521_SCR_CLK_SRC_PLL_125M );
855+ break ;
856+ default :
857+ phydev_warn (phydev , "Freq err:%u\n" , freq );
858+ return - EINVAL ;
859+ }
860+ } else if (phydev -> drv -> phy_id == PHY_ID_YT8531S ) {
861+ return 0 ;
862+ } else {
863+ phydev_warn (phydev , "PHY id err\n" );
864+ return - EINVAL ;
865+ }
866+
867+ return ytphy_modify_ext_with_lock (phydev , YTPHY_SYNCE_CFG_REG , mask ,
868+ val );
699869}
700870
701871/**
@@ -1180,61 +1350,36 @@ static int yt8521_resume(struct phy_device *phydev)
11801350 */
11811351static int yt8521_config_init (struct phy_device * phydev )
11821352{
1353+ struct device_node * node = phydev -> mdio .dev .of_node ;
11831354 int old_page ;
11841355 int ret = 0 ;
1185- u16 val ;
11861356
11871357 old_page = phy_select_page (phydev , YT8521_RSSR_UTP_SPACE );
11881358 if (old_page < 0 )
11891359 goto err_restore_page ;
11901360
1191- switch (phydev -> interface ) {
1192- case PHY_INTERFACE_MODE_RGMII :
1193- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS ;
1194- val |= YT8521_RC1R_RX_DELAY_DIS ;
1195- break ;
1196- case PHY_INTERFACE_MODE_RGMII_RXID :
1197- val = YT8521_RC1R_GE_TX_DELAY_DIS | YT8521_RC1R_FE_TX_DELAY_DIS ;
1198- val |= YT8521_RC1R_RX_DELAY_EN ;
1199- break ;
1200- case PHY_INTERFACE_MODE_RGMII_TXID :
1201- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN ;
1202- val |= YT8521_RC1R_RX_DELAY_DIS ;
1203- break ;
1204- case PHY_INTERFACE_MODE_RGMII_ID :
1205- val = YT8521_RC1R_GE_TX_DELAY_EN | YT8521_RC1R_FE_TX_DELAY_EN ;
1206- val |= YT8521_RC1R_RX_DELAY_EN ;
1207- break ;
1208- case PHY_INTERFACE_MODE_SGMII :
1209- break ;
1210- default : /* do not support other modes */
1211- ret = - EOPNOTSUPP ;
1212- goto err_restore_page ;
1213- }
1214-
12151361 /* set rgmii delay mode */
12161362 if (phydev -> interface != PHY_INTERFACE_MODE_SGMII ) {
1217- ret = ytphy_modify_ext (phydev , YT8521_RGMII_CONFIG1_REG ,
1218- (YT8521_RC1R_RX_DELAY_MASK |
1219- YT8521_RC1R_FE_TX_DELAY_MASK |
1220- YT8521_RC1R_GE_TX_DELAY_MASK ),
1221- val );
1363+ ret = ytphy_rgmii_clk_delay_config (phydev );
12221364 if (ret < 0 )
12231365 goto err_restore_page ;
12241366 }
12251367
1226- /* disable auto sleep */
1227- ret = ytphy_modify_ext (phydev , YT8521_EXTREG_SLEEP_CONTROL1_REG ,
1228- YT8521_ESC1R_SLEEP_SW , 0 );
1229- if (ret < 0 )
1230- goto err_restore_page ;
1231-
1232- /* enable RXC clock when no wire plug */
1233- ret = ytphy_modify_ext (phydev , YT8521_CLOCK_GATING_REG ,
1234- YT8521_CGR_RX_CLK_EN , 0 );
1235- if (ret < 0 )
1236- goto err_restore_page ;
1368+ if (of_property_read_bool (node , "motorcomm,auto-sleep-disabled" )) {
1369+ /* disable auto sleep */
1370+ ret = ytphy_modify_ext (phydev , YT8521_EXTREG_SLEEP_CONTROL1_REG ,
1371+ YT8521_ESC1R_SLEEP_SW , 0 );
1372+ if (ret < 0 )
1373+ goto err_restore_page ;
1374+ }
12371375
1376+ if (of_property_read_bool (node , "motorcomm,keep-pll-enabled" )) {
1377+ /* enable RXC clock when no wire plug */
1378+ ret = ytphy_modify_ext (phydev , YT8521_CLOCK_GATING_REG ,
1379+ YT8521_CGR_RX_CLK_EN , 0 );
1380+ if (ret < 0 )
1381+ goto err_restore_page ;
1382+ }
12381383err_restore_page :
12391384 return phy_restore_page (phydev , old_page , ret );
12401385}
0 commit comments