igb: Add device support for flashless SKU of i210 device
[deliverable/linux.git] / drivers / net / ethernet / davicom / dm9000.c
index 9105465b2a1a92c5561c99bbda0df7902182ccbb..a13b312b50f20dfd544d88a338bd4263a4a716af 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/spinlock.h>
 #include <linux/crc32.h>
 #include <linux/mii.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
 #include <linux/ethtool.h>
 #include <linux/dm9000.h>
 #include <linux/delay.h>
@@ -827,7 +829,7 @@ dm9000_hash_table_unlocked(struct net_device *dev)
        struct netdev_hw_addr *ha;
        int i, oft;
        u32 hash_val;
-       u16 hash_table[4];
+       u16 hash_table[4] = { 0, 0, 0, 0x8000 }; /* broadcast address */
        u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
 
        dm9000_dbg(db, 1, "entering %s\n", __func__);
@@ -835,13 +837,6 @@ dm9000_hash_table_unlocked(struct net_device *dev)
        for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
                iow(db, oft, dev->dev_addr[i]);
 
-       /* Clear Hash Table */
-       for (i = 0; i < 4; i++)
-               hash_table[i] = 0x0;
-
-       /* broadcast address */
-       hash_table[3] = 0x8000;
-
        if (dev->flags & IFF_PROMISC)
                rcr |= RCR_PRMSC;
 
@@ -1358,6 +1353,31 @@ static const struct net_device_ops dm9000_netdev_ops = {
 #endif
 };
 
+static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev)
+{
+       struct dm9000_plat_data *pdata;
+       struct device_node *np = dev->of_node;
+       const void *mac_addr;
+
+       if (!IS_ENABLED(CONFIG_OF) || !np)
+               return NULL;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return ERR_PTR(-ENOMEM);
+
+       if (of_find_property(np, "davicom,ext-phy", NULL))
+               pdata->flags |= DM9000_PLATF_EXT_PHY;
+       if (of_find_property(np, "davicom,no-eeprom", NULL))
+               pdata->flags |= DM9000_PLATF_NO_EEPROM;
+
+       mac_addr = of_get_mac_address(np);
+       if (mac_addr)
+               memcpy(pdata->dev_addr, mac_addr, sizeof(pdata->dev_addr));
+
+       return pdata;
+}
+
 /*
  * Search DM9000 board, allocate space and register it
  */
@@ -1373,6 +1393,12 @@ dm9000_probe(struct platform_device *pdev)
        int i;
        u32 id_val;
 
+       if (!pdata) {
+               pdata = dm9000_parse_dt(&pdev->dev);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+       }
+
        /* Init network device */
        ndev = alloc_etherdev(sizeof(struct board_info));
        if (!ndev)
@@ -1673,8 +1699,6 @@ dm9000_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
 
-       platform_set_drvdata(pdev, NULL);
-
        unregister_netdev(ndev);
        dm9000_release_board(pdev, netdev_priv(ndev));
        free_netdev(ndev);              /* free device structure */
@@ -1683,11 +1707,20 @@ dm9000_drv_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id dm9000_of_matches[] = {
+       { .compatible = "davicom,dm9000", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dm9000_of_matches);
+#endif
+
 static struct platform_driver dm9000_driver = {
        .driver = {
                .name    = "dm9000",
                .owner   = THIS_MODULE,
                .pm      = &dm9000_drv_pm_ops,
+               .of_match_table = of_match_ptr(dm9000_of_matches),
        },
        .probe   = dm9000_probe,
        .remove  = dm9000_drv_remove,
This page took 0.032774 seconds and 5 git commands to generate.