aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/files-4.19/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mediatek/files-4.19/drivers/net')
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig1
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile4
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c139
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h5
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c87
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h5
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h35
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c12
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c182
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c24
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h8
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h8
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c195
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h22
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.c183
-rw-r--r--target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.h40
16 files changed, 456 insertions, 494 deletions
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig
index cf83c6a436..d9e0230cf0 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Kconfig
@@ -1,4 +1,3 @@
config MT753X_GSW
tristate "Driver for the MediaTek MT753x switch"
-
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile
index 3829bacfe9..7aae451cd1 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/Makefile
@@ -7,5 +7,5 @@ obj-$(CONFIG_MT753X_GSW) += mt753x.o
mt753x-$(CONFIG_SWCONFIG) += mt753x_swconfig.o
mt753x-y += mt753x_mdio.o mt7530.o mt7531.o \
- mt753x_common.o mt753x_nl.o
-
+ mt753x_common.o mt753x_vlan.o \
+ mt753x_nl.o
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c
index 45d4984c1a..014b83be9e 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Driver for MediaTek MT7530 gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/kernel.h>
@@ -276,19 +272,73 @@ static void mt7530_core_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val)
gsw->mmd_write(gsw, 0, 0x1f, reg, val);
}
+static void mt7530_trgmii_setting(struct gsw_mt753x *gsw)
+{
+ u16 i;
+
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, 0x0780);
+ mdelay(1);
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0);
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, 0x87);
+ mdelay(1);
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, 0x87);
+
+ /* PLL BIAS enable */
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP4,
+ RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN);
+ mdelay(1);
+
+ /* PLL LPF enable */
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP4,
+ RG_SYSPLL_DDSFBK_EN |
+ RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN);
+
+ /* sys PLL enable */
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP2,
+ RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
+ (1 << RG_SYSPLL_POSDIV_S));
+
+ /* LCDDDS PWDS */
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP7,
+ (3 << RG_LCCDS_C_S) |
+ RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
+ mdelay(1);
+
+ /* Enable MT7530 TRGMII clock */
+ mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, GSWCK_EN | TRGMIICK_EN);
+
+ /* lower Tx Driving */
+ for (i = 0 ; i < NUM_TRGMII_ODT; i++)
+ mt753x_reg_write(gsw, TRGMII_TD_ODT(i),
+ (4 << TX_DM_DRVP_S) | (4 << TX_DM_DRVN_S));
+}
+
+static void mt7530_rgmii_setting(struct gsw_mt753x *gsw)
+{
+ u32 val;
+
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, 0x0c80);
+ mdelay(1);
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0);
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, 0x87);
+ mdelay(1);
+ mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, 0x87);
+
+ val = mt753x_reg_read(gsw, TRGMII_TXCTRL);
+ val &= ~TXC_INV;
+ mt753x_reg_write(gsw, TRGMII_TXCTRL, val);
+
+ mt753x_reg_write(gsw, TRGMII_TCK_CTRL,
+ (8 << TX_TAP_S) | (0x55 << TX_TRAIN_WD_S));
+}
+
static int mt7530_mac_port_setup(struct gsw_mt753x *gsw)
{
u32 hwstrap, p6ecr = 0, p5mcr, p6mcr, phyad;
- hwstrap = mt753x_reg_read(gsw, HWSTRAP);
+ hwstrap = mt753x_reg_read(gsw, MHWSTRAP);
hwstrap &= ~(P6_INTF_DIS | P5_INTF_MODE_RGMII | P5_INTF_DIS_S);
- hwstrap |= CHG_TRAP | P5_INTF_SEL_GMAC5;
-
- if (gsw->direct_phy_access)
- hwstrap &= ~C_MDIO_BPS_S;
- else
- hwstrap |= C_MDIO_BPS_S;
-
+ hwstrap |= P5_INTF_SEL_GMAC5;
if (!gsw->port5_cfg.enabled) {
p5mcr = FORCE_MODE;
hwstrap |= P5_INTF_DIS_S;
@@ -358,10 +408,11 @@ parse_p6:
switch (gsw->port6_cfg.phy_mode) {
case PHY_INTERFACE_MODE_RGMII:
+ p6ecr = BIT(1);
break;
case PHY_INTERFACE_MODE_TRGMII:
/* set MT7530 central align */
- p6ecr = BIT(1); /* TODO: confirm this */
+ p6ecr = BIT(0);
break;
default:
dev_info(gsw->dev, "%s is not supported by port6\n",
@@ -382,8 +433,7 @@ parse_p6:
static void mt7530_core_pll_setup(struct gsw_mt753x *gsw)
{
- u32 hwstrap, val, ncpo1, ssc_delta;
- int i;
+ u32 hwstrap;
hwstrap = mt753x_reg_read(gsw, HWSTRAP);
@@ -418,48 +468,23 @@ static void mt7530_core_pll_setup(struct gsw_mt753x *gsw)
break;
}
+ hwstrap = mt753x_reg_read(gsw, HWSTRAP);
+ hwstrap |= CHG_TRAP;
+ if (gsw->direct_phy_access)
+ hwstrap &= ~C_MDIO_BPS_S;
+ else
+ hwstrap |= C_MDIO_BPS_S;
+
+ mt753x_reg_write(gsw, MHWSTRAP, hwstrap);
+
if (gsw->port6_cfg.enabled &&
gsw->port6_cfg.phy_mode == PHY_INTERFACE_MODE_TRGMII) {
- ncpo1 = 0x1400;
- ssc_delta = 0x57;
+ mt7530_trgmii_setting(gsw);
} else {
/* RGMII */
- ncpo1 = 0x0c80;
- ssc_delta = 0x87;
+ mt7530_rgmii_setting(gsw);
}
- /* Setup the MT7530 TRGMII Tx Clock */
- mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, ncpo1);
- mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0);
- mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, ssc_delta);
- mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, ssc_delta);
- mt7530_core_reg_write(gsw, CORE_PLL_GROUP4,
- RG_SYSPLL_DDSFBK_EN |
- RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN);
-
- mt7530_core_reg_write(gsw, CORE_PLL_GROUP2,
- RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
- (1 << RG_SYSPLL_POSDIV_S));
-
- mt7530_core_reg_write(gsw, CORE_PLL_GROUP7,
- RG_LCDDS_PCW_NCPO_CHG | (3 << RG_LCCDS_C_S) |
- RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
-
- /* Enable MT7530 TRGMII clock */
- mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, GSWCK_EN | TRGMIICK_EN);
-
- val = mt753x_reg_read(gsw, TRGMII_TXCTRL);
- val &= ~TXC_INV;
- mt753x_reg_write(gsw, TRGMII_TXCTRL, val);
-
- /* lower Tx Driving */
- for (i = 0 ; i < NUM_TRGMII_ODT; i++)
- mt753x_reg_write(gsw, TRGMII_TD_ODT(i),
- (8 << TX_DM_DRVP_S) | (8 << TX_DM_DRVN_S));
-
- mt753x_reg_write(gsw, TRGMII_TCK_CTRL,
- (8 << TX_TAP_S) | (0x55 << TX_TRAIN_WD_S));
-
/* delay setting for 10/1000M */
mt753x_reg_write(gsw, P5RGMIIRXCR,
CSR_RGMII_EDGE_ALIGN |
@@ -519,13 +544,17 @@ static void mt7530_phy_setting(struct gsw_mt753x *gsw)
}
}
+static inline bool get_phy_access_mode(const struct device_node *np)
+{
+ return of_property_read_bool(np, "mt7530,direct-phy-access");
+}
+
static int mt7530_sw_init(struct gsw_mt753x *gsw)
{
int i;
u32 val;
- gsw->direct_phy_access = of_property_read_bool(gsw->dev->of_node,
- "mt7530,direct-phy-access");
+ gsw->direct_phy_access = get_phy_access_mode(gsw->dev->of_node);
/* Force MT7530 to use (in)direct PHY access */
val = mt753x_reg_read(gsw, HWSTRAP);
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h
index b4c8a02861..ef2d68417a 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7530.h
@@ -1,7 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
+ * Copyright (c) 2018 MediaTek Inc.
*/
#ifndef _MT7530_H_
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c
index 4d44141a61..5b9f359168 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Driver for MediaTek MT7531 gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Zhanguo Ju <zhanguo.ju@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/kernel.h>
@@ -66,6 +62,11 @@
/* PHY ENABLE Register bitmap define */
#define PHY_DEV1F 0x1f
#define PHY_DEV1F_REG_44 0x44
+#define PHY_DEV1F_REG_104 0x104
+#define PHY_DEV1F_REG_10A 0x10a
+#define PHY_DEV1F_REG_10B 0x10b
+#define PHY_DEV1F_REG_10C 0x10c
+#define PHY_DEV1F_REG_10D 0x10d
#define PHY_DEV1F_REG_268 0x268
#define PHY_DEV1F_REG_269 0x269
#define PHY_DEV1F_REG_403 0x403
@@ -74,6 +75,8 @@
#define GBE_EFUSE_SETTING BIT(3)
#define PHY_EN_BYPASS_MODE BIT(4)
#define POWER_ON_OFF BIT(5)
+#define PHY_PLL_M GENMASK(9, 8)
+#define PHY_PLL_SEL(x) (((x) << 8) & GENMASK(9, 8))
/* PHY EEE Register bitmap of define */
#define PHY_DEV07 0x07
@@ -142,7 +145,7 @@
#define ANA_PLLGP_CR5 0x78bc
/* GPIO mode define */
-#define GPIO_MODE_REGS(x) (0x7c0c + ((x / 8) * 4))
+#define GPIO_MODE_REGS(x) (0x7c0c + (((x) / 8) * 4))
#define GPIO_MODE_S 4
/* GPIO GROUP IOLB SMT0 Control */
@@ -638,6 +641,68 @@ static int mt7531_set_gpio_pinmux(struct gsw_mt753x *gsw)
return 0;
}
+static void mt7531_phy_pll_setup(struct gsw_mt753x *gsw)
+{
+ u32 hwstrap;
+ u32 val;
+
+ hwstrap = mt753x_reg_read(gsw, HWSTRAP);
+
+ switch ((hwstrap & XTAL_FSEL_M) >> XTAL_FSEL_S) {
+ case XTAL_25MHZ:
+ /* disable pll auto calibration */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_104, 0x608);
+
+ /* change pll sel */
+ val = gsw->mmd_read(gsw, 0, PHY_DEV1F,
+ PHY_DEV1F_REG_403);
+ val &= ~(PHY_PLL_M);
+ val |= PHY_PLL_SEL(3);
+ gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
+
+ /* set divider ratio */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F,
+ PHY_DEV1F_REG_10A, 0x1009);
+
+ /* set divider ratio */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10B, 0x7c6);
+
+ /* capacitance and resistance adjustment */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F,
+ PHY_DEV1F_REG_10C, 0xa8be);
+
+ break;
+ case XTAL_40MHZ:
+ /* disable pll auto calibration */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_104, 0x608);
+
+ /* change pll sel */
+ val = gsw->mmd_read(gsw, 0, PHY_DEV1F,
+ PHY_DEV1F_REG_403);
+ val &= ~(PHY_PLL_M);
+ val |= PHY_PLL_SEL(3);
+ gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
+
+ /* set divider ratio */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F,
+ PHY_DEV1F_REG_10A, 0x1018);
+
+ /* set divider ratio */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10B, 0xc676);
+
+ /* capacitance and resistance adjustment */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F,
+ PHY_DEV1F_REG_10C, 0xd8be);
+ break;
+ }
+
+ /* power down pll. additional delay is not required via mdio access */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10D, 0x10);
+
+ /* power up pll */
+ gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10D, 0x14);
+}
+
static void mt7531_phy_setting(struct gsw_mt753x *gsw)
{
int i;
@@ -694,7 +759,7 @@ static void mt7531_adjust_line_driving(struct gsw_mt753x *gsw, u32 port)
gsw->mmd_write(gsw, port, PHY_DEV1E, RXADC_CONTROL_3, 0x4444);
/* Adjust Line driver current for different mode */
- gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_271, 0x2c63);
+ gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_271, 0x2ca5);
/* Adjust Line driver current for different mode */
gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_272, 0xc6b);
@@ -709,10 +774,10 @@ static void mt7531_adjust_line_driving(struct gsw_mt753x *gsw, u32 port)
gsw->mmd_write(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_41, 0x3333);
/* Adjust TX class AB driver 1 */
- gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_268, 0x3aa);
+ gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_268, 0x388);
/* Adjust TX class AB driver 2 */
- gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_269, 0xaaaa);
+ gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_269, 0x4448);
}
static void mt7531_eee_setting(struct gsw_mt753x *gsw, u32 port)
@@ -797,6 +862,8 @@ static int mt7531_sw_post_init(struct gsw_mt753x *gsw)
int i;
u32 val;
+ mt7531_phy_pll_setup(gsw);
+
/* Internal PHYs are disabled by default. SW should enable them.
* Note that this may already be enabled in bootloader stage.
*/
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h
index 736cb0c349..e4ef81e94a 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt7531.h
@@ -1,7 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
+ * Copyright (c) 2018 MediaTek Inc.
*/
#ifndef _MT7531_H_
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h
index b9bca5416f..317b31ddcc 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x.h
@@ -1,11 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Driver for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _MT753X_H_
@@ -22,13 +18,10 @@
#include <linux/switch.h>
#endif
+#include "mt753x_vlan.h"
+
#define MT753X_DFL_CPU_PORT 6
-#define MT753X_NUM_PORTS 7
#define MT753X_NUM_PHYS 5
-#define MT753X_NUM_VLANS 4095
-
-#define MT753X_MAX_VID 4095
-#define MT753X_MIN_VID 0
#define MT753X_DFL_SMI_ADDR 0x1f
#define MT753X_SMI_ADDR_MASK 0x1f
@@ -40,16 +33,6 @@ enum mt753x_model {
MT7531 = 0x7531
};
-struct mt753x_port_entry {
- u16 pvid;
-};
-
-struct mt753x_vlan_entry {
- u16 vid;
- u8 member;
- u8 etags;
-};
-
struct mt753x_port_cfg {
struct device_node *np;
int phy_mode;
@@ -82,7 +65,7 @@ struct gsw_mt753x {
struct mt753x_port_cfg port5_cfg;
struct mt753x_port_cfg port6_cfg;
- bool phy_status_poll;
+ int phy_status_poll;
struct mt753x_phy phys[MT753X_NUM_PHYS];
int phy_link_sts;
@@ -93,14 +76,13 @@ struct gsw_mt753x {
#ifdef CONFIG_SWCONFIG
struct switch_dev swdev;
+ u32 cpu_port;
+#endif
+ int global_vlan_enable;
struct mt753x_vlan_entry vlan_entries[MT753X_NUM_VLANS];
struct mt753x_port_entry port_entries[MT753X_NUM_PORTS];
- int global_vlan_enable;
- u32 cpu_port;
-#endif
-
int (*mii_read)(struct gsw_mt753x *gsw, int phy, int reg);
void (*mii_write)(struct gsw_mt753x *gsw, int phy, int reg, u16 val);
@@ -228,5 +210,4 @@ void mt753x_irq_enable(struct gsw_mt753x *gsw);
#define MT753X_REG_PAGE_ADDR_M 0xffc0
#define MT753X_REG_ADDR_S 2
#define MT753X_REG_ADDR_M 0x3c
-
#endif /* _MT753X_H_ */
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c
index c836a63607..18f925956d 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_common.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Common part for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/kernel.h>
@@ -56,8 +52,8 @@ static void display_port_link_status(struct gsw_mt753x *gsw, u32 port)
}
if (pmsr & MAC_LNK_STS) {
- dev_info(gsw->dev, "Port %d Link is Up - %s/%s\n",
- port, speed, (pmsr & MAC_DPX_STS) ? "Full" : "Half");
+ dev_info(gsw->dev, "Port %d Link is Up - %s/%s\n",
+ port, speed, (pmsr & MAC_DPX_STS) ? "Full" : "Half");
} else {
dev_info(gsw->dev, "Port %d Link is Down\n", port);
}
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
index 695713eed4..8a9a45c0be 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_mdio.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Driver for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/kernel.h>
@@ -232,6 +228,11 @@ void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
mutex_unlock(&gsw->mii_lock);
}
+static inline int mt753x_get_duplex(const struct device_node *np)
+{
+ return of_property_read_bool(np, "full-duplex");
+}
+
static void mt753x_load_port_cfg(struct gsw_mt753x *gsw)
{
struct device_node *port_np;
@@ -279,9 +280,7 @@ static void mt753x_load_port_cfg(struct gsw_mt753x *gsw)
u32 speed;
port_cfg->force_link = 1;
- port_cfg->duplex = of_property_read_bool(
- fixed_link_node,
- "full-duplex");
+ port_cfg->duplex = mt753x_get_duplex(fixed_link_node);
if (of_property_read_u32(fixed_link_node, "speed",
&speed)) {
@@ -331,6 +330,7 @@ static void mt753x_remove_gsw(struct gsw_mt753x *gsw)
mutex_unlock(&mt753x_devs_lock);
}
+
struct gsw_mt753x *mt753x_get_gsw(u32 id)
{
struct gsw_mt753x *dev;
@@ -416,150 +416,6 @@ static int mt753x_hw_reset(struct gsw_mt753x *gsw)
return 0;
}
-static int mt753x_mdio_read(struct mii_bus *bus, int addr, int reg)
-{
- struct gsw_mt753x *gsw = bus->priv;
-
- return gsw->mii_read(gsw, addr, reg);
-}
-
-static int mt753x_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
-{
- struct gsw_mt753x *gsw = bus->priv;
-
- gsw->mii_write(gsw, addr, reg, val);
-
- return 0;
-}
-
-static const struct net_device_ops mt753x_dummy_netdev_ops = {
-};
-
-static void mt753x_phy_link_handler(struct net_device *dev)
-{
- struct mt753x_phy *phy = container_of(dev, struct mt753x_phy, netdev);
- struct phy_device *phydev = phy->phydev;
- struct gsw_mt753x *gsw = phy->gsw;
- u32 port = phy - gsw->phys;
-
- if (phydev->link) {
- dev_info(gsw->dev,
- "Port %d Link is Up - %s/%s - flow control %s\n",
- port, phy_speed_to_str(phydev->speed),
- (phydev->duplex == DUPLEX_FULL) ? "Full" : "Half",
- phydev->pause ? "rx/tx" : "off");
- } else {
- dev_info(gsw->dev, "Port %d Link is Down\n", port);
- }
-}
-
-static void mt753x_connect_internal_phys(struct gsw_mt753x *gsw,
- struct device_node *mii_np)
-{
- struct device_node *phy_np;
- struct mt753x_phy *phy;
- int phy_mode;
- u32 phyad;
-
- if (!mii_np)
- return;
-
- for_each_child_of_node(mii_np, phy_np) {
- if (of_property_read_u32(phy_np, "reg", &phyad))
- continue;
-
- if (phyad >= MT753X_NUM_PHYS)
- continue;
-
- phy_mode = of_get_phy_mode(phy_np);
- if (phy_mode < 0) {
- dev_info(gsw->dev, "incorrect phy-mode %d for PHY %d\n",
- phy_mode, phyad);
- continue;
- }
-
- phy = &gsw->phys[phyad];
- phy->gsw = gsw;
-
- init_dummy_netdev(&phy->netdev);
- phy->netdev.netdev_ops = &mt753x_dummy_netdev_ops;
-
- phy->phydev = of_phy_connect(&phy->netdev, phy_np,
- mt753x_phy_link_handler, 0, phy_mode);
- if (!phy->phydev) {
- dev_info(gsw->dev, "could not connect to PHY %d\n",
- phyad);
- continue;
- }
-
- phy_start(phy->phydev);
- }
-}
-
-static void mt753x_disconnect_internal_phys(struct gsw_mt753x *gsw)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(gsw->phys); i++) {
- if (gsw->phys[i].phydev) {
- phy_stop(gsw->phys[i].phydev);
- phy_disconnect(gsw->phys[i].phydev);
- gsw->phys[i].phydev = NULL;
- }
- }
-}
-
-static int mt753x_mdio_register(struct gsw_mt753x *gsw)
-{
- struct device_node *mii_np;
- int i, ret;
-
- mii_np = of_get_child_by_name(gsw->dev->of_node, "mdio-bus");
- if (mii_np && !of_device_is_available(mii_np)) {
- ret = -ENODEV;
- goto err_put_node;
- }
-
- gsw->gphy_bus = devm_mdiobus_alloc(gsw->dev);
- if (!gsw->gphy_bus) {
- ret = -ENOMEM;
- goto err_put_node;
- }
-
- gsw->gphy_bus->name = "mt753x_mdio";
- gsw->gphy_bus->read = mt753x_mdio_read;
- gsw->gphy_bus->write = mt753x_mdio_write;
- gsw->gphy_bus->priv = gsw;
- gsw->gphy_bus->parent = gsw->dev;
- gsw->gphy_bus->phy_mask = BIT(MT753X_NUM_PHYS) - 1;
-
- for (i = 0; i < PHY_MAX_ADDR; i++)
- gsw->gphy_bus->irq[i] = PHY_POLL;
-
- if (mii_np)
- snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "%s@%s",
- mii_np->name, gsw->dev->of_node->name);
- else
- snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "mdio@%s",
- gsw->dev->of_node->name);
-
- ret = of_mdiobus_register(gsw->gphy_bus, mii_np);
-
- if (ret) {
- devm_mdiobus_free(gsw->dev, gsw->gphy_bus);
- gsw->gphy_bus = NULL;
- } else {
- if (gsw->phy_status_poll)
- mt753x_connect_internal_phys(gsw, mii_np);
- }
-
-err_put_node:
- if (mii_np)
- of_node_put(mii_np);
-
- return ret;
-}
-
static irqreturn_t mt753x_irq_handler(int irq, void *dev)
{
struct gsw_mt753x *gsw = dev;
@@ -580,6 +436,7 @@ static int mt753x_probe(struct platform_device *pdev)
struct mii_bus *mdio_bus;
int ret = -EINVAL;
struct chip_rev rev;
+ struct mt753x_mapping *map;
int i;
mdio = of_parse_phandle(np, "mediatek,mdio", 0);
@@ -599,12 +456,21 @@ static int mt753x_probe(struct platform_device *pdev)
mutex_init(&gsw->mii_lock);
/* Switch hard reset */
- mt753x_hw_reset(gsw);
+ if (mt753x_hw_reset(gsw))
+ goto fail;
/* Fetch the SMI address dirst */
if (of_property_read_u32(np, "mediatek,smi-addr", &gsw->smi_addr))
gsw->smi_addr = MT753X_DFL_SMI_ADDR;
+ /* Get LAN/WAN port mapping */
+ map = mt753x_find_mapping(np);
+ if (map) {
+ mt753x_apply_mapping(gsw, map);
+ gsw->global_vlan_enable = 1;
+ dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name);
+ }
+
/* Load MAC port configurations */
mt753x_load_port_cfg(gsw);
@@ -653,11 +519,7 @@ static int mt753x_probe(struct platform_device *pdev)
mt753x_add_gsw(gsw);
- mt753x_mdio_register(gsw);
-
-#ifdef CONFIG_SWCONFIG
mt753x_swconfig_init(gsw);
-#endif
if (sw->post_init)
sw->post_init(gsw);
@@ -687,10 +549,6 @@ static int mt753x_remove(struct platform_device *pdev)
mt753x_swconfig_destroy(gsw);
#endif
- mt753x_disconnect_internal_phys(gsw);
-
- mdiobus_unregister(gsw->gphy_bus);
-
mt753x_remove_gsw(gsw);
platform_set_drvdata(pdev, NULL);
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c
index 756df4e21f..78aecd34ed 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Configuration layer for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/types.h>
@@ -17,10 +13,6 @@
#include "mt753x.h"
#include "mt753x_nl.h"
-#define MT753X_NL_CMD_REQ_ATTRS(attr) \
- .required_attrs = attr, \
- .nr_required_attrs = ARRAY_SIZE(attr),
-
struct mt753x_nl_cmd_item {
enum mt753x_cmd cmd;
bool require_dev;
@@ -61,7 +53,6 @@ static const struct genl_ops mt753x_nl_ops[] = {
};
static struct genl_family mt753x_nl_family = {
-// .id = GENL_ID_GENERATE,
.name = MT753X_GENL_NAME,
.version = MT753X_GENL_VERSION,
.maxattr = MT753X_NR_ATTR_TYPE,
@@ -208,7 +199,8 @@ static int mt753x_nl_reply_read(struct genl_info *info, struct gsw_mt753x *gsw)
{
struct sk_buff *rep_skb = NULL;
s32 phy, devad, reg;
- int ret, value;
+ int value;
+ int ret = 0;
phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1);
devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1);
@@ -252,7 +244,7 @@ static int mt753x_nl_reply_write(struct genl_info *info, struct gsw_mt753x *gsw)
struct sk_buff *rep_skb = NULL;
s32 phy, devad, reg;
u32 value;
- int ret;
+ int ret = 0;
phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1);
devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1);
@@ -312,12 +304,14 @@ static const struct mt753x_nl_cmd_item mt753x_nl_cmds[] = {
.cmd = MT753X_CMD_READ,
.require_dev = true,
.process = mt753x_nl_reply_read,
- MT753X_NL_CMD_REQ_ATTRS(mt753x_nl_cmd_read_attrs)
+ .required_attrs = mt753x_nl_cmd_read_attrs,
+ .nr_required_attrs = ARRAY_SIZE(mt753x_nl_cmd_read_attrs),
}, {
.cmd = MT753X_CMD_WRITE,
.require_dev = true,
.process = mt753x_nl_reply_write,
- MT753X_NL_CMD_REQ_ATTRS(mt753x_nl_cmd_write_attrs)
+ .required_attrs = mt753x_nl_cmd_write_attrs,
+ .nr_required_attrs = ARRAY_SIZE(mt753x_nl_cmd_write_attrs),
}
};
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h
index f6a1df34e6..3c06273802 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_nl.h
@@ -1,11 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Driver for MediaTek MT753x gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _MT753X_NL_H_
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h
index 15255277ab..0c91b8e0ec 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_regs.h
@@ -1,11 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Register definitions for MediaTek MT753x Gigabit switches
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _MT753X_REGS_H_
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c
index fb2ee1c1b7..b601b90fb1 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * OpenWrt swconfig support for MediaTek MT753x Gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/if.h>
@@ -93,64 +89,6 @@ enum {
MT753X_ATTR_ENABLE_VLAN,
};
-struct mt753x_mapping {
- char *name;
- u16 pvids[MT753X_NUM_PORTS];
- u8 members[MT753X_NUM_VLANS];
- u8 etags[MT753X_NUM_VLANS];
- u16 vids[MT753X_NUM_VLANS];
-} mt753x_defaults[] = {
- {
- .name = "llllw",
- .pvids = { 1, 1, 1, 1, 2, 2, 1 },
- .members = { 0, 0x4f, 0x30 },
- .etags = { 0, 0, 0 },
- .vids = { 0, 1, 2 },
- }, {
- .name = "wllll",
- .pvids = { 2, 1, 1, 1, 1, 2, 1 },
- .members = { 0, 0x5e, 0x21 },
- .etags = { 0, 0, 0 },
- .vids = { 0, 1, 2 },
- }, {
- .name = "lwlll",
- .pvids = { 1, 2, 1, 1, 1, 2, 1 },
- .members = { 0, 0x5d, 0x22 },
- .etags = { 0, 0, 0 },
- .vids = { 0, 1, 2 },
- },
-};
-
-struct mt753x_mapping *mt753x_find_mapping(struct device_node *np)
-{
- const char *map;
- int i;
-
- if (of_property_read_string(np, "mediatek,portmap", &map))
- return NULL;
-
- for (i = 0; i < ARRAY_SIZE(mt753x_defaults); i++)
- if (!strcmp(map, mt753x_defaults[i].name))
- return &mt753x_defaults[i];
-
- return NULL;
-}
-
-static void mt753x_apply_mapping(struct gsw_mt753x *gsw,
- struct mt753x_mapping *map)
-{
- int i = 0;
-
- for (i = 0; i < MT753X_NUM_PORTS; i++)
- gsw->port_entries[i].pvid = map->pvids[i];
-
- for (i = 0; i < MT753X_NUM_VLANS; i++) {
- gsw->vlan_entries[i].member = map->members[i];
- gsw->vlan_entries[i].etags = map->etags[i];
- gsw->vlan_entries[i].vid = map->vids[i];
- }
-}
-
static int mt753x_get_vlan_enable(struct switch_dev *dev,
const struct switch_attr *attr,
struct switch_val *val)
@@ -201,27 +139,6 @@ static int mt753x_set_port_pvid(struct switch_dev *dev, int port, int pvid)
return 0;
}
-static void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val)
-{
- int i;
-
- mt753x_reg_write(gsw, VTCR,
- VTCR_BUSY | ((cmd << VTCR_FUNC_S) & VTCR_FUNC_M) |
- (val & VTCR_VID_M));
-
- for (i = 0; i < 300; i++) {
- u32 val = mt753x_reg_read(gsw, VTCR);
-
- if ((val & VTCR_BUSY) == 0)
- break;
-
- usleep_range(1000, 1100);
- }
-
- if (i == 300)
- dev_info(gsw->dev, "vtcr timeout\n");
-}
-
static int mt753x_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
{
struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
@@ -447,114 +364,16 @@ static void mt753x_port_isolation(struct gsw_mt753x *gsw)
(VA_TRANSPARENT_PORT << VLAN_ATTR_S));
}
-static void mt753x_write_vlan_entry(struct gsw_mt753x *gsw, int vlan, u16 vid,
- u8 ports, u8 etags)
-{
- int port;
- u32 val;
-
- /* vlan port membership */
- if (ports)
- mt753x_reg_write(gsw, VAWD1,
- IVL_MAC | VTAG_EN | VENTRY_VALID |
- ((ports << PORT_MEM_S) & PORT_MEM_M));
- else
- mt753x_reg_write(gsw, VAWD1, 0);
-
- /* egress mode */
- val = 0;
- for (port = 0; port < MT753X_NUM_PORTS; port++) {
- if (etags & BIT(port))
- val |= ETAG_CTRL_TAG << PORT_ETAG_S(port);
- else
- val |= ETAG_CTRL_UNTAG << PORT_ETAG_S(port);
- }
- mt753x_reg_write(gsw, VAWD2, val);
-
- /* write to vlan table */
- mt753x_vlan_ctrl(gsw, VTCR_WRITE_VLAN_ENTRY, vid);
-}
-
static int mt753x_apply_config(struct switch_dev *dev)
{
struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
- int i, j;
- u8 tag_ports;
- u8 untag_ports;
if (!gsw->global_vlan_enable) {
mt753x_port_isolation(gsw);
return 0;
}
- /* set all ports as security mode */
- for (i = 0; i < MT753X_NUM_PORTS; i++)
- mt753x_reg_write(gsw, PCR(i),
- PORT_MATRIX_M | SECURITY_MODE);
-
- /* check if a port is used in tag/untag vlan egress mode */
- tag_ports = 0;
- untag_ports = 0;
-
- for (i = 0; i < MT753X_NUM_VLANS; i++) {
- u8 member = gsw->vlan_entries[i].member;
- u8 etags = gsw->vlan_entries[i].etags;
-
- if (!member)
- continue;
-
- for (j = 0; j < MT753X_NUM_PORTS; j++) {
- if (!(member & BIT(j)))
- continue;
-
- if (etags & BIT(j))
- tag_ports |= 1u << j;
- else
- untag_ports |= 1u << j;
- }
- }
-
- /* set all untag-only ports as transparent and the rest as user port */
- for (i = 0; i < MT753X_NUM_PORTS; i++) {
- u32 pvc_mode = 0x8100 << STAG_VPID_S;
-
- if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
- pvc_mode = (0x8100 << STAG_VPID_S) |
- (VA_TRANSPARENT_PORT << VLAN_ATTR_S);
-
- mt753x_reg_write(gsw, PVC(i), pvc_mode);
- }
-
- /* first clear the swtich vlan table */
- for (i = 0; i < MT753X_NUM_VLANS; i++)
- mt753x_write_vlan_entry(gsw, i, i, 0, 0);
-
- /* now program only vlans with members to avoid
- * clobbering remapped entries in later iterations
- */
- for (i = 0; i < MT753X_NUM_VLANS; i++) {
- u16 vid = gsw->vlan_entries[i].vid;
- u8 member = gsw->vlan_entries[i].member;
- u8 etags = gsw->vlan_entries[i].etags;
-
- if (member)
- mt753x_write_vlan_entry(gsw, i, vid, member, etags);
- }
-
- /* Port Default PVID */
- for (i = 0; i < MT753X_NUM_PORTS; i++) {
- int vlan = gsw->port_entries[i].pvid;
- u16 pvid = 0;
- u32 val;
-
- if (vlan < MT753X_NUM_VLANS && gsw->vlan_entries[vlan].member)
- pvid = gsw->vlan_entries[vlan].vid;
-
- val = mt753x_reg_read(gsw, PPBV1(i));
- val &= ~GRP_PORT_VID_M;
- val |= pvid;
- mt753x_reg_write(gsw, PPBV1(i), val);
- }
+ mt753x_apply_vlan_config(gsw);
return 0;
}
@@ -659,7 +478,6 @@ int mt753x_swconfig_init(struct gsw_mt753x *gsw)
{
struct device_node *np = gsw->dev->of_node;
struct switch_dev *swdev;
- struct mt753x_mapping *map;
int ret;
if (of_property_read_u32(np, "mediatek,cpuport", &gsw->cpu_port))
@@ -676,14 +494,11 @@ int mt753x_swconfig_init(struct gsw_mt753x *gsw)
ret = register_switch(swdev, NULL);
if (ret) {
- dev_err(gsw->dev, "Failed to register switch %s\n",
- swdev->name);
+ dev_notice(gsw->dev, "Failed to register switch %s\n",
+ swdev->name);
return ret;
}
- map = mt753x_find_mapping(gsw->dev->of_node);
- if (map)
- mt753x_apply_mapping(gsw, map);
mt753x_apply_config(swdev);
return 0;
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h
index 971a2cc90a..b877d8957e 100644
--- a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_swconfig.h
@@ -1,19 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- * OpenWrt swconfig support for MediaTek MT753x Gigabit switch
- *
- * Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
- *
+ * Copyright (c) 2018 MediaTek Inc.
* Author: Weijie Gao <weijie.gao@mediatek.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _MT753X_SWCONFIG_H_
#define _MT753X_SWCONFIG_H_
+#ifdef CONFIG_SWCONFIG
#include <linux/switch.h>
+#include "mt753x.h"
int mt753x_swconfig_init(struct gsw_mt753x *gsw);
void mt753x_swconfig_destroy(struct gsw_mt753x *gsw);
+#else
+static inline int mt753x_swconfig_init(struct gsw_mt753x *gsw)
+{
+ mt753x_apply_vlan_config(gsw);
+
+ return 0;
+}
+
+static inline void mt753x_swconfig_destroy(struct gsw_mt753x *gsw)
+{
+}
+#endif
#endif /* _MT753X_SWCONFIG_H_ */
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.c b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.c
new file mode 100644
index 0000000000..f3c8c38f3e
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#include "mt753x.h"
+#include "mt753x_regs.h"
+
+struct mt753x_mapping mt753x_def_mapping[] = {
+ {
+ .name = "llllw",
+ .pvids = { 1, 1, 1, 1, 2, 2, 1 },
+ .members = { 0, 0x4f, 0x30 },
+ .etags = { 0, 0, 0 },
+ .vids = { 0, 1, 2 },
+ }, {
+ .name = "wllll",
+ .pvids = { 2, 1, 1, 1, 1, 2, 1 },
+ .members = { 0, 0x5e, 0x21 },
+ .etags = { 0, 0, 0 },
+ .vids = { 0, 1, 2 },
+ }, {
+ .name = "lwlll",
+ .pvids = { 1, 2, 1, 1, 1, 2, 1 },
+ .members = { 0, 0x5d, 0x22 },
+ .etags = { 0, 0, 0 },
+ .vids = { 0, 1, 2 },
+ },
+};
+
+void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val)
+{
+ int i;
+
+ mt753x_reg_write(gsw, VTCR,
+ VTCR_BUSY | ((cmd << VTCR_FUNC_S) & VTCR_FUNC_M) |
+ (val & VTCR_VID_M));
+
+ for (i = 0; i < 300; i++) {
+ u32 val = mt753x_reg_read(gsw, VTCR);
+
+ if ((val & VTCR_BUSY) == 0)
+ break;
+
+ usleep_range(1000, 1100);
+ }
+
+ if (i == 300)
+ dev_info(gsw->dev, "vtcr timeout\n");
+}
+
+static void mt753x_write_vlan_entry(struct gsw_mt753x *gsw, int vlan, u16 vid,
+ u8 ports, u8 etags)
+{
+ int port;
+ u32 val;
+
+ /* vlan port membership */
+ if (ports)
+ mt753x_reg_write(gsw, VAWD1,
+ IVL_MAC | VTAG_EN | VENTRY_VALID |
+ ((ports << PORT_MEM_S) & PORT_MEM_M));
+ else
+ mt753x_reg_write(gsw, VAWD1, 0);
+
+ /* egress mode */
+ val = 0;
+ for (port = 0; port < MT753X_NUM_PORTS; port++) {
+ if (etags & BIT(port))
+ val |= ETAG_CTRL_TAG << PORT_ETAG_S(port);
+ else
+ val |= ETAG_CTRL_UNTAG << PORT_ETAG_S(port);
+ }
+ mt753x_reg_write(gsw, VAWD2, val);
+
+ /* write to vlan table */
+ mt753x_vlan_ctrl(gsw, VTCR_WRITE_VLAN_ENTRY, vid);
+}
+
+void mt753x_apply_vlan_config(struct gsw_mt753x *gsw)
+{
+ int i, j;
+ u8 tag_ports;
+ u8 untag_ports;
+
+ /* set all ports as security mode */
+ for (i = 0; i < MT753X_NUM_PORTS; i++)
+ mt753x_reg_write(gsw, PCR(i),
+ PORT_MATRIX_M | SECURITY_MODE);
+
+ /* check if a port is used in tag/untag vlan egress mode */
+ tag_ports = 0;
+ untag_ports = 0;
+
+ for (i = 0; i < MT753X_NUM_VLANS; i++) {
+ u8 member = gsw->vlan_entries[i].member;
+ u8 etags = gsw->vlan_entries[i].etags;
+
+ if (!member)
+ continue;
+
+ for (j = 0; j < MT753X_NUM_PORTS; j++) {
+ if (!(member & BIT(j)))
+ continue;
+
+ if (etags & BIT(j))
+ tag_ports |= 1u << j;
+ else
+ untag_ports |= 1u << j;
+ }
+ }
+
+ /* set all untag-only ports as transparent and the rest as user port */
+ for (i = 0; i < MT753X_NUM_PORTS; i++) {
+ u32 pvc_mode = 0x8100 << STAG_VPID_S;
+
+ if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
+ pvc_mode = (0x8100 << STAG_VPID_S) |
+ (VA_TRANSPARENT_PORT << VLAN_ATTR_S);
+
+ mt753x_reg_write(gsw, PVC(i), pvc_mode);
+ }
+
+ /* first clear the switch vlan table */
+ for (i = 0; i < MT753X_NUM_VLANS; i++)
+ mt753x_write_vlan_entry(gsw, i, i, 0, 0);
+
+ /* now program only vlans with members to avoid
+ * clobbering remapped entries in later iterations
+ */
+ for (i = 0; i < MT753X_NUM_VLANS; i++) {
+ u16 vid = gsw->vlan_entries[i].vid;
+ u8 member = gsw->vlan_entries[i].member;
+ u8 etags = gsw->vlan_entries[i].etags;
+
+ if (member)
+ mt753x_write_vlan_entry(gsw, i, vid, member, etags);
+ }
+
+ /* Port Default PVID */
+ for (i = 0; i < MT753X_NUM_PORTS; i++) {
+ int vlan = gsw->port_entries[i].pvid;
+ u16 pvid = 0;
+ u32 val;
+
+ if (vlan < MT753X_NUM_VLANS && gsw->vlan_entries[vlan].member)
+ pvid = gsw->vlan_entries[vlan].vid;
+
+ val = mt753x_reg_read(gsw, PPBV1(i));
+ val &= ~GRP_PORT_VID_M;
+ val |= pvid;
+ mt753x_reg_write(gsw, PPBV1(i), val);
+ }
+}
+
+struct mt753x_mapping *mt753x_find_mapping(struct device_node *np)
+{
+ const char *map;
+ int i;
+
+ if (of_property_read_string(np, "mediatek,portmap", &map))
+ return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(mt753x_def_mapping); i++)
+ if (!strcmp(map, mt753x_def_mapping[i].name))
+ return &mt753x_def_mapping[i];
+
+ return NULL;
+}
+
+void mt753x_apply_mapping(struct gsw_mt753x *gsw, struct mt753x_mapping *map)
+{
+ int i = 0;
+
+ for (i = 0; i < MT753X_NUM_PORTS; i++)
+ gsw->port_entries[i].pvid = map->pvids[i];
+
+ for (i = 0; i < MT753X_NUM_VLANS; i++) {
+ gsw->vlan_entries[i].member = map->members[i];
+ gsw->vlan_entries[i].etags = map->etags[i];
+ gsw->vlan_entries[i].vid = map->vids[i];
+ }
+}
diff --git a/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.h b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.h
new file mode 100644
index 0000000000..66c9cf984e
--- /dev/null
+++ b/target/linux/mediatek/files-4.19/drivers/net/phy/mtk/mt753x/mt753x_vlan.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#ifndef _MT753X_VLAN_H_
+#define _MT753X_VLAN_H_
+
+#define MT753X_NUM_PORTS 7
+#define MT753X_NUM_VLANS 4095
+#define MT753X_MAX_VID 4095
+#define MT753X_MIN_VID 0
+
+struct gsw_mt753x;
+
+struct mt753x_port_entry {
+ u16 pvid;
+};
+
+struct mt753x_vlan_entry {
+ u16 vid;
+ u8 member;
+ u8 etags;
+};
+
+struct mt753x_mapping {
+ char *name;
+ u16 pvids[MT753X_NUM_PORTS];
+ u8 members[MT753X_NUM_VLANS];
+ u8 etags[MT753X_NUM_VLANS];
+ u16 vids[MT753X_NUM_VLANS];
+};
+
+extern struct mt753x_mapping mt753x_defaults[];
+
+void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val);
+void mt753x_apply_vlan_config(struct gsw_mt753x *gsw);
+struct mt753x_mapping *mt753x_find_mapping(struct device_node *np);
+void mt753x_apply_mapping(struct gsw_mt753x *gsw, struct mt753x_mapping *map);
+#endif /* _MT753X_VLAN_H_ */