mirror of
https://github.com/torvalds/linux.git
synced 2024-11-19 10:31:48 +00:00
net: velocity: Add platform device support to VIA velocity driver
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>
This commit is contained in:
parent
e2c41f143f
commit
6dffbe53fb
20
Documentation/devicetree/bindings/net/via-velocity.txt
Normal file
20
Documentation/devicetree/bindings/net/via-velocity.txt
Normal file
@ -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;
|
||||
};
|
@ -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
|
||||
|
@ -65,7 +65,11 @@
|
||||
#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>
|
||||
@ -80,10 +84,24 @@
|
||||
|
||||
#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), ®s->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(®s->rev_id);
|
||||
|
||||
mac_wol_reset(regs);
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = readb(®s->PAR[i]);
|
||||
netdev->dev_addr[i] = readb(®s->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);
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user