3737#define PHYREG8 0x1C
3838#define PHYREG8_SSC_EN BIT(4)
3939
40+ #define PHYREG10 0x24
41+ #define PHYREG10_SSC_PCM_MASK GENMASK(3, 0)
42+ #define PHYREG10_SSC_PCM_3500PPM 7
43+
4044#define PHYREG11 0x28
4145#define PHYREG11_SU_TRIM_0_7 0xF0
4246
6165#define PHYREG16 0x3C
6266#define PHYREG16_SSC_CNT_VALUE 0x5f
6367
68+ #define PHYREG17 0x40
69+
6470#define PHYREG18 0x44
6571#define PHYREG18_PLL_LOOP 0x32
6672
73+ #define PHYREG21 0x50
74+ #define PHYREG21_RX_SQUELCH_VAL 0x0D
75+
6776#define PHYREG27 0x6C
6877#define PHYREG27_RX_TRIM_RK3588 0x4C
6978
79+ #define PHYREG30 0x74
80+
7081#define PHYREG32 0x7C
7182#define PHYREG32_SSC_MASK GENMASK(7, 4)
83+ #define PHYREG32_SSC_DIR_MASK GENMASK(5, 4)
7284#define PHYREG32_SSC_DIR_SHIFT 4
7385#define PHYREG32_SSC_UPWARD 0
7486#define PHYREG32_SSC_DOWNWARD 1
87+ #define PHYREG32_SSC_OFFSET_MASK GENMASK(7, 6)
7588#define PHYREG32_SSC_OFFSET_SHIFT 6
7689#define PHYREG32_SSC_OFFSET_500PPM 1
7790
7891#define PHYREG33 0x80
7992#define PHYREG33_PLL_KVCO_MASK GENMASK(4, 2)
8093#define PHYREG33_PLL_KVCO_SHIFT 2
8194#define PHYREG33_PLL_KVCO_VALUE 2
95+ #define PHYREG33_PLL_KVCO_VALUE_RK3576 4
8296
8397struct rockchip_combphy_priv ;
8498
@@ -98,6 +112,7 @@ struct rockchip_combphy_grfcfg {
98112 struct combphy_reg pipe_rxterm_set ;
99113 struct combphy_reg pipe_txelec_set ;
100114 struct combphy_reg pipe_txcomp_set ;
115+ struct combphy_reg pipe_clk_24m ;
101116 struct combphy_reg pipe_clk_25m ;
102117 struct combphy_reg pipe_clk_100m ;
103118 struct combphy_reg pipe_phymode_sel ;
@@ -584,6 +599,266 @@ static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
584599 .combphy_cfg = rk3568_combphy_cfg ,
585600};
586601
602+ static int rk3576_combphy_cfg (struct rockchip_combphy_priv * priv )
603+ {
604+ const struct rockchip_combphy_grfcfg * cfg = priv -> cfg -> grfcfg ;
605+ unsigned long rate ;
606+ u32 val ;
607+
608+ switch (priv -> type ) {
609+ case PHY_TYPE_PCIE :
610+ /* Set SSC downward spread spectrum */
611+ val = FIELD_PREP (PHYREG32_SSC_MASK , PHYREG32_SSC_DOWNWARD );
612+ rockchip_combphy_updatel (priv , PHYREG32_SSC_MASK , val , PHYREG32 );
613+
614+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> con0_for_pcie , true);
615+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> con1_for_pcie , true);
616+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> con2_for_pcie , true);
617+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> con3_for_pcie , true);
618+ break ;
619+
620+ case PHY_TYPE_USB3 :
621+ /* Set SSC downward spread spectrum */
622+ val = FIELD_PREP (PHYREG32_SSC_MASK , PHYREG32_SSC_DOWNWARD );
623+ rockchip_combphy_updatel (priv , PHYREG32_SSC_MASK , val , PHYREG32 );
624+
625+ /* Enable adaptive CTLE for USB3.0 Rx */
626+ val = readl (priv -> mmio + PHYREG15 );
627+ val |= PHYREG15_CTLE_EN ;
628+ writel (val , priv -> mmio + PHYREG15 );
629+
630+ /* Set PLL KVCO fine tuning signals */
631+ rockchip_combphy_updatel (priv , PHYREG33_PLL_KVCO_MASK , BIT (3 ), PHYREG33 );
632+
633+ /* Set PLL LPF R1 to su_trim[10:7]=1001 */
634+ writel (PHYREG12_PLL_LPF_ADJ_VALUE , priv -> mmio + PHYREG12 );
635+
636+ /* Set PLL input clock divider 1/2 */
637+ val = FIELD_PREP (PHYREG6_PLL_DIV_MASK , PHYREG6_PLL_DIV_2 );
638+ rockchip_combphy_updatel (priv , PHYREG6_PLL_DIV_MASK , val , PHYREG6 );
639+
640+ /* Set PLL loop divider */
641+ writel (PHYREG18_PLL_LOOP , priv -> mmio + PHYREG18 );
642+
643+ /* Set PLL KVCO to min and set PLL charge pump current to max */
644+ writel (PHYREG11_SU_TRIM_0_7 , priv -> mmio + PHYREG11 );
645+
646+ /* Set Rx squelch input filler bandwidth */
647+ writel (PHYREG21_RX_SQUELCH_VAL , priv -> mmio + PHYREG21 );
648+
649+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> pipe_txcomp_sel , false);
650+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> pipe_txelec_sel , false);
651+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> usb_mode_set , true);
652+ break ;
653+
654+ case PHY_TYPE_SATA :
655+ /* Enable adaptive CTLE for SATA Rx */
656+ val = readl (priv -> mmio + PHYREG15 );
657+ val |= PHYREG15_CTLE_EN ;
658+ writel (val , priv -> mmio + PHYREG15 );
659+
660+ /* Set tx_rterm = 50 ohm and rx_rterm = 43.5 ohm */
661+ val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT ;
662+ val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT ;
663+ writel (val , priv -> mmio + PHYREG7 );
664+
665+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> con0_for_sata , true);
666+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> con1_for_sata , true);
667+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> con2_for_sata , true);
668+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> con3_for_sata , true);
669+ rockchip_combphy_param_write (priv -> pipe_grf , & cfg -> pipe_con0_for_sata , true);
670+ rockchip_combphy_param_write (priv -> pipe_grf , & cfg -> pipe_con1_for_sata , true);
671+ break ;
672+
673+ default :
674+ dev_err (priv -> dev , "incompatible PHY type\n" );
675+ return - EINVAL ;
676+ }
677+
678+ rate = clk_get_rate (priv -> refclk );
679+
680+ switch (rate ) {
681+ case REF_CLOCK_24MHz :
682+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> pipe_clk_24m , true);
683+ if (priv -> type == PHY_TYPE_USB3 || priv -> type == PHY_TYPE_SATA ) {
684+ /* Set ssc_cnt[9:0]=0101111101 & 31.5KHz */
685+ val = FIELD_PREP (PHYREG15_SSC_CNT_MASK , PHYREG15_SSC_CNT_VALUE );
686+ rockchip_combphy_updatel (priv , PHYREG15_SSC_CNT_MASK ,
687+ val , PHYREG15 );
688+
689+ writel (PHYREG16_SSC_CNT_VALUE , priv -> mmio + PHYREG16 );
690+ } else if (priv -> type == PHY_TYPE_PCIE ) {
691+ /* PLL KVCO tuning fine */
692+ val = FIELD_PREP (PHYREG33_PLL_KVCO_MASK , PHYREG33_PLL_KVCO_VALUE_RK3576 );
693+ rockchip_combphy_updatel (priv , PHYREG33_PLL_KVCO_MASK ,
694+ val , PHYREG33 );
695+
696+ /* Set up rx_pck invert and rx msb to disable */
697+ writel (0x00 , priv -> mmio + PHYREG27 );
698+
699+ /*
700+ * Set up SU adjust signal:
701+ * su_trim[7:0], PLL KVCO adjust bits[2:0] to min
702+ * su_trim[15:8], PLL LPF R1 adujst bits[9:7]=3'b011
703+ * su_trim[31:24], CKDRV adjust
704+ */
705+ writel (0x90 , priv -> mmio + PHYREG11 );
706+ writel (0x02 , priv -> mmio + PHYREG12 );
707+ writel (0x57 , priv -> mmio + PHYREG14 );
708+
709+ writel (PHYREG16_SSC_CNT_VALUE , priv -> mmio + PHYREG16 );
710+ }
711+ break ;
712+
713+ case REF_CLOCK_25MHz :
714+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> pipe_clk_25m , true);
715+ break ;
716+
717+ case REF_CLOCK_100MHz :
718+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> pipe_clk_100m , true);
719+ if (priv -> type == PHY_TYPE_PCIE ) {
720+ /* gate_tx_pck_sel length select work for L1SS */
721+ writel (0xc0 , priv -> mmio + PHYREG30 );
722+
723+ /* PLL KVCO tuning fine */
724+ val = FIELD_PREP (PHYREG33_PLL_KVCO_MASK , PHYREG33_PLL_KVCO_VALUE_RK3576 );
725+ rockchip_combphy_updatel (priv , PHYREG33_PLL_KVCO_MASK ,
726+ val , PHYREG33 );
727+
728+ /* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */
729+ writel (0x4c , priv -> mmio + PHYREG27 );
730+
731+ /*
732+ * Set up SU adjust signal:
733+ * su_trim[7:0], PLL KVCO adjust bits[2:0] to min
734+ * su_trim[15:8], bypass PLL loop divider code, and
735+ * PLL LPF R1 adujst bits[9:7]=3'b101
736+ * su_trim[23:16], CKRCV adjust
737+ * su_trim[31:24], CKDRV adjust
738+ */
739+ writel (0x90 , priv -> mmio + PHYREG11 );
740+ writel (0x43 , priv -> mmio + PHYREG12 );
741+ writel (0x88 , priv -> mmio + PHYREG13 );
742+ writel (0x56 , priv -> mmio + PHYREG14 );
743+ } else if (priv -> type == PHY_TYPE_SATA ) {
744+ /* downward spread spectrum +500ppm */
745+ val = FIELD_PREP (PHYREG32_SSC_DIR_MASK , PHYREG32_SSC_DOWNWARD );
746+ val |= FIELD_PREP (PHYREG32_SSC_OFFSET_MASK , PHYREG32_SSC_OFFSET_500PPM );
747+ rockchip_combphy_updatel (priv , PHYREG32_SSC_MASK , val , PHYREG32 );
748+
749+ /* ssc ppm adjust to 3500ppm */
750+ rockchip_combphy_updatel (priv , PHYREG10_SSC_PCM_MASK ,
751+ PHYREG10_SSC_PCM_3500PPM ,
752+ PHYREG10 );
753+ }
754+ break ;
755+
756+ default :
757+ dev_err (priv -> dev , "Unsupported rate: %lu\n" , rate );
758+ return - EINVAL ;
759+ }
760+
761+ if (priv -> ext_refclk ) {
762+ rockchip_combphy_param_write (priv -> phy_grf , & cfg -> pipe_clk_ext , true);
763+ if (priv -> type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz ) {
764+ val = FIELD_PREP (PHYREG33_PLL_KVCO_MASK , PHYREG33_PLL_KVCO_VALUE_RK3576 );
765+ rockchip_combphy_updatel (priv , PHYREG33_PLL_KVCO_MASK ,
766+ val , PHYREG33 );
767+
768+ /* Set up rx_trim: PLL LPF C1 85pf R1 2.5kohm */
769+ writel (0x0c , priv -> mmio + PHYREG27 );
770+
771+ /*
772+ * Set up SU adjust signal:
773+ * su_trim[7:0], PLL KVCO adjust bits[2:0] to min
774+ * su_trim[15:8], bypass PLL loop divider code, and
775+ * PLL LPF R1 adujst bits[9:7]=3'b101.
776+ * su_trim[23:16], CKRCV adjust
777+ * su_trim[31:24], CKDRV adjust
778+ */
779+ writel (0x90 , priv -> mmio + PHYREG11 );
780+ writel (0x43 , priv -> mmio + PHYREG12 );
781+ writel (0x88 , priv -> mmio + PHYREG13 );
782+ writel (0x56 , priv -> mmio + PHYREG14 );
783+ }
784+ }
785+
786+ if (priv -> enable_ssc ) {
787+ val = readl (priv -> mmio + PHYREG8 );
788+ val |= PHYREG8_SSC_EN ;
789+ writel (val , priv -> mmio + PHYREG8 );
790+
791+ if (priv -> type == PHY_TYPE_PCIE && rate == REF_CLOCK_24MHz ) {
792+ /* Set PLL loop divider */
793+ writel (0x00 , priv -> mmio + PHYREG17 );
794+ writel (PHYREG18_PLL_LOOP , priv -> mmio + PHYREG18 );
795+
796+ /* Set up rx_pck invert and rx msb to disable */
797+ writel (0x00 , priv -> mmio + PHYREG27 );
798+
799+ /*
800+ * Set up SU adjust signal:
801+ * su_trim[7:0], PLL KVCO adjust bits[2:0] to min
802+ * su_trim[15:8], PLL LPF R1 adujst bits[9:7]=3'b101
803+ * su_trim[23:16], CKRCV adjust
804+ * su_trim[31:24], CKDRV adjust
805+ */
806+ writel (0x90 , priv -> mmio + PHYREG11 );
807+ writel (0x02 , priv -> mmio + PHYREG12 );
808+ writel (0x08 , priv -> mmio + PHYREG13 );
809+ writel (0x57 , priv -> mmio + PHYREG14 );
810+ writel (0x40 , priv -> mmio + PHYREG15 );
811+
812+ writel (PHYREG16_SSC_CNT_VALUE , priv -> mmio + PHYREG16 );
813+
814+ val = FIELD_PREP (PHYREG33_PLL_KVCO_MASK , PHYREG33_PLL_KVCO_VALUE_RK3576 );
815+ writel (val , priv -> mmio + PHYREG33 );
816+ }
817+ }
818+
819+ return 0 ;
820+ }
821+
822+ static const struct rockchip_combphy_grfcfg rk3576_combphy_grfcfgs = {
823+ /* pipe-phy-grf */
824+ .pcie_mode_set = { 0x0000 , 5 , 0 , 0x00 , 0x11 },
825+ .usb_mode_set = { 0x0000 , 5 , 0 , 0x00 , 0x04 },
826+ .pipe_rxterm_set = { 0x0000 , 12 , 12 , 0x00 , 0x01 },
827+ .pipe_txelec_set = { 0x0004 , 1 , 1 , 0x00 , 0x01 },
828+ .pipe_txcomp_set = { 0x0004 , 4 , 4 , 0x00 , 0x01 },
829+ .pipe_clk_24m = { 0x0004 , 14 , 13 , 0x00 , 0x00 },
830+ .pipe_clk_25m = { 0x0004 , 14 , 13 , 0x00 , 0x01 },
831+ .pipe_clk_100m = { 0x0004 , 14 , 13 , 0x00 , 0x02 },
832+ .pipe_phymode_sel = { 0x0008 , 1 , 1 , 0x00 , 0x01 },
833+ .pipe_rate_sel = { 0x0008 , 2 , 2 , 0x00 , 0x01 },
834+ .pipe_rxterm_sel = { 0x0008 , 8 , 8 , 0x00 , 0x01 },
835+ .pipe_txelec_sel = { 0x0008 , 12 , 12 , 0x00 , 0x01 },
836+ .pipe_txcomp_sel = { 0x0008 , 15 , 15 , 0x00 , 0x01 },
837+ .pipe_clk_ext = { 0x000c , 9 , 8 , 0x02 , 0x01 },
838+ .pipe_phy_status = { 0x0034 , 6 , 6 , 0x01 , 0x00 },
839+ .con0_for_pcie = { 0x0000 , 15 , 0 , 0x00 , 0x1000 },
840+ .con1_for_pcie = { 0x0004 , 15 , 0 , 0x00 , 0x0000 },
841+ .con2_for_pcie = { 0x0008 , 15 , 0 , 0x00 , 0x0101 },
842+ .con3_for_pcie = { 0x000c , 15 , 0 , 0x00 , 0x0200 },
843+ .con0_for_sata = { 0x0000 , 15 , 0 , 0x00 , 0x0129 },
844+ .con1_for_sata = { 0x0004 , 15 , 0 , 0x00 , 0x0000 },
845+ .con2_for_sata = { 0x0008 , 15 , 0 , 0x00 , 0x80c1 },
846+ .con3_for_sata = { 0x000c , 15 , 0 , 0x00 , 0x0407 },
847+ /* php-grf */
848+ .pipe_con0_for_sata = { 0x001C , 2 , 0 , 0x00 , 0x2 },
849+ .pipe_con1_for_sata = { 0x0020 , 2 , 0 , 0x00 , 0x2 },
850+ };
851+
852+ static const struct rockchip_combphy_cfg rk3576_combphy_cfgs = {
853+ .num_phys = 2 ,
854+ .phy_ids = {
855+ 0x2b050000 ,
856+ 0x2b060000
857+ },
858+ .grfcfg = & rk3576_combphy_grfcfgs ,
859+ .combphy_cfg = rk3576_combphy_cfg ,
860+ };
861+
587862static int rk3588_combphy_cfg (struct rockchip_combphy_priv * priv )
588863{
589864 const struct rockchip_combphy_grfcfg * cfg = priv -> cfg -> grfcfg ;
@@ -775,6 +1050,10 @@ static const struct of_device_id rockchip_combphy_of_match[] = {
7751050 .compatible = "rockchip,rk3568-naneng-combphy" ,
7761051 .data = & rk3568_combphy_cfgs ,
7771052 },
1053+ {
1054+ .compatible = "rockchip,rk3576-naneng-combphy" ,
1055+ .data = & rk3576_combphy_cfgs ,
1056+ },
7781057 {
7791058 .compatible = "rockchip,rk3588-naneng-combphy" ,
7801059 .data = & rk3588_combphy_cfgs ,
0 commit comments