net: stmmac: Use driver data and callbacks tied with compatible strings
authorChen-Yu Tsai <wens@csie.org>
Fri, 17 Jan 2014 13:24:46 +0000 (21:24 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 20 Jan 2014 04:02:03 +0000 (20:02 -0800)
The stmmac driver core allows passing feature flags and callbacks via
platform data. Add a similar stmmac_of_data to pass flags and callbacks
tied to compatible strings. This allows us to extend stmmac with glue
layers for different SoCs.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
include/linux/stmmac.h

index 82110f141d09d89b4240880519e3d8f29bfe94f0..bf119db15212d054a31441c5b25ec75987667ffd 100644 (file)
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_net.h>
+#include <linux/of_device.h>
 #include "stmmac.h"
 
+static const struct of_device_id stmmac_dt_ids[] = {
+       /* SoC specific glue layers should come before generic bindings */
+       { .compatible = "st,spear600-gmac"},
+       { .compatible = "snps,dwmac-3.610"},
+       { .compatible = "snps,dwmac-3.70a"},
+       { .compatible = "snps,dwmac-3.710"},
+       { .compatible = "snps,dwmac"},
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
+
 #ifdef CONFIG_OF
 static int stmmac_probe_config_dt(struct platform_device *pdev,
                                  struct plat_stmmacenet_data *plat,
@@ -35,10 +47,32 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
 {
        struct device_node *np = pdev->dev.of_node;
        struct stmmac_dma_cfg *dma_cfg;
+       const struct of_device_id *device;
 
        if (!np)
                return -ENODEV;
 
+       device = of_match_device(stmmac_dt_ids, &pdev->dev);
+       if (!device)
+               return -ENODEV;
+
+       if (device->data) {
+               const struct stmmac_of_data *data = device->data;
+               plat->has_gmac = data->has_gmac;
+               plat->enh_desc = data->enh_desc;
+               plat->tx_coe = data->tx_coe;
+               plat->rx_coe = data->rx_coe;
+               plat->bugged_jumbo = data->bugged_jumbo;
+               plat->pmt = data->pmt;
+               plat->riwt_off = data->riwt_off;
+               plat->fix_mac_speed = data->fix_mac_speed;
+               plat->bus_setup = data->bus_setup;
+               plat->setup = data->setup;
+               plat->free = data->free;
+               plat->init = data->init;
+               plat->exit = data->exit;
+       }
+
        *mac = of_get_mac_address(np);
        plat->interface = of_get_phy_mode(np);
 
@@ -259,16 +293,6 @@ static int stmmac_pltfr_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
                        stmmac_pltfr_suspend, stmmac_pltfr_resume);
 
-static const struct of_device_id stmmac_dt_ids[] = {
-       { .compatible = "st,spear600-gmac"},
-       { .compatible = "snps,dwmac-3.610"},
-       { .compatible = "snps,dwmac-3.70a"},
-       { .compatible = "snps,dwmac-3.710"},
-       { .compatible = "snps,dwmac"},
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, stmmac_dt_ids);
-
 struct platform_driver stmmac_pltfr_driver = {
        .probe = stmmac_pltfr_probe,
        .remove = stmmac_pltfr_remove,
index 0a5a7aca562e2d70f84f45752425684ab964da0a..1367974b7e84a84e7c30cee52c7c77e37f8d0319 100644 (file)
@@ -121,4 +121,22 @@ struct plat_stmmacenet_data {
        void *custom_data;
        void *bsp_priv;
 };
+
+/* of_data for SoC glue layer device tree bindings */
+
+struct stmmac_of_data {
+       int has_gmac;
+       int enh_desc;
+       int tx_coe;
+       int rx_coe;
+       int bugged_jumbo;
+       int pmt;
+       int riwt_off;
+       void (*fix_mac_speed)(void *priv, unsigned int speed);
+       void (*bus_setup)(void __iomem *ioaddr);
+       void *(*setup)(struct platform_device *pdev);
+       void (*free)(struct platform_device *pdev, void *priv);
+       int (*init)(struct platform_device *pdev, void *priv);
+       void (*exit)(struct platform_device *pdev, void *priv);
+};
 #endif