6868 */
6969#define PRG_ETH0_ADJ_SKEW GENMASK(24, 20)
7070
71+ #define PRG_ETH1 0x4
72+
73+ /* Defined for adding a delay to the input RX_CLK for better timing.
74+ * Each step is 200ps. These bits are used with external RGMII PHYs
75+ * because RGMII RX only has the small window. cfg_rxclk_dly can
76+ * adjust the window between RX_CLK and RX_DATA and improve the stability
77+ * of "rx data valid".
78+ */
79+ #define PRG_ETH1_CFG_RXCLK_DLY GENMASK(19, 16)
80+
7181struct meson8b_dwmac ;
7282
7383struct meson8b_dwmac_data {
7484 int (* set_phy_mode )(struct meson8b_dwmac * dwmac );
85+ bool has_prg_eth1_rgmii_rx_delay ;
7586};
7687
7788struct meson8b_dwmac {
@@ -270,30 +281,35 @@ static int meson8b_devm_clk_prepare_enable(struct meson8b_dwmac *dwmac,
270281
271282static int meson8b_init_rgmii_delays (struct meson8b_dwmac * dwmac )
272283{
273- u32 tx_dly_config , rx_dly_config , delay_config ;
284+ u32 tx_dly_config , rx_adj_config , cfg_rxclk_dly , delay_config ;
274285 int ret ;
275286
287+ rx_adj_config = 0 ;
288+ cfg_rxclk_dly = 0 ;
276289 tx_dly_config = FIELD_PREP (PRG_ETH0_TXDLY_MASK ,
277290 dwmac -> tx_delay_ns >> 1 );
278291
279- if (dwmac -> rx_delay_ps == 2000 )
280- rx_dly_config = PRG_ETH0_ADJ_ENABLE | PRG_ETH0_ADJ_SETUP ;
281- else
282- rx_dly_config = 0 ;
292+ if (dwmac -> data -> has_prg_eth1_rgmii_rx_delay )
293+ cfg_rxclk_dly = FIELD_PREP (PRG_ETH1_CFG_RXCLK_DLY ,
294+ dwmac -> rx_delay_ps / 200 );
295+ else if (dwmac -> rx_delay_ps == 2000 )
296+ rx_adj_config = PRG_ETH0_ADJ_ENABLE | PRG_ETH0_ADJ_SETUP ;
283297
284298 switch (dwmac -> phy_mode ) {
285299 case PHY_INTERFACE_MODE_RGMII :
286- delay_config = tx_dly_config | rx_dly_config ;
300+ delay_config = tx_dly_config | rx_adj_config ;
287301 break ;
288302 case PHY_INTERFACE_MODE_RGMII_RXID :
289303 delay_config = tx_dly_config ;
304+ cfg_rxclk_dly = 0 ;
290305 break ;
291306 case PHY_INTERFACE_MODE_RGMII_TXID :
292- delay_config = rx_dly_config ;
307+ delay_config = rx_adj_config ;
293308 break ;
294309 case PHY_INTERFACE_MODE_RGMII_ID :
295310 case PHY_INTERFACE_MODE_RMII :
296311 delay_config = 0 ;
312+ cfg_rxclk_dly = 0 ;
297313 break ;
298314 default :
299315 dev_err (dwmac -> dev , "unsupported phy-mode %s\n" ,
@@ -323,6 +339,9 @@ static int meson8b_init_rgmii_delays(struct meson8b_dwmac *dwmac)
323339 PRG_ETH0_ADJ_DELAY | PRG_ETH0_ADJ_SKEW ,
324340 delay_config );
325341
342+ meson8b_dwmac_mask_bits (dwmac , PRG_ETH1 , PRG_ETH1_CFG_RXCLK_DLY ,
343+ cfg_rxclk_dly );
344+
326345 return 0 ;
327346}
328347
@@ -423,11 +442,20 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
423442 dwmac -> rx_delay_ps *= 1000 ;
424443 }
425444
426- if (dwmac -> rx_delay_ps != 0 && dwmac -> rx_delay_ps != 2000 ) {
427- dev_err (& pdev -> dev ,
428- "The only allowed RX delays values are: 0ps, 2000ps" );
429- ret = - EINVAL ;
430- goto err_remove_config_dt ;
445+ if (dwmac -> data -> has_prg_eth1_rgmii_rx_delay ) {
446+ if (dwmac -> rx_delay_ps != 0 && dwmac -> rx_delay_ps != 2000 ) {
447+ dev_err (dwmac -> dev ,
448+ "The only allowed RGMII RX delays values are: 0ps, 2000ps" );
449+ ret = - EINVAL ;
450+ goto err_remove_config_dt ;
451+ }
452+ } else {
453+ if (dwmac -> rx_delay_ps > 3000 || dwmac -> rx_delay_ps % 200 ) {
454+ dev_err (dwmac -> dev ,
455+ "The RGMII RX delay range is 0..3000ps in 200ps steps" );
456+ ret = - EINVAL ;
457+ goto err_remove_config_dt ;
458+ }
431459 }
432460
433461 dwmac -> timing_adj_clk = devm_clk_get_optional (dwmac -> dev ,
@@ -469,10 +497,17 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
469497
470498static const struct meson8b_dwmac_data meson8b_dwmac_data = {
471499 .set_phy_mode = meson8b_set_phy_mode ,
500+ .has_prg_eth1_rgmii_rx_delay = false,
472501};
473502
474503static const struct meson8b_dwmac_data meson_axg_dwmac_data = {
475504 .set_phy_mode = meson_axg_set_phy_mode ,
505+ .has_prg_eth1_rgmii_rx_delay = false,
506+ };
507+
508+ static const struct meson8b_dwmac_data meson_g12a_dwmac_data = {
509+ .set_phy_mode = meson_axg_set_phy_mode ,
510+ .has_prg_eth1_rgmii_rx_delay = true,
476511};
477512
478513static const struct of_device_id meson8b_dwmac_match [] = {
@@ -494,7 +529,7 @@ static const struct of_device_id meson8b_dwmac_match[] = {
494529 },
495530 {
496531 .compatible = "amlogic,meson-g12a-dwmac" ,
497- .data = & meson_axg_dwmac_data ,
532+ .data = & meson_g12a_dwmac_data ,
498533 },
499534 { }
500535};
0 commit comments