19
19
* ksz9477
20
20
*/
21
21
22
+ #include <linux/bitfield.h>
22
23
#include <linux/kernel.h>
23
24
#include <linux/module.h>
24
25
#include <linux/phy.h>
@@ -490,9 +491,50 @@ static int ksz9021_config_init(struct phy_device *phydev)
490
491
491
492
/* MMD Address 0x2 */
492
493
#define MII_KSZ9031RN_CONTROL_PAD_SKEW 4
494
+ #define MII_KSZ9031RN_RX_CTL_M GENMASK(7, 4)
495
+ #define MII_KSZ9031RN_TX_CTL_M GENMASK(3, 0)
496
+
493
497
#define MII_KSZ9031RN_RX_DATA_PAD_SKEW 5
498
+ #define MII_KSZ9031RN_RXD3 GENMASK(15, 12)
499
+ #define MII_KSZ9031RN_RXD2 GENMASK(11, 8)
500
+ #define MII_KSZ9031RN_RXD1 GENMASK(7, 4)
501
+ #define MII_KSZ9031RN_RXD0 GENMASK(3, 0)
502
+
494
503
#define MII_KSZ9031RN_TX_DATA_PAD_SKEW 6
504
+ #define MII_KSZ9031RN_TXD3 GENMASK(15, 12)
505
+ #define MII_KSZ9031RN_TXD2 GENMASK(11, 8)
506
+ #define MII_KSZ9031RN_TXD1 GENMASK(7, 4)
507
+ #define MII_KSZ9031RN_TXD0 GENMASK(3, 0)
508
+
495
509
#define MII_KSZ9031RN_CLK_PAD_SKEW 8
510
+ #define MII_KSZ9031RN_GTX_CLK GENMASK(9, 5)
511
+ #define MII_KSZ9031RN_RX_CLK GENMASK(4, 0)
512
+
513
+ /* KSZ9031 has internal RGMII_IDRX = 1.2ns and RGMII_IDTX = 0ns. To
514
+ * provide different RGMII options we need to configure delay offset
515
+ * for each pad relative to build in delay.
516
+ */
517
+ /* keep rx as "No delay adjustment" and set rx_clk to +0.60ns to get delays of
518
+ * 1.80ns
519
+ */
520
+ #define RX_ID 0x7
521
+ #define RX_CLK_ID 0x19
522
+
523
+ /* set rx to +0.30ns and rx_clk to -0.90ns to compensate the
524
+ * internal 1.2ns delay.
525
+ */
526
+ #define RX_ND 0xc
527
+ #define RX_CLK_ND 0x0
528
+
529
+ /* set tx to -0.42ns and tx_clk to +0.96ns to get 1.38ns delay */
530
+ #define TX_ID 0x0
531
+ #define TX_CLK_ID 0x1f
532
+
533
+ /* set tx and tx_clk to "No delay adjustment" to keep 0ns
534
+ * dealy
535
+ */
536
+ #define TX_ND 0x7
537
+ #define TX_CLK_ND 0xf
496
538
497
539
/* MMD Address 0x1C */
498
540
#define MII_KSZ9031RN_EDPD 0x23
@@ -501,7 +543,8 @@ static int ksz9021_config_init(struct phy_device *phydev)
501
543
static int ksz9031_of_load_skew_values (struct phy_device * phydev ,
502
544
const struct device_node * of_node ,
503
545
u16 reg , size_t field_sz ,
504
- const char * field [], u8 numfields )
546
+ const char * field [], u8 numfields ,
547
+ bool * update )
505
548
{
506
549
int val [4 ] = {-1 , -2 , -3 , -4 };
507
550
int matches = 0 ;
@@ -517,6 +560,8 @@ static int ksz9031_of_load_skew_values(struct phy_device *phydev,
517
560
if (!matches )
518
561
return 0 ;
519
562
563
+ * update |= true;
564
+
520
565
if (matches < numfields )
521
566
newval = phy_read_mmd (phydev , 2 , reg );
522
567
else
@@ -565,6 +610,67 @@ static int ksz9031_enable_edpd(struct phy_device *phydev)
565
610
reg | MII_KSZ9031RN_EDPD_ENABLE );
566
611
}
567
612
613
+ static int ksz9031_config_rgmii_delay (struct phy_device * phydev )
614
+ {
615
+ u16 rx , tx , rx_clk , tx_clk ;
616
+ int ret ;
617
+
618
+ switch (phydev -> interface ) {
619
+ case PHY_INTERFACE_MODE_RGMII :
620
+ tx = TX_ND ;
621
+ tx_clk = TX_CLK_ND ;
622
+ rx = RX_ND ;
623
+ rx_clk = RX_CLK_ND ;
624
+ break ;
625
+ case PHY_INTERFACE_MODE_RGMII_ID :
626
+ tx = TX_ID ;
627
+ tx_clk = TX_CLK_ID ;
628
+ rx = RX_ID ;
629
+ rx_clk = RX_CLK_ID ;
630
+ break ;
631
+ case PHY_INTERFACE_MODE_RGMII_RXID :
632
+ tx = TX_ND ;
633
+ tx_clk = TX_CLK_ND ;
634
+ rx = RX_ID ;
635
+ rx_clk = RX_CLK_ID ;
636
+ break ;
637
+ case PHY_INTERFACE_MODE_RGMII_TXID :
638
+ tx = TX_ID ;
639
+ tx_clk = TX_CLK_ID ;
640
+ rx = RX_ND ;
641
+ rx_clk = RX_CLK_ND ;
642
+ break ;
643
+ default :
644
+ return 0 ;
645
+ }
646
+
647
+ ret = phy_write_mmd (phydev , 2 , MII_KSZ9031RN_CONTROL_PAD_SKEW ,
648
+ FIELD_PREP (MII_KSZ9031RN_RX_CTL_M , rx ) |
649
+ FIELD_PREP (MII_KSZ9031RN_TX_CTL_M , tx ));
650
+ if (ret < 0 )
651
+ return ret ;
652
+
653
+ ret = phy_write_mmd (phydev , 2 , MII_KSZ9031RN_RX_DATA_PAD_SKEW ,
654
+ FIELD_PREP (MII_KSZ9031RN_RXD3 , rx ) |
655
+ FIELD_PREP (MII_KSZ9031RN_RXD2 , rx ) |
656
+ FIELD_PREP (MII_KSZ9031RN_RXD1 , rx ) |
657
+ FIELD_PREP (MII_KSZ9031RN_RXD0 , rx ));
658
+ if (ret < 0 )
659
+ return ret ;
660
+
661
+ ret = phy_write_mmd (phydev , 2 , MII_KSZ9031RN_TX_DATA_PAD_SKEW ,
662
+ FIELD_PREP (MII_KSZ9031RN_TXD3 , tx ) |
663
+ FIELD_PREP (MII_KSZ9031RN_TXD2 , tx ) |
664
+ FIELD_PREP (MII_KSZ9031RN_TXD1 , tx ) |
665
+ FIELD_PREP (MII_KSZ9031RN_TXD0 , tx ));
666
+ if (ret < 0 )
667
+ return ret ;
668
+
669
+ return phy_write_mmd (phydev , 2 , MII_KSZ9031RN_CLK_PAD_SKEW ,
670
+ FIELD_PREP (MII_KSZ9031RN_GTX_CLK , tx_clk ) |
671
+ FIELD_PREP (MII_KSZ9031RN_RX_CLK , rx_clk ));
672
+ }
673
+
568
674
static int ksz9031_config_init (struct phy_device * phydev )
569
675
{
570
676
const struct device * dev = & phydev -> mdio .dev ;
@@ -597,21 +703,33 @@ static int ksz9031_config_init(struct phy_device *phydev)
597
703
} while (!of_node && dev_walker );
598
704
599
705
if (of_node ) {
706
+ bool update = false;
707
+
708
+ if (phy_interface_is_rgmii (phydev )) {
709
+ result = ksz9031_config_rgmii_delay (phydev );
710
+ if (result < 0 )
711
+ return result ;
712
+ }
713
+
600
714
ksz9031_of_load_skew_values (phydev , of_node ,
601
715
MII_KSZ9031RN_CLK_PAD_SKEW , 5 ,
602
- clk_skews , 2 );
716
+ clk_skews , 2 , & update );
603
717
604
718
ksz9031_of_load_skew_values (phydev , of_node ,
605
719
MII_KSZ9031RN_CONTROL_PAD_SKEW , 4 ,
606
- control_skews , 2 );
720
+ control_skews , 2 , & update );
607
721
608
722
ksz9031_of_load_skew_values (phydev , of_node ,
609
723
MII_KSZ9031RN_RX_DATA_PAD_SKEW , 4 ,
610
- rx_data_skews , 4 );
724
+ rx_data_skews , 4 , & update );
611
725
612
726
ksz9031_of_load_skew_values (phydev , of_node ,
613
727
MII_KSZ9031RN_TX_DATA_PAD_SKEW , 4 ,
614
- tx_data_skews , 4 );
728
+ tx_data_skews , 4 , & update );
729
+
730
+ if (update && phydev -> interface != PHY_INTERFACE_MODE_RGMII )
731
+ phydev_warn (phydev ,
732
+ "*-skew-ps values should be used only with phy-mode = \"rgmii\"\n" );
615
733
616
734
/* Silicon Errata Sheet (DS80000691D or DS80000692D):
617
735
* When the device links in the 1000BASE-T slave mode only,
0 commit comments