aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c')
-rw-r--r--target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c247
1 files changed, 229 insertions, 18 deletions
diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c
index c0ec939263..74fe0bb6ff 100644
--- a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c
+++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c
@@ -50,7 +50,11 @@
#define GSW_REG_PHY_TIMEOUT (5 * HZ)
+#ifdef CONFIG_SOC_MT7621
+#define MT7620A_GSW_REG_PIAC 0x0004
+#else
#define MT7620A_GSW_REG_PIAC 0x7004
+#endif
#define GSW_NUM_VLANS 16
#define GSW_NUM_VIDS 4096
@@ -74,13 +78,21 @@
#define GSW_REG_ISR 0x700c
#define GSW_REG_GPC1 0x7014
+#define SYSC_REG_CHIP_REV_ID 0x0c
#define SYSC_REG_CFG1 0x14
+#define SYSC_REG_RESET_CTRL 0x34
+#define RST_CTRL_MCM BIT(2)
+#define SYSC_PAD_RGMII2_MDIO 0x58
+#define SYSC_GPIO_MODE 0x60
#define PORT_IRQ_ST_CHG 0x7f
-#define SYSCFG1 0x14
+#ifdef CONFIG_SOC_MT7621
+#define ESW_PHY_POLLING 0x0000
+#else
#define ESW_PHY_POLLING 0x7000
+#endif
#define PMCR_IPG BIT(18)
#define PMCR_MAC_MODE BIT(16)
@@ -200,6 +212,26 @@ int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
return _mt7620_mii_read(gsw, phy_addr, phy_reg);
}
+static void
+mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val)
+{
+ _mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
+ _mt7620_mii_write(gsw, 0x1f, (reg >> 2) & 0xf, val & 0xffff);
+ _mt7620_mii_write(gsw, 0x1f, 0x10, val >> 16);
+}
+
+static u32
+mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg)
+{
+ u16 high, low;
+
+ _mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
+ low = _mt7620_mii_read(gsw, 0x1f, (reg >> 2) & 0xf);
+ high = _mt7620_mii_read(gsw, 0x1f, 0x10);
+
+ return (high << 16) | (low & 0xffff);
+}
+
static unsigned char *fe_speed_str(int speed)
{
switch (speed) {
@@ -250,7 +282,7 @@ void mt7620_mdio_link_adjust(struct fe_priv *priv, int port)
mt7620a_handle_carrier(priv);
}
-static irqreturn_t gsw_interrupt(int irq, void *_priv)
+static irqreturn_t gsw_interrupt_mt7620(int irq, void *_priv)
{
struct fe_priv *priv = (struct fe_priv *) _priv;
struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv;
@@ -281,6 +313,33 @@ static irqreturn_t gsw_interrupt(int irq, void *_priv)
return IRQ_HANDLED;
}
+static irqreturn_t gsw_interrupt_mt7621(int irq, void *_priv)
+{
+ struct fe_priv *priv = (struct fe_priv *) _priv;
+ struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv;
+ u32 reg, i;
+
+ reg = mt7530_mdio_r32(gsw, 0x700c);
+
+ for (i = 0; i < 5; i++)
+ if (reg & BIT(i)) {
+ unsigned int link = mt7530_mdio_r32(gsw, 0x3008 + (i * 0x100)) & 0x1;
+
+ if (link != priv->link[i]) {
+ priv->link[i] = link;
+ if (link)
+ netdev_info(priv->netdev, "port %d link up\n", i);
+ else
+ netdev_info(priv->netdev, "port %d link down\n", i);
+ }
+ }
+
+ mt7620a_handle_carrier(priv);
+ mt7530_mdio_w32(gsw, 0x700c, 0x1f);
+
+ return IRQ_HANDLED;
+}
+
static int mt7620_is_bga(void)
{
u32 bga = rt_sysc_r32(0x0c);
@@ -299,7 +358,7 @@ static void gsw_auto_poll(struct mt7620_gsw *gsw)
msb = phy;
}
- if (lsb)
+ if (lsb == msb)
lsb--;
gsw_w32(gsw, PHY_AN_EN | PHY_PRE_EN | PMY_MDC_CONF(5) | (msb << 8) | lsb, ESW_PHY_POLLING);
@@ -354,10 +413,10 @@ void mt7620_port_init(struct fe_priv *priv, struct device_node *np)
if (!priv->phy->phy_node[id] && !priv->phy->phy_fixed[id])
return;
- val = rt_sysc_r32(SYSCFG1);
+ val = rt_sysc_r32(SYSC_REG_CFG1);
val &= ~(3 << shift);
val |= mask << shift;
- rt_sysc_w32(val, SYSCFG1);
+ rt_sysc_w32(val, SYSC_REG_CFG1);
if (priv->phy->phy_fixed[id]) {
const __be32 *link = priv->phy->phy_fixed[id];
@@ -411,7 +470,7 @@ void mt7620_port_init(struct fe_priv *priv, struct device_node *np)
}
}
-static void gsw_hw_init(struct mt7620_gsw *gsw, struct device_node *np)
+static void gsw_hw_init_mt7620(struct mt7620_gsw *gsw, struct device_node *np)
{
u32 is_BGA = mt7620_is_bga();
@@ -487,9 +546,9 @@ static void gsw_hw_init(struct mt7620_gsw *gsw, struct device_node *np)
/* setup port 4 */
if (gsw->port4 == PORT4_EPHY) {
- u32 val = rt_sysc_r32(SYSCFG1);
+ u32 val = rt_sysc_r32(SYSC_REG_CFG1);
val |= 3 << 14;
- rt_sysc_w32(val, SYSCFG1);
+ rt_sysc_w32(val, SYSC_REG_CFG1);
_mt7620_mii_write(gsw, 4, 30, 0xa000);
_mt7620_mii_write(gsw, 4, 4, 0x05e1);
_mt7620_mii_write(gsw, 4, 16, 0x1313);
@@ -497,6 +556,145 @@ static void gsw_hw_init(struct mt7620_gsw *gsw, struct device_node *np)
}
}
+static void gsw_hw_init_mt7621(struct mt7620_gsw *gsw, struct device_node *np)
+{
+ u32 i;
+ u32 val;
+
+ /* Hardware reset Switch */
+ val = rt_sysc_r32(SYSC_REG_RESET_CTRL);
+ rt_sysc_w32(val | RST_CTRL_MCM, SYSC_REG_RESET_CTRL);
+ udelay(1000);
+ rt_sysc_w32(val, SYSC_REG_RESET_CTRL);
+ udelay(10000);
+
+ /* reduce RGMII2 PAD driving strength */
+ rt_sysc_m32(3 << 4, 0, SYSC_PAD_RGMII2_MDIO);
+
+ /* gpio mux - RGMII1=Normal mode */
+ rt_sysc_m32(BIT(14), 0, SYSC_GPIO_MODE);
+
+ //GMAC1= RGMII mode
+ rt_sysc_m32(3 << 12, 0, SYSC_REG_CFG1);
+
+ /* enable MDIO to control MT7530 */
+ rt_sysc_m32(3 << 12, 0, SYSC_GPIO_MODE);
+
+ /* turn off all PHYs */
+ for (i = 0; i <= 4; i++) {
+ _mt7620_mii_read(gsw, i, 0x0);
+ val |= (0x1 << 11);
+ _mt7620_mii_write(gsw, i, 0x0, val);
+ }
+
+ /* reset the switch */
+ mt7530_mdio_w32(gsw, 0x7000, 0x3);
+ udelay(10);
+
+ if ((rt_sysc_r32(SYSC_REG_CHIP_REV_ID) & 0xFFFF) == 0x0101) {
+ /* (GE1, Force 1000M/FD, FC ON) */
+ gsw_w32(gsw, 0x2005e30b, 0x100);
+ mt7530_mdio_w32(gsw, 0x3600, 0x5e30b);
+ } else {
+ /* (GE1, Force 1000M/FD, FC ON) */
+ gsw_w32(gsw, 0x2005e33b, 0x100);
+ mt7530_mdio_w32(gsw, 0x3600, 0x5e33b);
+ }
+
+ /* (GE2, Link down) */
+ gsw_w32(gsw, 0x8000, 0x200);
+
+ //val = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable
+ val = mt7530_mdio_r32(gsw, 0x7804);
+ val &= ~(1<<8); //Enable Port 6
+ val |= (1<<6); //Disable Port 5
+ val |= (1<<13); //Port 5 as GMAC, no Internal PHY
+
+ val |= (1<<16);//change HW-TRAP
+ printk("change HW-TRAP to 0x%x\n", val);
+ mt7530_mdio_w32(gsw, 0x7804, val);
+
+ val = rt_sysc_r32(0x10);
+ val = (val >> 6) & 0x7;
+ if (val >= 6) {
+ /* 25Mhz Xtal - do nothing */
+ } else if(val >=3) {
+ /* 40Mhz */
+
+ /* disable MT7530 core clock */
+ _mt7620_mii_write(gsw, 0, 13, 0x1f);
+ _mt7620_mii_write(gsw, 0, 14, 0x410);
+ _mt7620_mii_write(gsw, 0, 13, 0x401f);
+ _mt7620_mii_write(gsw, 0, 14, 0x0);
+
+ /* disable MT7530 PLL */
+ _mt7620_mii_write(gsw, 0, 13, 0x1f);
+ _mt7620_mii_write(gsw, 0, 14, 0x40d);
+ _mt7620_mii_write(gsw, 0, 13, 0x401f);
+ _mt7620_mii_write(gsw, 0, 14, 0x2020);
+
+ /* for MT7530 core clock = 500Mhz */
+ _mt7620_mii_write(gsw, 0, 13, 0x1f);
+ _mt7620_mii_write(gsw, 0, 14, 0x40e);
+ _mt7620_mii_write(gsw, 0, 13, 0x401f);
+ _mt7620_mii_write(gsw, 0, 14, 0x119);
+
+ /* enable MT7530 PLL */
+ _mt7620_mii_write(gsw, 0, 13, 0x1f);
+ _mt7620_mii_write(gsw, 0, 14, 0x40d);
+ _mt7620_mii_write(gsw, 0, 13, 0x401f);
+ _mt7620_mii_write(gsw, 0, 14, 0x2820);
+
+ udelay(20);
+
+ /* enable MT7530 core clock */
+ _mt7620_mii_write(gsw, 0, 13, 0x1f);
+ _mt7620_mii_write(gsw, 0, 14, 0x410);
+ _mt7620_mii_write(gsw, 0, 13, 0x401f);
+ } else {
+ /* 20Mhz Xtal - TODO */
+ }
+
+ /* RGMII */
+ _mt7620_mii_write(gsw, 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);
+ mt7530_mdio_w32(gsw, 0x7b00, 0x102); //delay setting for 10/1000M
+ mt7530_mdio_w32(gsw, 0x7b04, 0x14); //delay setting for 10/1000M
+
+ /*Tx Driving*/
+ mt7530_mdio_w32(gsw, 0x7a54, 0x44); //lower driving
+ mt7530_mdio_w32(gsw, 0x7a5c, 0x44); //lower driving
+ mt7530_mdio_w32(gsw, 0x7a64, 0x44); //lower driving
+ mt7530_mdio_w32(gsw, 0x7a6c, 0x44); //lower driving
+ mt7530_mdio_w32(gsw, 0x7a74, 0x44); //lower driving
+ mt7530_mdio_w32(gsw, 0x7a7c, 0x44); //lower driving
+
+ //LANWANPartition();
+
+ /* turn on all PHYs */
+ for (i = 0; i <= 4; i++) {
+ val = _mt7620_mii_read(gsw, i, 0);
+ val &= ~BIT(11);
+ _mt7620_mii_write(gsw, i, 0, val);
+ }
+
+ /* enable irq */
+ val = mt7530_mdio_r32(gsw, 0x7808);
+ val |= 3 << 16;
+ mt7530_mdio_w32(gsw, 0x7808, val);
+}
+
void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac)
{
struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv;
@@ -529,6 +727,14 @@ int mt7620_gsw_config(struct fe_priv *priv)
return 0;
}
+int mt7621_gsw_config(struct fe_priv *priv)
+{
+ if (priv->mii_bus && priv->mii_bus->phy_map[0x1f])
+ mt7530_probe(priv->device, NULL, priv->mii_bus, 1);
+
+ return 0;
+}
+
int mt7620_gsw_probe(struct fe_priv *priv)
{
struct mt7620_gsw *gsw;
@@ -548,12 +754,6 @@ int mt7620_gsw_probe(struct fe_priv *priv)
return -ENOMEM;
}
- gsw->irq = irq_of_parse_and_map(np, 0);
- if (!gsw->irq) {
- dev_err(priv->device, "no gsw irq resource found\n");
- return -ENOMEM;
- }
-
gsw->base = of_iomap(np, 0);
if (!gsw->base) {
dev_err(priv->device, "gsw ioremap failed\n");
@@ -569,12 +769,23 @@ int mt7620_gsw_probe(struct fe_priv *priv)
else if (port4 && !strcmp(port4, "gmac"))
gsw->port4 = PORT4_EXT;
else
- WARN_ON(port4);
+ gsw->port4 = PORT4_EPHY;
- gsw_hw_init(gsw, np);
+ if (IS_ENABLED(CONFIG_SOC_MT7620))
+ gsw_hw_init_mt7620(gsw, np);
+ else
+ gsw_hw_init_mt7621(gsw, np);
- gsw_w32(gsw, ~PORT_IRQ_ST_CHG, GSW_REG_IMR);
- request_irq(gsw->irq, gsw_interrupt, 0, "gsw", priv);
+ gsw->irq = irq_of_parse_and_map(np, 0);
+ if (gsw->irq) {
+ if (IS_ENABLED(CONFIG_SOC_MT7620)) {
+ request_irq(gsw->irq, gsw_interrupt_mt7620, 0, "gsw", priv);
+ gsw_w32(gsw, ~PORT_IRQ_ST_CHG, GSW_REG_IMR);
+ } else {
+ request_irq(gsw->irq, gsw_interrupt_mt7621, 0, "gsw", priv);
+ mt7530_mdio_w32(gsw, 0x7008, 0x1f);
+ }
+ }
return 0;
}