Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.19 gmac #57

Merged
merged 8 commits into from
Jan 9, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
Original file line number Diff line number Diff line change
@@ -155,6 +155,18 @@
};
};

gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-mode = "trgmii";

fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};

mdio: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
@@ -173,29 +185,44 @@
port@0 {
reg = <0>;
label = "wan";
default_cpu = <&cpu_port1>;
};

port@1 {
reg = <1>;
label = "lan0";
default_cpu = <&cpu_port0>;
};

port@2 {
reg = <2>;
label = "lan1";
default_cpu = <&cpu_port0>;
};

port@3 {
reg = <3>;
label = "lan2";
default_cpu = <&cpu_port0>;
};

port@4 {
reg = <4>;
label = "lan3";
default_cpu = <&cpu_port0>;
};

port@6 {
cpu_port1: port@5 {
reg = <5>;
label = "cpu";
ethernet = <&gmac1>;
phy-mode = "trgmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
cpu_port0: port@6 {
reg = <6>;
label = "cpu";
ethernet = <&gmac0>;
55 changes: 38 additions & 17 deletions drivers/net/dsa/mt7530.c
Original file line number Diff line number Diff line change
@@ -678,10 +678,19 @@ static int
mt7530_cpu_port_enable(struct mt7530_priv *priv,
int port)
{
u8 port_mask = 0;
int i;

/* Enable Mediatek header mode on the cpu port */
mt7530_write(priv, MT7530_PVC_P(port),
PORT_SPEC_TAG);

/* Enable Mediatek header mode on the GMAC that the cpu port
* connects to
*/
regmap_write_bits(priv->ethernet, MTK_GDMA_FWD_CFG(port),
GDMA_SPEC_TAG, GDMA_SPEC_TAG);

/* Setup the MAC by default for the cpu port */
mt7530_write(priv, MT7530_PMCR_P(port), PMCR_CPUP_LINK);

@@ -694,8 +703,14 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv,
/* CPU port gets connected to all user ports of
* the switch
*/

for (i = 0; i < MT7530_NUM_PORTS; i++)
if ((priv->ds->ports[port].type == DSA_PORT_TYPE_USER) &&
(dsa_port_upstream_port(priv->ds, i) == port))
port_mask |= BIT(i);

mt7530_write(priv, MT7530_PCR_P(port),
PCR_MATRIX(dsa_user_ports(priv->ds)));
PCR_MATRIX(port_mask));

return 0;
}
@@ -705,6 +720,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
struct phy_device *phy)
{
struct mt7530_priv *priv = ds->priv;
u8 upstream = dsa_port_upstream_port(ds, port);

mutex_lock(&priv->reg_mutex);

@@ -715,7 +731,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
* restore the port matrix if the port is the member of a certain
* bridge.
*/
priv->ports[port].pm |= PCR_MATRIX(BIT(MT7530_CPU_PORT));
priv->ports[port].pm |= PCR_MATRIX(BIT(upstream));
priv->ports[port].enable = true;
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
priv->ports[port].pm);
@@ -778,7 +794,8 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
struct net_device *bridge)
{
struct mt7530_priv *priv = ds->priv;
u32 port_bitmap = BIT(MT7530_CPU_PORT);
u8 upstream = dsa_port_upstream_port(ds, port);
u32 port_bitmap = BIT(upstream);
int i;

mutex_lock(&priv->reg_mutex);
@@ -879,6 +896,7 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
struct net_device *bridge)
{
struct mt7530_priv *priv = ds->priv;
u8 upstream = dsa_port_upstream_port(ds, port);
int i;

mutex_lock(&priv->reg_mutex);
@@ -906,8 +924,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
*/
if (priv->ports[port].enable)
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
PCR_MATRIX(BIT(MT7530_CPU_PORT)));
priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT));
PCR_MATRIX(BIT(upstream)));
priv->ports[port].pm = PCR_MATRIX(BIT(upstream));

mt7530_port_set_vlan_unaware(ds, port);

@@ -1198,15 +1216,7 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port,
static enum dsa_tag_protocol
mtk_get_tag_protocol(struct dsa_switch *ds, int port)
{
struct mt7530_priv *priv = ds->priv;

if (port != MT7530_CPU_PORT) {
dev_warn(priv->dev,
"port not matched with tagging CPU port\n");
return DSA_TAG_PROTO_NONE;
} else {
return DSA_TAG_PROTO_MTK;
}
return DSA_TAG_PROTO_MTK;
}

static int
@@ -1279,8 +1289,13 @@ mt7530_setup(struct dsa_switch *ds)

/* Enable Port 6 only; P5 as GMAC5 which currently is not supported */
val = mt7530_read(priv, MT7530_MHWTRAP);
val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS;
val &= ~MHWTRAP_P5_DIS & ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS;
val |= MHWTRAP_MANUAL;
if (!dsa_is_cpu_port(ds, 5)) {
val |= MHWTRAP_P5_DIS;
val |= MHWTRAP_P5_MAC_SEL;
val |= MHWTRAP_P5_RGMII_MODE;
}
mt7530_write(priv, MT7530_MHWTRAP, val);

/* Enable and reset MIB counters */
@@ -1334,7 +1349,7 @@ static int
mt7530_probe(struct mdio_device *mdiodev)
{
struct mt7530_priv *priv;
struct device_node *dn;
struct device_node *dn, *mdio;

dn = mdiodev->dev.of_node;

@@ -1381,8 +1396,14 @@ mt7530_probe(struct mdio_device *mdiodev)
return PTR_ERR(priv->reset);
}
}
mdio = of_get_parent(dn);
if (!mdio)
return -EINVAL;

priv->bus = of_mdio_find_bus(mdio);
if (!priv->bus)
return -EPROBE_DEFER;

priv->bus = mdiodev->bus;
priv->dev = &mdiodev->dev;
priv->ds->priv = priv;
priv->ds->ops = &mt7530_switch_ops;
4 changes: 4 additions & 0 deletions drivers/net/dsa/mt7530.h
Original file line number Diff line number Diff line change
@@ -23,6 +23,10 @@

#define TRGMII_BASE(x) (0x10000 + (x))

/* Registers for GDMA configuration access */
#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000))
#define GDMA_SPEC_TAG BIT(24)

/* Registers to ethsys access */
#define ETHSYS_CLKCFG0 0x2c
#define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11)
22 changes: 22 additions & 0 deletions include/net/dsa.h
Original file line number Diff line number Diff line change
@@ -202,6 +202,10 @@ struct dsa_port {
struct net_device *bridge_dev;
struct devlink_port devlink_port;
struct phylink *pl;

struct net_device *ethernet;
int upstream;

/*
* Original copy of the master netdev ethtool_ops
*/
@@ -314,6 +318,12 @@ static inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device,
return ds->rtable[device];
}


static inline bool dsa_is_upstream_port(struct dsa_switch *ds, int p)
{
return dsa_is_cpu_port(ds, p) || dsa_is_dsa_port(ds, p);
}

/* Return the local port used to reach the dedicated CPU port */
static inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port)
{
@@ -326,6 +336,18 @@ static inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port)
return dsa_towards_port(ds, cpu_dp->ds->index, cpu_dp->index);
}

static inline u8 dsa_port_upstream_port(struct dsa_switch *ds, int port)
{
/*
* If this port has a specific upstream cpu port, use it,
* otherwise use the switch default.
*/
if (ds->ports[port].upstream)
return ds->ports[port].upstream;
else
return dsa_upstream_port(ds, port);
}

typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
bool is_static, void *data);
struct dsa_switch_ops {
36 changes: 36 additions & 0 deletions net/dsa/dsa2.c
Original file line number Diff line number Diff line change
@@ -255,6 +255,24 @@ static void dsa_tree_teardown_default_cpu(struct dsa_switch_tree *dst)
dst->cpu_dp = NULL;
}

static int dsa_user_parse(struct dsa_port *port, u32 index,
struct dsa_switch *ds)
{
struct device_node *cpu_port;
const unsigned int *cpu_port_reg;
int cpu_port_index;

cpu_port = of_parse_phandle(port->dn, "default_cpu", 0);
if (cpu_port) {
cpu_port_reg = of_get_property(cpu_port, "reg", NULL);
if (!cpu_port_reg)
return -EINVAL;
cpu_port_index = be32_to_cpup(cpu_port_reg);
ds->ports[index].upstream = cpu_port_index;
}
return 0;
}

static int dsa_port_setup(struct dsa_port *dp)
{
struct dsa_switch *ds = dp->ds;
@@ -285,6 +303,8 @@ static int dsa_port_setup(struct dsa_port *dp)
ds->index, dp->index);
return err;
}
if (dp->master)
dp->master->dsa_ptr = dp;
break;
case DSA_PORT_TYPE_DSA:
/* dp->index is used now as port_number. However
@@ -305,12 +325,17 @@ static int dsa_port_setup(struct dsa_port *dp)
devlink_port_attrs_set(&dp->devlink_port,
DEVLINK_PORT_FLAVOUR_PHYSICAL,
dp->index, false, 0);
err = dsa_user_parse(dp, dp->index, ds);
if (err)
return err;

err = dsa_slave_create(dp);
if (err)
dev_err(ds->dev, "failed to create slave for port %d.%d\n",
ds->index, dp->index);
else
devlink_port_type_eth_set(&dp->devlink_port, dp->slave);

break;
}

@@ -326,6 +351,14 @@ static void dsa_port_teardown(struct dsa_port *dp)
case DSA_PORT_TYPE_UNUSED:
break;
case DSA_PORT_TYPE_CPU:
dsa_port_link_unregister_of(dp);
if (dp->master)
dp->master->dsa_ptr = NULL;
if (dp->ethernet) {
dev_put(dp->ethernet);
dp->ethernet = NULL;
}
break;
case DSA_PORT_TYPE_DSA:
dsa_port_link_unregister_of(dp);
break;
@@ -580,6 +613,9 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master)
dp->master = master;
dp->dst = dst;

dev_hold(master);
ds->ports[dp->index].ethernet = master;

return 0;
}

5 changes: 5 additions & 0 deletions net/dsa/dsa_priv.h
Original file line number Diff line number Diff line change
@@ -81,6 +81,8 @@ struct dsa_slave_priv {

/* TC context */
struct list_head mall_tc_list;

struct net_device *master;
};

/* dsa.c */
@@ -187,7 +189,10 @@ static inline struct net_device *
dsa_slave_to_master(const struct net_device *dev)
{
struct dsa_port *dp = dsa_slave_to_port(dev);
struct dsa_slave_priv *p = netdev_priv(dev);

if (p->master)
return p->master;
return dp->cpu_dp->master;
}

3 changes: 2 additions & 1 deletion net/dsa/slave.c
Original file line number Diff line number Diff line change
@@ -1291,11 +1291,11 @@ static void dsa_slave_notify(struct net_device *dev, unsigned long val)
int dsa_slave_create(struct dsa_port *port)
{
const struct dsa_port *cpu_dp = port->cpu_dp;
struct net_device *master = cpu_dp->master;
struct dsa_switch *ds = port->ds;
const char *name = port->name;
struct net_device *slave_dev;
struct dsa_slave_priv *p;
struct net_device *master = ds->ports[port->upstream].ethernet;
int ret;

if (!ds->num_tx_queues)
@@ -1334,6 +1334,7 @@ int dsa_slave_create(struct dsa_port *port)
p->dp = port;
INIT_LIST_HEAD(&p->mall_tc_list);
p->xmit = cpu_dp->tag_ops->xmit;
p->master = master;
port->slave = slave_dev;

netif_carrier_off(slave_dev);