aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2020-09-07 17:47:15 +0200
committerFelix Fietkau <nbd@nbd.name>2020-09-09 11:51:47 +0200
commitc18a872825c8dd27a398e4f5b2f98c9b5066d8a9 (patch)
tree84346bfe67bfeb7c3d72bc806e6979297b24d9a0 /target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch
parentd8104c83535634906a4f3bd92f2e59c7fa7ceefd (diff)
downloadupstream-c18a872825c8dd27a398e4f5b2f98c9b5066d8a9.tar.gz
upstream-c18a872825c8dd27a398e4f5b2f98c9b5066d8a9.tar.bz2
upstream-c18a872825c8dd27a398e4f5b2f98c9b5066d8a9.zip
mediatek: backport the latest version of the mt7531 support patches
Fixes unknown unicast flooding issue Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch')
-rw-r--r--target/linux/mediatek/patches-5.4/0603-net-dsa-mt7530-Extend-device-data-ready-for-adding-a.patch458
1 files changed, 458 insertions, 0 deletions
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 <landen.chao@mediatek.com>
+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 <landen.chao@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+---
+
+--- 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;