From c18a872825c8dd27a398e4f5b2f98c9b5066d8a9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 7 Sep 2020 17:47:15 +0200 Subject: mediatek: backport the latest version of the mt7531 support patches Fixes unknown unicast flooding issue Signed-off-by: Felix Fietkau --- ...530-Extend-device-data-ready-for-adding-a.patch | 458 +++++++++++++++++++++ 1 file changed, 458 insertions(+) create mode 100644 target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch (limited to 'target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch') diff --git a/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch b/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch new file mode 100644 index 0000000000..5ae3376290 --- /dev/null +++ b/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch @@ -0,0 +1,458 @@ +From: Landen Chao +Date: Fri, 4 Sep 2020 22:21:57 +0800 +Subject: [PATCH] net: dsa: mt7530: Extend device data ready for adding a + new hardware + +Add a structure holding required operations for each device such as device +initialization, PHY port read or write, a checker whether PHY interface is +supported on a certain port, MAC port setup for either bus pad or a +specific PHY interface. + +The patch is done for ready adding a new hardware MT7531, and keep the +same setup logic of existing hardware. + +Signed-off-by: Landen Chao +Signed-off-by: Sean Wang +--- + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -372,8 +372,9 @@ mt7530_fdb_write(struct mt7530_priv *pri + mt7530_write(priv, MT7530_ATA1 + (i * 4), reg[i]); + } + ++/* Setup TX circuit including relevant PAD and driving */ + static int +-mt7530_pad_clk_setup(struct dsa_switch *ds, int mode) ++mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) + { + struct mt7530_priv *priv = ds->priv; + u32 ncpo1, ssc_delta, trgint, i, xtal; +@@ -387,7 +388,7 @@ mt7530_pad_clk_setup(struct dsa_switch * + return -EINVAL; + } + +- switch (mode) { ++ switch (interface) { + case PHY_INTERFACE_MODE_RGMII: + trgint = 0; + /* PLL frequency: 125MHz */ +@@ -409,7 +410,8 @@ mt7530_pad_clk_setup(struct dsa_switch * + } + break; + default: +- dev_err(priv->dev, "xMII mode %d not supported\n", mode); ++ dev_err(priv->dev, "xMII interface %d not supported\n", ++ interface); + return -EINVAL; + } + +@@ -1344,12 +1346,11 @@ mt7530_setup(struct dsa_switch *ds) + return 0; + } + +-static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port, +- unsigned int mode, +- const struct phylink_link_state *state) ++static bool ++mt7530_phy_mode_supported(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state) + { + struct mt7530_priv *priv = ds->priv; +- u32 mcr_cur, mcr_new; + + switch (port) { + case 0: /* Internal phy */ +@@ -1358,33 +1359,114 @@ static void mt7530_phylink_mac_config(st + case 3: + case 4: + if (state->interface != PHY_INTERFACE_MODE_GMII) +- return; ++ goto unsupported; + break; + case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ +- if (priv->p5_interface == state->interface) +- break; + if (!phy_interface_mode_is_rgmii(state->interface) && + state->interface != PHY_INTERFACE_MODE_MII && + state->interface != PHY_INTERFACE_MODE_GMII) +- return; ++ goto unsupported; ++ break; ++ case 6: /* 1st cpu port */ ++ if (state->interface != PHY_INTERFACE_MODE_RGMII && ++ state->interface != PHY_INTERFACE_MODE_TRGMII) ++ goto unsupported; ++ break; ++ default: ++ dev_err(priv->dev, "%s: unsupported port: %i\n", __func__, ++ port); ++ goto unsupported; ++ } ++ ++ return true; ++ ++unsupported: ++ return false; ++} ++ ++static bool ++mt753x_phy_mode_supported(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->phy_mode_supported(ds, port, state); ++} ++ ++static int ++mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->pad_setup(ds, state->interface); ++} ++ ++static int ++mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ /* Only need to setup port5. */ ++ if (port != 5) ++ return 0; ++ ++ mt7530_setup_port5(priv->ds, interface); ++ ++ return 0; ++} ++ ++static int ++mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->mac_port_config(ds, port, mode, state->interface); ++} ++ ++static void ++mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 mcr_cur, mcr_new; ++ ++ if (!mt753x_phy_mode_supported(ds, port, state)) ++ goto unsupported; ++ ++ switch (port) { ++ case 0: /* Internal phy */ ++ case 1: ++ case 2: ++ case 3: ++ case 4: ++ if (state->interface != PHY_INTERFACE_MODE_GMII) ++ goto unsupported; ++ break; ++ case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ ++ if (priv->p5_interface == state->interface) ++ break; ++ ++ if (mt753x_mac_config(ds, port, mode, state) < 0) ++ goto unsupported; + +- mt7530_setup_port5(ds, state->interface); + break; + case 6: /* 1st cpu port */ + if (priv->p6_interface == state->interface) + break; + +- if (state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_TRGMII) +- return; ++ mt753x_pad_setup(ds, state); + +- /* Setup TX circuit incluing relevant PAD and driving */ +- mt7530_pad_clk_setup(ds, state->interface); ++ if (mt753x_mac_config(ds, port, mode, state) < 0) ++ goto unsupported; + + priv->p6_interface = state->interface; + break; + default: +- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); ++unsupported: ++ dev_err(ds->dev, "%s: unsupported %s port: %i\n", ++ __func__, phy_modes(state->interface), port); + return; + } + +@@ -1452,61 +1534,44 @@ static void mt7530_phylink_mac_link_up(s + mt7530_set(priv, MT7530_PMCR_P(port), mcr); + } + +-static void mt7530_phylink_validate(struct dsa_switch *ds, int port, +- unsigned long *supported, +- struct phylink_link_state *state) ++static void ++mt7530_mac_port_validate(struct dsa_switch *ds, int port, ++ unsigned long *supported) + { ++ if (port == 5) ++ phylink_set(supported, 1000baseX_Full); ++} ++ ++static void ++mt753x_phylink_validate(struct dsa_switch *ds, int port, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + +- switch (port) { +- case 0: /* Internal phy */ +- case 1: +- case 2: +- case 3: +- case 4: +- if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_GMII) +- goto unsupported; +- break; +- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ +- if (state->interface != PHY_INTERFACE_MODE_NA && +- !phy_interface_mode_is_rgmii(state->interface) && +- state->interface != PHY_INTERFACE_MODE_MII && +- state->interface != PHY_INTERFACE_MODE_GMII) +- goto unsupported; +- break; +- case 6: /* 1st cpu port */ +- if (state->interface != PHY_INTERFACE_MODE_NA && +- state->interface != PHY_INTERFACE_MODE_RGMII && +- state->interface != PHY_INTERFACE_MODE_TRGMII) +- goto unsupported; +- break; +- default: +- dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); +-unsupported: ++ if (state->interface != PHY_INTERFACE_MODE_NA && ++ !mt753x_phy_mode_supported(ds, port, state)) { + linkmode_zero(supported); + return; + } + + phylink_set_port_modes(mask); +- phylink_set(mask, Autoneg); + +- if (state->interface == PHY_INTERFACE_MODE_TRGMII) { +- phylink_set(mask, 1000baseT_Full); +- } else { ++ if (state->interface != PHY_INTERFACE_MODE_TRGMII) { + phylink_set(mask, 10baseT_Half); + phylink_set(mask, 10baseT_Full); + phylink_set(mask, 100baseT_Half); + phylink_set(mask, 100baseT_Full); +- +- if (state->interface != PHY_INTERFACE_MODE_MII) { +- phylink_set(mask, 1000baseT_Half); +- phylink_set(mask, 1000baseT_Full); +- if (port == 5) +- phylink_set(mask, 1000baseX_Full); +- } ++ phylink_set(mask, Autoneg); + } + ++ /* This switch only supports 1G full-duplex. */ ++ if (state->interface != PHY_INTERFACE_MODE_MII) ++ phylink_set(mask, 1000baseT_Full); ++ ++ priv->info->mac_port_validate(ds, port, mask); ++ + phylink_set(mask, Pause); + phylink_set(mask, Asym_Pause); + +@@ -1602,12 +1667,45 @@ static int mt7530_set_mac_eee(struct dsa + return 0; + } + ++static int ++mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port, ++ struct phylink_link_state *state) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->mac_port_get_state(ds, port, state); ++} ++ ++static int ++mt753x_setup(struct dsa_switch *ds) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->sw_setup(ds); ++} ++ ++static int ++mt753x_phy_read(struct dsa_switch *ds, int port, int regnum) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->phy_read(ds, port, regnum); ++} ++ ++static int ++mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ return priv->info->phy_write(ds, port, regnum, val); ++} ++ + static const struct dsa_switch_ops mt7530_switch_ops = { + .get_tag_protocol = mtk_get_tag_protocol, +- .setup = mt7530_setup, ++ .setup = mt753x_setup, + .get_strings = mt7530_get_strings, +- .phy_read = mt7530_phy_read, +- .phy_write = mt7530_phy_write, ++ .phy_read = mt753x_phy_read, ++ .phy_write = mt753x_phy_write, + .get_ethtool_stats = mt7530_get_ethtool_stats, + .get_sset_count = mt7530_get_sset_count, + .port_enable = mt7530_port_enable, +@@ -1624,18 +1722,43 @@ static const struct dsa_switch_ops mt753 + .port_vlan_del = mt7530_port_vlan_del, + .port_mirror_add = mt7530_port_mirror_add, + .port_mirror_del = mt7530_port_mirror_del, +- .phylink_validate = mt7530_phylink_validate, +- .phylink_mac_link_state = mt7530_phylink_mac_link_state, +- .phylink_mac_config = mt7530_phylink_mac_config, ++ .phylink_validate = mt753x_phylink_validate, ++ .phylink_mac_link_state = mt753x_phylink_mac_link_state, ++ .phylink_mac_config = mt753x_phylink_mac_config, + .phylink_mac_link_down = mt7530_phylink_mac_link_down, + .phylink_mac_link_up = mt7530_phylink_mac_link_up, + .get_mac_eee = mt7530_get_mac_eee, + .set_mac_eee = mt7530_set_mac_eee, + }; + ++static const struct mt753x_info mt753x_table[] = { ++ [ID_MT7621] = { ++ .id = ID_MT7621, ++ .sw_setup = mt7530_setup, ++ .phy_read = mt7530_phy_read, ++ .phy_write = mt7530_phy_write, ++ .pad_setup = mt7530_pad_clk_setup, ++ .phy_mode_supported = mt7530_phy_mode_supported, ++ .mac_port_validate = mt7530_mac_port_validate, ++ .mac_port_get_state = mt7530_phylink_mac_link_state, ++ .mac_port_config = mt7530_mac_config, ++ }, ++ [ID_MT7530] = { ++ .id = ID_MT7530, ++ .sw_setup = mt7530_setup, ++ .phy_read = mt7530_phy_read, ++ .phy_write = mt7530_phy_write, ++ .pad_setup = mt7530_pad_clk_setup, ++ .phy_mode_supported = mt7530_phy_mode_supported, ++ .mac_port_validate = mt7530_mac_port_validate, ++ .mac_port_get_state = mt7530_phylink_mac_link_state, ++ .mac_port_config = mt7530_mac_config, ++ }, ++}; ++ + static const struct of_device_id mt7530_of_match[] = { +- { .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, }, +- { .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, }, ++ { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, ++ { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, mt7530_of_match); +@@ -1673,8 +1796,21 @@ mt7530_probe(struct mdio_device *mdiodev + /* Get the hardware identifier from the devicetree node. + * We will need it for some of the clock and regulator setup. + */ +- priv->id = (unsigned int)(unsigned long) +- of_device_get_match_data(&mdiodev->dev); ++ priv->info = of_device_get_match_data(&mdiodev->dev); ++ if (!priv->info) ++ return -EINVAL; ++ ++ /* Sanity check if these required device operations are filled ++ * properly. ++ */ ++ if (!priv->info->sw_setup || !priv->info->pad_setup || ++ !priv->info->phy_read || !priv->info->phy_write || ++ !priv->info->phy_mode_supported || ++ !priv->info->mac_port_validate || ++ !priv->info->mac_port_get_state || !priv->info->mac_port_config) ++ return -EINVAL; ++ ++ priv->id = priv->info->id; + + if (priv->id == ID_MT7530) { + priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -11,7 +11,7 @@ + #define MT7530_NUM_FDB_RECORDS 2048 + #define MT7530_ALL_MEMBERS 0xff + +-enum { ++enum mt753x_id { + ID_MT7530 = 0, + ID_MT7621 = 1, + }; +@@ -451,6 +451,40 @@ static const char *p5_intf_modes(unsigne + } + } + ++/* struct mt753x_info - This is the main data structure for holding the specific ++ * part for each supported device ++ * @sw_setup: Holding the handler to a device initialization ++ * @phy_read: Holding the way reading PHY port ++ * @phy_write: Holding the way writing PHY port ++ * @pad_setup: Holding the way setting up the bus pad for a certain ++ * MAC port ++ * @phy_mode_supported: Check if the PHY type is being supported on a certain ++ * port ++ * @mac_port_validate: Holding the way to set addition validate type for a ++ * certan MAC port ++ * @mac_port_get_state: Holding the way getting the MAC/PCS state for a certain ++ * MAC port ++ * @mac_port_config: Holding the way setting up the PHY attribute to a ++ * certain MAC port ++ */ ++struct mt753x_info { ++ enum mt753x_id id; ++ ++ int (*sw_setup)(struct dsa_switch *ds); ++ int (*phy_read)(struct dsa_switch *ds, int port, int regnum); ++ int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val); ++ int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); ++ bool (*phy_mode_supported)(struct dsa_switch *ds, int port, ++ const struct phylink_link_state *state); ++ void (*mac_port_validate)(struct dsa_switch *ds, int port, ++ unsigned long *supported); ++ int (*mac_port_get_state)(struct dsa_switch *ds, int port, ++ struct phylink_link_state *state); ++ int (*mac_port_config)(struct dsa_switch *ds, int port, ++ unsigned int mode, ++ phy_interface_t interface); ++}; ++ + /* struct mt7530_priv - This is the main data structure for holding the state + * of the driver + * @dev: The device pointer +@@ -476,6 +510,7 @@ struct mt7530_priv { + struct regulator *core_pwr; + struct regulator *io_pwr; + struct gpio_desc *reset; ++ const struct mt753x_info *info; + unsigned int id; + bool mcm; + phy_interface_t p6_interface; -- cgit v1.2.3