bd492ca1ecdff894f80f9839f6e60672c698454d
[openwrt/staging/linusw.git] /
1 From 9ec092d2feb69045dd289845024301fb91c064ee Mon Sep 17 00:00:00 2001
2 From: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
3 Date: Tue, 14 Jun 2022 13:22:27 +0200
4 Subject: [PATCH 1/2] net: ethernet: stmmac: add missing sgmii configure for
5 ipq806x
6
7 The different gmacid require different configuration based on the soc
8 and on the gmac id. Add these missing configuration taken from the
9 original driver.
10
11 Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
12 Link: https://lore.kernel.org/r/20220614112228.1998-1-ansuelsmth@gmail.com
13 Signed-off-by: Paolo Abeni <pabeni@redhat.com>
14 ---
15 drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
16 .../ethernet/stmicro/stmmac/dwmac-ipq806x.c | 93 +++++++++++++++----
17 2 files changed, 78 insertions(+), 16 deletions(-)
18
19 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
20 +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
21 @@ -83,6 +83,7 @@ config DWMAC_IPQ806X
22 default ARCH_QCOM
23 depends on OF && (ARCH_QCOM || COMPILE_TEST)
24 select MFD_SYSCON
25 + select QCOM_SOCINFO
26 help
27 Support for QCA IPQ806X DWMAC Ethernet.
28
29 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
30 +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
31 @@ -27,6 +27,8 @@
32 #include <linux/stmmac.h>
33 #include <linux/of_mdio.h>
34 #include <linux/module.h>
35 +#include <linux/sys_soc.h>
36 +#include <linux/bitfield.h>
37
38 #include "stmmac_platform.h"
39
40 @@ -75,11 +77,20 @@
41 #define QSGMII_PHY_RX_SIGNAL_DETECT_EN BIT(2)
42 #define QSGMII_PHY_TX_DRIVER_EN BIT(3)
43 #define QSGMII_PHY_QSGMII_EN BIT(7)
44 -#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET 12
45 -#define QSGMII_PHY_RX_DC_BIAS_OFFSET 18
46 -#define QSGMII_PHY_RX_INPUT_EQU_OFFSET 20
47 -#define QSGMII_PHY_CDR_PI_SLEW_OFFSET 22
48 -#define QSGMII_PHY_TX_DRV_AMP_OFFSET 28
49 +#define QSGMII_PHY_DEEMPHASIS_LVL_MASK GENMASK(11, 10)
50 +#define QSGMII_PHY_DEEMPHASIS_LVL(x) FIELD_PREP(QSGMII_PHY_DEEMPHASIS_LVL_MASK, (x))
51 +#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK GENMASK(14, 12)
52 +#define QSGMII_PHY_PHASE_LOOP_GAIN(x) FIELD_PREP(QSGMII_PHY_PHASE_LOOP_GAIN_MASK, (x))
53 +#define QSGMII_PHY_RX_DC_BIAS_MASK GENMASK(19, 18)
54 +#define QSGMII_PHY_RX_DC_BIAS(x) FIELD_PREP(QSGMII_PHY_RX_DC_BIAS_MASK, (x))
55 +#define QSGMII_PHY_RX_INPUT_EQU_MASK GENMASK(21, 20)
56 +#define QSGMII_PHY_RX_INPUT_EQU(x) FIELD_PREP(QSGMII_PHY_RX_INPUT_EQU_MASK, (x))
57 +#define QSGMII_PHY_CDR_PI_SLEW_MASK GENMASK(23, 22)
58 +#define QSGMII_PHY_CDR_PI_SLEW(x) FIELD_PREP(QSGMII_PHY_CDR_PI_SLEW_MASK, (x))
59 +#define QSGMII_PHY_TX_SLEW_MASK GENMASK(27, 26)
60 +#define QSGMII_PHY_TX_SLEW(x) FIELD_PREP(QSGMII_PHY_TX_SLEW_MASK, (x))
61 +#define QSGMII_PHY_TX_DRV_AMP_MASK GENMASK(31, 28)
62 +#define QSGMII_PHY_TX_DRV_AMP(x) FIELD_PREP(QSGMII_PHY_TX_DRV_AMP_MASK, (x))
63
64 struct ipq806x_gmac {
65 struct platform_device *pdev;
66 @@ -242,6 +253,64 @@ static void ipq806x_gmac_fix_mac_speed(v
67 ipq806x_gmac_set_speed(gmac, speed);
68 }
69
70 +static const struct soc_device_attribute ipq806x_gmac_soc_v1[] = {
71 + {
72 + .revision = "1.*",
73 + },
74 + {
75 + /* sentinel */
76 + }
77 +};
78 +
79 +static int
80 +ipq806x_gmac_configure_qsgmii_params(struct ipq806x_gmac *gmac)
81 +{
82 + struct platform_device *pdev = gmac->pdev;
83 + const struct soc_device_attribute *soc;
84 + struct device *dev = &pdev->dev;
85 + u32 qsgmii_param;
86 +
87 + switch (gmac->id) {
88 + case 1:
89 + soc = soc_device_match(ipq806x_gmac_soc_v1);
90 +
91 + if (soc)
92 + qsgmii_param = QSGMII_PHY_TX_DRV_AMP(0xc) |
93 + QSGMII_PHY_TX_SLEW(0x2) |
94 + QSGMII_PHY_DEEMPHASIS_LVL(0x2);
95 + else
96 + qsgmii_param = QSGMII_PHY_TX_DRV_AMP(0xd) |
97 + QSGMII_PHY_TX_SLEW(0x0) |
98 + QSGMII_PHY_DEEMPHASIS_LVL(0x0);
99 +
100 + qsgmii_param |= QSGMII_PHY_RX_DC_BIAS(0x2);
101 + break;
102 + case 2:
103 + case 3:
104 + qsgmii_param = QSGMII_PHY_RX_DC_BIAS(0x3) |
105 + QSGMII_PHY_TX_DRV_AMP(0xc);
106 + break;
107 + default: /* gmac 0 can't be set in SGMII mode */
108 + dev_err(dev, "gmac id %d can't be in SGMII mode", gmac->id);
109 + return -EINVAL;
110 + }
111 +
112 + /* Common params across all gmac id */
113 + qsgmii_param |= QSGMII_PHY_CDR_EN |
114 + QSGMII_PHY_RX_FRONT_EN |
115 + QSGMII_PHY_RX_SIGNAL_DETECT_EN |
116 + QSGMII_PHY_TX_DRIVER_EN |
117 + QSGMII_PHY_QSGMII_EN |
118 + QSGMII_PHY_PHASE_LOOP_GAIN(0x4) |
119 + QSGMII_PHY_RX_INPUT_EQU(0x1) |
120 + QSGMII_PHY_CDR_PI_SLEW(0x2);
121 +
122 + regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
123 + qsgmii_param);
124 +
125 + return 0;
126 +}
127 +
128 static int ipq806x_gmac_probe(struct platform_device *pdev)
129 {
130 struct plat_stmmacenet_data *plat_dat;
131 @@ -328,17 +397,9 @@ static int ipq806x_gmac_probe(struct pla
132 regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
133
134 if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
135 - regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
136 - QSGMII_PHY_CDR_EN |
137 - QSGMII_PHY_RX_FRONT_EN |
138 - QSGMII_PHY_RX_SIGNAL_DETECT_EN |
139 - QSGMII_PHY_TX_DRIVER_EN |
140 - QSGMII_PHY_QSGMII_EN |
141 - 0x4ul << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
142 - 0x3ul << QSGMII_PHY_RX_DC_BIAS_OFFSET |
143 - 0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
144 - 0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
145 - 0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
146 + err = ipq806x_gmac_configure_qsgmii_params(gmac);
147 + if (err)
148 + goto err_remove_config_dt;
149 }
150
151 plat_dat->has_gmac = true;