linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible
@ 2016-06-20 17:13 Vivien Didelot
  2016-06-20 17:13 ` [PATCH v5 net-next v5 01/14] net: dsa: mv88e6xxx: fix style issues Vivien Didelot
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:13 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

This patchset factorizes the legacy and new SMI probing and abstracts
the switch register accesses. This simplifies adding support for new
chips or alternative register accesses.

This will allow us to use a compatible chip info to describe how to
access the SMI device and its switch ID register at probe time.

For the legacy probe, we fix the compatible info to 88E6085. For the
MDIO probe, we will use the compatible info from the device node data.

All patches are reviewed.

Changes since v4:

  - fix debug printing (was 'val' instead of '*val')

Changes since v3 [3]:

  - better register access abstraction using the chip structure

Changes since v2 [2]:

  - do not guess compatible model in legacy probe
  - add low level SMI API using a chip structure
  - allocate before probe and detection
  - add 3 cosmetic patches

Changes since v1 [1]:

  - merge style fix from Ben Dooks
  - add Acked-by/Reviewed-by tags
  - drop one compatible string per model
  - detect the SMI device based on the compatible info
  - add an SMI ops structure

[1] https://lkml.org/lkml/2016/6/8/1201
[2] https://lkml.org/lkml/2016/6/14/671
[3] https://lkml.org/lkml/2016/6/17/995

Vivien Didelot (14):
  net: dsa: mv88e6xxx: fix style issues
  net: dsa: mv88e6xxx: remove redundant assignments
  net: dsa: mv88e6xxx: use already declared variables
  net: dsa: mv88e6xxx: do not increment bus refcount
  net: dsa: mv88e6xxx: add switch register helpers
  net: dsa: mv88e6xxx: use gpio get optional variant
  net: dsa: mv88e6xxx: remove table args in info lookup
  net: dsa: mv88e6xxx: rename smi_mutex to reg_lock
  net: dsa: mv88e6xxx: add chip allocation helper
  net: dsa: mv88e6xxx: add SMI init helper
  net: dsa: mv88e6xxx: add detection helper
  net: dsa: mv88e6xxx: pass compatible info
  net: dsa: mv88e6xxx: add port base address to info
  net: dsa: mv88e6xxx: abstract switch registers accesses

 drivers/net/dsa/mv88e6xxx.c | 567 ++++++++++++++++++++++++++++----------------
 drivers/net/dsa/mv88e6xxx.h |  34 ++-
 2 files changed, 385 insertions(+), 216 deletions(-)

-- 
2.9.0

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 01/14] net: dsa: mv88e6xxx: fix style issues
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
@ 2016-06-20 17:13 ` Vivien Didelot
  2016-06-20 17:13 ` [PATCH v5 net-next v5 02/14] net: dsa: mv88e6xxx: remove redundant assignments Vivien Didelot
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:13 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

This patch fixes 5 style problems reported by checkpatch:

    WARNING: suspect code indent for conditional statements (8, 24)
    #492: FILE: drivers/net/dsa/mv88e6xxx.c:492:
    +	if (phydev->link)
    +			reg |= PORT_PCS_CTRL_LINK_UP;

    CHECK: Logical continuations should be on the previous line
    #1318: FILE: drivers/net/dsa/mv88e6xxx.c:1318:
    +		     oldstate == PORT_CONTROL_STATE_FORWARDING)
    +		    && (state == PORT_CONTROL_STATE_DISABLED ||

    CHECK: multiple assignments should be avoided
    #1662: FILE: drivers/net/dsa/mv88e6xxx.c:1662:
    +		vlan->vid_begin = vlan->vid_end = next.vid;

    WARNING: line over 80 characters
    #2097: FILE: drivers/net/dsa/mv88e6xxx.c:2097:
    +				       const struct switchdev_obj_port_vlan *vlan,

    WARNING: suspect code indent for conditional statements (16, 32)
    #2734: FILE: drivers/net/dsa/mv88e6xxx.c:2734:
    +		if (mv88e6xxx_6352_family(ps) || mv88e6xxx_6351_family(ps) ||
    [...]
    +				reg |= PORT_CONTROL_EGRESS_ADD_TAG;

    total: 0 errors, 3 warnings, 2 checks, 3805 lines checked

It also rebases and integrates changes sent by Ben Dooks [1]:

    The driver has a number of functions that are not exported or
    declared elsewhere, so make them static to avoid the following
    warnings from sparse:

    drivers/net/dsa/mv88e6xxx.c:113:5: warning: symbol 'mv88e6xxx_reg_read' was not declared. Should it be static?
    drivers/net/dsa/mv88e6xxx.c:167:5: warning: symbol 'mv88e6xxx_reg_write' was not declared. Should it be static?
    drivers/net/dsa/mv88e6xxx.c:231:5: warning: symbol 'mv88e6xxx_set_addr' was not declared. Should it be static?
    drivers/net/dsa/mv88e6xxx.c:367:6: warning: symbol 'mv88e6xxx_ppu_state_init' was not declared. Should it be static?
    drivers/net/dsa/mv88e6xxx.c:3157:5: warning: symbol 'mv88e6xxx_phy_page_read' was not declared. Should it be static?
    drivers/net/dsa/mv88e6xxx.c:3169:5: warning: symbol 'mv88e6xxx_phy_page_write' was not declared. Should it be static?
    drivers/net/dsa/mv88e6xxx.c:3583:26: warning: symbol 'mv88e6xxx_switch_driver' was not declared. Should it be static?
    drivers/net/dsa/mv88e6xxx.c:3621:5: warning: symbol 'mv88e6xxx_probe' was not declared. Should it be static?

[1] http://patchwork.ozlabs.org/patch/632708/

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 42 +++++++++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 19 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index ee06055..1972ec5 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -111,7 +111,8 @@ static int _mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps,
 	return ret;
 }
 
-int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr, int reg)
+static int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr,
+			      int reg)
 {
 	int ret;
 
@@ -165,8 +166,8 @@ static int _mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
 	return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val);
 }
 
-int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
-			int reg, u16 val)
+static int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
+			       int reg, u16 val)
 {
 	int ret;
 
@@ -229,7 +230,7 @@ static int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
 	return 0;
 }
 
-int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr)
+static int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
@@ -370,7 +371,7 @@ static void mv88e6xxx_ppu_access_put(struct mv88e6xxx_priv_state *ps)
 	mutex_unlock(&ps->ppu_mutex);
 }
 
-void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
+static void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
 {
 	mutex_init(&ps->ppu_mutex);
 	INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
@@ -490,7 +491,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
 
 	reg |= PORT_PCS_CTRL_FORCE_LINK;
 	if (phydev->link)
-			reg |= PORT_PCS_CTRL_LINK_UP;
+		reg |= PORT_PCS_CTRL_LINK_UP;
 
 	if (mv88e6xxx_6065_family(ps) && phydev->speed > SPEED_100)
 		goto out;
@@ -1314,9 +1315,9 @@ static int _mv88e6xxx_port_state(struct mv88e6xxx_priv_state *ps, int port,
 		 * Blocking or Listening state.
 		 */
 		if ((oldstate == PORT_CONTROL_STATE_LEARNING ||
-		     oldstate == PORT_CONTROL_STATE_FORWARDING)
-		    && (state == PORT_CONTROL_STATE_DISABLED ||
-			state == PORT_CONTROL_STATE_BLOCKING)) {
+		     oldstate == PORT_CONTROL_STATE_FORWARDING) &&
+		    (state == PORT_CONTROL_STATE_DISABLED ||
+		     state == PORT_CONTROL_STATE_BLOCKING)) {
 			ret = _mv88e6xxx_atu_remove(ps, 0, port, false);
 			if (ret)
 				return ret;
@@ -1659,7 +1660,8 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
 			continue;
 
 		/* reinit and dump this VLAN obj */
-		vlan->vid_begin = vlan->vid_end = next.vid;
+		vlan->vid_begin = next.vid;
+		vlan->vid_end = next.vid;
 		vlan->flags = 0;
 
 		if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED)
@@ -2093,9 +2095,10 @@ unlock:
 	return ret;
 }
 
-static int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
-				       const struct switchdev_obj_port_vlan *vlan,
-				       struct switchdev_trans *trans)
+static int
+mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
+			    const struct switchdev_obj_port_vlan *vlan,
+			    struct switchdev_trans *trans)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int err;
@@ -2735,7 +2738,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_priv_state *ps, int port)
 		    mv88e6xxx_6165_family(ps) || mv88e6xxx_6097_family(ps) ||
 		    mv88e6xxx_6095_family(ps) || mv88e6xxx_6065_family(ps) ||
 		    mv88e6xxx_6185_family(ps) || mv88e6xxx_6320_family(ps)) {
-				reg |= PORT_CONTROL_EGRESS_ADD_TAG;
+			reg |= PORT_CONTROL_EGRESS_ADD_TAG;
 		}
 	}
 	if (dsa_is_dsa_port(ds, port)) {
@@ -3158,7 +3161,8 @@ unlock:
 	return err;
 }
 
-int mv88e6xxx_mdio_page_read(struct dsa_switch *ds, int port, int page, int reg)
+static int mv88e6xxx_mdio_page_read(struct dsa_switch *ds, int port, int page,
+				    int reg)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
@@ -3170,8 +3174,8 @@ int mv88e6xxx_mdio_page_read(struct dsa_switch *ds, int port, int page, int reg)
 	return ret;
 }
 
-int mv88e6xxx_mdio_page_write(struct dsa_switch *ds, int port, int page,
-			      int reg, int val)
+static int mv88e6xxx_mdio_page_write(struct dsa_switch *ds, int port, int page,
+				     int reg, int val)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
@@ -3650,7 +3654,7 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 	return name;
 }
 
-struct dsa_switch_driver mv88e6xxx_switch_driver = {
+static struct dsa_switch_driver mv88e6xxx_switch_driver = {
 	.tag_protocol		= DSA_TAG_PROTO_EDSA,
 	.probe			= mv88e6xxx_drv_probe,
 	.setup			= mv88e6xxx_setup,
@@ -3686,7 +3690,7 @@ struct dsa_switch_driver mv88e6xxx_switch_driver = {
 	.port_fdb_dump          = mv88e6xxx_port_fdb_dump,
 };
 
-int mv88e6xxx_probe(struct mdio_device *mdiodev)
+static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 {
 	struct device *dev = &mdiodev->dev;
 	struct device_node *np = dev->of_node;
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 02/14] net: dsa: mv88e6xxx: remove redundant assignments
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
  2016-06-20 17:13 ` [PATCH v5 net-next v5 01/14] net: dsa: mv88e6xxx: fix style issues Vivien Didelot
@ 2016-06-20 17:13 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 03/14] net: dsa: mv88e6xxx: use already declared variables Vivien Didelot
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:13 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

The chip->ds and ds->slave_mii_bus assignments are common to both legacy
and new MDIO probing and are already done in the later setup code.

Remove the duplicated assignments from the MDIO probing code.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 1972ec5..673283a 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3708,7 +3708,6 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	ds->priv = ps;
 	ds->dev = dev;
 	ps->dev = dev;
-	ps->ds = ds;
 	ps->bus = mdiodev->bus;
 	ps->sw_addr = mdiodev->addr;
 	mutex_init(&ps->smi_mutex);
@@ -3748,8 +3747,6 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	if (err)
 		return err;
 
-	ds->slave_mii_bus = ps->mdio_bus;
-
 	dev_set_drvdata(dev, ds);
 
 	err = dsa_register_switch(ds, mdiodev->dev.of_node);
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 03/14] net: dsa: mv88e6xxx: use already declared variables
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
  2016-06-20 17:13 ` [PATCH v5 net-next v5 01/14] net: dsa: mv88e6xxx: fix style issues Vivien Didelot
  2016-06-20 17:13 ` [PATCH v5 net-next v5 02/14] net: dsa: mv88e6xxx: remove redundant assignments Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 04/14] net: dsa: mv88e6xxx: do not increment bus refcount Vivien Didelot
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

In the MDIO probing function, dev is already assigned to &mdiodev->dev
and np is already assigned to mdiodev->dev.of_node, so use them.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 673283a..b3170ea 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3728,7 +3728,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	if (!ps->info)
 		return -ENODEV;
 
-	ps->reset = devm_gpiod_get(&mdiodev->dev, "reset", GPIOD_ASIS);
+	ps->reset = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
 	if (IS_ERR(ps->reset)) {
 		err = PTR_ERR(ps->reset);
 		if (err == -ENOENT) {
@@ -3743,13 +3743,13 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	    !of_property_read_u32(np, "eeprom-length", &eeprom_len))
 		ps->eeprom_len = eeprom_len;
 
-	err = mv88e6xxx_mdio_register(ps, mdiodev->dev.of_node);
+	err = mv88e6xxx_mdio_register(ps, np);
 	if (err)
 		return err;
 
 	dev_set_drvdata(dev, ds);
 
-	err = dsa_register_switch(ds, mdiodev->dev.of_node);
+	err = dsa_register_switch(ds, np);
 	if (err) {
 		mv88e6xxx_mdio_unregister(ps);
 		return err;
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 04/14] net: dsa: mv88e6xxx: do not increment bus refcount
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (2 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 03/14] net: dsa: mv88e6xxx: use already declared variables Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 05/14] net: dsa: mv88e6xxx: add switch register helpers Vivien Didelot
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

The MDIO device probe and remove functions are respectively incrementing
and decrementing the bus refcount themselves. Since these bus level
actions are out of the device scope, remove them.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Acked-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index b3170ea..4b4bffc 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3712,8 +3712,6 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	ps->sw_addr = mdiodev->addr;
 	mutex_init(&ps->smi_mutex);
 
-	get_device(&ps->bus->dev);
-
 	ds->drv = &mv88e6xxx_switch_driver;
 
 	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
@@ -3767,7 +3765,6 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
 	dsa_unregister_switch(ds);
-	put_device(&ps->bus->dev);
 
 	mv88e6xxx_mdio_unregister(ps);
 }
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 05/14] net: dsa: mv88e6xxx: add switch register helpers
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (3 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 04/14] net: dsa: mv88e6xxx: do not increment bus refcount Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 06/14] net: dsa: mv88e6xxx: use gpio get optional variant Vivien Didelot
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

The mixed assignments, allocations and registrations in the probe code
make it hard to follow the logic and figure out what is DSA or chip
specific.

Extract the struct dsa_switch related code in a simple
mv88e6xxx_register_switch helper function.

For symmetry in the code, add a mv88e6xxx_unregister_switch function.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 41 ++++++++++++++++++++++++++++-------------
 1 file changed, 28 insertions(+), 13 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 4b4bffc..ad7735d 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3690,30 +3690,48 @@ static struct dsa_switch_driver mv88e6xxx_switch_driver = {
 	.port_fdb_dump          = mv88e6xxx_port_fdb_dump,
 };
 
+static int mv88e6xxx_register_switch(struct mv88e6xxx_priv_state *ps,
+				     struct device_node *np)
+{
+	struct device *dev = ps->dev;
+	struct dsa_switch *ds;
+
+	ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL);
+	if (!ds)
+		return -ENOMEM;
+
+	ds->dev = dev;
+	ds->priv = ps;
+	ds->drv = &mv88e6xxx_switch_driver;
+
+	dev_set_drvdata(dev, ds);
+
+	return dsa_register_switch(ds, np);
+}
+
+static void mv88e6xxx_unregister_switch(struct mv88e6xxx_priv_state *ps)
+{
+	dsa_unregister_switch(ps->ds);
+}
+
 static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 {
 	struct device *dev = &mdiodev->dev;
 	struct device_node *np = dev->of_node;
 	struct mv88e6xxx_priv_state *ps;
 	int id, prod_num, rev;
-	struct dsa_switch *ds;
 	u32 eeprom_len;
 	int err;
 
-	ds = devm_kzalloc(dev, sizeof(*ds) + sizeof(*ps), GFP_KERNEL);
-	if (!ds)
+	ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
+	if (!ps)
 		return -ENOMEM;
 
-	ps = (struct mv88e6xxx_priv_state *)(ds + 1);
-	ds->priv = ps;
-	ds->dev = dev;
 	ps->dev = dev;
 	ps->bus = mdiodev->bus;
 	ps->sw_addr = mdiodev->addr;
 	mutex_init(&ps->smi_mutex);
 
-	ds->drv = &mv88e6xxx_switch_driver;
-
 	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
 	if (id < 0)
 		return id;
@@ -3745,9 +3763,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	if (err)
 		return err;
 
-	dev_set_drvdata(dev, ds);
-
-	err = dsa_register_switch(ds, np);
+	err = mv88e6xxx_register_switch(ps, np);
 	if (err) {
 		mv88e6xxx_mdio_unregister(ps);
 		return err;
@@ -3764,8 +3780,7 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
 	struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
-	dsa_unregister_switch(ds);
-
+	mv88e6xxx_unregister_switch(ps);
 	mv88e6xxx_mdio_unregister(ps);
 }
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 06/14] net: dsa: mv88e6xxx: use gpio get optional variant
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (4 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 05/14] net: dsa: mv88e6xxx: add switch register helpers Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 07/14] net: dsa: mv88e6xxx: remove table args in info lookup Vivien Didelot
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

Use the optional variant to get the reset GPIO line, instead of checking
for the -ENOENT error.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index ad7735d..ec28465 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3744,16 +3744,9 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	if (!ps->info)
 		return -ENODEV;
 
-	ps->reset = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
-	if (IS_ERR(ps->reset)) {
-		err = PTR_ERR(ps->reset);
-		if (err == -ENOENT) {
-			/* Optional, so not an error */
-			ps->reset = NULL;
-		} else {
-			return err;
-		}
-	}
+	ps->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
+	if (IS_ERR(ps->reset))
+		return PTR_ERR(ps->reset);
 
 	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM) &&
 	    !of_property_read_u32(np, "eeprom-length", &eeprom_len))
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 07/14] net: dsa: mv88e6xxx: remove table args in info lookup
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (5 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 06/14] net: dsa: mv88e6xxx: use gpio get optional variant Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 08/14] net: dsa: mv88e6xxx: rename smi_mutex to reg_lock Vivien Didelot
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

The mv88e6xxx_table array and the mv88e6xxx_lookup_info function are
static, so remove the table and size arguments from the lookup function.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index ec28465..75e5408 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3590,15 +3590,13 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 	},
 };
 
-static const struct mv88e6xxx_info *
-mv88e6xxx_lookup_info(unsigned int prod_num, const struct mv88e6xxx_info *table,
-		      unsigned int num)
+static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
 {
 	int i;
 
-	for (i = 0; i < num; ++i)
-		if (table[i].prod_num == prod_num)
-			return &table[i];
+	for (i = 0; i < ARRAY_SIZE(mv88e6xxx_table); ++i)
+		if (mv88e6xxx_table[i].prod_num == prod_num)
+			return &mv88e6xxx_table[i];
 
 	return NULL;
 }
@@ -3625,8 +3623,7 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 	prod_num = (id & 0xfff0) >> 4;
 	rev = id & 0x000f;
 
-	info = mv88e6xxx_lookup_info(prod_num, mv88e6xxx_table,
-				     ARRAY_SIZE(mv88e6xxx_table));
+	info = mv88e6xxx_lookup_info(prod_num);
 	if (!info)
 		return NULL;
 
@@ -3739,8 +3736,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	prod_num = (id & 0xfff0) >> 4;
 	rev = id & 0x000f;
 
-	ps->info = mv88e6xxx_lookup_info(prod_num, mv88e6xxx_table,
-					 ARRAY_SIZE(mv88e6xxx_table));
+	ps->info = mv88e6xxx_lookup_info(prod_num);
 	if (!ps->info)
 		return -ENODEV;
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 08/14] net: dsa: mv88e6xxx: rename smi_mutex to reg_lock
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (6 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 07/14] net: dsa: mv88e6xxx: remove table args in info lookup Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 09/14] net: dsa: mv88e6xxx: add chip allocation helper Vivien Didelot
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

The chip smi_mutex mutex is used to protect the access to the internal
switch registers, not only the Multi-chip Addressing Mode, as commented.

Since we will isolate SMI-specific pieces of code, avoid the confusion
now by renaming smi_mutex to reg_lock. No functional changes here.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 120 ++++++++++++++++++++++----------------------
 drivers/net/dsa/mv88e6xxx.h |   7 +--
 2 files changed, 62 insertions(+), 65 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 75e5408..2c86172 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -29,10 +29,10 @@
 #include <net/switchdev.h>
 #include "mv88e6xxx.h"
 
-static void assert_smi_lock(struct mv88e6xxx_priv_state *ps)
+static void assert_reg_lock(struct mv88e6xxx_priv_state *ps)
 {
-	if (unlikely(!mutex_is_locked(&ps->smi_mutex))) {
-		dev_err(ps->dev, "SMI lock not held!\n");
+	if (unlikely(!mutex_is_locked(&ps->reg_lock))) {
+		dev_err(ps->dev, "Switch registers lock not held!\n");
 		dump_stack();
 	}
 }
@@ -99,7 +99,7 @@ static int _mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps,
 {
 	int ret;
 
-	assert_smi_lock(ps);
+	assert_reg_lock(ps);
 
 	ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg);
 	if (ret < 0)
@@ -116,9 +116,9 @@ static int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr,
 {
 	int ret;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 	ret = _mv88e6xxx_reg_read(ps, addr, reg);
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return ret;
 }
@@ -158,7 +158,7 @@ static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
 static int _mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
 				int reg, u16 val)
 {
-	assert_smi_lock(ps);
+	assert_reg_lock(ps);
 
 	dev_dbg(ps->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
 		addr, reg, val);
@@ -171,9 +171,9 @@ static int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
 {
 	int ret;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 	ret = _mv88e6xxx_reg_write(ps, addr, reg, val);
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return ret;
 }
@@ -320,7 +320,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
 
 	ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	if (mutex_trylock(&ps->ppu_mutex)) {
 		if (mv88e6xxx_ppu_enable(ps) == 0)
@@ -328,7 +328,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
 		mutex_unlock(&ps->ppu_mutex);
 	}
 
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 }
 
 static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
@@ -477,7 +477,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
 	if (!phy_is_pseudo_fixed_link(phydev))
 		return;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_PCS_CTRL);
 	if (ret < 0)
@@ -528,7 +528,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
 	_mv88e6xxx_reg_write(ps, REG_PORT(port), PORT_PCS_CTRL, reg);
 
 out:
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 }
 
 static int _mv88e6xxx_stats_wait(struct mv88e6xxx_priv_state *ps)
@@ -753,11 +753,11 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
 	int ret;
 	int i, j;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	ret = _mv88e6xxx_stats_snapshot(ps, port);
 	if (ret < 0) {
-		mutex_unlock(&ps->smi_mutex);
+		mutex_unlock(&ps->reg_lock);
 		return;
 	}
 	for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
@@ -768,7 +768,7 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
 		}
 	}
 
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 }
 
 static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
@@ -787,7 +787,7 @@ static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
 
 	memset(p, 0xff, 32 * sizeof(u16));
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	for (i = 0; i < 32; i++) {
 		int ret;
@@ -797,7 +797,7 @@ static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
 			p[i] = ret;
 	}
 
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 }
 
 static int _mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg, int offset,
@@ -824,9 +824,9 @@ static int mv88e6xxx_wait(struct mv88e6xxx_priv_state *ps, int reg,
 {
 	int ret;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 	ret = _mv88e6xxx_wait(ps, reg, offset, mask);
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return ret;
 }
@@ -1123,7 +1123,7 @@ static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
 		return -EOPNOTSUPP;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	reg = mv88e6xxx_mdio_read_indirect(ps, port, 16);
 	if (reg < 0)
@@ -1140,7 +1140,7 @@ static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
 	reg = 0;
 
 out:
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 	return reg;
 }
 
@@ -1154,7 +1154,7 @@ static int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEE))
 		return -EOPNOTSUPP;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	ret = mv88e6xxx_mdio_read_indirect(ps, port, 16);
 	if (ret < 0)
@@ -1168,7 +1168,7 @@ static int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 
 	ret = mv88e6xxx_mdio_write_indirect(ps, port, 16, reg);
 out:
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return ret;
 }
@@ -1402,9 +1402,9 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
 		break;
 	}
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 	err = _mv88e6xxx_port_state(ps, port, stp_state);
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	if (err)
 		netdev_err(ds->ports[port].netdev,
@@ -1638,7 +1638,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
 		return -EOPNOTSUPP;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
 	if (err)
@@ -1676,7 +1676,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
 	} while (next.vid < GLOBAL_VTU_VID_MASK);
 
 unlock:
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return err;
 }
@@ -2004,7 +2004,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
 	if (!vid_begin)
 		return -EOPNOTSUPP;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	err = _mv88e6xxx_vtu_vid_write(ps, vid_begin - 1);
 	if (err)
@@ -2043,7 +2043,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
 	} while (vlan.vid < vid_end);
 
 unlock:
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return err;
 }
@@ -2066,7 +2066,7 @@ static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
 		return -EOPNOTSUPP;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	ret = _mv88e6xxx_reg_read(ps, REG_PORT(port), PORT_CONTROL_2);
 	if (ret < 0)
@@ -2090,7 +2090,7 @@ static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
 
 	ret = 0;
 unlock:
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return ret;
 }
@@ -2149,7 +2149,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
 		return;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
 		if (_mv88e6xxx_port_vlan_add(ps, port, vid, untagged))
@@ -2161,7 +2161,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
 		netdev_err(ds->ports[port].netdev, "failed to set PVID %d\n",
 			   vlan->vid_end);
 
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 }
 
 static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_priv_state *ps,
@@ -2210,7 +2210,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VTU))
 		return -EOPNOTSUPP;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	err = _mv88e6xxx_port_pvid_get(ps, port, &pvid);
 	if (err)
@@ -2229,7 +2229,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
 	}
 
 unlock:
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return err;
 }
@@ -2341,11 +2341,11 @@ static void mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
 		return;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 	if (_mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid, state))
 		netdev_err(ds->ports[port].netdev,
 			   "failed to load MAC address\n");
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 }
 
 static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
@@ -2357,10 +2357,10 @@ static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
 		return -EOPNOTSUPP;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 	ret = _mv88e6xxx_port_fdb_load(ps, port, fdb->addr, fdb->vid,
 				       GLOBAL_ATU_DATA_STATE_UNUSED);
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return ret;
 }
@@ -2465,7 +2465,7 @@ static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_ATU))
 		return -EOPNOTSUPP;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	/* Dump port's default Filtering Information Database (VLAN ID 0) */
 	err = _mv88e6xxx_port_fid_get(ps, port, &fid);
@@ -2496,7 +2496,7 @@ static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
 	} while (vlan.vid < GLOBAL_VTU_VID_MASK);
 
 unlock:
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return err;
 }
@@ -2510,7 +2510,7 @@ static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
 		return -EOPNOTSUPP;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	/* Assign the bridge and remap each port's VLANTable */
 	ps->ports[port].bridge_dev = bridge;
@@ -2523,7 +2523,7 @@ static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
 		}
 	}
 
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return err;
 }
@@ -2537,7 +2537,7 @@ static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
 	if (!mv88e6xxx_has(ps, MV88E6XXX_FLAG_VLANTABLE))
 		return;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	/* Unassign the bridge and remap each port's VLANTable */
 	ps->ports[port].bridge_dev = NULL;
@@ -2548,7 +2548,7 @@ static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port)
 				netdev_warn(ds->ports[i].netdev,
 					    "failed to remap\n");
 
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 }
 
 static int _mv88e6xxx_mdio_page_write(struct mv88e6xxx_priv_state *ps,
@@ -3139,7 +3139,7 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
 	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
 		mutex_init(&ps->eeprom_mutex);
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	err = mv88e6xxx_switch_reset(ps);
 	if (err)
@@ -3156,7 +3156,7 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
 	}
 
 unlock:
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return err;
 }
@@ -3167,9 +3167,9 @@ static int mv88e6xxx_mdio_page_read(struct dsa_switch *ds, int port, int page,
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 	ret = _mv88e6xxx_mdio_page_read(ps, port, page, reg);
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return ret;
 }
@@ -3180,9 +3180,9 @@ static int mv88e6xxx_mdio_page_write(struct dsa_switch *ds, int port, int page,
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 	ret = _mv88e6xxx_mdio_page_write(ps, port, page, reg, val);
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 
 	return ret;
 }
@@ -3204,7 +3204,7 @@ static int mv88e6xxx_mdio_read(struct mii_bus *bus, int port, int regnum)
 	if (addr < 0)
 		return 0xffff;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
 		ret = mv88e6xxx_mdio_read_ppu(ps, addr, regnum);
@@ -3213,7 +3213,7 @@ static int mv88e6xxx_mdio_read(struct mii_bus *bus, int port, int regnum)
 	else
 		ret = mv88e6xxx_mdio_read_direct(ps, addr, regnum);
 
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 	return ret;
 }
 
@@ -3227,7 +3227,7 @@ static int mv88e6xxx_mdio_write(struct mii_bus *bus, int port, int regnum,
 	if (addr < 0)
 		return 0xffff;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
 		ret = mv88e6xxx_mdio_write_ppu(ps, addr, regnum, val);
@@ -3236,7 +3236,7 @@ static int mv88e6xxx_mdio_write(struct mii_bus *bus, int port, int regnum,
 	else
 		ret = mv88e6xxx_mdio_write_direct(ps, addr, regnum, val);
 
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 	return ret;
 }
 
@@ -3310,7 +3310,7 @@ static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
 
 	*temp = 0;
 
-	mutex_lock(&ps->smi_mutex);
+	mutex_lock(&ps->reg_lock);
 
 	ret = mv88e6xxx_mdio_write_direct(ps, 0x0, 0x16, 0x6);
 	if (ret < 0)
@@ -3343,7 +3343,7 @@ static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
 
 error:
 	mv88e6xxx_mdio_write_direct(ps, 0x0, 0x16, 0x0);
-	mutex_unlock(&ps->smi_mutex);
+	mutex_unlock(&ps->reg_lock);
 	return ret;
 }
 
@@ -3637,7 +3637,7 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 	ps->sw_addr = sw_addr;
 	ps->info = info;
 	ps->dev = dsa_dev;
-	mutex_init(&ps->smi_mutex);
+	mutex_init(&ps->reg_lock);
 
 	err = mv88e6xxx_mdio_register(ps, NULL);
 	if (err)
@@ -3727,7 +3727,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	ps->dev = dev;
 	ps->bus = mdiodev->bus;
 	ps->sw_addr = mdiodev->addr;
-	mutex_init(&ps->smi_mutex);
+	mutex_init(&ps->reg_lock);
 
 	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
 	if (id < 0)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 8221c3c..b279f8c 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -554,11 +554,8 @@ struct mv88e6xxx_priv_state {
 	/* The device this structure is associated to */
 	struct device *dev;
 
-	/* When using multi-chip addressing, this mutex protects
-	 * access to the indirect access registers.  (In single-chip
-	 * mode, this mutex is effectively useless.)
-	 */
-	struct mutex	smi_mutex;
+	/* This mutex protects the access to the switch registers */
+	struct mutex reg_lock;
 
 	/* The MII bus and the address on the bus that is used to
 	 * communication with the switch
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 09/14] net: dsa: mv88e6xxx: add chip allocation helper
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (7 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 08/14] net: dsa: mv88e6xxx: rename smi_mutex to reg_lock Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 10/14] net: dsa: mv88e6xxx: add SMI init helper Vivien Didelot
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

Add an helper function to allocate the chip structure at the beginning
of the probe functions. It will be used to initialize the SMI access.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 39 +++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 2c86172..113092a 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3601,6 +3601,21 @@ static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
 	return NULL;
 }
 
+static struct mv88e6xxx_priv_state *mv88e6xxx_alloc_chip(struct device *dev)
+{
+	struct mv88e6xxx_priv_state *ps;
+
+	ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
+	if (!ps)
+		return NULL;
+
+	ps->dev = dev;
+
+	mutex_init(&ps->reg_lock);
+
+	return ps;
+}
+
 static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 				       struct device *host_dev, int sw_addr,
 				       void **priv)
@@ -3616,32 +3631,30 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 	if (!bus)
 		return NULL;
 
+	ps = mv88e6xxx_alloc_chip(dsa_dev);
+	if (!ps)
+		return NULL;
+
 	id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
 	if (id < 0)
-		return NULL;
+		goto free;
 
 	prod_num = (id & 0xfff0) >> 4;
 	rev = id & 0x000f;
 
 	info = mv88e6xxx_lookup_info(prod_num);
 	if (!info)
-		return NULL;
+		goto free;
 
 	name = info->name;
 
-	ps = devm_kzalloc(dsa_dev, sizeof(*ps), GFP_KERNEL);
-	if (!ps)
-		return NULL;
-
 	ps->bus = bus;
 	ps->sw_addr = sw_addr;
 	ps->info = info;
-	ps->dev = dsa_dev;
-	mutex_init(&ps->reg_lock);
 
 	err = mv88e6xxx_mdio_register(ps, NULL);
 	if (err)
-		return NULL;
+		goto free;
 
 	*priv = ps;
 
@@ -3649,6 +3662,10 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 		 prod_num, name, rev);
 
 	return name;
+free:
+	devm_kfree(dsa_dev, ps);
+
+	return NULL;
 }
 
 static struct dsa_switch_driver mv88e6xxx_switch_driver = {
@@ -3720,14 +3737,12 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	u32 eeprom_len;
 	int err;
 
-	ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
+	ps = mv88e6xxx_alloc_chip(dev);
 	if (!ps)
 		return -ENOMEM;
 
-	ps->dev = dev;
 	ps->bus = mdiodev->bus;
 	ps->sw_addr = mdiodev->addr;
-	mutex_init(&ps->reg_lock);
 
 	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
 	if (id < 0)
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 10/14] net: dsa: mv88e6xxx: add SMI init helper
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (8 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 09/14] net: dsa: mv88e6xxx: add chip allocation helper Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 11/14] net: dsa: mv88e6xxx: add detection helper Vivien Didelot
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

Add an helper function to isolate SMI specific assignments and checks.

This function will later help choosing the different SMI accesses based
of the compatible info.

Since the chip structure is already allocated in the legacy probe, use
the mv88e6xxx_reg_read access routine instead of __mv88e6xxx_reg_read.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 113092a..4e24ac5 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3616,6 +3616,19 @@ static struct mv88e6xxx_priv_state *mv88e6xxx_alloc_chip(struct device *dev)
 	return ps;
 }
 
+static int mv88e6xxx_smi_init(struct mv88e6xxx_priv_state *ps,
+			      struct mii_bus *bus, int sw_addr)
+{
+	/* ADDR[0] pin is unavailable externally and considered zero */
+	if (sw_addr & 0x1)
+		return -EINVAL;
+
+	ps->bus = bus;
+	ps->sw_addr = sw_addr;
+
+	return 0;
+}
+
 static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 				       struct device *host_dev, int sw_addr,
 				       void **priv)
@@ -3635,7 +3648,11 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 	if (!ps)
 		return NULL;
 
-	id = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
+	err = mv88e6xxx_smi_init(ps, bus, sw_addr);
+	if (err)
+		goto free;
+
+	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
 	if (id < 0)
 		goto free;
 
@@ -3648,8 +3665,6 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 
 	name = info->name;
 
-	ps->bus = bus;
-	ps->sw_addr = sw_addr;
 	ps->info = info;
 
 	err = mv88e6xxx_mdio_register(ps, NULL);
@@ -3741,8 +3756,9 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	if (!ps)
 		return -ENOMEM;
 
-	ps->bus = mdiodev->bus;
-	ps->sw_addr = mdiodev->addr;
+	err = mv88e6xxx_smi_init(ps, mdiodev->bus, mdiodev->addr);
+	if (err)
+		return err;
 
 	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
 	if (id < 0)
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 11/14] net: dsa: mv88e6xxx: add detection helper
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (9 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 10/14] net: dsa: mv88e6xxx: add SMI init helper Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 12/14] net: dsa: mv88e6xxx: pass compatible info Vivien Didelot
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

Extract the common detection code which assigns the info structure to
the chip given the read switch ID.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 64 +++++++++++++++++++++------------------------
 1 file changed, 30 insertions(+), 34 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 4e24ac5..de92add 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3601,6 +3601,30 @@ static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
 	return NULL;
 }
 
+static int mv88e6xxx_detect(struct mv88e6xxx_priv_state *ps)
+{
+	const struct mv88e6xxx_info *info;
+	int id, prod_num, rev;
+
+	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
+	if (id < 0)
+		return id;
+
+	prod_num = (id & 0xfff0) >> 4;
+	rev = id & 0x000f;
+
+	info = mv88e6xxx_lookup_info(prod_num);
+	if (!info)
+		return -ENODEV;
+
+	ps->info = info;
+
+	dev_info(ps->dev, "switch 0x%x detected: %s, revision %u\n",
+		 ps->info->prod_num, ps->info->name, rev);
+
+	return 0;
+}
+
 static struct mv88e6xxx_priv_state *mv88e6xxx_alloc_chip(struct device *dev)
 {
 	struct mv88e6xxx_priv_state *ps;
@@ -3633,11 +3657,8 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 				       struct device *host_dev, int sw_addr,
 				       void **priv)
 {
-	const struct mv88e6xxx_info *info;
 	struct mv88e6xxx_priv_state *ps;
 	struct mii_bus *bus;
-	const char *name;
-	int id, prod_num, rev;
 	int err;
 
 	bus = dsa_host_dev_to_mii_bus(host_dev);
@@ -3652,31 +3673,17 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 	if (err)
 		goto free;
 
-	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
-	if (id < 0)
-		goto free;
-
-	prod_num = (id & 0xfff0) >> 4;
-	rev = id & 0x000f;
-
-	info = mv88e6xxx_lookup_info(prod_num);
-	if (!info)
+	err = mv88e6xxx_detect(ps);
+	if (err)
 		goto free;
 
-	name = info->name;
-
-	ps->info = info;
-
 	err = mv88e6xxx_mdio_register(ps, NULL);
 	if (err)
 		goto free;
 
 	*priv = ps;
 
-	dev_info(&ps->bus->dev, "switch 0x%x probed: %s, revision %u\n",
-		 prod_num, name, rev);
-
-	return name;
+	return ps->info->name;
 free:
 	devm_kfree(dsa_dev, ps);
 
@@ -3748,7 +3755,6 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	struct device *dev = &mdiodev->dev;
 	struct device_node *np = dev->of_node;
 	struct mv88e6xxx_priv_state *ps;
-	int id, prod_num, rev;
 	u32 eeprom_len;
 	int err;
 
@@ -3760,16 +3766,9 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	if (err)
 		return err;
 
-	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
-	if (id < 0)
-		return id;
-
-	prod_num = (id & 0xfff0) >> 4;
-	rev = id & 0x000f;
-
-	ps->info = mv88e6xxx_lookup_info(prod_num);
-	if (!ps->info)
-		return -ENODEV;
+	err = mv88e6xxx_detect(ps);
+	if (err)
+		return err;
 
 	ps->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
 	if (IS_ERR(ps->reset))
@@ -3789,9 +3788,6 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 		return err;
 	}
 
-	dev_info(dev, "switch 0x%x probed: %s, revision %u\n",
-		 prod_num, ps->info->name, rev);
-
 	return 0;
 }
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 12/14] net: dsa: mv88e6xxx: pass compatible info
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (10 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 11/14] net: dsa: mv88e6xxx: add detection helper Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 13/14] net: dsa: mv88e6xxx: add port base address to info Vivien Didelot
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

After allocating the chip structure, pass it a compatible info pointer.

The compatible info structure will be used later to describe how to
access the switch registers and where to read the switch ID.

For the standard MDIO probe, get it from the device node data. For the
legacy DSA driver probing, pass it the 88E6085 info.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index de92add..cadd1e3 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -21,6 +21,7 @@
 #include <linux/list.h>
 #include <linux/mdio.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/of_mdio.h>
 #include <linux/netdevice.h>
 #include <linux/gpio/consumer.h>
@@ -3617,6 +3618,7 @@ static int mv88e6xxx_detect(struct mv88e6xxx_priv_state *ps)
 	if (!info)
 		return -ENODEV;
 
+	/* Update the compatible info with the probed one */
 	ps->info = info;
 
 	dev_info(ps->dev, "switch 0x%x detected: %s, revision %u\n",
@@ -3669,6 +3671,9 @@ static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
 	if (!ps)
 		return NULL;
 
+	/* Legacy SMI probing will only support chips similar to 88E6085 */
+	ps->info = &mv88e6xxx_table[MV88E6085];
+
 	err = mv88e6xxx_smi_init(ps, bus, sw_addr);
 	if (err)
 		goto free;
@@ -3754,14 +3759,21 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 {
 	struct device *dev = &mdiodev->dev;
 	struct device_node *np = dev->of_node;
+	const struct mv88e6xxx_info *compat_info;
 	struct mv88e6xxx_priv_state *ps;
 	u32 eeprom_len;
 	int err;
 
+	compat_info = of_device_get_match_data(dev);
+	if (!compat_info)
+		return -EINVAL;
+
 	ps = mv88e6xxx_alloc_chip(dev);
 	if (!ps)
 		return -ENOMEM;
 
+	ps->info = compat_info;
+
 	err = mv88e6xxx_smi_init(ps, mdiodev->bus, mdiodev->addr);
 	if (err)
 		return err;
@@ -3801,7 +3813,10 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
 }
 
 static const struct of_device_id mv88e6xxx_of_match[] = {
-	{ .compatible = "marvell,mv88e6085" },
+	{
+		.compatible = "marvell,mv88e6085",
+		.data = &mv88e6xxx_table[MV88E6085],
+	},
 	{ /* sentinel */ },
 };
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 13/14] net: dsa: mv88e6xxx: add port base address to info
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (11 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 12/14] net: dsa: mv88e6xxx: pass compatible info Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-20 17:14 ` [PATCH v5 net-next v5 14/14] net: dsa: mv88e6xxx: abstract switch registers accesses Vivien Didelot
  2016-06-21  8:05 ` [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible David Miller
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

The switch ID is located at address 0x3 of every Port Registers bank.

But not all Marvell switches have their Port Registers SMI Addresses
starting at 0x10. 88E6060 starts at 0x8 and 88E6390 starts at 0x0.

Add this data in the info structure and use it in the detection code.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 19 ++++++++++++++++++-
 drivers/net/dsa/mv88e6xxx.h |  1 +
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index cadd1e3..789f938a 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -3443,6 +3443,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6085",
 		.num_databases = 4096,
 		.num_ports = 10,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6097,
 	},
 
@@ -3452,6 +3453,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6095/88E6095F",
 		.num_databases = 256,
 		.num_ports = 11,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6095,
 	},
 
@@ -3461,6 +3463,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6123",
 		.num_databases = 4096,
 		.num_ports = 3,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6165,
 	},
 
@@ -3470,6 +3473,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6131",
 		.num_databases = 256,
 		.num_ports = 8,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6185,
 	},
 
@@ -3479,6 +3483,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6161",
 		.num_databases = 4096,
 		.num_ports = 6,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6165,
 	},
 
@@ -3488,6 +3493,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6165",
 		.num_databases = 4096,
 		.num_ports = 6,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6165,
 	},
 
@@ -3497,6 +3503,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6171",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6351,
 	},
 
@@ -3506,6 +3513,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6172",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6352,
 	},
 
@@ -3515,6 +3523,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6175",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6351,
 	},
 
@@ -3524,6 +3533,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6176",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6352,
 	},
 
@@ -3533,6 +3543,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6185",
 		.num_databases = 256,
 		.num_ports = 10,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6185,
 	},
 
@@ -3542,6 +3553,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6240",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6352,
 	},
 
@@ -3551,6 +3563,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6320",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6320,
 	},
 
@@ -3560,6 +3573,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6321",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6320,
 	},
 
@@ -3569,6 +3583,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6350",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6351,
 	},
 
@@ -3578,6 +3593,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6351",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6351,
 	},
 
@@ -3587,6 +3603,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.name = "Marvell 88E6352",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.port_base_addr = 0x10,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6352,
 	},
 };
@@ -3607,7 +3624,7 @@ static int mv88e6xxx_detect(struct mv88e6xxx_priv_state *ps)
 	const struct mv88e6xxx_info *info;
 	int id, prod_num, rev;
 
-	id = mv88e6xxx_reg_read(ps, REG_PORT(0), PORT_SWITCH_ID);
+	id = mv88e6xxx_reg_read(ps, ps->info->port_base_addr, PORT_SWITCH_ID);
 	if (id < 0)
 		return id;
 
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index b279f8c..8e6fe6b 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -519,6 +519,7 @@ struct mv88e6xxx_info {
 	const char *name;
 	unsigned int num_databases;
 	unsigned int num_ports;
+	unsigned int port_base_addr;
 	unsigned long flags;
 };
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 net-next v5 14/14] net: dsa: mv88e6xxx: abstract switch registers accesses
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (12 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 13/14] net: dsa: mv88e6xxx: add port base address to info Vivien Didelot
@ 2016-06-20 17:14 ` Vivien Didelot
  2016-06-21  8:05 ` [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible David Miller
  14 siblings, 0 replies; 16+ messages in thread
From: Vivien Didelot @ 2016-06-20 17:14 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Andrew Lunn,
	Florian Fainelli, Ben Dooks, Sergei Shtylyov, Vivien Didelot

When the SMI address of the switch chip is zero, the chip assumes to be
the only one on the SMI master bus and thus responds to all its known
SMI devices addresses (port registers, Global2, etc.)

When its SMI address is not zero, some chips (e.g. 88E6352) use an
indirect access through two SMI Command and Data registers.

Other models (e.g. 88E6060) using less than 16 internal SMI addresses
always use a direct access.

Add a capability flag to describe chips supporting the (indirect)
Multi-chip Addressing Mode, and a low-level API to access the registers
via SMI.

Other accesses (like Ethernet management frames) may be added later.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx.c | 204 +++++++++++++++++++++++++++++++-------------
 drivers/net/dsa/mv88e6xxx.h |  26 +++++-
 2 files changed, 170 insertions(+), 60 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 789f938a..9b116d8 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -38,21 +38,74 @@ static void assert_reg_lock(struct mv88e6xxx_priv_state *ps)
 	}
 }
 
-/* If the switch's ADDR[4:0] strap pins are strapped to zero, it will
- * use all 32 SMI bus addresses on its SMI bus, and all switch registers
- * will be directly accessible on some {device address,register address}
- * pair.  If the ADDR[4:0] pins are not strapped to zero, the switch
- * will only respond to SMI transactions to that specific address, and
- * an indirect addressing mechanism needs to be used to access its
- * registers.
+/* The switch ADDR[4:1] configuration pins define the chip SMI device address
+ * (ADDR[0] is always zero, thus only even SMI addresses can be strapped).
+ *
+ * When ADDR is all zero, the chip uses Single-chip Addressing Mode, assuming it
+ * is the only device connected to the SMI master. In this mode it responds to
+ * all 32 possible SMI addresses, and thus maps directly the internal devices.
+ *
+ * When ADDR is non-zero, the chip uses Multi-chip Addressing Mode, allowing
+ * multiple devices to share the SMI interface. In this mode it responds to only
+ * 2 registers, used to indirectly access the internal SMI devices.
  */
-static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
+
+static int mv88e6xxx_smi_read(struct mv88e6xxx_priv_state *ps,
+			      int addr, int reg, u16 *val)
+{
+	if (!ps->smi_ops)
+		return -EOPNOTSUPP;
+
+	return ps->smi_ops->read(ps, addr, reg, val);
+}
+
+static int mv88e6xxx_smi_write(struct mv88e6xxx_priv_state *ps,
+			       int addr, int reg, u16 val)
+{
+	if (!ps->smi_ops)
+		return -EOPNOTSUPP;
+
+	return ps->smi_ops->write(ps, addr, reg, val);
+}
+
+static int mv88e6xxx_smi_single_chip_read(struct mv88e6xxx_priv_state *ps,
+					  int addr, int reg, u16 *val)
+{
+	int ret;
+
+	ret = mdiobus_read_nested(ps->bus, addr, reg);
+	if (ret < 0)
+		return ret;
+
+	*val = ret & 0xffff;
+
+	return 0;
+}
+
+static int mv88e6xxx_smi_single_chip_write(struct mv88e6xxx_priv_state *ps,
+					   int addr, int reg, u16 val)
+{
+	int ret;
+
+	ret = mdiobus_write_nested(ps->bus, addr, reg, val);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct mv88e6xxx_ops mv88e6xxx_smi_single_chip_ops = {
+	.read = mv88e6xxx_smi_single_chip_read,
+	.write = mv88e6xxx_smi_single_chip_write,
+};
+
+static int mv88e6xxx_smi_multi_chip_wait(struct mv88e6xxx_priv_state *ps)
 {
 	int ret;
 	int i;
 
 	for (i = 0; i < 16; i++) {
-		ret = mdiobus_read_nested(bus, sw_addr, SMI_CMD);
+		ret = mdiobus_read_nested(ps->bus, ps->sw_addr, SMI_CMD);
 		if (ret < 0)
 			return ret;
 
@@ -63,108 +116,134 @@ static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
 	return -ETIMEDOUT;
 }
 
-static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr,
-				int reg)
+static int mv88e6xxx_smi_multi_chip_read(struct mv88e6xxx_priv_state *ps,
+					 int addr, int reg, u16 *val)
 {
 	int ret;
 
-	if (sw_addr == 0)
-		return mdiobus_read_nested(bus, addr, reg);
-
 	/* Wait for the bus to become free. */
-	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+	ret = mv88e6xxx_smi_multi_chip_wait(ps);
 	if (ret < 0)
 		return ret;
 
 	/* Transmit the read command. */
-	ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD,
+	ret = mdiobus_write_nested(ps->bus, ps->sw_addr, SMI_CMD,
 				   SMI_CMD_OP_22_READ | (addr << 5) | reg);
 	if (ret < 0)
 		return ret;
 
 	/* Wait for the read command to complete. */
-	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+	ret = mv88e6xxx_smi_multi_chip_wait(ps);
 	if (ret < 0)
 		return ret;
 
 	/* Read the data. */
-	ret = mdiobus_read_nested(bus, sw_addr, SMI_DATA);
-	if (ret < 0)
-		return ret;
-
-	return ret & 0xffff;
-}
-
-static int _mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps,
-			       int addr, int reg)
-{
-	int ret;
-
-	assert_reg_lock(ps);
-
-	ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg);
+	ret = mdiobus_read_nested(ps->bus, ps->sw_addr, SMI_DATA);
 	if (ret < 0)
 		return ret;
 
-	dev_dbg(ps->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
-		addr, reg, ret);
-
-	return ret;
-}
+	*val = ret & 0xffff;
 
-static int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr,
-			      int reg)
-{
-	int ret;
-
-	mutex_lock(&ps->reg_lock);
-	ret = _mv88e6xxx_reg_read(ps, addr, reg);
-	mutex_unlock(&ps->reg_lock);
-
-	return ret;
+	return 0;
 }
 
-static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
-				 int reg, u16 val)
+static int mv88e6xxx_smi_multi_chip_write(struct mv88e6xxx_priv_state *ps,
+					  int addr, int reg, u16 val)
 {
 	int ret;
 
-	if (sw_addr == 0)
-		return mdiobus_write_nested(bus, addr, reg, val);
-
 	/* Wait for the bus to become free. */
-	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+	ret = mv88e6xxx_smi_multi_chip_wait(ps);
 	if (ret < 0)
 		return ret;
 
 	/* Transmit the data to write. */
-	ret = mdiobus_write_nested(bus, sw_addr, SMI_DATA, val);
+	ret = mdiobus_write_nested(ps->bus, ps->sw_addr, SMI_DATA, val);
 	if (ret < 0)
 		return ret;
 
 	/* Transmit the write command. */
-	ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD,
+	ret = mdiobus_write_nested(ps->bus, ps->sw_addr, SMI_CMD,
 				   SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
 	if (ret < 0)
 		return ret;
 
 	/* Wait for the write command to complete. */
-	ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+	ret = mv88e6xxx_smi_multi_chip_wait(ps);
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
 
-static int _mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
-				int reg, u16 val)
+static const struct mv88e6xxx_ops mv88e6xxx_smi_multi_chip_ops = {
+	.read = mv88e6xxx_smi_multi_chip_read,
+	.write = mv88e6xxx_smi_multi_chip_write,
+};
+
+static int mv88e6xxx_read(struct mv88e6xxx_priv_state *ps,
+			  int addr, int reg, u16 *val)
+{
+	int err;
+
+	assert_reg_lock(ps);
+
+	err = mv88e6xxx_smi_read(ps, addr, reg, val);
+	if (err)
+		return err;
+
+	dev_dbg(ps->dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
+		addr, reg, *val);
+
+	return 0;
+}
+
+static int mv88e6xxx_write(struct mv88e6xxx_priv_state *ps,
+			   int addr, int reg, u16 val)
 {
+	int err;
+
 	assert_reg_lock(ps);
 
+	err = mv88e6xxx_smi_write(ps, addr, reg, val);
+	if (err)
+		return err;
+
 	dev_dbg(ps->dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
 		addr, reg, val);
 
-	return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val);
+	return 0;
+}
+
+static int _mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps,
+			       int addr, int reg)
+{
+	u16 val;
+	int err;
+
+	err = mv88e6xxx_read(ps, addr, reg, &val);
+	if (err)
+		return err;
+
+	return val;
+}
+
+static int mv88e6xxx_reg_read(struct mv88e6xxx_priv_state *ps, int addr,
+			      int reg)
+{
+	int ret;
+
+	mutex_lock(&ps->reg_lock);
+	ret = _mv88e6xxx_reg_read(ps, addr, reg);
+	mutex_unlock(&ps->reg_lock);
+
+	return ret;
+}
+
+static int _mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
+				int reg, u16 val)
+{
+	return mv88e6xxx_write(ps, addr, reg, val);
 }
 
 static int mv88e6xxx_reg_write(struct mv88e6xxx_priv_state *ps, int addr,
@@ -3666,6 +3745,13 @@ static int mv88e6xxx_smi_init(struct mv88e6xxx_priv_state *ps,
 	if (sw_addr & 0x1)
 		return -EINVAL;
 
+	if (sw_addr == 0)
+		ps->smi_ops = &mv88e6xxx_smi_single_chip_ops;
+	else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_MULTI_CHIP))
+		ps->smi_ops = &mv88e6xxx_smi_multi_chip_ops;
+	else
+		return -EINVAL;
+
 	ps->bus = bus;
 	ps->sw_addr = sw_addr;
 
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 8e6fe6b..a94acd8 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -387,6 +387,12 @@ enum mv88e6xxx_cap {
 	 */
 	MV88E6XXX_CAP_EEPROM,
 
+	/* Multi-chip Addressing Mode.
+	 * Some chips require an indirect SMI access when their SMI device
+	 * address is not zero. See SMI_CMD and SMI_DATA.
+	 */
+	MV88E6XXX_CAP_MULTI_CHIP,
+
 	/* Port State Filtering for 802.1D Spanning Tree.
 	 * See PORT_CONTROL_STATE_* values in the PORT_CONTROL register.
 	 */
@@ -439,6 +445,7 @@ enum mv88e6xxx_cap {
 #define MV88E6XXX_FLAG_ATU		BIT(MV88E6XXX_CAP_ATU)
 #define MV88E6XXX_FLAG_EEE		BIT(MV88E6XXX_CAP_EEE)
 #define MV88E6XXX_FLAG_EEPROM		BIT(MV88E6XXX_CAP_EEPROM)
+#define MV88E6XXX_FLAG_MULTI_CHIP	BIT(MV88E6XXX_CAP_MULTI_CHIP)
 #define MV88E6XXX_FLAG_PORTSTATE	BIT(MV88E6XXX_CAP_PORTSTATE)
 #define MV88E6XXX_FLAG_PPU		BIT(MV88E6XXX_CAP_PPU)
 #define MV88E6XXX_FLAG_PPU_ACTIVE	BIT(MV88E6XXX_CAP_PPU_ACTIVE)
@@ -452,25 +459,29 @@ enum mv88e6xxx_cap {
 
 #define MV88E6XXX_FLAGS_FAMILY_6095	\
 	(MV88E6XXX_FLAG_ATU |		\
+	 MV88E6XXX_FLAG_MULTI_CHIP |	\
 	 MV88E6XXX_FLAG_PPU |		\
 	 MV88E6XXX_FLAG_VLANTABLE |	\
 	 MV88E6XXX_FLAG_VTU)
 
 #define MV88E6XXX_FLAGS_FAMILY_6097	\
 	(MV88E6XXX_FLAG_ATU |		\
+	 MV88E6XXX_FLAG_MULTI_CHIP |	\
 	 MV88E6XXX_FLAG_PPU |		\
 	 MV88E6XXX_FLAG_STU |		\
 	 MV88E6XXX_FLAG_VLANTABLE |	\
 	 MV88E6XXX_FLAG_VTU)
 
 #define MV88E6XXX_FLAGS_FAMILY_6165	\
-	(MV88E6XXX_FLAG_STU |		\
+	(MV88E6XXX_FLAG_MULTI_CHIP |	\
+	 MV88E6XXX_FLAG_STU |		\
 	 MV88E6XXX_FLAG_SWITCH_MAC |	\
 	 MV88E6XXX_FLAG_TEMP |		\
 	 MV88E6XXX_FLAG_VTU)
 
 #define MV88E6XXX_FLAGS_FAMILY_6185	\
 	(MV88E6XXX_FLAG_ATU |		\
+	 MV88E6XXX_FLAG_MULTI_CHIP |	\
 	 MV88E6XXX_FLAG_PPU |		\
 	 MV88E6XXX_FLAG_VLANTABLE |	\
 	 MV88E6XXX_FLAG_VTU)
@@ -479,6 +490,7 @@ enum mv88e6xxx_cap {
 	(MV88E6XXX_FLAG_ATU |		\
 	 MV88E6XXX_FLAG_EEE |		\
 	 MV88E6XXX_FLAG_EEPROM |	\
+	 MV88E6XXX_FLAG_MULTI_CHIP |	\
 	 MV88E6XXX_FLAG_PORTSTATE |	\
 	 MV88E6XXX_FLAG_PPU_ACTIVE |	\
 	 MV88E6XXX_FLAG_SMI_PHY |	\
@@ -490,6 +502,7 @@ enum mv88e6xxx_cap {
 
 #define MV88E6XXX_FLAGS_FAMILY_6351	\
 	(MV88E6XXX_FLAG_ATU |		\
+	 MV88E6XXX_FLAG_MULTI_CHIP |	\
 	 MV88E6XXX_FLAG_PORTSTATE |	\
 	 MV88E6XXX_FLAG_PPU_ACTIVE |	\
 	 MV88E6XXX_FLAG_SMI_PHY |	\
@@ -503,6 +516,7 @@ enum mv88e6xxx_cap {
 	(MV88E6XXX_FLAG_ATU |		\
 	 MV88E6XXX_FLAG_EEE |		\
 	 MV88E6XXX_FLAG_EEPROM |	\
+	 MV88E6XXX_FLAG_MULTI_CHIP |	\
 	 MV88E6XXX_FLAG_PORTSTATE |	\
 	 MV88E6XXX_FLAG_PPU_ACTIVE |	\
 	 MV88E6XXX_FLAG_SMI_PHY |	\
@@ -542,6 +556,8 @@ struct mv88e6xxx_vtu_stu_entry {
 	u8	data[DSA_MAX_PORTS];
 };
 
+struct mv88e6xxx_ops;
+
 struct mv88e6xxx_priv_port {
 	struct net_device *bridge_dev;
 };
@@ -561,6 +577,7 @@ struct mv88e6xxx_priv_state {
 	/* The MII bus and the address on the bus that is used to
 	 * communication with the switch
 	 */
+	const struct mv88e6xxx_ops *smi_ops;
 	struct mii_bus *bus;
 	int sw_addr;
 
@@ -606,6 +623,13 @@ struct mv88e6xxx_priv_state {
 	struct mii_bus *mdio_bus;
 };
 
+struct mv88e6xxx_ops {
+	int (*read)(struct mv88e6xxx_priv_state *ps,
+		    int addr, int reg, u16 *val);
+	int (*write)(struct mv88e6xxx_priv_state *ps,
+		     int addr, int reg, u16 val);
+};
+
 enum stat_type {
 	BANK0,
 	BANK1,
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible
  2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
                   ` (13 preceding siblings ...)
  2016-06-20 17:14 ` [PATCH v5 net-next v5 14/14] net: dsa: mv88e6xxx: abstract switch registers accesses Vivien Didelot
@ 2016-06-21  8:05 ` David Miller
  14 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2016-06-21  8:05 UTC (permalink / raw)
  To: vivien.didelot
  Cc: netdev, linux-kernel, kernel, andrew, f.fainelli, ben.dooks,
	sergei.shtylyov

From: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Date: Mon, 20 Jun 2016 13:13:57 -0400

> This patchset factorizes the legacy and new SMI probing and abstracts
> the switch register accesses. This simplifies adding support for new
> chips or alternative register accesses.
> 
> This will allow us to use a compatible chip info to describe how to
> access the SMI device and its switch ID register at probe time.
> 
> For the legacy probe, we fix the compatible info to 88E6085. For the
> MDIO probe, we will use the compatible info from the device node data.
> 
> All patches are reviewed.

Series applied, thanks Vivien.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2016-06-21  8:06 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-20 17:13 [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible Vivien Didelot
2016-06-20 17:13 ` [PATCH v5 net-next v5 01/14] net: dsa: mv88e6xxx: fix style issues Vivien Didelot
2016-06-20 17:13 ` [PATCH v5 net-next v5 02/14] net: dsa: mv88e6xxx: remove redundant assignments Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 03/14] net: dsa: mv88e6xxx: use already declared variables Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 04/14] net: dsa: mv88e6xxx: do not increment bus refcount Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 05/14] net: dsa: mv88e6xxx: add switch register helpers Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 06/14] net: dsa: mv88e6xxx: use gpio get optional variant Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 07/14] net: dsa: mv88e6xxx: remove table args in info lookup Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 08/14] net: dsa: mv88e6xxx: rename smi_mutex to reg_lock Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 09/14] net: dsa: mv88e6xxx: add chip allocation helper Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 10/14] net: dsa: mv88e6xxx: add SMI init helper Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 11/14] net: dsa: mv88e6xxx: add detection helper Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 12/14] net: dsa: mv88e6xxx: pass compatible info Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 13/14] net: dsa: mv88e6xxx: add port base address to info Vivien Didelot
2016-06-20 17:14 ` [PATCH v5 net-next v5 14/14] net: dsa: mv88e6xxx: abstract switch registers accesses Vivien Didelot
2016-06-21  8:05 ` [PATCH v5 net-next v5 00/14] net: dsa: mv88e6xxx: probe compatible David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).