summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-05-20 18:58:28 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-20 18:58:28 -0400
commitbf4bd7a727a13f810c003f592425171adbbd0cda (patch)
tree4d8fee548a2e1e414b8bd9bb59725294e2be170d
parent81ee33d87362ac542cd8ad6d6fb7b886a51e2c96 (diff)
parent00baabe5286c41d21ed4a78f479b021eba1f0d51 (diff)
downloadlinux-bf4bd7a727a13f810c003f592425171adbbd0cda.tar.bz2
Merge branch 'mv88exxx-pdata'
Andrew Lunn says: ==================== Platform data support for mv88exxx There are a few Intel based platforms making use of the mv88exxx. These don't easily have access to device tree in order to instantiate the switch driver. These patches allow the use of platform data to hold the configuration. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c67
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h2
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.c3
-rw-r--r--include/linux/platform_data/mv88e6xxx.h18
5 files changed, 76 insertions, 15 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 658880464b9d..9f2045a5adac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 2bb3f03ee1cb..1fa1f820a437 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,42 +4366,82 @@ 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);
- if (chip->info->ops->get_eeprom &&
- !of_property_read_u32(np, "eeprom-length", &eeprom_len))
- chip->eeprom_len = eeprom_len;
+ if (chip->info->ops->get_eeprom) {
+ if (np)
+ of_property_read_u32(np, "eeprom-length",
+ &chip->eeprom_len);
+ else
+ chip->eeprom_len = pdata->eeprom_len;
+ }
mutex_lock(&chip->reg_lock);
err = mv88e6xxx_switch_reset(chip);
@@ -4468,6 +4510,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/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 012268046442..8ac3fbb15352 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -238,7 +238,7 @@ struct mv88e6xxx_chip {
struct gpio_desc *reset;
/* set to size of eeprom if supported by the switch */
- int eeprom_len;
+ u32 eeprom_len;
/* List of mdio busses */
struct list_head mdios;
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index f9bde011a3e6..91a3cb2452ac 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -1047,9 +1047,6 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
{
int err, irq, virq;
- if (!chip->dev->of_node)
- return -EINVAL;
-
chip->g2_irq.domain = irq_domain_add_simple(
chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
if (!chip->g2_irq.domain)
diff --git a/include/linux/platform_data/mv88e6xxx.h b/include/linux/platform_data/mv88e6xxx.h
new file mode 100644
index 000000000000..f63af2955ea0
--- /dev/null
+++ b/include/linux/platform_data/mv88e6xxx.h
@@ -0,0 +1,18 @@
+/* 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;
+ u32 eeprom_len;
+};
+
+#endif