Not all the world uses device tree. Some parts of the world still use
platform devices and platform data. Add basic support for probing a
Marvell switch via platform data.

Signed-off-by: Andrew Lunn <and...@lunn.ch>
---
 MAINTAINERS                             |  1 +
 drivers/net/dsa/mv88e6xxx/chip.c        | 56 +++++++++++++++++++++----
 include/linux/platform_data/mv88e6xxx.h | 17 ++++++++
 3 files changed, 67 insertions(+), 7 deletions(-)
 create mode 100644 include/linux/platform_data/mv88e6xxx.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 658880464b9d..9f2045a5adac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8466,6 +8466,7 @@ M:        Vivien Didelot 
<vivien.dide...@savoirfairelinux.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/dsa/mv88e6xxx/
+F:     linux/platform_data/mv88e6xxx.h
 F:     Documentation/devicetree/bindings/net/dsa/marvell.txt
 
 MARVELL ARMADA DRM SUPPORT
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 2bb3f03ee1cb..5b40382036ea 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -28,6 +28,7 @@
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_mdio.h>
+#include <linux/platform_data/mv88e6xxx.h>
 #include <linux/netdevice.h>
 #include <linux/gpio/consumer.h>
 #include <linux/phy.h>
@@ -4350,6 +4351,7 @@ static int mv88e6xxx_register_switch(struct 
mv88e6xxx_chip *chip)
                return -ENOMEM;
 
        ds->priv = chip;
+       ds->dev = dev;
        ds->ops = &mv88e6xxx_switch_ops;
        ds->ageing_time_min = chip->info->age_time_coeff;
        ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
@@ -4364,36 +4366,73 @@ static void mv88e6xxx_unregister_switch(struct 
mv88e6xxx_chip *chip)
        dsa_unregister_switch(chip->ds);
 }
 
+static const void *pdata_device_get_match_data(struct device *dev)
+{
+       const struct of_device_id *matches = dev->driver->of_match_table;
+       const struct dsa_mv88e6xxx_pdata *pdata = dev->platform_data;
+
+       for (; matches->name[0] || matches->type[0] || matches->compatible[0];
+            matches++) {
+               if (!strcmp(pdata->compatible, matches->compatible))
+                       return matches->data;
+       }
+       return NULL;
+}
+
 static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 {
+       struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data;
        struct device *dev = &mdiodev->dev;
        struct device_node *np = dev->of_node;
        const struct mv88e6xxx_info *compat_info;
        struct mv88e6xxx_chip *chip;
        u32 eeprom_len;
+       int port;
        int err;
 
-       compat_info = of_device_get_match_data(dev);
+       if (np)
+               compat_info = of_device_get_match_data(dev);
+
+       if (pdata) {
+               compat_info = pdata_device_get_match_data(dev);
+
+               if (!pdata->netdev)
+                       return -EINVAL;
+
+               for (port = 0; port < DSA_MAX_PORTS; port++) {
+                       if (!(pdata->enabled_ports & (1 << port)))
+                               continue;
+                       if (strcmp(pdata->cd.port_names[port], "cpu"))
+                               continue;
+                       pdata->cd.netdev[port] = &pdata->netdev->dev;
+                       break;
+               }
+       }
+
        if (!compat_info)
                return -EINVAL;
 
        chip = mv88e6xxx_alloc_chip(dev);
-       if (!chip)
-               return -ENOMEM;
+       if (!chip) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        chip->info = compat_info;
 
        err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr);
        if (err)
-               return err;
+               goto out;
 
        chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
-       if (IS_ERR(chip->reset))
-               return PTR_ERR(chip->reset);
+       if (IS_ERR(chip->reset)) {
+               err = PTR_ERR(chip->reset);
+               goto out;
+       }
 
        err = mv88e6xxx_detect(chip);
        if (err)
-               return err;
+               goto out;
 
        mv88e6xxx_phy_init(chip);
 
@@ -4468,6 +4507,9 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
                mv88e6xxx_irq_poll_free(chip);
        mutex_unlock(&chip->reg_lock);
 out:
+       if (pdata)
+               dev_put(pdata->netdev);
+
        return err;
 }
 
diff --git a/include/linux/platform_data/mv88e6xxx.h 
b/include/linux/platform_data/mv88e6xxx.h
new file mode 100644
index 000000000000..88e91e05f48f
--- /dev/null
+++ b/include/linux/platform_data/mv88e6xxx.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DSA_MV88E6XXX_H
+#define __DSA_MV88E6XXX_H
+
+#include <net/dsa.h>
+
+struct dsa_mv88e6xxx_pdata {
+       /* Must be first, such that dsa_register_switch() can access this
+        * without gory pointer manipulations
+        */
+       struct dsa_chip_data cd;
+       const char *compatible;
+       unsigned int enabled_ports;
+       struct net_device *netdev;
+};
+
+#endif
-- 
2.17.0

Reply via email to