summaryrefslogtreecommitdiff
path: root/drivers/net/arcnet/com20020-pci.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-09-29 14:36:33 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-29 14:36:33 -0400
commit2b7fc477b0423cbcc7be8ad8652e3552198de418 (patch)
tree58f6e51300fb344252e171ce4b167498e6be81e3 /drivers/net/arcnet/com20020-pci.c
parent41c91996d99394a75912aa5bfda300b85789ed43 (diff)
parent5b85bad2a473a8b90cac93d21ab024ba221a8b09 (diff)
Merge branch 'arcnet-EAE'
Michael Grzeschik says: ==================== ARCNET: add support for EAE multi interfac card this series adds support for the PLX Bridge based multi interface pci cards and adds support to change device address on com200xx chips during runtime. This series is based on v3.17-rc7. It is fixed for build against com20020_cs. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/arcnet/com20020-pci.c')
-rw-r--r--drivers/net/arcnet/com20020-pci.c369
1 files changed, 286 insertions, 83 deletions
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 7bb292e59559..6c99ff0b0bdd 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -38,6 +38,7 @@
#include <linux/pci.h>
#include <linux/arcdevice.h>
#include <linux/com20020.h>
+#include <linux/list.h>
#include <asm/io.h>
@@ -61,115 +62,317 @@ module_param(clockp, int, 0);
module_param(clockm, int, 0);
MODULE_LICENSE("GPL");
+static void com20020pci_remove(struct pci_dev *pdev);
+
static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ struct com20020_pci_card_info *ci;
struct net_device *dev;
struct arcnet_local *lp;
- int ioaddr, err;
+ struct com20020_priv *priv;
+ int i, ioaddr, ret;
+ struct resource *r;
if (pci_enable_device(pdev))
return -EIO;
- dev = alloc_arcdev(device);
- if (!dev)
- return -ENOMEM;
- dev->netdev_ops = &com20020_netdev_ops;
+ priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
+ GFP_KERNEL);
+ ci = (struct com20020_pci_card_info *)id->driver_data;
+ priv->ci = ci;
- lp = netdev_priv(dev);
+ INIT_LIST_HEAD(&priv->list_dev);
- pci_set_drvdata(pdev, dev);
- // SOHARD needs PCI base addr 4
- if (pdev->vendor==0x10B5) {
- BUGMSG(D_NORMAL, "SOHARD\n");
- ioaddr = pci_resource_start(pdev, 4);
- }
- else {
- BUGMSG(D_NORMAL, "Contemporary Controls\n");
- ioaddr = pci_resource_start(pdev, 2);
- }
+ for (i = 0; i < ci->devcount; i++) {
+ struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
+ struct com20020_dev *card;
- if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com20020-pci")) {
- BUGMSG(D_INIT, "IO region %xh-%xh already allocated.\n",
- ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
- err = -EBUSY;
- goto out_dev;
- }
+ dev = alloc_arcdev(device);
+ if (!dev) {
+ ret = -ENOMEM;
+ goto out_port;
+ }
- // Dummy access after Reset
- // ARCNET controller needs this access to detect bustype
- outb(0x00,ioaddr+1);
- inb(ioaddr+1);
-
- dev->base_addr = ioaddr;
- dev->irq = pdev->irq;
- dev->dev_addr[0] = node;
- lp->card_name = "PCI COM20020";
- lp->card_flags = id->driver_data;
- lp->backplane = backplane;
- lp->clockp = clockp & 7;
- lp->clockm = clockm & 3;
- lp->timeout = timeout;
- lp->hw.owner = THIS_MODULE;
-
- if (ASTATUS() == 0xFF) {
- BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, "
- "but seems empty!\n", ioaddr);
- err = -EIO;
- goto out_port;
- }
- if (com20020_check(dev)) {
- err = -EIO;
- goto out_port;
+ dev->netdev_ops = &com20020_netdev_ops;
+
+ lp = netdev_priv(dev);
+
+ BUGMSG(D_NORMAL, "%s Controls\n", ci->name);
+ ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
+
+ r = devm_request_region(&pdev->dev, ioaddr, cm->size,
+ "com20020-pci");
+ if (!r) {
+ pr_err("IO region %xh-%xh already allocated.\n",
+ ioaddr, ioaddr + cm->size - 1);
+ ret = -EBUSY;
+ goto out_port;
+ }
+
+ /* Dummy access after Reset
+ * ARCNET controller needs
+ * this access to detect bustype
+ */
+ outb(0x00, ioaddr + 1);
+ inb(ioaddr + 1);
+
+ dev->base_addr = ioaddr;
+ dev->dev_addr[0] = node;
+ dev->irq = pdev->irq;
+ lp->card_name = "PCI COM20020";
+ lp->card_flags = ci->flags;
+ lp->backplane = backplane;
+ lp->clockp = clockp & 7;
+ lp->clockm = clockm & 3;
+ lp->timeout = timeout;
+ lp->hw.owner = THIS_MODULE;
+
+ if (ASTATUS() == 0xFF) {
+ pr_err("IO address %Xh is empty!\n", ioaddr);
+ ret = -EIO;
+ goto out_port;
+ }
+ if (com20020_check(dev)) {
+ ret = -EIO;
+ goto out_port;
+ }
+
+ card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
+ GFP_KERNEL);
+ if (!card) {
+ pr_err("%s out of memory!\n", __func__);
+ return -ENOMEM;
+ }
+
+ card->index = i;
+ card->pci_priv = priv;
+ card->dev = dev;
+
+ dev_set_drvdata(&dev->dev, card);
+
+ ret = com20020_found(dev, IRQF_SHARED);
+ if (ret)
+ goto out_port;
+
+ list_add(&card->list, &priv->list_dev);
}
- if ((err = com20020_found(dev, IRQF_SHARED)) != 0)
- goto out_port;
+ pci_set_drvdata(pdev, priv);
return 0;
out_port:
- release_region(ioaddr, ARCNET_TOTAL_SIZE);
-out_dev:
- free_netdev(dev);
- return err;
+ com20020pci_remove(pdev);
+ return ret;
}
static void com20020pci_remove(struct pci_dev *pdev)
{
- struct net_device *dev = pci_get_drvdata(pdev);
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
- free_netdev(dev);
+ struct com20020_dev *card, *tmpcard;
+ struct com20020_priv *priv;
+
+ priv = pci_get_drvdata(pdev);
+
+ list_for_each_entry_safe(card, tmpcard, &priv->list_dev, list) {
+ struct net_device *dev = card->dev;
+
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ free_netdev(dev);
+ }
}
+static struct com20020_pci_card_info card_info_10mbit = {
+ .name = "ARC-PCI",
+ .devcount = 1,
+ .chan_map_tbl = {
+ { 2, 0x00, 0x08 },
+ },
+ .flags = ARC_CAN_10MBIT,
+};
+
+static struct com20020_pci_card_info card_info_5mbit = {
+ .name = "ARC-PCI",
+ .devcount = 1,
+ .chan_map_tbl = {
+ { 2, 0x00, 0x08 },
+ },
+ .flags = ARC_IS_5MBIT,
+};
+
+static struct com20020_pci_card_info card_info_sohard = {
+ .name = "PLX-PCI",
+ .devcount = 1,
+ /* SOHARD needs PCI base addr 4 */
+ .chan_map_tbl = {
+ {4, 0x00, 0x08},
+ },
+ .flags = ARC_CAN_10MBIT,
+};
+
+static struct com20020_pci_card_info card_info_eae = {
+ .name = "EAE PLX-PCI",
+ .devcount = 2,
+ .chan_map_tbl = {
+ { 2, 0x00, 0x08 },
+ { 2, 0x08, 0x08 }
+ },
+ .flags = ARC_CAN_10MBIT,
+};
+
static const struct pci_device_id com20020pci_id_table[] = {
- { 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1571, 0xa004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1571, 0xa005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1571, 0xa006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1571, 0xa007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1571, 0xa008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1571, 0xa009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
- { 0x1571, 0xa00a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
- { 0x1571, 0xa00b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
- { 0x1571, 0xa00c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
- { 0x1571, 0xa00d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
- { 0x1571, 0xa00e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
- { 0x1571, 0xa201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- { 0x1571, 0xa202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- { 0x1571, 0xa203, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- { 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- { 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- { 0x10B5, 0x9030, 0x10B5, 0x2978, 0, 0, ARC_CAN_10MBIT },
- { 0x10B5, 0x9050, 0x10B5, 0x2273, 0, 0, ARC_CAN_10MBIT },
- { 0x14BA, 0x6000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- { 0x10B5, 0x2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
- {0,}
+ {
+ 0x1571, 0xa001,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ 0,
+ },
+ {
+ 0x1571, 0xa002,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ 0,
+ },
+ {
+ 0x1571, 0xa003,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ 0
+ },
+ {
+ 0x1571, 0xa004,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ 0,
+ },
+ {
+ 0x1571, 0xa005,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ 0
+ },
+ {
+ 0x1571, 0xa006,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ 0
+ },
+ {
+ 0x1571, 0xa007,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ 0
+ },
+ {
+ 0x1571, 0xa008,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ 0
+ },
+ {
+ 0x1571, 0xa009,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_5mbit
+ },
+ {
+ 0x1571, 0xa00a,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_5mbit
+ },
+ {
+ 0x1571, 0xa00b,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_5mbit
+ },
+ {
+ 0x1571, 0xa00c,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_5mbit
+ },
+ {
+ 0x1571, 0xa00d,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_5mbit
+ },
+ {
+ 0x1571, 0xa00e,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_5mbit
+ },
+ {
+ 0x1571, 0xa201,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_10mbit
+ },
+ {
+ 0x1571, 0xa202,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_10mbit
+ },
+ {
+ 0x1571, 0xa203,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_10mbit
+ },
+ {
+ 0x1571, 0xa204,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_10mbit
+ },
+ {
+ 0x1571, 0xa205,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_10mbit
+ },
+ {
+ 0x1571, 0xa206,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_10mbit
+ },
+ {
+ 0x10B5, 0x9030,
+ 0x10B5, 0x2978,
+ 0, 0,
+ (kernel_ulong_t)&card_info_sohard
+ },
+ {
+ 0x10B5, 0x9050,
+ 0x10B5, 0x2273,
+ 0, 0,
+ (kernel_ulong_t)&card_info_sohard
+ },
+ {
+ 0x10B5, 0x9050,
+ 0x10B5, 0x3292,
+ 0, 0,
+ (kernel_ulong_t)&card_info_eae
+ },
+ {
+ 0x14BA, 0x6000,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_10mbit
+ },
+ {
+ 0x10B5, 0x2200,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ (kernel_ulong_t)&card_info_10mbit
+ },
+ { 0, }
};
MODULE_DEVICE_TABLE(pci, com20020pci_id_table);