net: velocity: Add platform device support to VIA velocity driver
authorTony Prisk <linux@prisktech.co.nz>
Sat, 18 May 2013 09:39:07 +0000 (09:39 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 20 May 2013 20:40:39 +0000 (13:40 -0700)
Add support for the VIA Velocity network driver to be bound to a
OF created platform device.

Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/devicetree/bindings/net/via-velocity.txt [new file with mode: 0644]
drivers/net/ethernet/via/Kconfig
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/via/via-velocity.h

diff --git a/Documentation/devicetree/bindings/net/via-velocity.txt b/Documentation/devicetree/bindings/net/via-velocity.txt
new file mode 100644 (file)
index 0000000..b3db469
--- /dev/null
@@ -0,0 +1,20 @@
+* VIA Velocity 10/100/1000 Network Controller
+
+Required properties:
+- compatible : Should be "via,velocity-vt6110"
+- reg : Address and length of the io space
+- interrupts : Should contain the controller interrupt line
+
+Optional properties:
+- no-eeprom : PCI network cards use an external EEPROM to store data. Embedded
+       devices quite often set this data in uboot and do not provide an eeprom.
+       Specify this option if you have no external eeprom.
+
+Examples:
+
+eth0@d8004000 {
+       compatible = "via,velocity-vt6110";
+       reg = <0xd8004000 0x400>;
+       interrupts = <10>;
+       no-eeprom;
+};
index 68a9ba66feba866f2da80d39f34eed63fc8082ca..6a87097d88c06b316a3a05e24a8017d4d350780e 100644 (file)
@@ -5,7 +5,6 @@
 config NET_VENDOR_VIA
        bool "VIA devices"
        default y
-       depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
@@ -45,7 +44,7 @@ config VIA_RHINE_MMIO
 
 config VIA_VELOCITY
        tristate "VIA Velocity support"
-       depends on PCI
+       depends on (PCI || USE_OF)
        select CRC32
        select CRC_CCITT
        select NET_CORE
index 5996cee0ffa7d5e31ab357ad556763dea6da798a..76919948b4ee32bd4e79a9ddce25e962e6437add 100644 (file)
 #include <linux/if.h>
 #include <linux/uaccess.h>
 #include <linux/proc_fs.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/inetdevice.h>
+#include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 
 #include "via-velocity.h"
 
+enum velocity_bus_type {
+       BUS_PCI,
+       BUS_PLATFORM,
+};
 
 static int velocity_nics;
 static int msglevel = MSG_LEVEL_INFO;
 
+static void velocity_set_power_state(struct velocity_info *vptr, char state)
+{
+       void *addr = vptr->mac_regs;
+
+       if (vptr->pdev)
+               pci_set_power_state(vptr->pdev, state);
+       else
+               writeb(state, addr + 0x154);
+}
+
 /**
  *     mac_get_cam_mask        -       Read a CAM mask
  *     @regs: register block for this velocity
@@ -362,12 +380,23 @@ static struct velocity_info_tbl chip_info_table[] = {
  *     Describe the PCI device identifiers that we support in this
  *     device driver. Used for hotplug autoloading.
  */
-static DEFINE_PCI_DEVICE_TABLE(velocity_id_table) = {
+
+static DEFINE_PCI_DEVICE_TABLE(velocity_pci_id_table) = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
        { }
 };
 
-MODULE_DEVICE_TABLE(pci, velocity_id_table);
+MODULE_DEVICE_TABLE(pci, velocity_pci_id_table);
+
+/**
+ *     Describe the OF device identifiers that we support in this
+ *     device driver. Used for devicetree nodes.
+ */
+static struct of_device_id velocity_of_ids[] = {
+       { .compatible = "via,velocity-vt6110", .data = &chip_info_table[0] },
+       { /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, velocity_of_ids);
 
 /**
  *     get_chip_name   -       identifier to name
@@ -385,29 +414,6 @@ static const char *get_chip_name(enum chip_type chip_id)
        return chip_info_table[i].name;
 }
 
-/**
- *     velocity_remove1        -       device unplug
- *     @pdev: PCI device being removed
- *
- *     Device unload callback. Called on an unplug or on module
- *     unload for each active device that is present. Disconnects
- *     the device from the network layer and frees all the resources
- */
-static void velocity_remove1(struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct velocity_info *vptr = netdev_priv(dev);
-
-       unregister_netdev(dev);
-       iounmap(vptr->mac_regs);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
-       free_netdev(dev);
-
-       velocity_nics--;
-}
-
 /**
  *     velocity_set_int_opt    -       parser for integer options
  *     @opt: pointer to option value
@@ -1181,6 +1187,17 @@ static void mii_init(struct velocity_info *vptr, u32 mii_status)
        u16 BMCR;
 
        switch (PHYID_GET_PHY_ID(vptr->phy_id)) {
+       case PHYID_ICPLUS_IP101A:
+               MII_REG_BITS_ON((ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP),
+                                               MII_ADVERTISE, vptr->mac_regs);
+               if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
+                       MII_REG_BITS_ON(TCSR_ECHODIS, MII_SREVISION,
+                                                               vptr->mac_regs);
+               else
+                       MII_REG_BITS_OFF(TCSR_ECHODIS, MII_SREVISION,
+                                                               vptr->mac_regs);
+               MII_REG_BITS_ON(PLED_LALBE, MII_TPISTATUS, vptr->mac_regs);
+               break;
        case PHYID_CICADA_CS8201:
                /*
                 *      Reset to hardware default
@@ -1312,6 +1329,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
                                    enum velocity_init_type type)
 {
        struct mac_regs __iomem *regs = vptr->mac_regs;
+       struct net_device *netdev = vptr->netdev;
        int i, mii_status;
 
        mac_wol_reset(regs);
@@ -1320,7 +1338,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
        case VELOCITY_INIT_RESET:
        case VELOCITY_INIT_WOL:
 
-               netif_stop_queue(vptr->netdev);
+               netif_stop_queue(netdev);
 
                /*
                 *      Reset RX to prevent RX pointer not on the 4X location
@@ -1333,7 +1351,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
                if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
                        velocity_print_link_status(vptr);
                        if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
-                               netif_wake_queue(vptr->netdev);
+                               netif_wake_queue(netdev);
                }
 
                enable_flow_control_ability(vptr);
@@ -1353,9 +1371,11 @@ static void velocity_init_registers(struct velocity_info *vptr,
                velocity_soft_reset(vptr);
                mdelay(5);
 
-               mac_eeprom_reload(regs);
-               for (i = 0; i < 6; i++)
-                       writeb(vptr->netdev->dev_addr[i], &(regs->PAR[i]));
+               if (!vptr->no_eeprom) {
+                       mac_eeprom_reload(regs);
+                       for (i = 0; i < 6; i++)
+                               writeb(netdev->dev_addr[i], regs->PAR + i);
+               }
 
                /*
                 *      clear Pre_ACPI bit.
@@ -1378,7 +1398,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
                /*
                 *      Set packet filter: Receive directed and broadcast address
                 */
-               velocity_set_multi(vptr->netdev);
+               velocity_set_multi(netdev);
 
                /*
                 *      Enable MII auto-polling
@@ -1405,14 +1425,14 @@ static void velocity_init_registers(struct velocity_info *vptr,
                writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), &regs->CR0Set);
 
                mii_status = velocity_get_opt_media_mode(vptr);
-               netif_stop_queue(vptr->netdev);
+               netif_stop_queue(netdev);
 
                mii_init(vptr, mii_status);
 
                if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {
                        velocity_print_link_status(vptr);
                        if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
-                               netif_wake_queue(vptr->netdev);
+                               netif_wake_queue(netdev);
                }
 
                enable_flow_control_ability(vptr);
@@ -2233,15 +2253,15 @@ static int velocity_open(struct net_device *dev)
                goto out;
 
        /* Ensure chip is running */
-       pci_set_power_state(vptr->pdev, PCI_D0);
+       velocity_set_power_state(vptr, PCI_D0);
 
        velocity_init_registers(vptr, VELOCITY_INIT_COLD);
 
-       ret = request_irq(vptr->pdev->irq, velocity_intr, IRQF_SHARED,
+       ret = request_irq(dev->irq, velocity_intr, IRQF_SHARED,
                          dev->name, dev);
        if (ret < 0) {
                /* Power down the chip */
-               pci_set_power_state(vptr->pdev, PCI_D3hot);
+               velocity_set_power_state(vptr, PCI_D3hot);
                velocity_free_rings(vptr);
                goto out;
        }
@@ -2314,6 +2334,7 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
 
                tmp_vptr->netdev = dev;
                tmp_vptr->pdev = vptr->pdev;
+               tmp_vptr->dev = vptr->dev;
                tmp_vptr->options = vptr->options;
                tmp_vptr->tx.numq = vptr->tx.numq;
 
@@ -2413,7 +2434,7 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
           saving then we need to bring the device back up to talk to it */
 
        if (!netif_running(dev))
-               pci_set_power_state(vptr->pdev, PCI_D0);
+               velocity_set_power_state(vptr, PCI_D0);
 
        switch (cmd) {
        case SIOCGMIIPHY:       /* Get address of MII PHY in use. */
@@ -2426,7 +2447,7 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                ret = -EOPNOTSUPP;
        }
        if (!netif_running(dev))
-               pci_set_power_state(vptr->pdev, PCI_D3hot);
+               velocity_set_power_state(vptr, PCI_D3hot);
 
 
        return ret;
@@ -2492,7 +2513,7 @@ static int velocity_close(struct net_device *dev)
        if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED)
                velocity_get_ip(vptr);
 
-       free_irq(vptr->pdev->irq, dev);
+       free_irq(dev->irq, dev);
 
        velocity_free_rings(vptr);
 
@@ -2631,13 +2652,9 @@ static const struct net_device_ops velocity_netdev_ops = {
  *     Set up the initial velocity_info struct for the device that has been
  *     discovered.
  */
-static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr,
-                              const struct velocity_info_tbl *info)
+static void velocity_init_info(struct velocity_info *vptr,
+                               const struct velocity_info_tbl *info)
 {
-       memset(vptr, 0, sizeof(struct velocity_info));
-
-       vptr->dev = &pdev->dev;
-       vptr->pdev = pdev;
        vptr->chip_id = info->chip_id;
        vptr->tx.numq = info->txqueue;
        vptr->multicast_limit = MCAM_SIZE;
@@ -2652,10 +2669,9 @@ static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr,
  *     Retrieve the PCI configuration space data that interests us from
  *     the kernel PCI layer
  */
-static int velocity_get_pci_info(struct velocity_info *vptr,
-                                struct pci_dev *pdev)
+static int velocity_get_pci_info(struct velocity_info *vptr)
 {
-       vptr->rev_id = pdev->revision;
+       struct pci_dev *pdev = vptr->pdev;
 
        pci_set_master(pdev);
 
@@ -2678,7 +2694,37 @@ static int velocity_get_pci_info(struct velocity_info *vptr,
                dev_err(&pdev->dev, "region #1 is too small.\n");
                return -EINVAL;
        }
-       vptr->pdev = pdev;
+
+       return 0;
+}
+
+/**
+ *     velocity_get_platform_info - retrieve platform info for device
+ *     @vptr: velocity device
+ *     @pdev: platform device it matches
+ *
+ *     Retrieve the Platform configuration data that interests us
+ */
+static int velocity_get_platform_info(struct velocity_info *vptr)
+{
+       struct resource res;
+       int ret;
+
+       if (of_get_property(vptr->dev->of_node, "no-eeprom", NULL))
+               vptr->no_eeprom = 1;
+
+       ret = of_address_to_resource(vptr->dev->of_node, 0, &res);
+       if (ret) {
+               dev_err(vptr->dev, "unable to find memory address\n");
+               return ret;
+       }
+
+       vptr->memaddr = res.start;
+
+       if (resource_size(&res) < VELOCITY_IO_SIZE) {
+               dev_err(vptr->dev, "memory region is too small.\n");
+               return -EINVAL;
+       }
 
        return 0;
 }
@@ -2707,21 +2753,22 @@ static u32 velocity_get_link(struct net_device *dev)
 }
 
 /**
- *     velocity_found1         -       set up discovered velocity card
+ *     velocity_probe - set up discovered velocity device
  *     @pdev: PCI device
  *     @ent: PCI device table entry that matched
+ *     @bustype: bus that device is connected to
  *
  *     Configure a discovered adapter from scratch. Return a negative
  *     errno error code on failure paths.
  */
-static int velocity_found1(struct pci_dev *pdev,
-                          const struct pci_device_id *ent)
+static int velocity_probe(struct device *dev, int irq,
+                          const struct velocity_info_tbl *info,
+                          enum velocity_bus_type bustype)
 {
        static int first = 1;
-       struct net_device *dev;
+       struct net_device *netdev;
        int i;
        const char *drv_string;
-       const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data];
        struct velocity_info *vptr;
        struct mac_regs __iomem *regs;
        int ret = -ENOMEM;
@@ -2730,19 +2777,18 @@ static int velocity_found1(struct pci_dev *pdev,
         * can support more than MAX_UNITS.
         */
        if (velocity_nics >= MAX_UNITS) {
-               dev_notice(&pdev->dev, "already found %d NICs.\n",
-                          velocity_nics);
+               dev_notice(dev, "already found %d NICs.\n", velocity_nics);
                return -ENODEV;
        }
 
-       dev = alloc_etherdev(sizeof(struct velocity_info));
-       if (!dev)
+       netdev = alloc_etherdev(sizeof(struct velocity_info));
+       if (!netdev)
                goto out;
 
        /* Chain it all together */
 
-       SET_NETDEV_DEV(dev, &pdev->dev);
-       vptr = netdev_priv(dev);
+       SET_NETDEV_DEV(netdev, dev);
+       vptr = netdev_priv(netdev);
 
        if (first) {
                printk(KERN_INFO "%s Ver. %s\n",
@@ -2752,41 +2798,41 @@ static int velocity_found1(struct pci_dev *pdev,
                first = 0;
        }
 
-       velocity_init_info(pdev, vptr, info);
+       netdev->irq = irq;
+       vptr->netdev = netdev;
+       vptr->dev = dev;
 
-       vptr->netdev = dev;
+       velocity_init_info(vptr, info);
 
-       ret = pci_enable_device(pdev);
-       if (ret < 0)
-               goto err_free_dev;
+       if (bustype == BUS_PCI) {
+               vptr->pdev = to_pci_dev(dev);
 
-       ret = velocity_get_pci_info(vptr, pdev);
-       if (ret < 0) {
-               /* error message already printed */
-               goto err_disable;
-       }
-
-       ret = pci_request_regions(pdev, VELOCITY_NAME);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "No PCI resources.\n");
-               goto err_disable;
+               ret = velocity_get_pci_info(vptr);
+               if (ret < 0)
+                       goto err_free_dev;
+       } else {
+               vptr->pdev = NULL;
+               ret = velocity_get_platform_info(vptr);
+               if (ret < 0)
+                       goto err_free_dev;
        }
 
        regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);
        if (regs == NULL) {
                ret = -EIO;
-               goto err_release_res;
+               goto err_free_dev;
        }
 
        vptr->mac_regs = regs;
+       vptr->rev_id = readb(&regs->rev_id);
 
        mac_wol_reset(regs);
 
        for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = readb(&regs->PAR[i]);
+               netdev->dev_addr[i] = readb(&regs->PAR[i]);
 
 
-       drv_string = dev_driver_string(&pdev->dev);
+       drv_string = dev_driver_string(dev);
 
        velocity_get_options(&vptr->options, velocity_nics, drv_string);
 
@@ -2807,46 +2853,125 @@ static int velocity_found1(struct pci_dev *pdev,
 
        vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
 
-       dev->netdev_ops = &velocity_netdev_ops;
-       dev->ethtool_ops = &velocity_ethtool_ops;
-       netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT);
+       netdev->netdev_ops = &velocity_netdev_ops;
+       netdev->ethtool_ops = &velocity_ethtool_ops;
+       netif_napi_add(netdev, &vptr->napi, velocity_poll,
+                                                       VELOCITY_NAPI_WEIGHT);
 
-       dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
+       netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
                           NETIF_F_HW_VLAN_CTAG_TX;
-       dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_FILTER |
-                        NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_IP_CSUM;
+       netdev->features |= NETIF_F_HW_VLAN_CTAG_TX |
+                       NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX |
+                       NETIF_F_IP_CSUM;
 
-       ret = register_netdev(dev);
+       ret = register_netdev(netdev);
        if (ret < 0)
                goto err_iounmap;
 
-       if (!velocity_get_link(dev)) {
-               netif_carrier_off(dev);
+       if (!velocity_get_link(netdev)) {
+               netif_carrier_off(netdev);
                vptr->mii_status |= VELOCITY_LINK_FAIL;
        }
 
        velocity_print_info(vptr);
-       pci_set_drvdata(pdev, dev);
+       dev_set_drvdata(vptr->dev, netdev);
 
        /* and leave the chip powered down */
 
-       pci_set_power_state(pdev, PCI_D3hot);
+       velocity_set_power_state(vptr, PCI_D3hot);
        velocity_nics++;
 out:
        return ret;
 
 err_iounmap:
        iounmap(regs);
-err_release_res:
-       pci_release_regions(pdev);
-err_disable:
-       pci_disable_device(pdev);
 err_free_dev:
-       free_netdev(dev);
+       free_netdev(netdev);
        goto out;
 }
 
-#ifdef CONFIG_PM
+/**
+ *     velocity_remove - device unplug
+ *     @dev: device being removed
+ *
+ *     Device unload callback. Called on an unplug or on module
+ *     unload for each active device that is present. Disconnects
+ *     the device from the network layer and frees all the resources
+ */
+static int velocity_remove(struct device *dev)
+{
+       struct net_device *netdev = dev_get_drvdata(dev);
+       struct velocity_info *vptr = netdev_priv(netdev);
+
+       unregister_netdev(netdev);
+       iounmap(vptr->mac_regs);
+       free_netdev(netdev);
+       velocity_nics--;
+
+       return 0;
+}
+
+static int velocity_pci_probe(struct pci_dev *pdev,
+                              const struct pci_device_id *ent)
+{
+       const struct velocity_info_tbl *info =
+                                       &chip_info_table[ent->driver_data];
+       int ret;
+
+       ret = pci_enable_device(pdev);
+       if (ret < 0)
+               return ret;
+
+       ret = pci_request_regions(pdev, VELOCITY_NAME);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "No PCI resources.\n");
+               goto fail1;
+       }
+
+       ret = velocity_probe(&pdev->dev, pdev->irq, info, BUS_PCI);
+       if (ret == 0)
+               return 0;
+
+       pci_release_regions(pdev);
+fail1:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void velocity_pci_remove(struct pci_dev *pdev)
+{
+       velocity_remove(&pdev->dev);
+
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+}
+
+static int velocity_platform_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id;
+       const struct velocity_info_tbl *info;
+       int irq;
+
+       of_id = of_match_device(velocity_of_ids, &pdev->dev);
+       if (!of_id)
+               return -EINVAL;
+       info = of_id->data;
+
+       irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+       if (!irq)
+               return -EINVAL;
+
+       return velocity_probe(&pdev->dev, irq, info, BUS_PLATFORM);
+}
+
+static int velocity_platform_remove(struct platform_device *pdev)
+{
+       velocity_remove(&pdev->dev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
 /**
  *     wol_calc_crc            -       WOL CRC
  *     @pattern: data pattern
@@ -3003,10 +3128,10 @@ static void velocity_save_context(struct velocity_info *vptr, struct velocity_co
 
 }
 
-static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
+static int velocity_suspend(struct device *dev)
 {
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct velocity_info *vptr = netdev_priv(dev);
+       struct net_device *netdev = dev_get_drvdata(dev);
+       struct velocity_info *vptr = netdev_priv(netdev);
        unsigned long flags;
 
        if (!netif_running(vptr->netdev))
@@ -3015,20 +3140,23 @@ static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
        netif_device_detach(vptr->netdev);
 
        spin_lock_irqsave(&vptr->lock, flags);
-       pci_save_state(pdev);
+       if (vptr->pdev)
+               pci_save_state(vptr->pdev);
 
        if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
                velocity_get_ip(vptr);
                velocity_save_context(vptr, &vptr->context);
                velocity_shutdown(vptr);
                velocity_set_wol(vptr);
-               pci_enable_wake(pdev, PCI_D3hot, 1);
-               pci_set_power_state(pdev, PCI_D3hot);
+               if (vptr->pdev)
+                       pci_enable_wake(vptr->pdev, PCI_D3hot, 1);
+               velocity_set_power_state(vptr, PCI_D3hot);
        } else {
                velocity_save_context(vptr, &vptr->context);
                velocity_shutdown(vptr);
-               pci_disable_device(pdev);
-               pci_set_power_state(pdev, pci_choose_state(pdev, state));
+               if (vptr->pdev)
+                       pci_disable_device(vptr->pdev);
+               velocity_set_power_state(vptr, PCI_D3hot);
        }
 
        spin_unlock_irqrestore(&vptr->lock, flags);
@@ -3070,19 +3198,22 @@ static void velocity_restore_context(struct velocity_info *vptr, struct velocity
                writeb(*((u8 *) (context->mac_reg + i)), ptr + i);
 }
 
-static int velocity_resume(struct pci_dev *pdev)
+static int velocity_resume(struct device *dev)
 {
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct velocity_info *vptr = netdev_priv(dev);
+       struct net_device *netdev = dev_get_drvdata(dev);
+       struct velocity_info *vptr = netdev_priv(netdev);
        unsigned long flags;
        int i;
 
        if (!netif_running(vptr->netdev))
                return 0;
 
-       pci_set_power_state(pdev, PCI_D0);
-       pci_enable_wake(pdev, 0, 0);
-       pci_restore_state(pdev);
+       velocity_set_power_state(vptr, PCI_D0);
+
+       if (vptr->pdev) {
+               pci_enable_wake(vptr->pdev, 0, 0);
+               pci_restore_state(vptr->pdev);
+       }
 
        mac_wol_reset(vptr->mac_regs);
 
@@ -3104,23 +3235,34 @@ static int velocity_resume(struct pci_dev *pdev)
 
        return 0;
 }
-#endif
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(velocity_pm_ops, velocity_suspend, velocity_resume);
 
 /*
  *     Definition for our device driver. The PCI layer interface
  *     uses this to handle all our card discover and plugging
  */
-static struct pci_driver velocity_driver = {
+static struct pci_driver velocity_pci_driver = {
        .name           = VELOCITY_NAME,
-       .id_table       = velocity_id_table,
-       .probe          = velocity_found1,
-       .remove         = velocity_remove1,
-#ifdef CONFIG_PM
-       .suspend        = velocity_suspend,
-       .resume         = velocity_resume,
-#endif
+       .id_table       = velocity_pci_id_table,
+       .probe          = velocity_pci_probe,
+       .remove         = velocity_pci_remove,
+       .driver = {
+               .pm = &velocity_pm_ops,
+       },
 };
 
+static struct platform_driver velocity_platform_driver = {
+       .probe          = velocity_platform_probe,
+       .remove         = velocity_platform_remove,
+       .driver = {
+               .name = "via-velocity",
+               .owner = THIS_MODULE,
+               .of_match_table = velocity_of_ids,
+               .pm = &velocity_pm_ops,
+       },
+};
 
 /**
  *     velocity_ethtool_up     -       pre hook for ethtool
@@ -3133,7 +3275,7 @@ static int velocity_ethtool_up(struct net_device *dev)
 {
        struct velocity_info *vptr = netdev_priv(dev);
        if (!netif_running(dev))
-               pci_set_power_state(vptr->pdev, PCI_D0);
+               velocity_set_power_state(vptr, PCI_D0);
        return 0;
 }
 
@@ -3148,7 +3290,7 @@ static void velocity_ethtool_down(struct net_device *dev)
 {
        struct velocity_info *vptr = netdev_priv(dev);
        if (!netif_running(dev))
-               pci_set_power_state(vptr->pdev, PCI_D3hot);
+               velocity_set_power_state(vptr, PCI_D3hot);
 }
 
 static int velocity_get_settings(struct net_device *dev,
@@ -3268,9 +3410,14 @@ static int velocity_set_settings(struct net_device *dev,
 static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct velocity_info *vptr = netdev_priv(dev);
+
        strlcpy(info->driver, VELOCITY_NAME, sizeof(info->driver));
        strlcpy(info->version, VELOCITY_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(vptr->pdev), sizeof(info->bus_info));
+       if (vptr->pdev)
+               strlcpy(info->bus_info, pci_name(vptr->pdev),
+                                               sizeof(info->bus_info));
+       else
+               strlcpy(info->bus_info, "platform", sizeof(info->bus_info));
 }
 
 static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -3560,13 +3707,20 @@ static void velocity_unregister_notifier(void)
  */
 static int __init velocity_init_module(void)
 {
-       int ret;
+       int ret_pci, ret_platform;
 
        velocity_register_notifier();
-       ret = pci_register_driver(&velocity_driver);
-       if (ret < 0)
+
+       ret_pci = pci_register_driver(&velocity_pci_driver);
+       ret_platform = platform_driver_register(&velocity_platform_driver);
+
+       /* if both_registers failed, remove the notifier */
+       if ((ret_pci < 0) && (ret_platform < 0)) {
                velocity_unregister_notifier();
-       return ret;
+               return ret_pci;
+       }
+
+       return 0;
 }
 
 /**
@@ -3580,7 +3734,9 @@ static int __init velocity_init_module(void)
 static void __exit velocity_cleanup_module(void)
 {
        velocity_unregister_notifier();
-       pci_unregister_driver(&velocity_driver);
+
+       pci_unregister_driver(&velocity_pci_driver);
+       platform_driver_unregister(&velocity_platform_driver);
 }
 
 module_init(velocity_init_module);
index c38bbaed4d126edc4212747f9f9b71af86afc89a..9453bfa9324a54fd41c86cabf3ca95c3536ed790 100644 (file)
@@ -1265,7 +1265,7 @@ struct velocity_context {
 #define PHYID_VT3216_64BIT  0x000FC600UL
 #define PHYID_MARVELL_1000  0x01410C50UL
 #define PHYID_MARVELL_1000S 0x01410C40UL
-
+#define PHYID_ICPLUS_IP101A 0x02430C54UL
 #define PHYID_REV_ID_MASK   0x0000000FUL
 
 #define PHYID_GET_PHY_ID(i)         ((i) & ~PHYID_REV_ID_MASK)
@@ -1437,6 +1437,7 @@ struct velocity_info {
        struct device *dev;
        struct pci_dev *pdev;
        struct net_device *netdev;
+       int no_eeprom;
 
        unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
        u8 ip_addr[4];