net: dsa: mv88e6xxx: Add minimal platform_data support
authorAndrew Lunn <andrew@lunn.ch>
Sat, 19 May 2018 20:31:34 +0000 (22:31 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sun, 20 May 2018 22:58:27 +0000 (18:58 -0400)
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 <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
MAINTAINERS
drivers/net/dsa/mv88e6xxx/chip.c
include/linux/platform_data/mv88e6xxx.h [new file with mode: 0644]

index 658880464b9d6c4e1d0b91c927e3934c73b048bd..9f2045a5adac3cfbdb336d4ba5a546a8c1ef7805 100644 (file)
@@ -8466,6 +8466,7 @@ M:        Vivien Didelot <vivien.didelot@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
index 2bb3f03ee1cb2e8ff9b38f98375de36beb8aa0f5..5b40382036eabbd9f74b34a19aaf699a5834d584 100644 (file)
@@ -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 @@ out_g1_irq:
                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 (file)
index 0000000..88e91e0
--- /dev/null
@@ -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