Commit ddda1ac1 authored by Greg Ungerer's avatar Greg Ungerer Committed by David S. Miller

net: dsa: mt7530: support the 7530 switch on the Mediatek MT7621 SoC

The MediaTek MT7621 SoC device contains a 7530 switch, and the existing
linux kernel 7530 DSA switch driver can be used with it.

The bulk of the changes required stem from the 7621 having different
regulator and pad setup. The existing setup of these in the 7530
driver appears to be very specific to its implemtation in the Mediatek
7623 SoC. (Not entirely surprising given the 7623 is a quad core ARM
based SoC, and the 7621 is a dual core, dual thread MIPS based SoC).

Create a new devicetree type, "mediatek,mt7621", to support the 7530
switch in the 7621 SoC. There appears to be no usable ID register to
distinguish it from a 7530 in other hardware at runtime. This is used
to carry out the appropriate configuration and setup.
Signed-off-by: default avatarGreg Ungerer <gerg@kernel.org>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Acked-by: default avatarSean Wang <sean.wang@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 889bcbde
...@@ -621,17 +621,19 @@ static void mt7530_adjust_link(struct dsa_switch *ds, int port, ...@@ -621,17 +621,19 @@ static void mt7530_adjust_link(struct dsa_switch *ds, int port,
struct mt7530_priv *priv = ds->priv; struct mt7530_priv *priv = ds->priv;
if (phy_is_pseudo_fixed_link(phydev)) { if (phy_is_pseudo_fixed_link(phydev)) {
dev_dbg(priv->dev, "phy-mode for master device = %x\n", if (priv->id == ID_MT7530) {
phydev->interface); dev_dbg(priv->dev, "phy-mode for master device = %x\n",
phydev->interface);
/* Setup TX circuit incluing relevant PAD and driving */
mt7530_pad_clk_setup(ds, phydev->interface); /* Setup TX circuit incluing relevant PAD and driving */
mt7530_pad_clk_setup(ds, phydev->interface);
/* Setup RX circuit, relevant PAD and driving on the host
* which must be placed after the setup on the device side is /* Setup RX circuit, relevant PAD and driving on the
* all finished. * host which must be placed after the setup on the
*/ * device side is all finished.
mt7623_pad_clk_setup(ds); */
mt7623_pad_clk_setup(ds);
}
} else { } else {
u16 lcl_adv = 0, rmt_adv = 0; u16 lcl_adv = 0, rmt_adv = 0;
u8 flowctrl; u8 flowctrl;
...@@ -687,6 +689,10 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv, ...@@ -687,6 +689,10 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv,
/* Unknown unicast frame fordwarding to the cpu port */ /* Unknown unicast frame fordwarding to the cpu port */
mt7530_set(priv, MT7530_MFC, UNU_FFP(BIT(port))); mt7530_set(priv, MT7530_MFC, UNU_FFP(BIT(port)));
/* Set CPU port number */
if (priv->id == ID_MT7621)
mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
/* CPU port gets connected to all user ports of /* CPU port gets connected to all user ports of
* the switch * the switch
*/ */
...@@ -1219,24 +1225,27 @@ mt7530_setup(struct dsa_switch *ds) ...@@ -1219,24 +1225,27 @@ mt7530_setup(struct dsa_switch *ds)
* as two netdev instances. * as two netdev instances.
*/ */
dn = ds->ports[MT7530_CPU_PORT].master->dev.of_node->parent; dn = ds->ports[MT7530_CPU_PORT].master->dev.of_node->parent;
priv->ethernet = syscon_node_to_regmap(dn);
if (IS_ERR(priv->ethernet))
return PTR_ERR(priv->ethernet);
regulator_set_voltage(priv->core_pwr, 1000000, 1000000); if (priv->id == ID_MT7530) {
ret = regulator_enable(priv->core_pwr); priv->ethernet = syscon_node_to_regmap(dn);
if (ret < 0) { if (IS_ERR(priv->ethernet))
dev_err(priv->dev, return PTR_ERR(priv->ethernet);
"Failed to enable core power: %d\n", ret);
return ret; regulator_set_voltage(priv->core_pwr, 1000000, 1000000);
} ret = regulator_enable(priv->core_pwr);
if (ret < 0) {
dev_err(priv->dev,
"Failed to enable core power: %d\n", ret);
return ret;
}
regulator_set_voltage(priv->io_pwr, 3300000, 3300000); regulator_set_voltage(priv->io_pwr, 3300000, 3300000);
ret = regulator_enable(priv->io_pwr); ret = regulator_enable(priv->io_pwr);
if (ret < 0) { if (ret < 0) {
dev_err(priv->dev, "Failed to enable io pwr: %d\n", dev_err(priv->dev, "Failed to enable io pwr: %d\n",
ret); ret);
return ret; return ret;
}
} }
/* Reset whole chip through gpio pin or memory-mapped registers for /* Reset whole chip through gpio pin or memory-mapped registers for
...@@ -1326,6 +1335,13 @@ static const struct dsa_switch_ops mt7530_switch_ops = { ...@@ -1326,6 +1335,13 @@ static const struct dsa_switch_ops mt7530_switch_ops = {
.port_vlan_del = mt7530_port_vlan_del, .port_vlan_del = mt7530_port_vlan_del,
}; };
static const struct of_device_id mt7530_of_match[] = {
{ .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, },
{ .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, mt7530_of_match);
static int static int
mt7530_probe(struct mdio_device *mdiodev) mt7530_probe(struct mdio_device *mdiodev)
{ {
...@@ -1356,13 +1372,21 @@ mt7530_probe(struct mdio_device *mdiodev) ...@@ -1356,13 +1372,21 @@ mt7530_probe(struct mdio_device *mdiodev)
} }
} }
priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); /* Get the hardware identifier from the devicetree node.
if (IS_ERR(priv->core_pwr)) * We will need it for some of the clock and regulator setup.
return PTR_ERR(priv->core_pwr); */
priv->id = (unsigned int)(unsigned long)
of_device_get_match_data(&mdiodev->dev);
priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); if (priv->id == ID_MT7530) {
if (IS_ERR(priv->io_pwr)) priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
return PTR_ERR(priv->io_pwr); if (IS_ERR(priv->core_pwr))
return PTR_ERR(priv->core_pwr);
priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
if (IS_ERR(priv->io_pwr))
return PTR_ERR(priv->io_pwr);
}
/* Not MCM that indicates switch works as the remote standalone /* Not MCM that indicates switch works as the remote standalone
* integrated circuit so the GPIO pin would be used to complete * integrated circuit so the GPIO pin would be used to complete
...@@ -1408,12 +1432,6 @@ mt7530_remove(struct mdio_device *mdiodev) ...@@ -1408,12 +1432,6 @@ mt7530_remove(struct mdio_device *mdiodev)
mutex_destroy(&priv->reg_mutex); mutex_destroy(&priv->reg_mutex);
} }
static const struct of_device_id mt7530_of_match[] = {
{ .compatible = "mediatek,mt7530" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, mt7530_of_match);
static struct mdio_driver mt7530_mdio_driver = { static struct mdio_driver mt7530_mdio_driver = {
.probe = mt7530_probe, .probe = mt7530_probe,
.remove = mt7530_remove, .remove = mt7530_remove,
......
...@@ -19,6 +19,11 @@ ...@@ -19,6 +19,11 @@
#define MT7530_NUM_FDB_RECORDS 2048 #define MT7530_NUM_FDB_RECORDS 2048
#define MT7530_ALL_MEMBERS 0xff #define MT7530_ALL_MEMBERS 0xff
enum {
ID_MT7530 = 0,
ID_MT7621 = 1,
};
#define NUM_TRGMII_CTRL 5 #define NUM_TRGMII_CTRL 5
#define TRGMII_BASE(x) (0x10000 + (x)) #define TRGMII_BASE(x) (0x10000 + (x))
...@@ -36,6 +41,9 @@ ...@@ -36,6 +41,9 @@
#define UNM_FFP(x) (((x) & 0xff) << 16) #define UNM_FFP(x) (((x) & 0xff) << 16)
#define UNU_FFP(x) (((x) & 0xff) << 8) #define UNU_FFP(x) (((x) & 0xff) << 8)
#define UNU_FFP_MASK UNU_FFP(~0) #define UNU_FFP_MASK UNU_FFP(~0)
#define CPU_EN BIT(7)
#define CPU_PORT(x) ((x) << 4)
#define CPU_MASK (0xf << 4)
/* Registers for address table access */ /* Registers for address table access */
#define MT7530_ATA1 0x74 #define MT7530_ATA1 0x74
...@@ -430,6 +438,7 @@ struct mt7530_priv { ...@@ -430,6 +438,7 @@ struct mt7530_priv {
struct regulator *core_pwr; struct regulator *core_pwr;
struct regulator *io_pwr; struct regulator *io_pwr;
struct gpio_desc *reset; struct gpio_desc *reset;
unsigned int id;
bool mcm; bool mcm;
struct mt7530_port ports[MT7530_NUM_PORTS]; struct mt7530_port ports[MT7530_NUM_PORTS];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment