aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-5.10/101-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch
blob: 3c497ead6afc71d816786bd0f05b1559a3271de8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
@@ -64,6 +64,17 @@
 #define NSS_COMMON_CLK_DIV_SGMII_100		4
 #define NSS_COMMON_CLK_DIV_SGMII_10		49
 
+#define QSGMII_PCS_ALL_CH_CTL			0x80
+#define QSGMII_PCS_CH_SPEED_FORCE		0x2
+#define QSGMII_PCS_CH_SPEED_10			0x0
+#define QSGMII_PCS_CH_SPEED_100			0x4
+#define QSGMII_PCS_CH_SPEED_1000		0x8
+#define QSGMII_PCS_CH_SPEED_MASK		(QSGMII_PCS_CH_SPEED_FORCE | \
+						 QSGMII_PCS_CH_SPEED_10 | \
+						 QSGMII_PCS_CH_SPEED_100 | \
+						 QSGMII_PCS_CH_SPEED_1000)
+#define QSGMII_PCS_CH_SPEED_SHIFT(x)		(x * 4)
+
 #define QSGMII_PCS_CAL_LCKDT_CTL		0x120
 #define QSGMII_PCS_CAL_LCKDT_CTL_RST		BIT(19)
 
@@ -241,6 +252,36 @@ static void ipq806x_gmac_fix_mac_speed(v
 	ipq806x_gmac_set_speed(gmac, speed);
 }
 
+static int
+ipq806x_gmac_get_qsgmii_pcs_speed_val(struct platform_device *pdev) {
+	struct device_node *fixed_link_node;
+	int rv;
+	int fixed_link_speed;
+
+	if (!of_phy_is_fixed_link(pdev->dev.of_node))
+		return 0;
+
+	fixed_link_node = of_get_child_by_name(pdev->dev.of_node, "fixed-link");
+	if (!fixed_link_node)
+		return -1;
+
+	rv = of_property_read_u32(fixed_link_node, "speed", &fixed_link_speed);
+	of_node_put(fixed_link_node);
+	if (rv)
+		return -1;
+
+	switch (fixed_link_speed) {
+	case SPEED_1000:
+		return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_1000;
+	case SPEED_100:
+		return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_100;
+	case SPEED_10:
+		return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_10;
+	}
+
+	return -1;
+}
+
 static int ipq806x_gmac_probe(struct platform_device *pdev)
 {
 	struct plat_stmmacenet_data *plat_dat;
@@ -249,6 +290,7 @@ static int ipq806x_gmac_probe(struct pla
 	struct ipq806x_gmac *gmac;
 	int val;
 	int err;
+	int qsgmii_pcs_speed;
 
 	val = stmmac_get_platform_resources(pdev, &stmmac_res);
 	if (val)
@@ -345,6 +387,17 @@ static int ipq806x_gmac_probe(struct pla
 			     0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
 			     0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
 			     0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
+
+		qsgmii_pcs_speed = ipq806x_gmac_get_qsgmii_pcs_speed_val(pdev);
+		if (qsgmii_pcs_speed != -1) {
+			regmap_update_bits(
+			    gmac->qsgmii_csr,
+			    QSGMII_PCS_ALL_CH_CTL,
+			    QSGMII_PCS_CH_SPEED_MASK <<
+				QSGMII_PCS_CH_SPEED_SHIFT(gmac->id),
+			    qsgmii_pcs_speed <<
+				QSGMII_PCS_CH_SPEED_SHIFT(gmac->id));
+		}
 	}
 
 	plat_dat->has_gmac = true;