diff options
Diffstat (limited to 'target/linux/mediatek/patches-4.4/0089-net-mediatek-add-gsw-mt7530-driver.patch')
-rw-r--r-- | target/linux/mediatek/patches-4.4/0089-net-mediatek-add-gsw-mt7530-driver.patch | 2380 |
1 files changed, 0 insertions, 2380 deletions
diff --git a/target/linux/mediatek/patches-4.4/0089-net-mediatek-add-gsw-mt7530-driver.patch b/target/linux/mediatek/patches-4.4/0089-net-mediatek-add-gsw-mt7530-driver.patch deleted file mode 100644 index f035b24e05..0000000000 --- a/target/linux/mediatek/patches-4.4/0089-net-mediatek-add-gsw-mt7530-driver.patch +++ /dev/null @@ -1,2380 +0,0 @@ -From 46f10e3c9c25668efb85babe9ac5e37d019c2794 Mon Sep 17 00:00:00 2001 -From: John Crispin <blogic@openwrt.org> -Date: Mon, 11 Apr 2016 03:11:54 +0200 -Subject: [PATCH 89/91] net: mediatek add gsw/mt7530 driver - -Signed-off-by: John Crispin <blogic@openwrt.org> ---- - drivers/net/ethernet/mediatek/Makefile | 2 +- - drivers/net/ethernet/mediatek/gsw_mt7620.h | 251 +++++++ - drivers/net/ethernet/mediatek/gsw_mt7623.c | 1084 +++++++++++++++++++++++++++ - drivers/net/ethernet/mediatek/mt7530.c | 808 ++++++++++++++++++++ - drivers/net/ethernet/mediatek/mt7530.h | 20 + - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 59 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 + - 7 files changed, 2198 insertions(+), 30 deletions(-) - create mode 100644 drivers/net/ethernet/mediatek/gsw_mt7620.h - create mode 100644 drivers/net/ethernet/mediatek/gsw_mt7623.c - create mode 100644 drivers/net/ethernet/mediatek/mt7530.c - create mode 100644 drivers/net/ethernet/mediatek/mt7530.h - -diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile -index aa3f1c8..82001c4 100644 ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -2,4 +2,4 @@ - # Makefile for the Mediatek SoCs built-in ethernet macs - # - --obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth_soc.o -+obj-$(CONFIG_NET_MEDIATEK_SOC) += mt7530.o gsw_mt7623.o mtk_eth_soc.o -diff --git a/drivers/net/ethernet/mediatek/gsw_mt7620.h b/drivers/net/ethernet/mediatek/gsw_mt7620.h -new file mode 100644 -index 0000000..6fca8f2 ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/gsw_mt7620.h -@@ -0,0 +1,251 @@ -+/* This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org> -+ * Copyright (C) 2009-2016 Felix Fietkau <nbd@nbd.name> -+ * Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com> -+ */ -+ -+#ifndef _RALINK_GSW_MT7620_H__ -+#define _RALINK_GSW_MT7620_H__ -+ -+#define GSW_REG_PHY_TIMEOUT (5 * HZ) -+ -+#define MT7620_GSW_REG_PIAC 0x0004 -+ -+#define GSW_NUM_VLANS 16 -+#define GSW_NUM_VIDS 4096 -+#define GSW_NUM_PORTS 7 -+#define GSW_PORT6 6 -+ -+#define GSW_MDIO_ACCESS BIT(31) -+#define GSW_MDIO_READ BIT(19) -+#define GSW_MDIO_WRITE BIT(18) -+#define GSW_MDIO_START BIT(16) -+#define GSW_MDIO_ADDR_SHIFT 20 -+#define GSW_MDIO_REG_SHIFT 25 -+ -+#define GSW_REG_PORT_PMCR(x) (0x3000 + (x * 0x100)) -+#define GSW_REG_PORT_STATUS(x) (0x3008 + (x * 0x100)) -+#define GSW_REG_SMACCR0 0x3fE4 -+#define GSW_REG_SMACCR1 0x3fE8 -+#define GSW_REG_CKGCR 0x3ff0 -+ -+#define GSW_REG_IMR 0x7008 -+#define GSW_REG_ISR 0x700c -+#define GSW_REG_GPC1 0x7014 -+ -+#define SYSC_REG_CHIP_REV_ID 0x0c -+#define SYSC_REG_CFG 0x10 -+#define SYSC_REG_CFG1 0x14 -+#define RST_CTRL_MCM BIT(2) -+#define SYSC_PAD_RGMII2_MDIO 0x58 -+#define SYSC_GPIO_MODE 0x60 -+ -+#define PORT_IRQ_ST_CHG 0x7f -+ -+#define MT7621_ESW_PHY_POLLING 0x0000 -+#define MT7620_ESW_PHY_POLLING 0x7000 -+ -+#define PMCR_IPG BIT(18) -+#define PMCR_MAC_MODE BIT(16) -+#define PMCR_FORCE BIT(15) -+#define PMCR_TX_EN BIT(14) -+#define PMCR_RX_EN BIT(13) -+#define PMCR_BACKOFF BIT(9) -+#define PMCR_BACKPRES BIT(8) -+#define PMCR_RX_FC BIT(5) -+#define PMCR_TX_FC BIT(4) -+#define PMCR_SPEED(_x) (_x << 2) -+#define PMCR_DUPLEX BIT(1) -+#define PMCR_LINK BIT(0) -+ -+#define PHY_AN_EN BIT(31) -+#define PHY_PRE_EN BIT(30) -+#define PMY_MDC_CONF(_x) ((_x & 0x3f) << 24) -+ -+/* ethernet subsystem config register */ -+#define ETHSYS_SYSCFG0 0x14 -+/* ethernet subsystem clock register */ -+#define ETHSYS_CLKCFG0 0x2c -+#define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11) -+ -+/* p5 RGMII wrapper TX clock control register */ -+#define MT7530_P5RGMIITXCR 0x7b04 -+/* p5 RGMII wrapper RX clock control register */ -+#define MT7530_P5RGMIIRXCR 0x7b00 -+/* TRGMII TDX ODT registers */ -+#define MT7530_TRGMII_TD0_ODT 0x7a54 -+#define MT7530_TRGMII_TD1_ODT 0x7a5c -+#define MT7530_TRGMII_TD2_ODT 0x7a64 -+#define MT7530_TRGMII_TD3_ODT 0x7a6c -+#define MT7530_TRGMII_TD4_ODT 0x7a74 -+#define MT7530_TRGMII_TD5_ODT 0x7a7c -+/* TRGMII TCK ctrl register */ -+#define MT7530_TRGMII_TCK_CTRL 0x7a78 -+/* TRGMII Tx ctrl register */ -+#define MT7530_TRGMII_TXCTRL 0x7a40 -+/* port 6 extended control register */ -+#define MT7530_P6ECR 0x7830 -+/* IO driver control register */ -+#define MT7530_IO_DRV_CR 0x7810 -+/* top signal control register */ -+#define MT7530_TOP_SIG_CTRL 0x7808 -+/* modified hwtrap register */ -+#define MT7530_MHWTRAP 0x7804 -+/* hwtrap status register */ -+#define MT7530_HWTRAP 0x7800 -+/* status interrupt register */ -+#define MT7530_SYS_INT_STS 0x700c -+/* system nterrupt register */ -+#define MT7530_SYS_INT_EN 0x7008 -+/* system control register */ -+#define MT7530_SYS_CTRL 0x7000 -+/* port MAC status register */ -+#define MT7530_PMSR_P(x) (0x3008 + (x * 0x100)) -+/* port MAC control register */ -+#define MT7530_PMCR_P(x) (0x3000 + (x * 0x100)) -+ -+#define MT7621_XTAL_SHIFT 6 -+#define MT7621_XTAL_MASK 0x7 -+#define MT7621_XTAL_25 6 -+#define MT7621_XTAL_40 3 -+#define MT7621_MDIO_DRV_MASK (3 << 4) -+#define MT7621_GE1_MODE_MASK (3 << 12) -+ -+#define TRGMII_TXCTRL_TXC_INV BIT(30) -+#define P6ECR_INTF_MODE_RGMII BIT(1) -+#define P5RGMIIRXCR_C_ALIGN BIT(8) -+#define P5RGMIIRXCR_DELAY_2 BIT(1) -+#define P5RGMIITXCR_DELAY_2 (BIT(8) | BIT(2)) -+ -+/* TOP_SIG_CTRL bits */ -+#define TOP_SIG_CTRL_NORMAL (BIT(17) | BIT(16)) -+ -+/* MHWTRAP bits */ -+#define MHWTRAP_MANUAL BIT(16) -+#define MHWTRAP_P5_MAC_SEL BIT(13) -+#define MHWTRAP_P6_DIS BIT(8) -+#define MHWTRAP_P5_RGMII_MODE BIT(7) -+#define MHWTRAP_P5_DIS BIT(6) -+#define MHWTRAP_PHY_ACCESS BIT(5) -+ -+/* HWTRAP bits */ -+#define HWTRAP_XTAL_SHIFT 9 -+#define HWTRAP_XTAL_MASK 0x3 -+ -+/* SYS_CTRL bits */ -+#define SYS_CTRL_SW_RST BIT(1) -+#define SYS_CTRL_REG_RST BIT(0) -+ -+/* PMCR bits */ -+#define PMCR_IFG_XMIT_96 BIT(18) -+#define PMCR_MAC_MODE BIT(16) -+#define PMCR_FORCE_MODE BIT(15) -+#define PMCR_TX_EN BIT(14) -+#define PMCR_RX_EN BIT(13) -+#define PMCR_BACK_PRES_EN BIT(9) -+#define PMCR_BACKOFF_EN BIT(8) -+#define PMCR_TX_FC_EN BIT(5) -+#define PMCR_RX_FC_EN BIT(4) -+#define PMCR_FORCE_SPEED_1000 BIT(3) -+#define PMCR_FORCE_FDX BIT(1) -+#define PMCR_FORCE_LNK BIT(0) -+#define PMCR_FIXED_LINK (PMCR_IFG_XMIT_96 | PMCR_MAC_MODE | \ -+ PMCR_FORCE_MODE | PMCR_TX_EN | PMCR_RX_EN | \ -+ PMCR_BACK_PRES_EN | PMCR_BACKOFF_EN | \ -+ PMCR_FORCE_SPEED_1000 | PMCR_FORCE_FDX | \ -+ PMCR_FORCE_LNK) -+ -+#define PMCR_FIXED_LINK_FC (PMCR_FIXED_LINK | \ -+ PMCR_TX_FC_EN | PMCR_RX_FC_EN) -+ -+/* TRGMII control registers */ -+#define GSW_INTF_MODE 0x390 -+#define GSW_TRGMII_TD0_ODT 0x354 -+#define GSW_TRGMII_TD1_ODT 0x35c -+#define GSW_TRGMII_TD2_ODT 0x364 -+#define GSW_TRGMII_TD3_ODT 0x36c -+#define GSW_TRGMII_TXCTL_ODT 0x374 -+#define GSW_TRGMII_TCK_ODT 0x37c -+#define GSW_TRGMII_RCK_CTRL 0x300 -+ -+#define INTF_MODE_TRGMII BIT(1) -+#define TRGMII_RCK_CTRL_RX_RST BIT(31) -+ -+ -+/* possible XTAL speed */ -+#define MT7623_XTAL_40 0 -+#define MT7623_XTAL_20 1 -+#define MT7623_XTAL_25 3 -+ -+/* GPIO port control registers */ -+#define GPIO_OD33_CTRL8 0x4c0 -+#define GPIO_BIAS_CTRL 0xed0 -+#define GPIO_DRV_SEL10 0xf00 -+ -+/* on MT7620 the functio of port 4 can be software configured */ -+enum { -+ PORT4_EPHY = 0, -+ PORT4_EXT, -+}; -+ -+/* struct mt7620_gsw - the structure that holds the SoC specific data -+ * @dev: The Device struct -+ * @base: The base address -+ * @piac_offset: The PIAC base may change depending on SoC -+ * @irq: The IRQ we are using -+ * @port4: The port4 mode on MT7620 -+ * @autopoll: Is MDIO autopolling enabled -+ * @ethsys: The ethsys register map -+ * @pctl: The pin control register map -+ * @clk_trgpll: The trgmii pll clock -+ */ -+struct mt7620_gsw { -+ struct mtk_eth *eth; -+ struct device *dev; -+ void __iomem *base; -+ u32 piac_offset; -+ int irq; -+ int port4; -+ unsigned long int autopoll; -+ -+ struct regmap *ethsys; -+ struct regmap *pctl; -+ -+ struct clk *clk_trgpll; -+ -+ int trgmii_force; -+ bool wllll; -+}; -+ -+/* switch register I/O wrappers */ -+void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg); -+u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned reg); -+ -+/* the callback used by the driver core to bringup the switch */ -+int mtk_gsw_init(struct mtk_eth *eth); -+ -+/* MDIO access wrappers */ -+int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); -+int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg); -+void mt7620_mdio_link_adjust(struct mtk_eth *eth, int port); -+int mt7620_has_carrier(struct mtk_eth *eth); -+void mt7620_print_link_state(struct mtk_eth *eth, int port, int link, -+ int speed, int duplex); -+void mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val); -+u32 mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg); -+void mt7530_mdio_m32(struct mt7620_gsw *gsw, u32 mask, u32 set, u32 reg); -+ -+u32 _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, -+ u32 phy_register, u32 write_data); -+u32 _mtk_mdio_read(struct mtk_eth *eth, int phy_addr, int phy_reg); -+void mt7620_handle_carrier(struct mtk_eth *eth); -+ -+#endif -diff --git a/drivers/net/ethernet/mediatek/gsw_mt7623.c b/drivers/net/ethernet/mediatek/gsw_mt7623.c -new file mode 100644 -index 0000000..0c6b8a6 ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/gsw_mt7623.c -@@ -0,0 +1,1084 @@ -+/* This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org> -+ * Copyright (C) 2009-2016 Felix Fietkau <nbd@nbd.name> -+ * Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com> -+ */ -+ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/types.h> -+#include <linux/platform_device.h> -+#include <linux/of_device.h> -+#include <linux/of_irq.h> -+#include <linux/of_gpio.h> -+#include <linux/of_mdio.h> -+#include <linux/clk.h> -+#include <linux/mfd/syscon.h> -+#include <linux/regulator/consumer.h> -+#include <linux/pm_runtime.h> -+#include <linux/regmap.h> -+#include <linux/reset.h> -+#include <linux/mii.h> -+#include <linux/interrupt.h> -+#include <linux/netdevice.h> -+#include <linux/dma-mapping.h> -+#include <linux/phy.h> -+#include <linux/ethtool.h> -+#include <linux/version.h> -+#include <linux/atomic.h> -+ -+#include "mtk_eth_soc.h" -+#include "gsw_mt7620.h" -+#include "mt7530.h" -+ -+#define ETHSYS_CLKCFG0 0x2c -+#define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11) -+ -+void mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val) -+{ -+ _mtk_mdio_write(gsw->eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff); -+ _mtk_mdio_write(gsw->eth, 0x1f, (reg >> 2) & 0xf, val & 0xffff); -+ _mtk_mdio_write(gsw->eth, 0x1f, 0x10, val >> 16); -+} -+ -+u32 mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg) -+{ -+ u16 high, low; -+ -+ _mtk_mdio_write(gsw->eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff); -+ low = _mtk_mdio_read(gsw->eth, 0x1f, (reg >> 2) & 0xf); -+ high = _mtk_mdio_read(gsw->eth, 0x1f, 0x10); -+ -+ return (high << 16) | (low & 0xffff); -+} -+ -+void mt7530_mdio_m32(struct mt7620_gsw *gsw, u32 mask, u32 set, u32 reg) -+{ -+ u32 val = mt7530_mdio_r32(gsw, reg); -+ -+ val &= mask; -+ val |= set; -+ mt7530_mdio_w32(gsw, reg, val); -+} -+ -+void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg) -+{ -+ mtk_w32(gsw->eth, val, reg + 0x10000); -+} -+ -+u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned reg) -+{ -+ return mtk_r32(gsw->eth, reg + 0x10000); -+} -+ -+void mtk_switch_m32(struct mt7620_gsw *gsw, u32 mask, u32 set, unsigned reg) -+{ -+ u32 val = mtk_switch_r32(gsw, reg); -+ -+ val &= mask; -+ val |= set; -+ -+ mtk_switch_w32(gsw, val, reg); -+} -+ -+int mt7623_gsw_config(struct mtk_eth *eth) -+{ -+ if (eth->mii_bus && eth->mii_bus->phy_map[0x1f]) -+ mt7530_probe(eth->dev, NULL, eth->mii_bus, 1); -+ -+ return 0; -+} -+ -+static irqreturn_t gsw_interrupt_mt7623(int irq, void *_eth) -+{ -+ struct mtk_eth *eth = (struct mtk_eth *)_eth; -+ struct mt7620_gsw *gsw = (struct mt7620_gsw *)eth->sw_priv; -+ u32 reg, i; -+ -+ reg = mt7530_mdio_r32(gsw, 0x700c); -+ -+ for (i = 0; i < 5; i++) -+ if (reg & BIT(i)) { -+ unsigned int link; -+ -+ link = mt7530_mdio_r32(gsw, -+ 0x3008 + (i * 0x100)) & 0x1; -+ -+ if (link) -+ dev_info(gsw->dev, -+ "port %d link up\n", i); -+ else -+ dev_info(gsw->dev, -+ "port %d link down\n", i); -+ } -+ -+// mt7620_handle_carrier(eth); -+ mt7530_mdio_w32(gsw, 0x700c, 0x1f); -+ -+ return IRQ_HANDLED; -+} -+ -+static void wait_loop(struct mt7620_gsw *gsw) -+{ -+ int i; -+ int read_data; -+ -+ for (i = 0; i < 320; i = i + 1) -+ read_data = mtk_switch_r32(gsw, 0x610); -+} -+ -+static void trgmii_calibration_7623(struct mt7620_gsw *gsw) -+{ -+ -+ unsigned int tap_a[5] = { 0, 0, 0, 0, 0 }; /* minumum delay for all correct */ -+ unsigned int tap_b[5] = { 0, 0, 0, 0, 0 }; /* maximum delay for all correct */ -+ unsigned int final_tap[5]; -+ unsigned int rxc_step_size; -+ unsigned int rxd_step_size; -+ unsigned int read_data; -+ unsigned int tmp; -+ unsigned int rd_wd; -+ int i; -+ unsigned int err_cnt[5]; -+ unsigned int init_toggle_data; -+ unsigned int err_flag[5]; -+ unsigned int err_total_flag; -+ unsigned int training_word; -+ unsigned int rd_tap; -+ u32 val; -+ -+ u32 TRGMII_7623_base; -+ u32 TRGMII_7623_RD_0; -+ u32 TRGMII_RCK_CTRL; -+ -+ TRGMII_7623_base = 0x300; /* 0xFB110300 */ -+ TRGMII_7623_RD_0 = TRGMII_7623_base + 0x10; -+ TRGMII_RCK_CTRL = TRGMII_7623_base; -+ rxd_step_size = 0x1; -+ rxc_step_size = 0x4; -+ init_toggle_data = 0x00000055; -+ training_word = 0x000000AC; -+ -+ /* RX clock gating in MT7623 */ -+ mtk_switch_m32(gsw, 0x3fffffff, 0, TRGMII_7623_base + 0x04); -+ -+ /* Assert RX reset in MT7623 */ -+ mtk_switch_m32(gsw, 0, 0x80000000, TRGMII_7623_base + 0x00); -+ -+ /* Set TX OE edge in MT7623 */ -+ mtk_switch_m32(gsw, 0, 0x00002000, TRGMII_7623_base + 0x78); -+ -+ /* Disable RX clock gating in MT7623 */ -+ mtk_switch_m32(gsw, 0, 0xC0000000, TRGMII_7623_base + 0x04); -+ -+ /* Release RX reset in MT7623 */ -+ mtk_switch_m32(gsw, 0x7fffffff, 0, TRGMII_7623_base); -+ -+ for (i = 0; i < 5; i++) -+ mtk_switch_m32(gsw, 0, 0x80000000, TRGMII_7623_RD_0 + i * 8); -+ -+ pr_err("Enable Training Mode in MT7530\n"); -+ read_data = mt7530_mdio_r32(gsw, 0x7A40); -+ read_data |= 0xC0000000; -+ mt7530_mdio_w32(gsw, 0x7A40, read_data); /* Enable Training Mode in MT7530 */ -+ err_total_flag = 0; -+ pr_err("Adjust RXC delay in MT7623\n"); -+ read_data = 0x0; -+ while (err_total_flag == 0 && read_data != 0x68) { -+ pr_err("2nd Enable EDGE CHK in MT7623\n"); -+ /* Enable EDGE CHK in MT7623 */ -+ for (i = 0; i < 5; i++) -+ mtk_switch_m32(gsw, 0x4fffffff, 0x40000000, TRGMII_7623_RD_0 + i * 8); -+ -+ wait_loop(gsw); -+ err_total_flag = 1; -+ for (i = 0; i < 5; i++) { -+ err_cnt[i] = -+ mtk_switch_r32(gsw, TRGMII_7623_RD_0 + i * 8) >> 8; -+ err_cnt[i] &= 0x0000000f; -+ rd_wd = mtk_switch_r32(gsw, TRGMII_7623_RD_0 + i * 8) >> 16; -+ rd_wd &= 0x000000ff; -+ val = mtk_switch_r32(gsw, TRGMII_7623_RD_0 + i * 8); -+ pr_err("ERR_CNT = %d, RD_WD =%x, TRGMII_7623_RD_0=%x\n", -+ err_cnt[i], rd_wd, val); -+ if (err_cnt[i] != 0) { -+ err_flag[i] = 1; -+ } else if (rd_wd != 0x55) { -+ err_flag[i] = 1; -+ } else { -+ err_flag[i] = 0; -+ } -+ err_total_flag = err_flag[i] & err_total_flag; -+ } -+ -+ pr_err("2nd Disable EDGE CHK in MT7623\n"); -+ /* Disable EDGE CHK in MT7623 */ -+ for (i = 0; i < 5; i++) -+ mtk_switch_m32(gsw, 0x4fffffff, 0x40000000, TRGMII_7623_RD_0 + i * 8); -+ wait_loop(gsw); -+ pr_err("2nd Disable EDGE CHK in MT7623\n"); -+ /* Adjust RXC delay */ -+ /* RX clock gating in MT7623 */ -+ mtk_switch_m32(gsw, 0x3fffffff, 0, TRGMII_7623_base + 0x04); -+ read_data = mtk_switch_r32(gsw, TRGMII_7623_base); -+ if (err_total_flag == 0) { -+ tmp = (read_data & 0x0000007f) + rxc_step_size; -+ pr_err(" RXC delay = %d\n", tmp); -+ read_data >>= 8; -+ read_data &= 0xffffff80; -+ read_data |= tmp; -+ read_data <<= 8; -+ read_data &= 0xffffff80; -+ read_data |= tmp; -+ mtk_switch_w32(gsw, read_data, TRGMII_7623_base); -+ } else { -+ tmp = (read_data & 0x0000007f) + 16; -+ pr_err(" RXC delay = %d\n", tmp); -+ read_data >>= 8; -+ read_data &= 0xffffff80; -+ read_data |= tmp; -+ read_data <<= 8; -+ read_data &= 0xffffff80; -+ read_data |= tmp; -+ mtk_switch_w32(gsw, read_data, TRGMII_7623_base); -+ } -+ read_data &= 0x000000ff; -+ -+ /* Disable RX clock gating in MT7623 */ -+ mtk_switch_m32(gsw, 0, 0xC0000000, TRGMII_7623_base + 0x04); -+ for (i = 0; i < 5; i++) -+ mtk_switch_m32(gsw, 0, 0x80000000, TRGMII_7623_RD_0 + i * 8); -+ } -+ -+ /* Read RD_WD MT7623 */ -+ for (i = 0; i < 5; i++) { -+ rd_tap = 0; -+ while (err_flag[i] != 0 && rd_tap != 128) { -+ /* Enable EDGE CHK in MT7623 */ -+ mtk_switch_m32(gsw, 0x4fffffff, 0x40000000, TRGMII_7623_RD_0 + i * 8); -+ wait_loop(gsw); -+ -+ read_data = mtk_switch_r32(gsw, TRGMII_7623_RD_0 + i * 8); -+ err_cnt[i] = (read_data >> 8) & 0x0000000f; /* Read MT7623 Errcnt */ -+ rd_wd = (read_data >> 16) & 0x000000ff; -+ if (err_cnt[i] != 0 || rd_wd != 0x55) { -+ err_flag[i] = 1; -+ } else { -+ err_flag[i] = 0; -+ } -+ /* Disable EDGE CHK in MT7623 */ -+ mtk_switch_m32(gsw, 0x4fffffff, 0x40000000, TRGMII_7623_RD_0 + i * 8); -+ wait_loop(gsw); -+ if (err_flag[i] != 0) { -+ rd_tap = (read_data & 0x0000007f) + rxd_step_size; /* Add RXD delay in MT7623 */ -+ read_data = (read_data & 0xffffff80) | rd_tap; -+ mtk_switch_w32(gsw, read_data, -+ TRGMII_7623_RD_0 + i * 8); -+ tap_a[i] = rd_tap; -+ } else { -+ rd_tap = (read_data & 0x0000007f) + 48; -+ read_data = (read_data & 0xffffff80) | rd_tap; -+ mtk_switch_w32(gsw, read_data, -+ TRGMII_7623_RD_0 + i * 8); -+ } -+ -+ } -+ pr_err("MT7623 %dth bit Tap_a = %d\n", i, tap_a[i]); -+ } -+ /* pr_err("Last While Loop\n"); */ -+ for (i = 0; i < 5; i++) { -+ while ((err_flag[i] == 0) && (rd_tap != 128)) { -+ read_data = mtk_switch_r32(gsw, TRGMII_7623_RD_0 + i * 8); -+ rd_tap = (read_data & 0x0000007f) + rxd_step_size; /* Add RXD delay in MT7623 */ -+ read_data = (read_data & 0xffffff80) | rd_tap; -+ mtk_switch_w32(gsw, read_data, TRGMII_7623_RD_0 + i * 8); -+ /* Enable EDGE CHK in MT7623 */ -+ val = -+ mtk_switch_r32(gsw, TRGMII_7623_RD_0 + i * 8) | 0x40000000; -+ val &= 0x4fffffff; -+ mtk_switch_w32(gsw, val, TRGMII_7623_RD_0 + i * 8); -+ wait_loop(gsw); -+ read_data = mtk_switch_r32(gsw, TRGMII_7623_RD_0 + i * 8); -+ err_cnt[i] = (read_data >> 8) & 0x0000000f; /* Read MT7623 Errcnt */ -+ rd_wd = (read_data >> 16) & 0x000000ff; -+ if (err_cnt[i] != 0 || rd_wd != 0x55) { -+ err_flag[i] = 1; -+ } else { -+ err_flag[i] = 0; -+ } -+ -+ /* Disable EDGE CHK in MT7623 */ -+ mtk_switch_m32(gsw, 0x4fffffff, 0x40000000, TRGMII_7623_RD_0 + i * 8); -+ wait_loop(gsw); -+ -+ } -+ -+ tap_b[i] = rd_tap; /* -rxd_step_size; */ -+ pr_err("MT7623 %dth bit Tap_b = %d\n", i, tap_b[i]); -+ final_tap[i] = (tap_a[i] + tap_b[i]) / 2; /* Calculate RXD delay = (TAP_A + TAP_B)/2 */ -+ read_data = (read_data & 0xffffff80) | final_tap[i]; -+ mtk_switch_w32(gsw, read_data, TRGMII_7623_RD_0 + i * 8); -+ } -+ -+ read_data = mt7530_mdio_r32(gsw, 0x7A40); -+ read_data &= 0x3fffffff; -+ mt7530_mdio_w32(gsw, 0x7A40, read_data); -+} -+ -+static void trgmii_calibration_7530(struct mt7620_gsw *gsw) -+{ -+ -+ unsigned int tap_a[5] = { 0, 0, 0, 0, 0 }; -+ unsigned int tap_b[5] = { 0, 0, 0, 0, 0 }; -+ unsigned int final_tap[5]; -+ unsigned int rxc_step_size; -+ unsigned int rxd_step_size; -+ unsigned int read_data; -+ unsigned int tmp = 0; -+ int i; -+ unsigned int err_cnt[5]; -+ unsigned int rd_wd; -+ unsigned int init_toggle_data; -+ unsigned int err_flag[5]; -+ unsigned int err_total_flag; -+ unsigned int training_word; -+ unsigned int rd_tap; -+ -+ u32 TRGMII_7623_base; -+ u32 TRGMII_7530_RD_0; -+ u32 TRGMII_RCK_CTRL; -+ u32 TRGMII_7530_base; -+ u32 TRGMII_7530_TX_base; -+ u32 val; -+ -+ TRGMII_7623_base = 0x300; -+ TRGMII_7530_base = 0x7A00; -+ TRGMII_7530_RD_0 = TRGMII_7530_base + 0x10; -+ TRGMII_RCK_CTRL = TRGMII_7623_base; -+ rxd_step_size = 0x1; -+ rxc_step_size = 0x8; -+ init_toggle_data = 0x00000055; -+ training_word = 0x000000AC; -+ -+ TRGMII_7530_TX_base = TRGMII_7530_base + 0x50; -+ -+ /* pr_err("Calibration begin ........\n"); */ -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x40) | 0x80000000; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x40); -+ read_data = mt7530_mdio_r32(gsw, 0x7a10); -+ /* pr_err("TRGMII_7530_RD_0 is %x\n", read_data); */ -+ -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_base + 0x04); -+ read_data &= 0x3fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base + 0x04, read_data); /* RX clock gating in MT7530 */ -+ -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_base + 0x78); -+ read_data |= 0x00002000; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base + 0x78, read_data); /* Set TX OE edge in MT7530 */ -+ -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_base); -+ read_data |= 0x80000000; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base, read_data); /* Assert RX reset in MT7530 */ -+ -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_base); -+ read_data &= 0x7fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base, read_data); /* Release RX reset in MT7530 */ -+ -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_base + 0x04); -+ read_data |= 0xC0000000; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base + 0x04, read_data); /* Disable RX clock gating in MT7530 */ -+ -+ /* pr_err("Enable Training Mode in MT7623\n"); */ -+ /*Enable Training Mode in MT7623 */ -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x40) | 0x80000000; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x40); -+ if (gsw->trgmii_force == 2000) { -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x40) | 0xC0000000; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x40); -+ } else { -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x40) | 0x80000000; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x40); -+ } -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x078) & 0xfffff0ff; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x078); -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x50) & 0xfffff0ff; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x50); -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x58) & 0xfffff0ff; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x58); -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x60) & 0xfffff0ff; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x60); -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x68) & 0xfffff0ff; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x68); -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x70) & 0xfffff0ff; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x70); -+ val = mtk_switch_r32(gsw, TRGMII_7623_base + 0x78) & 0x00000800; -+ mtk_switch_w32(gsw, val, TRGMII_7623_base + 0x78); -+ err_total_flag = 0; -+ /* pr_err("Adjust RXC delay in MT7530\n"); */ -+ read_data = 0x0; -+ while (err_total_flag == 0 && (read_data != 0x68)) { -+ /* pr_err("2nd Enable EDGE CHK in MT7530\n"); */ -+ /* Enable EDGE CHK in MT7530 */ -+ for (i = 0; i < 5; i++) { -+ read_data = -+ mt7530_mdio_r32(gsw, TRGMII_7530_RD_0 + i * 8); -+ read_data |= 0x40000000; -+ read_data &= 0x4fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, -+ read_data); -+ wait_loop(gsw); -+ /* pr_err("2nd Disable EDGE CHK in MT7530\n"); */ -+ err_cnt[i] = -+ mt7530_mdio_r32(gsw, TRGMII_7530_RD_0 + i * 8); -+ /* pr_err("***** MT7530 %dth bit ERR_CNT =%x\n",i, err_cnt[i]); */ -+ /* pr_err("MT7530 %dth bit ERR_CNT =%x\n",i, err_cnt[i]); */ -+ err_cnt[i] >>= 8; -+ err_cnt[i] &= 0x0000ff0f; -+ rd_wd = err_cnt[i] >> 8; -+ rd_wd &= 0x000000ff; -+ err_cnt[i] &= 0x0000000f; -+ /* read_data = mt7530_mdio_r32(gsw,0x7a10,&read_data); */ -+ if (err_cnt[i] != 0) { -+ err_flag[i] = 1; -+ } else if (rd_wd != 0x55) { -+ err_flag[i] = 1; -+ } else { -+ err_flag[i] = 0; -+ } -+ if (i == 0) { -+ err_total_flag = err_flag[i]; -+ } else { -+ err_total_flag = err_flag[i] & err_total_flag; -+ } -+ /* Disable EDGE CHK in MT7530 */ -+ read_data = -+ mt7530_mdio_r32(gsw, TRGMII_7530_RD_0 + i * 8); -+ read_data |= 0x40000000; -+ read_data &= 0x4fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, -+ read_data); -+ wait_loop(gsw); -+ } -+ /*Adjust RXC delay */ -+ if (err_total_flag == 0) { -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_base); -+ read_data |= 0x80000000; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base, read_data); /* Assert RX reset in MT7530 */ -+ -+ read_data = -+ mt7530_mdio_r32(gsw, TRGMII_7530_base + 0x04); -+ read_data &= 0x3fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base + 0x04, read_data); /* RX clock gating in MT7530 */ -+ -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_base); -+ tmp = read_data; -+ tmp &= 0x0000007f; -+ tmp += rxc_step_size; -+ /* pr_err("Current rxc delay = %d\n", tmp); */ -+ read_data &= 0xffffff80; -+ read_data |= tmp; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base, read_data); -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_base); -+ /* pr_err("Current RXC delay = %x\n", read_data); */ -+ -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_base); -+ read_data &= 0x7fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base, read_data); /* Release RX reset in MT7530 */ -+ -+ read_data = -+ mt7530_mdio_r32(gsw, TRGMII_7530_base + 0x04); -+ read_data |= 0xc0000000; -+ mt7530_mdio_w32(gsw, TRGMII_7530_base + 0x04, read_data); /* Disable RX clock gating in MT7530 */ -+ pr_err("####### MT7530 RXC delay is %d\n", tmp); -+ } -+ read_data = tmp; -+ } -+ pr_err("Finish RXC Adjustment while loop\n"); -+ -+ /* pr_err("Read RD_WD MT7530\n"); */ -+ /* Read RD_WD MT7530 */ -+ for (i = 0; i < 5; i++) { -+ rd_tap = 0; -+ while (err_flag[i] != 0 && rd_tap != 128) { -+ /* Enable EDGE CHK in MT7530 */ -+ read_data = -+ mt7530_mdio_r32(gsw, TRGMII_7530_RD_0 + i * 8); -+ read_data |= 0x40000000; -+ read_data &= 0x4fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, -+ read_data); -+ wait_loop(gsw); -+ err_cnt[i] = (read_data >> 8) & 0x0000000f; -+ rd_wd = (read_data >> 16) & 0x000000ff; -+ if (err_cnt[i] != 0 || rd_wd != 0x55) { -+ err_flag[i] = 1; -+ } else { -+ err_flag[i] = 0; -+ } -+ if (err_flag[i] != 0) { -+ rd_tap = (read_data & 0x0000007f) + rxd_step_size; /* Add RXD delay in MT7530 */ -+ read_data = (read_data & 0xffffff80) | rd_tap; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, -+ read_data); -+ tap_a[i] = rd_tap; -+ } else { -+ tap_a[i] = (read_data & 0x0000007f); /* Record the min delay TAP_A */ -+ rd_tap = tap_a[i] + 0x4; -+ read_data = (read_data & 0xffffff80) | rd_tap; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, -+ read_data); -+ } -+ -+ /* Disable EDGE CHK in MT7530 */ -+ read_data = -+ mt7530_mdio_r32(gsw, TRGMII_7530_RD_0 + i * 8); -+ read_data |= 0x40000000; -+ read_data &= 0x4fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, -+ read_data); -+ wait_loop(gsw); -+ -+ } -+ pr_err("MT7530 %dth bit Tap_a = %d\n", i, tap_a[i]); -+ } -+ -+ /* pr_err("Last While Loop\n"); */ -+ for (i = 0; i < 5; i++) { -+ rd_tap = 0; -+ while (err_flag[i] == 0 && (rd_tap != 128)) { -+ /* Enable EDGE CHK in MT7530 */ -+ read_data = mt7530_mdio_r32(gsw, TRGMII_7530_RD_0 + i * 8); -+ read_data |= 0x40000000; -+ read_data &= 0x4fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, -+ read_data); -+ wait_loop(gsw); -+ err_cnt[i] = (read_data >> 8) & 0x0000000f; -+ rd_wd = (read_data >> 16) & 0x000000ff; -+ if (err_cnt[i] != 0 || rd_wd != 0x55) -+ err_flag[i] = 1; -+ else -+ err_flag[i] = 0; -+ -+ if (err_flag[i] == 0 && (rd_tap != 128)) { -+ /* Add RXD delay in MT7530 */ -+ rd_tap = (read_data & 0x0000007f) + rxd_step_size; -+ read_data = (read_data & 0xffffff80) | rd_tap; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, -+ read_data); -+ } -+ /* Disable EDGE CHK in MT7530 */ -+ read_data = -+ mt7530_mdio_r32(gsw, TRGMII_7530_RD_0 + i * 8); -+ read_data |= 0x40000000; -+ read_data &= 0x4fffffff; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, -+ read_data); -+ wait_loop(gsw); -+ } -+ tap_b[i] = rd_tap; /* - rxd_step_size; */ -+ pr_err("MT7530 %dth bit Tap_b = %d\n", i, tap_b[i]); -+ /* Calculate RXD delay = (TAP_A + TAP_B)/2 */ -+ final_tap[i] = (tap_a[i] + tap_b[i]) / 2; -+ /* pr_err("########****** MT7530 %dth bit Final Tap = %d\n", i, final_tap[i]); */ -+ -+ read_data = (read_data & 0xffffff80) | final_tap[i]; -+ mt7530_mdio_w32(gsw, TRGMII_7530_RD_0 + i * 8, read_data); -+ } -+ -+ if (gsw->trgmii_force == 2000) -+ mtk_switch_m32(gsw, 0x7fffffff, 0, TRGMII_7623_base + 0x40); -+ else -+ mtk_switch_m32(gsw, 0x3fffffff, 0, TRGMII_7623_base + 0x40); -+ -+} -+ -+static void mt7530_trgmii_clock_setting(struct mt7620_gsw *gsw, u32 xtal_mode) -+{ -+ -+ u32 regValue; -+ -+ /* TRGMII Clock */ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x410); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x1); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x404); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ -+ if (xtal_mode == 1) { -+ /* 25MHz */ -+ if (gsw->trgmii_force == 2600) -+ /* 325MHz */ -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x1a00); -+ else if (gsw->trgmii_force == 2000) -+ /* 250MHz */ -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x1400); -+ } else if (xtal_mode == 2) { -+ /* 40MHz */ -+ if (gsw->trgmii_force == 2600) -+ /* 325MHz */ -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x1040); -+ else if (gsw->trgmii_force == 2000) -+ /* 250MHz */ -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x0c80); -+ } -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x405); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x0); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x409); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ if (xtal_mode == 1) -+ /* 25MHz */ -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x0057); -+ else -+ /* 40MHz */ -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x0087); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x40a); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ if (xtal_mode == 1) -+ /* 25MHz */ -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x0057); -+ else -+ /* 40MHz */ -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x0087); -+ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x403); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x1800); -+ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x403); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x1c00); -+ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x401); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0xc020); -+ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x406); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0xa030); -+ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x406); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0xa038); -+ -+// udelay(120); /* for MT7623 bring up test */ -+ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x410); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x3); -+ -+ regValue = mt7530_mdio_r32(gsw, 0x7830); -+ regValue &= 0xFFFFFFFC; -+ regValue |= 0x00000001; -+ mt7530_mdio_w32(gsw, 0x7830, regValue); -+ -+ regValue = mt7530_mdio_r32(gsw, 0x7a40); -+ regValue &= ~(0x1 << 30); -+ regValue &= ~(0x1 << 28); -+ mt7530_mdio_w32(gsw, 0x7a40, regValue); -+ -+ mt7530_mdio_w32(gsw, 0x7a78, 0x55); -+// udelay(100); /* for mt7623 bring up test */ -+ -+ mtk_switch_m32(gsw, 0x7fffffff, 0, 0x300); -+ -+ trgmii_calibration_7623(gsw); -+ trgmii_calibration_7530(gsw); -+ -+ mtk_switch_m32(gsw, 0, 0x80000000, 0x300); -+ mtk_switch_m32(gsw, 0, 0x7fffffff, 0x300); -+ -+ /*MT7530 RXC reset */ -+ regValue = mt7530_mdio_r32(gsw, 0x7a00); -+ regValue |= (0x1 << 31); -+ mt7530_mdio_w32(gsw, 0x7a00, regValue); -+ mdelay(1); -+ regValue &= ~(0x1 << 31); -+ mt7530_mdio_w32(gsw, 0x7a00, regValue); -+ mdelay(100); -+} -+ -+static void mt7623_hw_init(struct mtk_eth *eth, struct mt7620_gsw *gsw, struct device_node *np) -+{ -+ u32 i; -+ u32 val; -+ u32 xtal_mode; -+ -+ regmap_update_bits(gsw->ethsys, ETHSYS_CLKCFG0, -+ ETHSYS_TRGMII_CLK_SEL362_5, -+ ETHSYS_TRGMII_CLK_SEL362_5); -+ -+ /* reset the TRGMII core */ -+ mtk_switch_m32(gsw, 0, INTF_MODE_TRGMII, GSW_INTF_MODE); -+ /* Assert MT7623 RXC reset */ -+ mtk_switch_m32(gsw, 0, TRGMII_RCK_CTRL_RX_RST, GSW_TRGMII_RCK_CTRL); -+ -+ /* Hardware reset Switch */ -+ device_reset(eth->dev); -+ -+ /* Wait for Switch Reset Completed*/ -+ for (i = 0; i < 100; i++) { -+ mdelay(10); -+ if (mt7530_mdio_r32(gsw, MT7530_HWTRAP)) -+ break; -+ } -+ -+ /* turn off all PHYs */ -+ for (i = 0; i <= 4; i++) { -+ val = _mtk_mdio_read(gsw->eth, i, 0x0); -+ val |= BIT(11); -+ _mtk_mdio_write(gsw->eth, i, 0x0, val); -+ } -+ -+ /* reset the switch */ -+ mt7530_mdio_w32(gsw, MT7530_SYS_CTRL, -+ SYS_CTRL_SW_RST | SYS_CTRL_REG_RST); -+ udelay(100); -+ -+ /* GE1, Force 1000M/FD, FC ON */ -+ mt7530_mdio_w32(gsw, MT7530_PMCR_P(6), PMCR_FIXED_LINK_FC); -+ -+ /* GE2, Force 1000M/FD, FC ON */ -+ mt7530_mdio_w32(gsw, MT7530_PMCR_P(5), PMCR_FIXED_LINK_FC); -+ -+ /* Enable Port 6, P5 as GMAC5, P5 disable */ -+ val = mt7530_mdio_r32(gsw, MT7530_MHWTRAP); -+ if (gsw->eth->mac[0] && -+ of_phy_is_fixed_link(gsw->eth->mac[0]->of_node)) -+ /* Enable Port 6 */ -+ val &= ~MHWTRAP_P6_DIS; -+ else -+ /* Disable Port 6 */ -+ val |= MHWTRAP_P6_DIS; -+ if (gsw->eth->mac[1] && -+ of_phy_is_fixed_link(gsw->eth->mac[1]->of_node)) { -+ /* Enable Port 5 */ -+ val &= ~MHWTRAP_P5_DIS; -+ /* Port 5 as PHY */ -+ val &= ~MHWTRAP_P5_MAC_SEL; -+ } else { -+ /* Disable Port 5 */ -+ val |= MHWTRAP_P5_DIS; -+ /* Port 5 as GMAC */ -+ val |= MHWTRAP_P5_MAC_SEL; -+ val |= BIT(7); -+ mt7530_mdio_w32(gsw, MT7530_PMCR_P(5), 0x8000); -+ } -+ /* gphy to port 0/4 */ -+ if (gsw->wllll) -+ val |= BIT(20); -+ else -+ val &= ~BIT(20); -+ -+ /* Set MT7530 phy direct access mode**/ -+ val &= ~MHWTRAP_PHY_ACCESS; -+ /* manual override of HW-Trap */ -+ val |= MHWTRAP_MANUAL; -+ mt7530_mdio_w32(gsw, MT7530_MHWTRAP, val); -+ dev_info(gsw->dev, "Setting MHWTRAP to 0x%08x\n", val); -+ -+ val = mt7530_mdio_r32(gsw, 0x7800); -+ val = (val >> 9) & 0x3; -+ if (val == 0x3) { -+ xtal_mode = 1; -+ /* 25Mhz Xtal - do nothing */ -+ } else if (val == 0x2) { -+ /* 40Mhz */ -+ xtal_mode = 2; -+ -+ /* disable MT7530 core clock */ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x410); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x0); -+ -+ /* disable MT7530 PLL */ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x40d); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x2020); -+ -+ /* for MT7530 core clock = 500Mhz */ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x40e); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x119); -+ -+ /* enable MT7530 PLL */ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x40d); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x2820); -+ -+ udelay(20); -+ -+ /* enable MT7530 core clock */ -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x1f); -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x410); -+ _mtk_mdio_write(gsw->eth, 0, 13, 0x401f); -+ } else { -+ xtal_mode = 3; -+ /* 20Mhz Xtal - TODO */ -+ } -+ -+ /* RGMII */ -+ _mtk_mdio_write(gsw->eth, 0, 14, 0x1); -+ -+ /* set MT7530 central align */ -+ val = mt7530_mdio_r32(gsw, 0x7830); -+ val &= ~1; -+ val |= 1<<1; -+ mt7530_mdio_w32(gsw, 0x7830, val); -+ -+ val = mt7530_mdio_r32(gsw, 0x7a40); -+ val &= ~(1<<30); -+ mt7530_mdio_w32(gsw, 0x7a40, val); -+ -+ mt7530_mdio_w32(gsw, 0x7a78, 0x855); -+ -+ /* delay setting for 10/1000M */ -+ mt7530_mdio_w32(gsw, 0x7b00, 0x104); -+ mt7530_mdio_w32(gsw, 0x7b04, 0x10); -+ -+ /* lower Tx Driving */ -+ mt7530_mdio_w32(gsw, 0x7a54, 0x88); -+ mt7530_mdio_w32(gsw, 0x7a5c, 0x88); -+ mt7530_mdio_w32(gsw, 0x7a64, 0x88); -+ mt7530_mdio_w32(gsw, 0x7a6c, 0x88); -+ mt7530_mdio_w32(gsw, 0x7a74, 0x88); -+ mt7530_mdio_w32(gsw, 0x7a7c, 0x88); -+ mt7530_mdio_w32(gsw, 0x7810, 0x11); -+ -+ /* Set MT7623/MT7683 TX Driving */ -+ mtk_switch_w32(gsw, 0x88, 0x354); -+ mtk_switch_w32(gsw, 0x88, 0x35c); -+ mtk_switch_w32(gsw, 0x88, 0x364); -+ mtk_switch_w32(gsw, 0x88, 0x36c); -+ mtk_switch_w32(gsw, 0x88, 0x374); -+ mtk_switch_w32(gsw, 0x88, 0x37c); -+ -+ /* Set GE2 driving and slew rate */ -+ regmap_write(gsw->pctl, 0xF00, 0xe00); -+ /* set GE2 TDSEL */ -+ regmap_write(gsw->pctl, 0x4C0, 0x5); -+ /* set GE2 TUNE */ -+ regmap_write(gsw->pctl, 0xED0, 0x0); -+ -+ regmap_write(gsw->pctl, 0xb70, 0); -+ regmap_write(gsw->pctl, 0x250, 0xffff); -+ regmap_write(gsw->pctl, 0x260, 0xff); -+ regmap_write(gsw->pctl, 0x380, 0x37); -+ regmap_write(gsw->pctl, 0x390, 0x40); -+ -+ mt7530_trgmii_clock_setting(gsw, xtal_mode); -+ -+ //LANWANPartition(gsw); -+ -+ /* disable EEE */ -+ for (i = 0; i <= 4; i++) { -+ _mtk_mdio_write(gsw->eth, i, 13, 0x7); -+ _mtk_mdio_write(gsw->eth, i, 14, 0x3C); -+ _mtk_mdio_write(gsw->eth, i, 13, 0x4007); -+ _mtk_mdio_write(gsw->eth, i, 14, 0x0); -+ -+ /* Increase SlvDPSready time */ -+ _mtk_mdio_write(gsw->eth, i, 31, 0x52b5); -+ _mtk_mdio_write(gsw->eth, i, 16, 0xafae); -+ _mtk_mdio_write(gsw->eth, i, 18, 0x2f); -+ _mtk_mdio_write(gsw->eth, i, 16, 0x8fae); -+ -+ /* Incease post_update_timer */ -+ _mtk_mdio_write(gsw->eth, i, 31, 0x3); -+ _mtk_mdio_write(gsw->eth, i, 17, 0x4b); -+ -+ /* Adjust 100_mse_threshold */ -+ _mtk_mdio_write(gsw->eth, i, 13, 0x1e); -+ _mtk_mdio_write(gsw->eth, i, 14, 0x123); -+ _mtk_mdio_write(gsw->eth, i, 13, 0x401e); -+ _mtk_mdio_write(gsw->eth, i, 14, 0xffff); -+ -+ /* Disable mcc */ -+ _mtk_mdio_write(gsw->eth, i, 13, 0x1e); -+ _mtk_mdio_write(gsw->eth, i, 14, 0xa6); -+ _mtk_mdio_write(gsw->eth, i, 13, 0x401e); -+ _mtk_mdio_write(gsw->eth, i, 14, 0x300); -+ -+ /* Disable HW auto downshift*/ -+ _mtk_mdio_write(gsw->eth, i, 31, 0x1); -+ val = _mtk_mdio_read(gsw->eth, i, 0x14); -+ val &= ~(1<<4); -+ _mtk_mdio_write(gsw->eth, i, 0x14, val); -+ } -+ -+ /* turn on all PHYs */ -+ for (i = 0; i <= 4; i++) { -+ val = _mtk_mdio_read(gsw->eth, i, 0); -+ val &= ~BIT(11); -+ _mtk_mdio_write(gsw->eth, i, 0, val); -+ } -+ -+ /* enable irq */ -+ mt7530_mdio_m32(gsw, 0, TOP_SIG_CTRL_NORMAL, MT7530_TOP_SIG_CTRL); -+} -+ -+static const struct of_device_id mediatek_gsw_match[] = { -+ { .compatible = "mediatek,mt7623-gsw" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mediatek_gsw_match); -+ -+int mtk_gsw_init(struct mtk_eth *eth) -+{ -+ struct device_node *np = eth->switch_np; -+ struct platform_device *pdev = of_find_device_by_node(np); -+ struct mt7620_gsw *gsw; -+ -+ if (!pdev) -+ return -ENODEV; -+ -+ if (!of_device_is_compatible(np, mediatek_gsw_match->compatible)) -+ return -EINVAL; -+ -+ gsw = platform_get_drvdata(pdev); -+ if (!gsw) -+ return -ENODEV; -+ gsw->eth = eth; -+ eth->sw_priv = gsw; -+ -+ mt7623_hw_init(eth, gsw, np); -+ -+ if (request_threaded_irq(gsw->irq, gsw_interrupt_mt7623, NULL, 0, -+ "gsw", eth)) -+ pr_err("fail to request irq\n"); -+ mt7530_mdio_w32(gsw, 0x7008, 0x1f); -+ -+ return 0; -+} -+ -+static int mt7623_gsw_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct device_node *pctl; -+ int reset_pin, ret; -+ struct mt7620_gsw *gsw; -+ struct regulator *supply; -+ -+ gsw = devm_kzalloc(&pdev->dev, sizeof(struct mt7620_gsw), GFP_KERNEL); -+ if (!gsw) -+ return -ENOMEM; -+ -+ gsw->dev = &pdev->dev; -+ gsw->trgmii_force = 2000; -+ gsw->irq = irq_of_parse_and_map(np, 0); -+ if (gsw->irq < 0) -+ return -EINVAL; -+ -+ gsw->ethsys = syscon_regmap_lookup_by_phandle(np, "mediatek,ethsys"); -+ if (IS_ERR(gsw->ethsys)) -+ return PTR_ERR(gsw->ethsys); -+ -+ reset_pin = of_get_named_gpio(np, "mediatek,reset-pin", 0); -+ if (reset_pin < 0) -+ return reset_pin; -+ -+ pctl = of_parse_phandle(np, "mediatek,pctl-regmap", 0); -+ if (IS_ERR(pctl)) -+ return PTR_ERR(pctl); -+ -+ gsw->pctl = syscon_node_to_regmap(pctl); -+ if (IS_ERR(pctl)) -+ return PTR_ERR(pctl); -+ -+ ret = devm_gpio_request(&pdev->dev, reset_pin, "mt7530-reset"); -+ if (ret) -+ return ret; -+ -+ gsw->clk_trgpll = devm_clk_get(&pdev->dev, "trgpll"); -+ -+ if (IS_ERR(gsw->clk_trgpll)) -+ return -ENODEV; -+ -+ supply = devm_regulator_get(&pdev->dev, "mt7530"); -+ if (IS_ERR(supply)) -+ return PTR_ERR(supply); -+ -+ regulator_set_voltage(supply, 1000000, 1000000); -+ ret = regulator_enable(supply); -+ if (ret) { -+ dev_err(&pdev->dev, "Failed to enable reg-7530: %d\n", ret); -+ return ret; -+ } -+ -+ gsw->wllll = of_property_read_bool(np, "mediatek,wllll"); -+ -+ pm_runtime_enable(&pdev->dev); -+ pm_runtime_get_sync(&pdev->dev); -+ -+ ret = clk_set_rate(gsw->clk_trgpll, 500000000); -+ if (ret) -+ return ret; -+ -+ regmap_write(gsw->ethsys, 0x34, 0x800000); -+ regmap_write(gsw->ethsys, 0x34, 0x0); -+ -+ clk_prepare_enable(gsw->clk_trgpll); -+ -+ gpio_direction_output(reset_pin, 0); -+ udelay(1000); -+ gpio_set_value(reset_pin, 1); -+ mdelay(100); -+ -+ platform_set_drvdata(pdev, gsw); -+ -+ return 0; -+} -+ -+static int mt7623_gsw_remove(struct platform_device *pdev) -+{ -+ struct mt7620_gsw *gsw = platform_get_drvdata(pdev); -+ -+ clk_disable_unprepare(gsw->clk_trgpll); -+ -+ pm_runtime_put_sync(&pdev->dev); -+ pm_runtime_disable(&pdev->dev); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ return 0; -+} -+ -+static struct platform_driver gsw_driver = { -+ .probe = mt7623_gsw_probe, -+ .remove = mt7623_gsw_remove, -+ .driver = { -+ .name = "mt7623-gsw", -+ .owner = THIS_MODULE, -+ .of_match_table = mediatek_gsw_match, -+ }, -+}; -+ -+module_platform_driver(gsw_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); -+MODULE_DESCRIPTION("GBit switch driver for Mediatek MT7623 SoC"); -diff --git a/drivers/net/ethernet/mediatek/mt7530.c b/drivers/net/ethernet/mediatek/mt7530.c -new file mode 100644 -index 0000000..2e9d280 ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mt7530.c -@@ -0,0 +1,808 @@ -+/* -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> -+ */ -+ -+#include <linux/if.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/if_ether.h> -+#include <linux/skbuff.h> -+#include <linux/netdevice.h> -+#include <linux/netlink.h> -+#include <linux/bitops.h> -+#include <net/genetlink.h> -+#include <linux/switch.h> -+#include <linux/delay.h> -+#include <linux/phy.h> -+#include <linux/netdevice.h> -+#include <linux/etherdevice.h> -+#include <linux/lockdep.h> -+#include <linux/workqueue.h> -+#include <linux/of_device.h> -+ -+#include "mt7530.h" -+ -+#define MT7530_CPU_PORT 6 -+#define MT7530_NUM_PORTS 8 -+#define MT7530_NUM_VLANS 16 -+#define MT7530_MAX_VID 4095 -+#define MT7530_MIN_VID 0 -+ -+/* registers */ -+#define REG_ESW_VLAN_VTCR 0x90 -+#define REG_ESW_VLAN_VAWD1 0x94 -+#define REG_ESW_VLAN_VAWD2 0x98 -+#define REG_ESW_VLAN_VTIM(x) (0x100 + 4 * ((x) / 2)) -+ -+#define REG_ESW_VLAN_VAWD1_IVL_MAC BIT(30) -+#define REG_ESW_VLAN_VAWD1_VTAG_EN BIT(28) -+#define REG_ESW_VLAN_VAWD1_VALID BIT(0) -+ -+/* vlan egress mode */ -+enum { -+ ETAG_CTRL_UNTAG = 0, -+ ETAG_CTRL_TAG = 2, -+ ETAG_CTRL_SWAP = 1, -+ ETAG_CTRL_STACK = 3, -+}; -+ -+#define REG_ESW_PORT_PCR(x) (0x2004 | ((x) << 8)) -+#define REG_ESW_PORT_PVC(x) (0x2010 | ((x) << 8)) -+#define REG_ESW_PORT_PPBV1(x) (0x2014 | ((x) << 8)) -+ -+#define REG_HWTRAP 0x7804 -+ -+#define MIB_DESC(_s , _o, _n) \ -+ { \ -+ .size = (_s), \ -+ .offset = (_o), \ -+ .name = (_n), \ -+ } -+ -+struct mt7xxx_mib_desc { -+ unsigned int size; -+ unsigned int offset; -+ const char *name; -+}; -+ -+#define MT7621_MIB_COUNTER_BASE 0x4000 -+#define MT7621_MIB_COUNTER_PORT_OFFSET 0x100 -+#define MT7621_STATS_TDPC 0x00 -+#define MT7621_STATS_TCRC 0x04 -+#define MT7621_STATS_TUPC 0x08 -+#define MT7621_STATS_TMPC 0x0C -+#define MT7621_STATS_TBPC 0x10 -+#define MT7621_STATS_TCEC 0x14 -+#define MT7621_STATS_TSCEC 0x18 -+#define MT7621_STATS_TMCEC 0x1C -+#define MT7621_STATS_TDEC 0x20 -+#define MT7621_STATS_TLCEC 0x24 -+#define MT7621_STATS_TXCEC 0x28 -+#define MT7621_STATS_TPPC 0x2C -+#define MT7621_STATS_TL64PC 0x30 -+#define MT7621_STATS_TL65PC 0x34 -+#define MT7621_STATS_TL128PC 0x38 -+#define MT7621_STATS_TL256PC 0x3C -+#define MT7621_STATS_TL512PC 0x40 -+#define MT7621_STATS_TL1024PC 0x44 -+#define MT7621_STATS_TOC 0x48 -+#define MT7621_STATS_RDPC 0x60 -+#define MT7621_STATS_RFPC 0x64 -+#define MT7621_STATS_RUPC 0x68 -+#define MT7621_STATS_RMPC 0x6C -+#define MT7621_STATS_RBPC 0x70 -+#define MT7621_STATS_RAEPC 0x74 -+#define MT7621_STATS_RCEPC 0x78 -+#define MT7621_STATS_RUSPC 0x7C -+#define MT7621_STATS_RFEPC 0x80 -+#define MT7621_STATS_ROSPC 0x84 -+#define MT7621_STATS_RJEPC 0x88 -+#define MT7621_STATS_RPPC 0x8C -+#define MT7621_STATS_RL64PC 0x90 -+#define MT7621_STATS_RL65PC 0x94 -+#define MT7621_STATS_RL128PC 0x98 -+#define MT7621_STATS_RL256PC 0x9C -+#define MT7621_STATS_RL512PC 0xA0 -+#define MT7621_STATS_RL1024PC 0xA4 -+#define MT7621_STATS_ROC 0xA8 -+#define MT7621_STATS_RDPC_CTRL 0xB0 -+#define MT7621_STATS_RDPC_ING 0xB4 -+#define MT7621_STATS_RDPC_ARL 0xB8 -+ -+static const struct mt7xxx_mib_desc mt7621_mibs[] = { -+ MIB_DESC(1, MT7621_STATS_TDPC, "TxDrop"), -+ MIB_DESC(1, MT7621_STATS_TCRC, "TxCRC"), -+ MIB_DESC(1, MT7621_STATS_TUPC, "TxUni"), -+ MIB_DESC(1, MT7621_STATS_TMPC, "TxMulti"), -+ MIB_DESC(1, MT7621_STATS_TBPC, "TxBroad"), -+ MIB_DESC(1, MT7621_STATS_TCEC, "TxCollision"), -+ MIB_DESC(1, MT7621_STATS_TSCEC, "TxSingleCol"), -+ MIB_DESC(1, MT7621_STATS_TMCEC, "TxMultiCol"), -+ MIB_DESC(1, MT7621_STATS_TDEC, "TxDefer"), -+ MIB_DESC(1, MT7621_STATS_TLCEC, "TxLateCol"), -+ MIB_DESC(1, MT7621_STATS_TXCEC, "TxExcCol"), -+ MIB_DESC(1, MT7621_STATS_TPPC, "TxPause"), -+ MIB_DESC(1, MT7621_STATS_TL64PC, "Tx64Byte"), -+ MIB_DESC(1, MT7621_STATS_TL65PC, "Tx65Byte"), -+ MIB_DESC(1, MT7621_STATS_TL128PC, "Tx128Byte"), -+ MIB_DESC(1, MT7621_STATS_TL256PC, "Tx256Byte"), -+ MIB_DESC(1, MT7621_STATS_TL512PC, "Tx512Byte"), -+ MIB_DESC(1, MT7621_STATS_TL1024PC, "Tx1024Byte"), -+ MIB_DESC(2, MT7621_STATS_TOC, "TxByte"), -+ MIB_DESC(1, MT7621_STATS_RDPC, "RxDrop"), -+ MIB_DESC(1, MT7621_STATS_RFPC, "RxFiltered"), -+ MIB_DESC(1, MT7621_STATS_RUPC, "RxUni"), -+ MIB_DESC(1, MT7621_STATS_RMPC, "RxMulti"), -+ MIB_DESC(1, MT7621_STATS_RBPC, "RxBroad"), -+ MIB_DESC(1, MT7621_STATS_RAEPC, "RxAlignErr"), -+ MIB_DESC(1, MT7621_STATS_RCEPC, "RxCRC"), -+ MIB_DESC(1, MT7621_STATS_RUSPC, "RxUnderSize"), -+ MIB_DESC(1, MT7621_STATS_RFEPC, "RxFragment"), -+ MIB_DESC(1, MT7621_STATS_ROSPC, "RxOverSize"), -+ MIB_DESC(1, MT7621_STATS_RJEPC, "RxJabber"), -+ MIB_DESC(1, MT7621_STATS_RPPC, "RxPause"), -+ MIB_DESC(1, MT7621_STATS_RL64PC, "Rx64Byte"), -+ MIB_DESC(1, MT7621_STATS_RL65PC, "Rx65Byte"), -+ MIB_DESC(1, MT7621_STATS_RL128PC, "Rx128Byte"), -+ MIB_DESC(1, MT7621_STATS_RL256PC, "Rx256Byte"), -+ MIB_DESC(1, MT7621_STATS_RL512PC, "Rx512Byte"), -+ MIB_DESC(1, MT7621_STATS_RL1024PC, "Rx1024Byte"), -+ MIB_DESC(2, MT7621_STATS_ROC, "RxByte"), -+ MIB_DESC(1, MT7621_STATS_RDPC_CTRL, "RxCtrlDrop"), -+ MIB_DESC(1, MT7621_STATS_RDPC_ING, "RxIngDrop"), -+ MIB_DESC(1, MT7621_STATS_RDPC_ARL, "RxARLDrop") -+}; -+ -+enum { -+ /* Global attributes. */ -+ MT7530_ATTR_ENABLE_VLAN, -+}; -+ -+struct mt7530_port_entry { -+ u16 pvid; -+}; -+ -+struct mt7530_vlan_entry { -+ u16 vid; -+ u8 member; -+ u8 etags; -+}; -+ -+struct mt7530_priv { -+ void __iomem *base; -+ struct mii_bus *bus; -+ struct switch_dev swdev; -+ -+ bool global_vlan_enable; -+ struct mt7530_vlan_entry vlan_entries[MT7530_NUM_VLANS]; -+ struct mt7530_port_entry port_entries[MT7530_NUM_PORTS]; -+}; -+ -+struct mt7530_mapping { -+ char *name; -+ u16 pvids[MT7530_NUM_PORTS]; -+ u8 members[MT7530_NUM_VLANS]; -+ u8 etags[MT7530_NUM_VLANS]; -+ u16 vids[MT7530_NUM_VLANS]; -+} mt7530_defaults[] = { -+ { -+ .name = "llllw", -+ .pvids = { 1, 1, 1, 1, 2, 1, 1 }, -+ .members = { 0, 0x6f, 0x50 }, -+ .etags = { 0, 0x40, 0x40 }, -+ .vids = { 0, 1, 2 }, -+ }, { -+ .name = "wllll", -+ .pvids = { 2, 1, 1, 1, 1, 1, 1 }, -+ .members = { 0, 0x7e, 0x41 }, -+ .etags = { 0, 0x40, 0x40 }, -+ .vids = { 0, 1, 2 }, -+ }, -+}; -+ -+struct mt7530_mapping* -+mt7530_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(mt7530_defaults); i++) -+ if (!strcmp(map, mt7530_defaults[i].name)) -+ return &mt7530_defaults[i]; -+ -+ return NULL; -+} -+ -+static void -+mt7530_apply_mapping(struct mt7530_priv *mt7530, struct mt7530_mapping *map) -+{ -+ int i = 0; -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ mt7530->port_entries[i].pvid = map->pvids[i]; -+ -+ for (i = 0; i < MT7530_NUM_VLANS; i++) { -+ mt7530->vlan_entries[i].member = map->members[i]; -+ mt7530->vlan_entries[i].etags = map->etags[i]; -+ mt7530->vlan_entries[i].vid = map->vids[i]; -+ } -+} -+ -+static int -+mt7530_reset_switch(struct switch_dev *dev) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ int i; -+ -+ memset(eth->port_entries, 0, sizeof(eth->port_entries)); -+ memset(eth->vlan_entries, 0, sizeof(eth->vlan_entries)); -+ -+ /* set default vid of each vlan to the same number of vlan, so the vid -+ * won't need be set explicitly. -+ */ -+ for (i = 0; i < MT7530_NUM_VLANS; i++) { -+ eth->vlan_entries[i].vid = i; -+ } -+ -+ return 0; -+} -+ -+static int -+mt7530_get_vlan_enable(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ -+ val->value.i = eth->global_vlan_enable; -+ -+ return 0; -+} -+ -+static int -+mt7530_set_vlan_enable(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ -+ eth->global_vlan_enable = val->value.i != 0; -+ -+ return 0; -+} -+ -+static u32 -+mt7530_r32(struct mt7530_priv *eth, u32 reg) -+{ -+ u32 val; -+ if (eth->bus) { -+ u16 high, low; -+ -+ mdiobus_write(eth->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); -+ low = mdiobus_read(eth->bus, 0x1f, (reg >> 2) & 0xf); -+ high = mdiobus_read(eth->bus, 0x1f, 0x10); -+ -+ return (high << 16) | (low & 0xffff); -+ } -+ -+ val = ioread32(eth->base + reg); -+ pr_debug("MT7530 MDIO Read [%04x]=%08x\n", reg, val); -+ -+ return val; -+} -+ -+static void -+mt7530_w32(struct mt7530_priv *eth, u32 reg, u32 val) -+{ -+ if (eth->bus) { -+ mdiobus_write(eth->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); -+ mdiobus_write(eth->bus, 0x1f, (reg >> 2) & 0xf, val & 0xffff); -+ mdiobus_write(eth->bus, 0x1f, 0x10, val >> 16); -+ return; -+ } -+ -+ pr_debug("MT7530 MDIO Write[%04x]=%08x\n", reg, val); -+ iowrite32(val, eth->base + reg); -+} -+ -+static void -+mt7530_vtcr(struct mt7530_priv *eth, u32 cmd, u32 val) -+{ -+ int i; -+ -+ mt7530_w32(eth, REG_ESW_VLAN_VTCR, BIT(31) | (cmd << 12) | val); -+ -+ for (i = 0; i < 20; i++) { -+ u32 val = mt7530_r32(eth, REG_ESW_VLAN_VTCR); -+ -+ if ((val & BIT(31)) == 0) -+ break; -+ -+ udelay(1000); -+ } -+ if (i == 20) -+ printk("mt7530: vtcr timeout\n"); -+} -+ -+static int -+mt7530_get_port_pvid(struct switch_dev *dev, int port, int *val) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ -+ if (port >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ *val = mt7530_r32(eth, REG_ESW_PORT_PPBV1(port)); -+ *val &= 0xfff; -+ -+ return 0; -+} -+ -+static int -+mt7530_set_port_pvid(struct switch_dev *dev, int port, int pvid) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ -+ if (port >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ if (pvid < MT7530_MIN_VID || pvid > MT7530_MAX_VID) -+ return -EINVAL; -+ -+ eth->port_entries[port].pvid = pvid; -+ -+ return 0; -+} -+ -+static int -+mt7530_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ u32 member; -+ u32 etags; -+ int i; -+ -+ val->len = 0; -+ -+ if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS) -+ return -EINVAL; -+ -+ mt7530_vtcr(eth, 0, val->port_vlan); -+ -+ member = mt7530_r32(eth, REG_ESW_VLAN_VAWD1); -+ member >>= 16; -+ member &= 0xff; -+ -+ etags = mt7530_r32(eth, REG_ESW_VLAN_VAWD2); -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ struct switch_port *p; -+ int etag; -+ -+ if (!(member & BIT(i))) -+ continue; -+ -+ p = &val->value.ports[val->len++]; -+ p->id = i; -+ -+ etag = (etags >> (i * 2)) & 0x3; -+ -+ if (etag == ETAG_CTRL_TAG) -+ p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED); -+ else if (etag != ETAG_CTRL_UNTAG) -+ printk("vlan egress tag control neither untag nor tag.\n"); -+ } -+ -+ return 0; -+} -+ -+static int -+mt7530_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ u8 member = 0; -+ u8 etags = 0; -+ int i; -+ -+ if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS || -+ val->len > MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ for (i = 0; i < val->len; i++) { -+ struct switch_port *p = &val->value.ports[i]; -+ -+ if (p->id >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ member |= BIT(p->id); -+ -+ if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) -+ etags |= BIT(p->id); -+ } -+ eth->vlan_entries[val->port_vlan].member = member; -+ eth->vlan_entries[val->port_vlan].etags = etags; -+ -+ return 0; -+} -+ -+static int -+mt7530_set_vid(struct switch_dev *dev, const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ int vlan; -+ u16 vid; -+ -+ vlan = val->port_vlan; -+ vid = (u16)val->value.i; -+ -+ if (vlan < 0 || vlan >= MT7530_NUM_VLANS) -+ return -EINVAL; -+ -+ if (vid < MT7530_MIN_VID || vid > MT7530_MAX_VID) -+ return -EINVAL; -+ -+ eth->vlan_entries[vlan].vid = vid; -+ return 0; -+} -+ -+static int -+mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ u32 vid; -+ int vlan; -+ -+ vlan = val->port_vlan; -+ -+ vid = mt7530_r32(eth, REG_ESW_VLAN_VTIM(vlan)); -+ if (vlan & 1) -+ vid = vid >> 12; -+ vid &= 0xfff; -+ -+ val->value.i = vid; -+ return 0; -+} -+ -+static int -+mt7530_apply_config(struct switch_dev *dev) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ int i, j; -+ u8 tag_ports; -+ u8 untag_ports; -+ -+ if (!eth->global_vlan_enable) { -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ mt7530_w32(eth, REG_ESW_PORT_PCR(i), 0x00ff0000); -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ mt7530_w32(eth, REG_ESW_PORT_PVC(i), 0x810000c0); -+ -+ return 0; -+ } -+ -+ /* set all ports as security mode */ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ mt7530_w32(eth, REG_ESW_PORT_PCR(i), 0x00ff0003); -+ -+ /* check if a port is used in tag/untag vlan egress mode */ -+ tag_ports = 0; -+ untag_ports = 0; -+ -+ for (i = 0; i < MT7530_NUM_VLANS; i++) { -+ u8 member = eth->vlan_entries[i].member; -+ u8 etags = eth->vlan_entries[i].etags; -+ -+ if (!member) -+ continue; -+ -+ for (j = 0; j < MT7530_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 < MT7530_NUM_PORTS; i++) { -+ u32 pvc_mode = 0x81000000; -+ -+ if (untag_ports & BIT(i) && !(tag_ports & BIT(i))) -+ pvc_mode = 0x810000c0; -+ -+ mt7530_w32(eth, REG_ESW_PORT_PVC(i), pvc_mode); -+ } -+ -+ for (i = 0; i < MT7530_NUM_VLANS; i++) { -+ u16 vid = eth->vlan_entries[i].vid; -+ u8 member = eth->vlan_entries[i].member; -+ u8 etags = eth->vlan_entries[i].etags; -+ u32 val; -+ -+ /* vid of vlan */ -+ val = mt7530_r32(eth, REG_ESW_VLAN_VTIM(i)); -+ if (i % 2 == 0) { -+ val &= 0xfff000; -+ val |= vid; -+ } else { -+ val &= 0xfff; -+ val |= (vid << 12); -+ } -+ mt7530_w32(eth, REG_ESW_VLAN_VTIM(i), val); -+ -+ /* vlan port membership */ -+ if (member) -+ mt7530_w32(eth, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | -+ REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) | -+ REG_ESW_VLAN_VAWD1_VALID); -+ else -+ mt7530_w32(eth, REG_ESW_VLAN_VAWD1, 0); -+ -+ /* egress mode */ -+ val = 0; -+ for (j = 0; j < MT7530_NUM_PORTS; j++) { -+ if (etags & BIT(j)) -+ val |= ETAG_CTRL_TAG << (j * 2); -+ else -+ val |= ETAG_CTRL_UNTAG << (j * 2); -+ } -+ mt7530_w32(eth, REG_ESW_VLAN_VAWD2, val); -+ -+ /* write to vlan table */ -+ mt7530_vtcr(eth, 1, i); -+ } -+ -+ /* Port Default PVID */ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ u32 val; -+ val = mt7530_r32(eth, REG_ESW_PORT_PPBV1(i)); -+ val &= ~0xfff; -+ val |= eth->port_entries[i].pvid; -+ mt7530_w32(eth, REG_ESW_PORT_PPBV1(i), val); -+ } -+ -+ return 0; -+} -+ -+static int -+mt7530_get_port_link(struct switch_dev *dev, int port, -+ struct switch_port_link *link) -+{ -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ u32 speed, pmsr; -+ -+ if (port < 0 || port >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ pmsr = mt7530_r32(eth, 0x3008 + (0x100 * port)); -+ -+ link->link = pmsr & 1; -+ link->duplex = (pmsr >> 1) & 1; -+ speed = (pmsr >> 2) & 3; -+ -+ switch (speed) { -+ case 0: -+ link->speed = SWITCH_PORT_SPEED_10; -+ break; -+ case 1: -+ link->speed = SWITCH_PORT_SPEED_100; -+ break; -+ case 2: -+ case 3: /* forced gige speed can be 2 or 3 */ -+ link->speed = SWITCH_PORT_SPEED_1000; -+ break; -+ default: -+ link->speed = SWITCH_PORT_SPEED_UNKNOWN; -+ break; -+ } -+ -+ return 0; -+} -+ -+static const struct switch_attr mt7530_global[] = { -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "enable_vlan", -+ .description = "VLAN mode (1:enabled)", -+ .max = 1, -+ .id = MT7530_ATTR_ENABLE_VLAN, -+ .get = mt7530_get_vlan_enable, -+ .set = mt7530_set_vlan_enable, -+ }, -+}; -+ -+static u64 get_mib_counter(struct mt7530_priv *eth, int i, int port) -+{ -+ unsigned int port_base; -+ u64 t; -+ -+ port_base = MT7621_MIB_COUNTER_BASE + -+ MT7621_MIB_COUNTER_PORT_OFFSET * port; -+ -+ t = mt7530_r32(eth, port_base + mt7621_mibs[i].offset); -+ if (mt7621_mibs[i].size == 2) { -+ u64 hi; -+ -+ hi = mt7530_r32(eth, port_base + mt7621_mibs[i].offset + 4); -+ t |= hi << 32; -+ } -+ -+ return t; -+} -+ -+static int mt7621_sw_get_port_mib(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ static char buf[4096]; -+ struct mt7530_priv *eth = container_of(dev, struct mt7530_priv, swdev); -+ int i, len = 0; -+ -+ if (val->port_vlan >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ len += snprintf(buf + len, sizeof(buf) - len, -+ "Port %d MIB counters\n", val->port_vlan); -+ -+ for (i = 0; i < sizeof(mt7621_mibs) / sizeof(*mt7621_mibs); ++i) { -+ u64 counter; -+ len += snprintf(buf + len, sizeof(buf) - len, -+ "%-11s: ", mt7621_mibs[i].name); -+ counter = get_mib_counter(eth, i, val->port_vlan); -+ len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", -+ counter); -+ } -+ -+ val->value.s = buf; -+ val->len = len; -+ return 0; -+} -+ -+static const struct switch_attr mt7621_port[] = { -+ { -+ .type = SWITCH_TYPE_STRING, -+ .name = "mib", -+ .description = "Get MIB counters for port", -+ .get = mt7621_sw_get_port_mib, -+ .set = NULL, -+ }, -+}; -+ -+static const struct switch_attr mt7530_port[] = { -+}; -+ -+static const struct switch_attr mt7530_vlan[] = { -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "vid", -+ .description = "VLAN ID (0-4094)", -+ .set = mt7530_set_vid, -+ .get = mt7530_get_vid, -+ .max = 4094, -+ }, -+}; -+ -+static const struct switch_dev_ops mt7621_ops = { -+ .attr_global = { -+ .attr = mt7530_global, -+ .n_attr = ARRAY_SIZE(mt7530_global), -+ }, -+/* .attr_port = { -+ .attr = mt7621_port, -+ .n_attr = ARRAY_SIZE(mt7621_port), -+ },*/ -+ .attr_vlan = { -+ .attr = mt7530_vlan, -+ .n_attr = ARRAY_SIZE(mt7530_vlan), -+ }, -+ .get_vlan_ports = mt7530_get_vlan_ports, -+ .set_vlan_ports = mt7530_set_vlan_ports, -+ .get_port_pvid = mt7530_get_port_pvid, -+ .set_port_pvid = mt7530_set_port_pvid, -+ .get_port_link = mt7530_get_port_link, -+ .apply_config = mt7530_apply_config, -+ .reset_switch = mt7530_reset_switch, -+}; -+ -+static const struct switch_dev_ops mt7530_ops = { -+ .attr_global = { -+ .attr = mt7530_global, -+ .n_attr = ARRAY_SIZE(mt7530_global), -+ }, -+ .attr_port = { -+ .attr = mt7530_port, -+ .n_attr = ARRAY_SIZE(mt7530_port), -+ }, -+ .attr_vlan = { -+ .attr = mt7530_vlan, -+ .n_attr = ARRAY_SIZE(mt7530_vlan), -+ }, -+ .get_vlan_ports = mt7530_get_vlan_ports, -+ .set_vlan_ports = mt7530_set_vlan_ports, -+ .get_port_pvid = mt7530_get_port_pvid, -+ .set_port_pvid = mt7530_set_port_pvid, -+ .get_port_link = mt7530_get_port_link, -+ .apply_config = mt7530_apply_config, -+ .reset_switch = mt7530_reset_switch, -+}; -+ -+int -+mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan) -+{ -+ struct switch_dev *swdev; -+ struct mt7530_priv *mt7530; -+ struct mt7530_mapping *map; -+ int ret; -+ -+ mt7530 = devm_kzalloc(dev, sizeof(struct mt7530_priv), GFP_KERNEL); -+ if (!mt7530) -+ return -ENOMEM; -+ -+ mt7530->base = base; -+ mt7530->bus = bus; -+ mt7530->global_vlan_enable = vlan; -+ -+ swdev = &mt7530->swdev; -+ if (bus) { -+ swdev->alias = "mt7530"; -+ swdev->name = "mt7530"; -+ } else if (IS_ENABLED(CONFIG_MACH_MT7623)) { -+ swdev->alias = "mt7623"; -+ swdev->name = "mt7623"; -+ } else if (IS_ENABLED(CONFIG_SOC_MT7621)) { -+ swdev->alias = "mt7621"; -+ swdev->name = "mt7621"; -+ } else { -+ swdev->alias = "mt7620"; -+ swdev->name = "mt7620"; -+ } -+ swdev->cpu_port = MT7530_CPU_PORT; -+ swdev->ports = MT7530_NUM_PORTS; -+ swdev->vlans = MT7530_NUM_VLANS; -+ if (IS_ENABLED(CONFIG_SOC_MT7621) || IS_ENABLED(CONFIG_MACH_MT7623)) -+ swdev->ops = &mt7621_ops; -+ else -+ swdev->ops = &mt7530_ops; -+ -+ ret = register_switch(swdev, NULL); -+ if (ret) { -+ dev_err(dev, "failed to register mt7530\n"); -+ return ret; -+ } -+ -+ mt7530_reset_switch(swdev); -+ -+ map = mt7530_find_mapping(dev->of_node); -+ if (map) -+ mt7530_apply_mapping(mt7530, map); -+ mt7530_apply_config(swdev); -+ -+ /* magic vodoo */ -+ if (!(IS_ENABLED(CONFIG_SOC_MT7621) || IS_ENABLED(CONFIG_MACH_MT7623)) && bus && mt7530_r32(mt7530, REG_HWTRAP) != 0x1117edf) { -+ dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n"); -+ mt7530_w32(mt7530, REG_HWTRAP, 0x1117edf); -+ } -+ dev_info(dev, "loaded %s driver\n", swdev->name); -+ -+ return 0; -+} -diff --git a/drivers/net/ethernet/mediatek/mt7530.h b/drivers/net/ethernet/mediatek/mt7530.h -new file mode 100644 -index 0000000..1fc8c62 ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mt7530.h -@@ -0,0 +1,20 @@ -+/* -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> -+ */ -+ -+#ifndef _MT7530_H__ -+#define _MT7530_H__ -+ -+int mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan); -+ -+#endif -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -index 6557026..bb62b91 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -24,6 +24,9 @@ - - #include "mtk_eth_soc.h" - -+/* the callback used by the driver core to bringup the switch */ -+int mtk_gsw_init(struct mtk_eth *eth); -+ - static int mtk_msg_level = -1; - module_param_named(msg_level, mtk_msg_level, int, 0); - MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)"); -@@ -69,7 +72,7 @@ static int mtk_mdio_busy_wait(struct mtk_eth *eth) - return 0; - if (time_after(jiffies, t_start + PHY_IAC_TIMEOUT)) - break; -- usleep_range(10, 20); -+// usleep_range(10, 20); - } - - dev_err(eth->dev, "mdio: MDIO timeout\n"); -@@ -1408,15 +1411,6 @@ static int __init mtk_hw_init(struct mtk_eth *eth) - reset_control_deassert(eth->rstc); - usleep_range(10, 20); - -- /* Set GE2 driving and slew rate */ -- regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00); -- -- /* set GE2 TDSEL */ -- regmap_write(eth->pctl, GPIO_OD33_CTRL8, 0x5); -- -- /* set GE2 TUNE */ -- regmap_write(eth->pctl, GPIO_BIAS_CTRL, 0x0); -- - /* GE1, Force 1000M/FD, FC ON */ - mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(0)); - -@@ -1439,6 +1433,8 @@ static int __init mtk_hw_init(struct mtk_eth *eth) - if (err) - return err; - -+ mtk_gsw_init(eth); -+ - /* disable delay and normal interrupt */ - mtk_w32(eth, 0, MTK_QDMA_DELAY_INT); - mtk_irq_disable(eth, MTK_TX_DONE_INT | MTK_RX_DONE_INT); -@@ -1466,6 +1462,8 @@ static int __init mtk_hw_init(struct mtk_eth *eth) - mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); - } - -+ mt7623_gsw_config(eth); -+ - return 0; - } - -@@ -1721,7 +1719,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) - { - struct mtk_mac *mac; - const __be32 *_id = of_get_property(np, "reg", NULL); -- int id, err; -+ int id; - - if (!_id) { - dev_err(eth->dev, "missing mac id\n"); -@@ -1755,8 +1753,8 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) - GFP_KERNEL); - if (!mac->hw_stats) { - dev_err(eth->dev, "failed to allocate counter memory\n"); -- err = -ENOMEM; -- goto free_netdev; -+ free_netdev(eth->netdev[id]); -+ return -ENOMEM; - } - spin_lock_init(&mac->hw_stats->stats_lock); - mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET; -@@ -1770,21 +1768,9 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) - eth->netdev[id]->features |= MTK_HW_FEATURES; - eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; - -- err = register_netdev(eth->netdev[id]); -- if (err) { -- dev_err(eth->dev, "error bringing up device\n"); -- goto free_netdev; -- } - eth->netdev[id]->irq = eth->irq[0]; -- netif_info(eth, probe, eth->netdev[id], -- "mediatek frame engine at 0x%08lx, irq %d\n", -- eth->netdev[id]->base_addr, eth->irq[0]); - - return 0; -- --free_netdev: -- free_netdev(eth->netdev[id]); -- return err; - } - - static int mtk_probe(struct platform_device *pdev) -@@ -1852,14 +1838,13 @@ static int mtk_probe(struct platform_device *pdev) - clk_prepare_enable(eth->clk_gp1); - clk_prepare_enable(eth->clk_gp2); - -+ eth->switch_np = of_parse_phandle(pdev->dev.of_node, -+ "mediatek,switch", 0); -+ - eth->dev = &pdev->dev; - eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE); - INIT_WORK(ð->pending_work, mtk_pending_work); - -- err = mtk_hw_init(eth); -- if (err) -- return err; -- - for_each_child_of_node(pdev->dev.of_node, mac_np) { - if (!of_device_is_compatible(mac_np, - "mediatek,eth-mac")) -@@ -1873,6 +1858,22 @@ static int mtk_probe(struct platform_device *pdev) - goto err_free_dev; - } - -+ err = mtk_hw_init(eth); -+ if (err) -+ return err; -+ -+ for (i = 0; i < MTK_MAX_DEVS; i++) { -+ if (!eth->netdev[i]) -+ continue; -+ err = register_netdev(eth->netdev[i]); -+ if (err) -+ dev_err(eth->dev, "error bringing up device\n"); -+ else -+ netif_info(eth, probe, eth->netdev[i], -+ "mediatek frame engine at 0x%08lx, irq %d\n", -+ eth->netdev[i]->base_addr, eth->irq[0]); -+ } -+ - /* we run 2 devices on the same DMA ring so we need a dummy device - * for NAPI to work - */ -diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -index bf158f8..5093518 100644 ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -406,6 +406,8 @@ struct mtk_eth { - struct mii_bus *mii_bus; - struct work_struct pending_work; - -+ struct device_node *switch_np; -+ void *sw_priv; - }; - - /* struct mtk_mac - the structure that holds the info about the MACs of the -@@ -433,4 +435,6 @@ void mtk_stats_update_mac(struct mtk_mac *mac); - void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); - u32 mtk_r32(struct mtk_eth *eth, unsigned reg); - -+int mt7623_gsw_config(struct mtk_eth *eth); -+ - #endif /* MTK_ETH_H */ --- -1.7.10.4 - |