blob: c53c205d4435db79da2aba7bc6940fd746e2dc3e [file] [log] [blame]
developer5d148cb2023-06-02 13:08:11 +08001From 90508a46a0fd6416dcaad2c7f0ef25a5a421bf4f Mon Sep 17 00:00:00 2001
2From: Sam Shih <sam.shih@mediatek.com>
3Date: Fri, 2 Jun 2023 13:06:00 +0800
4Subject: [PATCH]
5 [backport-networking-drivers][999-1706-net-dsa-support-mt7988.patch]
6
7---
8 drivers/net/dsa/mt7530.c | 191 ++++++++++++++++++++++++++++++++-------
9 drivers/net/dsa/mt7530.h | 11 ++-
10 2 files changed, 164 insertions(+), 38 deletions(-)
11
12diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
13index 63f8a632b..2cd5dae9c 100644
14--- a/drivers/net/dsa/mt7530.c
15+++ b/drivers/net/dsa/mt7530.c
developer2cdaeb12022-10-04 20:25:05 +080016@@ -19,6 +19,7 @@
17 #include <linux/reset.h>
18 #include <linux/gpio/consumer.h>
19 #include <net/dsa.h>
20+#include <linux/of_address.h>
developer5d148cb2023-06-02 13:08:11 +080021
developer2cdaeb12022-10-04 20:25:05 +080022 #include "mt7530.h"
23 #include "mt7530_nl.h"
developer5d148cb2023-06-02 13:08:11 +080024@@ -170,28 +171,44 @@ core_clear(struct mt7530_priv *priv, u32 reg, u32 val)
developer2cdaeb12022-10-04 20:25:05 +080025 core_rmw(priv, reg, val, 0);
26 }
developer5d148cb2023-06-02 13:08:11 +080027
developer2cdaeb12022-10-04 20:25:05 +080028+static void
29+mtk_w32(struct mt7530_priv *priv, u32 val, unsigned reg)
30+{
31+ __raw_writel(val, priv->base + reg);
32+}
33+
34+static u32
35+mtk_r32(struct mt7530_priv *priv, unsigned reg)
36+{
37+ return __raw_readl(priv->base + reg);
38+}
39+
40 static int
41 mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
42 {
43 struct mii_bus *bus = priv->bus;
44 u16 page, r, lo, hi;
45- int ret;
developer5d148cb2023-06-02 13:08:11 +080046+ int ret = 0;
47
developer2cdaeb12022-10-04 20:25:05 +080048- page = (reg >> 6) & 0x3ff;
49- r = (reg >> 2) & 0xf;
50- lo = val & 0xffff;
51- hi = val >> 16;
developer2cdaeb12022-10-04 20:25:05 +080052+ if (priv->direct_access){
53+ mtk_w32(priv, val, reg);
54+ } else {
55+ page = (reg >> 6) & 0x3ff;
56+ r = (reg >> 2) & 0xf;
57+ lo = val & 0xffff;
58+ hi = val >> 16;
developer5d148cb2023-06-02 13:08:11 +080059
60- /* MT7530 uses 31 as the pseudo port */
61- ret = bus->write(bus, 0x1f, 0x1f, page);
62- if (ret < 0)
63- goto err;
developer2cdaeb12022-10-04 20:25:05 +080064+ /* MT7530 uses 31 as the pseudo port */
65+ ret = bus->write(bus, 0x1f, 0x1f, page);
66+ if (ret < 0)
67+ goto err;
developer5d148cb2023-06-02 13:08:11 +080068
69- ret = bus->write(bus, 0x1f, r, lo);
70- if (ret < 0)
71- goto err;
developer2cdaeb12022-10-04 20:25:05 +080072+ ret = bus->write(bus, 0x1f, r, lo);
73+ if (ret < 0)
74+ goto err;
developer5d148cb2023-06-02 13:08:11 +080075
developer2cdaeb12022-10-04 20:25:05 +080076- ret = bus->write(bus, 0x1f, 0x10, hi);
77+ ret = bus->write(bus, 0x1f, 0x10, hi);
78+ }
79 err:
80 if (ret < 0)
81 dev_err(&bus->dev,
developer5d148cb2023-06-02 13:08:11 +080082@@ -206,21 +223,25 @@ mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
developer2cdaeb12022-10-04 20:25:05 +080083 u16 page, r, lo, hi;
84 int ret;
developer5d148cb2023-06-02 13:08:11 +080085
developer2cdaeb12022-10-04 20:25:05 +080086- page = (reg >> 6) & 0x3ff;
87- r = (reg >> 2) & 0xf;
88+ if (priv->direct_access){
89+ return mtk_r32(priv, reg);
90+ } else {
91+ page = (reg >> 6) & 0x3ff;
92+ r = (reg >> 2) & 0xf;
developer5d148cb2023-06-02 13:08:11 +080093
developer2cdaeb12022-10-04 20:25:05 +080094- /* MT7530 uses 31 as the pseudo port */
95- ret = bus->write(bus, 0x1f, 0x1f, page);
96- if (ret < 0) {
97- dev_err(&bus->dev,
98- "failed to read mt7530 register\n");
99- return ret;
100- }
101+ /* MT7530 uses 31 as the pseudo port */
102+ ret = bus->write(bus, 0x1f, 0x1f, page);
103+ if (ret < 0) {
104+ dev_err(&bus->dev,
105+ "failed to read mt7530 register\n");
106+ return ret;
107+ }
developer5d148cb2023-06-02 13:08:11 +0800108
developer2cdaeb12022-10-04 20:25:05 +0800109- lo = bus->read(bus, 0x1f, r);
110- hi = bus->read(bus, 0x1f, 0x10);
111+ lo = bus->read(bus, 0x1f, r);
112+ hi = bus->read(bus, 0x1f, 0x10);
developer5d148cb2023-06-02 13:08:11 +0800113
developer2cdaeb12022-10-04 20:25:05 +0800114- return (hi << 16) | (lo & 0xffff);
115+ return (hi << 16) | (lo & 0xffff);
116+ }
117 }
developer5d148cb2023-06-02 13:08:11 +0800118
developer2cdaeb12022-10-04 20:25:05 +0800119 void
developer5d148cb2023-06-02 13:08:11 +0800120@@ -1907,9 +1928,9 @@ mt7531_phy_supported(struct dsa_switch *ds, int port,
developer2cdaeb12022-10-04 20:25:05 +0800121 if (mt7531_is_rgmii_port(priv, port))
122 return phy_interface_mode_is_rgmii(state->interface);
123 fallthrough;
124- case 6: /* 1st cpu port supports sgmii/8023z only */
125- if (state->interface != PHY_INTERFACE_MODE_SGMII &&
126- !phy_interface_mode_is_8023z(state->interface))
127+ case 6: /* 1st cpu port supports sgmii/8023z/usxgmii/10gkr */
128+ if (state->interface != PHY_INTERFACE_MODE_SGMII && state->interface != PHY_INTERFACE_MODE_USXGMII &&
129+ state->interface != PHY_INTERFACE_MODE_10GKR && !phy_interface_mode_is_8023z(state->interface))
130 goto unsupported;
131 break;
132 default:
developer5d148cb2023-06-02 13:08:11 +0800133@@ -2018,6 +2039,13 @@ static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port,
developer2cdaeb12022-10-04 20:25:05 +0800134 phylink_set(supported, 1000baseX_Full);
135 phylink_set(supported, 2500baseX_Full);
136 phylink_set(supported, 2500baseT_Full);
137+ phylink_set(supported, 10000baseKR_Full);
138+ phylink_set(supported, 10000baseT_Full);
139+ phylink_set(supported, 10000baseCR_Full);
140+ phylink_set(supported, 10000baseSR_Full);
141+ phylink_set(supported, 10000baseLR_Full);
142+ phylink_set(supported, 10000baseLRM_Full);
143+ phylink_set(supported, 10000baseER_Full);
144 }
145 }
developer5d148cb2023-06-02 13:08:11 +0800146
147@@ -2166,6 +2194,8 @@ mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
developer2cdaeb12022-10-04 20:25:05 +0800148 case PHY_INTERFACE_MODE_NA:
149 case PHY_INTERFACE_MODE_1000BASEX:
150 case PHY_INTERFACE_MODE_2500BASEX:
151+ case PHY_INTERFACE_MODE_USXGMII:
152+ case PHY_INTERFACE_MODE_10GKR:
153 if (phylink_autoneg_inband(mode))
154 return -EINVAL;
developer5d148cb2023-06-02 13:08:11 +0800155
156@@ -2303,8 +2333,8 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
developer2cdaeb12022-10-04 20:25:05 +0800157 /* MT753x MAC works in 1G full duplex mode for all up-clocked
158 * variants.
159 */
160- if (interface == PHY_INTERFACE_MODE_TRGMII ||
161- (phy_interface_mode_is_8023z(interface))) {
162+ if (interface == PHY_INTERFACE_MODE_TRGMII || interface == PHY_INTERFACE_MODE_USXGMII ||
163+ interface == PHY_INTERFACE_MODE_10GKR || (phy_interface_mode_is_8023z(interface))) {
164 speed = SPEED_1000;
165 duplex = DUPLEX_FULL;
166 }
developer5d148cb2023-06-02 13:08:11 +0800167@@ -2403,8 +2433,8 @@ mt753x_phylink_validate(struct dsa_switch *ds, int port,
168
developer2cdaeb12022-10-04 20:25:05 +0800169 phylink_set_port_modes(mask);
developer5d148cb2023-06-02 13:08:11 +0800170
developer2cdaeb12022-10-04 20:25:05 +0800171- if (state->interface != PHY_INTERFACE_MODE_TRGMII ||
172- !phy_interface_mode_is_8023z(state->interface)) {
173+ if (state->interface != PHY_INTERFACE_MODE_TRGMII || state->interface != PHY_INTERFACE_MODE_USXGMII ||
174+ state->interface != PHY_INTERFACE_MODE_10GKR || !phy_interface_mode_is_8023z(state->interface)) {
175 phylink_set(mask, 10baseT_Half);
176 phylink_set(mask, 10baseT_Full);
177 phylink_set(mask, 100baseT_Half);
developer5d148cb2023-06-02 13:08:11 +0800178@@ -2608,6 +2638,66 @@ mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
developer2cdaeb12022-10-04 20:25:05 +0800179 return priv->info->phy_write(ds, port, regnum, val);
180 }
developer5d148cb2023-06-02 13:08:11 +0800181
developer2cdaeb12022-10-04 20:25:05 +0800182+static int
183+mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
184+{
185+ return 0;
186+}
187+
188+static int
189+mt7988_setup(struct dsa_switch *ds)
190+{
191+ struct mt7530_priv *priv = ds->priv;
192+ u32 unused_pm = 0;
193+ int ret, i;
194+
195+ /* Reset the switch through internal reset */
196+ mt7530_write(priv, MT7530_SYS_CTRL,
197+ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST);
198+
199+ /* BPDU to CPU port */
200+ mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK,
201+ BIT(MT7530_CPU_PORT));
202+ mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
203+ MT753X_BPDU_CPU_ONLY);
204+
205+ /* Enable and reset MIB counters */
206+ mt7530_mib_reset(ds);
207+
208+ for (i = 0; i < MT7530_NUM_PORTS; i++) {
209+ /* Disable forwarding by default on all ports */
210+ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
211+ PCR_MATRIX_CLR);
212+
213+ mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR);
214+
215+ if (dsa_is_unused_port(ds, i))
216+ unused_pm |= BIT(i);
217+ else if (dsa_is_cpu_port(ds, i))
218+ mt753x_cpu_port_enable(ds, i);
219+ else
220+ mt7530_port_disable(ds, i);
221+
222+ /* Enable consistent egress tag */
223+ mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
224+ PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
225+ }
226+
227+ mt7531_phy_setup(ds);
228+
229+ /* Group and enable unused ports as a standalone dumb switch. */
230+ setup_unused_ports(ds, unused_pm);
231+
232+ ds->configure_vlan_while_not_filtering = true;
233+
234+ /* Flush the FDB table */
235+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
236+ if (ret < 0)
237+ return ret;
238+
239+ return 0;
240+}
241+
242 static const struct dsa_switch_ops mt7530_switch_ops = {
243 .get_tag_protocol = mtk_get_tag_protocol,
244 .setup = mt753x_setup,
developer5d148cb2023-06-02 13:08:11 +0800245@@ -2677,12 +2767,28 @@ static const struct mt753x_info mt753x_table[] = {
developer2cdaeb12022-10-04 20:25:05 +0800246 .mac_pcs_an_restart = mt7531_sgmii_restart_an,
247 .mac_pcs_link_up = mt7531_sgmii_link_up_force,
248 },
249+ [ID_MT7988] = {
250+ .id = ID_MT7988,
251+ .sw_setup = mt7988_setup,
252+ .phy_read = mt7531_ind_phy_read,
253+ .phy_write = mt7531_ind_phy_write,
254+ .pad_setup = mt7988_pad_setup,
255+ .cpu_port_config = mt7531_cpu_port_config,
256+ .phy_mode_supported = mt7531_phy_supported,
257+ .mac_port_validate = mt7531_mac_port_validate,
258+ .mac_port_get_state = mt7531_phylink_mac_link_state,
259+ .mac_port_config = mt7531_mac_config,
260+ .mac_pcs_an_restart = mt7531_sgmii_restart_an,
261+ .mac_pcs_link_up = mt7531_sgmii_link_up_force,
262+ },
263+
264 };
developer5d148cb2023-06-02 13:08:11 +0800265
developer2cdaeb12022-10-04 20:25:05 +0800266 static const struct of_device_id mt7530_of_match[] = {
267 { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
268 { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
269 { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
270+ { .compatible = "mediatek,mt7988", .data = &mt753x_table[ID_MT7988], },
271 { /* sentinel */ },
272 };
273 MODULE_DEVICE_TABLE(of, mt7530_of_match);
developer5d148cb2023-06-02 13:08:11 +0800274@@ -2692,6 +2798,7 @@ mt7530_probe(struct mdio_device *mdiodev)
developer2cdaeb12022-10-04 20:25:05 +0800275 {
276 struct mt7530_priv *priv;
277 struct device_node *dn;
278+ struct device_node *switch_node = NULL;
279 int ret;
developer5d148cb2023-06-02 13:08:11 +0800280
developer2cdaeb12022-10-04 20:25:05 +0800281 dn = mdiodev->dev.of_node;
developer5d148cb2023-06-02 13:08:11 +0800282@@ -2761,6 +2868,16 @@ mt7530_probe(struct mdio_device *mdiodev)
developer2cdaeb12022-10-04 20:25:05 +0800283 }
284 }
developer5d148cb2023-06-02 13:08:11 +0800285
developer2cdaeb12022-10-04 20:25:05 +0800286+ switch_node = of_find_node_by_name(NULL, "switch0");
287+ if(switch_node) {
288+ priv->base = of_iomap(switch_node, 0);
289+ if(priv->base == NULL){
290+ dev_err(&mdiodev->dev, "of_iomap failed\n");
291+ return -ENOMEM;
292+ }
293+ priv->direct_access = 1;
294+ }
295+
296 priv->bus = mdiodev->bus;
297 priv->dev = &mdiodev->dev;
298 priv->ds->priv = priv;
developer5d148cb2023-06-02 13:08:11 +0800299@@ -2769,9 +2886,12 @@ mt7530_probe(struct mdio_device *mdiodev)
developer2cdaeb12022-10-04 20:25:05 +0800300 dev_set_drvdata(&mdiodev->dev, priv);
developer5d148cb2023-06-02 13:08:11 +0800301
developer2cdaeb12022-10-04 20:25:05 +0800302 ret = dsa_register_switch(priv->ds);
303- if (ret)
304- return ret;
developer2cdaeb12022-10-04 20:25:05 +0800305+ if (ret) {
306+ if(priv->base)
307+ iounmap(priv->base);
developer5d148cb2023-06-02 13:08:11 +0800308
developer2cdaeb12022-10-04 20:25:05 +0800309+ return ret;
310+ }
311 mt7530_nl_init(&priv);
developer5d148cb2023-06-02 13:08:11 +0800312
developer2cdaeb12022-10-04 20:25:05 +0800313 return 0;
developer5d148cb2023-06-02 13:08:11 +0800314@@ -2796,6 +2916,9 @@ mt7530_remove(struct mdio_device *mdiodev)
developer2cdaeb12022-10-04 20:25:05 +0800315 dsa_unregister_switch(priv->ds);
316 mutex_destroy(&priv->reg_mutex);
developer5d148cb2023-06-02 13:08:11 +0800317
developer2cdaeb12022-10-04 20:25:05 +0800318+ if(priv->base)
319+ iounmap(priv->base);
320+
321 mt7530_nl_exit();
322 }
developer5d148cb2023-06-02 13:08:11 +0800323
324diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
325index 130d7e5ec..7b175c5f2 100644
326--- a/drivers/net/dsa/mt7530.h
327+++ b/drivers/net/dsa/mt7530.h
developer2cdaeb12022-10-04 20:25:05 +0800328@@ -16,6 +16,7 @@ enum mt753x_id {
329 ID_MT7530 = 0,
330 ID_MT7621 = 1,
331 ID_MT7531 = 2,
332+ ID_MT7988 = 3,
333 };
developer5d148cb2023-06-02 13:08:11 +0800334
developer2cdaeb12022-10-04 20:25:05 +0800335 #define NUM_TRGMII_CTRL 5
336@@ -51,11 +52,11 @@ enum mt753x_id {
337 #define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16)
338 #define MT7531_CPU_PMAP_MASK GENMASK(7, 0)
developer5d148cb2023-06-02 13:08:11 +0800339
developer2cdaeb12022-10-04 20:25:05 +0800340-#define MT753X_MIRROR_REG(id) (((id) == ID_MT7531) ? \
341+#define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
342 MT7531_CFC : MT7530_MFC)
343-#define MT753X_MIRROR_EN(id) (((id) == ID_MT7531) ? \
344+#define MT753X_MIRROR_EN(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
345 MT7531_MIRROR_EN : MIRROR_EN)
346-#define MT753X_MIRROR_MASK(id) (((id) == ID_MT7531) ? \
347+#define MT753X_MIRROR_MASK(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
348 MT7531_MIRROR_MASK : MIRROR_MASK)
developer5d148cb2023-06-02 13:08:11 +0800349
developer2cdaeb12022-10-04 20:25:05 +0800350 /* Registers for BPDU and PAE frame control*/
351@@ -261,7 +262,7 @@ enum mt7530_vlan_port_attr {
352 MT7531_FORCE_DPX | \
353 MT7531_FORCE_RX_FC | \
354 MT7531_FORCE_TX_FC)
355-#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \
356+#define PMCR_FORCE_MODE_ID(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
357 MT7531_FORCE_MODE : \
358 PMCR_FORCE_MODE)
359 #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \
360@@ -733,6 +734,8 @@ struct mt7530_priv {
361 struct regulator *core_pwr;
362 struct regulator *io_pwr;
363 struct gpio_desc *reset;
364+ void __iomem *base;
365+ int direct_access;
366 const struct mt753x_info *info;
367 unsigned int id;
368 bool mcm;
developer5d148cb2023-06-02 13:08:11 +0800369--
3702.34.1
371