13878fb6fSWolfgang Grandegger /* 23878fb6fSWolfgang Grandegger * Copyright (C) 2008 Per Dalen <per.dalen@cnw.se> 33878fb6fSWolfgang Grandegger * 43878fb6fSWolfgang Grandegger * Parts of this software are based on (derived) the following: 53878fb6fSWolfgang Grandegger * 63878fb6fSWolfgang Grandegger * - Kvaser linux driver, version 4.72 BETA 73878fb6fSWolfgang Grandegger * Copyright (C) 2002-2007 KVASER AB 83878fb6fSWolfgang Grandegger * 93878fb6fSWolfgang Grandegger * - Lincan driver, version 0.3.3, OCERA project 103878fb6fSWolfgang Grandegger * Copyright (C) 2004 Pavel Pisa 113878fb6fSWolfgang Grandegger * Copyright (C) 2001 Arnaud Westenberg 123878fb6fSWolfgang Grandegger * 133878fb6fSWolfgang Grandegger * - Socketcan SJA1000 drivers 143878fb6fSWolfgang Grandegger * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com> 153878fb6fSWolfgang Grandegger * Copyright (c) 2002-2007 Volkswagen Group Electronic Research 163878fb6fSWolfgang Grandegger * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33, 173878fb6fSWolfgang Grandegger * 38106 Braunschweig, GERMANY 183878fb6fSWolfgang Grandegger * 193878fb6fSWolfgang Grandegger * This program is free software; you can redistribute it and/or modify 203878fb6fSWolfgang Grandegger * it under the terms of the version 2 of the GNU General Public License 213878fb6fSWolfgang Grandegger * as published by the Free Software Foundation 223878fb6fSWolfgang Grandegger * 233878fb6fSWolfgang Grandegger * This program is distributed in the hope that it will be useful, but 243878fb6fSWolfgang Grandegger * WITHOUT ANY WARRANTY; without even the implied warranty of 253878fb6fSWolfgang Grandegger * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 263878fb6fSWolfgang Grandegger * General Public License for more details. 273878fb6fSWolfgang Grandegger * 283878fb6fSWolfgang Grandegger * You should have received a copy of the GNU General Public License 293878fb6fSWolfgang Grandegger * along with this program; if not, write to the Free Software Foundation, 303878fb6fSWolfgang Grandegger * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 313878fb6fSWolfgang Grandegger */ 323878fb6fSWolfgang Grandegger 333878fb6fSWolfgang Grandegger #include <linux/kernel.h> 343878fb6fSWolfgang Grandegger #include <linux/module.h> 353878fb6fSWolfgang Grandegger #include <linux/interrupt.h> 363878fb6fSWolfgang Grandegger #include <linux/netdevice.h> 373878fb6fSWolfgang Grandegger #include <linux/delay.h> 383878fb6fSWolfgang Grandegger #include <linux/pci.h> 393878fb6fSWolfgang Grandegger #include <linux/can/dev.h> 403878fb6fSWolfgang Grandegger #include <linux/io.h> 413878fb6fSWolfgang Grandegger 423878fb6fSWolfgang Grandegger #include "sja1000.h" 433878fb6fSWolfgang Grandegger 443878fb6fSWolfgang Grandegger #define DRV_NAME "kvaser_pci" 453878fb6fSWolfgang Grandegger 463878fb6fSWolfgang Grandegger MODULE_AUTHOR("Per Dalen <per.dalen@cnw.se>"); 473878fb6fSWolfgang Grandegger MODULE_DESCRIPTION("Socket-CAN driver for KVASER PCAN PCI cards"); 483878fb6fSWolfgang Grandegger MODULE_SUPPORTED_DEVICE("KVASER PCAN PCI CAN card"); 493878fb6fSWolfgang Grandegger MODULE_LICENSE("GPL v2"); 503878fb6fSWolfgang Grandegger 513878fb6fSWolfgang Grandegger #define MAX_NO_OF_CHANNELS 4 /* max no of channels on a single card */ 523878fb6fSWolfgang Grandegger 533878fb6fSWolfgang Grandegger struct kvaser_pci { 543878fb6fSWolfgang Grandegger int channel; 553878fb6fSWolfgang Grandegger struct pci_dev *pci_dev; 563878fb6fSWolfgang Grandegger struct net_device *slave_dev[MAX_NO_OF_CHANNELS-1]; 573878fb6fSWolfgang Grandegger void __iomem *conf_addr; 583878fb6fSWolfgang Grandegger void __iomem *res_addr; 593878fb6fSWolfgang Grandegger int no_channels; 603878fb6fSWolfgang Grandegger u8 xilinx_ver; 613878fb6fSWolfgang Grandegger }; 623878fb6fSWolfgang Grandegger 633878fb6fSWolfgang Grandegger #define KVASER_PCI_CAN_CLOCK (16000000 / 2) 643878fb6fSWolfgang Grandegger 653878fb6fSWolfgang Grandegger /* 663878fb6fSWolfgang Grandegger * The board configuration is probably following: 673878fb6fSWolfgang Grandegger * RX1 is connected to ground. 683878fb6fSWolfgang Grandegger * TX1 is not connected. 693878fb6fSWolfgang Grandegger * CLKO is not connected. 703878fb6fSWolfgang Grandegger * Setting the OCR register to 0xDA is a good idea. 713878fb6fSWolfgang Grandegger * This means normal output mode , push-pull and the correct polarity. 723878fb6fSWolfgang Grandegger */ 733878fb6fSWolfgang Grandegger #define KVASER_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) 743878fb6fSWolfgang Grandegger 753878fb6fSWolfgang Grandegger /* 763878fb6fSWolfgang Grandegger * In the CDR register, you should set CBP to 1. 773878fb6fSWolfgang Grandegger * You will probably also want to set the clock divider value to 0 783878fb6fSWolfgang Grandegger * (meaning divide-by-2), the Pelican bit, and the clock-off bit 793878fb6fSWolfgang Grandegger * (you will have no need for CLKOUT anyway). 803878fb6fSWolfgang Grandegger */ 813878fb6fSWolfgang Grandegger #define KVASER_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) 823878fb6fSWolfgang Grandegger 833878fb6fSWolfgang Grandegger /* 843878fb6fSWolfgang Grandegger * These register values are valid for revision 14 of the Xilinx logic. 853878fb6fSWolfgang Grandegger */ 863878fb6fSWolfgang Grandegger #define XILINX_VERINT 7 /* Lower nibble simulate interrupts, 873878fb6fSWolfgang Grandegger high nibble version number. */ 883878fb6fSWolfgang Grandegger 893878fb6fSWolfgang Grandegger #define XILINX_PRESUMED_VERSION 14 903878fb6fSWolfgang Grandegger 913878fb6fSWolfgang Grandegger /* 923878fb6fSWolfgang Grandegger * Important S5920 registers 933878fb6fSWolfgang Grandegger */ 943878fb6fSWolfgang Grandegger #define S5920_INTCSR 0x38 953878fb6fSWolfgang Grandegger #define S5920_PTCR 0x60 963878fb6fSWolfgang Grandegger #define INTCSR_ADDON_INTENABLE_M 0x2000 973878fb6fSWolfgang Grandegger 983878fb6fSWolfgang Grandegger 993878fb6fSWolfgang Grandegger #define KVASER_PCI_PORT_BYTES 0x20 1003878fb6fSWolfgang Grandegger 1013878fb6fSWolfgang Grandegger #define PCI_CONFIG_PORT_SIZE 0x80 /* size of the config io-memory */ 1023878fb6fSWolfgang Grandegger #define PCI_PORT_SIZE 0x80 /* size of a channel io-memory */ 1033878fb6fSWolfgang Grandegger #define PCI_PORT_XILINX_SIZE 0x08 /* size of a xilinx io-memory */ 1043878fb6fSWolfgang Grandegger 1053878fb6fSWolfgang Grandegger #define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */ 1063878fb6fSWolfgang Grandegger #define KVASER_PCI_DEVICE_ID1 0x8406 1073878fb6fSWolfgang Grandegger 1083878fb6fSWolfgang Grandegger #define KVASER_PCI_VENDOR_ID2 0x1a07 /* the PCI device and vendor IDs */ 1093878fb6fSWolfgang Grandegger #define KVASER_PCI_DEVICE_ID2 0x0008 1103878fb6fSWolfgang Grandegger 111a3aa1884SAlexey Dobriyan static DEFINE_PCI_DEVICE_TABLE(kvaser_pci_tbl) = { 1123878fb6fSWolfgang Grandegger {KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,}, 1133878fb6fSWolfgang Grandegger {KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,}, 1143878fb6fSWolfgang Grandegger { 0,} 1153878fb6fSWolfgang Grandegger }; 1163878fb6fSWolfgang Grandegger 1173878fb6fSWolfgang Grandegger MODULE_DEVICE_TABLE(pci, kvaser_pci_tbl); 1183878fb6fSWolfgang Grandegger 119255a9154SWolfgang Grandegger static u8 kvaser_pci_read_reg(const struct sja1000_priv *priv, int port) 1203878fb6fSWolfgang Grandegger { 121255a9154SWolfgang Grandegger return ioread8(priv->reg_base + port); 1223878fb6fSWolfgang Grandegger } 1233878fb6fSWolfgang Grandegger 124255a9154SWolfgang Grandegger static void kvaser_pci_write_reg(const struct sja1000_priv *priv, 125255a9154SWolfgang Grandegger int port, u8 val) 1263878fb6fSWolfgang Grandegger { 127255a9154SWolfgang Grandegger iowrite8(val, priv->reg_base + port); 1283878fb6fSWolfgang Grandegger } 1293878fb6fSWolfgang Grandegger 1303878fb6fSWolfgang Grandegger static void kvaser_pci_disable_irq(struct net_device *dev) 1313878fb6fSWolfgang Grandegger { 1323878fb6fSWolfgang Grandegger struct sja1000_priv *priv = netdev_priv(dev); 1333878fb6fSWolfgang Grandegger struct kvaser_pci *board = priv->priv; 1343878fb6fSWolfgang Grandegger u32 intcsr; 1353878fb6fSWolfgang Grandegger 1363878fb6fSWolfgang Grandegger /* Disable interrupts from card */ 1373878fb6fSWolfgang Grandegger intcsr = ioread32(board->conf_addr + S5920_INTCSR); 1383878fb6fSWolfgang Grandegger intcsr &= ~INTCSR_ADDON_INTENABLE_M; 1393878fb6fSWolfgang Grandegger iowrite32(intcsr, board->conf_addr + S5920_INTCSR); 1403878fb6fSWolfgang Grandegger } 1413878fb6fSWolfgang Grandegger 1423878fb6fSWolfgang Grandegger static void kvaser_pci_enable_irq(struct net_device *dev) 1433878fb6fSWolfgang Grandegger { 1443878fb6fSWolfgang Grandegger struct sja1000_priv *priv = netdev_priv(dev); 1453878fb6fSWolfgang Grandegger struct kvaser_pci *board = priv->priv; 1463878fb6fSWolfgang Grandegger u32 tmp_en_io; 1473878fb6fSWolfgang Grandegger 1483878fb6fSWolfgang Grandegger /* Enable interrupts from card */ 1493878fb6fSWolfgang Grandegger tmp_en_io = ioread32(board->conf_addr + S5920_INTCSR); 1503878fb6fSWolfgang Grandegger tmp_en_io |= INTCSR_ADDON_INTENABLE_M; 1513878fb6fSWolfgang Grandegger iowrite32(tmp_en_io, board->conf_addr + S5920_INTCSR); 1523878fb6fSWolfgang Grandegger } 1533878fb6fSWolfgang Grandegger 1543878fb6fSWolfgang Grandegger static int number_of_sja1000_chip(void __iomem *base_addr) 1553878fb6fSWolfgang Grandegger { 1563878fb6fSWolfgang Grandegger u8 status; 1573878fb6fSWolfgang Grandegger int i; 1583878fb6fSWolfgang Grandegger 1593878fb6fSWolfgang Grandegger for (i = 0; i < MAX_NO_OF_CHANNELS; i++) { 1603878fb6fSWolfgang Grandegger /* reset chip */ 1613878fb6fSWolfgang Grandegger iowrite8(MOD_RM, base_addr + 162*06e1d1d7SOliver Hartkopp (i * KVASER_PCI_PORT_BYTES) + SJA1000_MOD); 1633878fb6fSWolfgang Grandegger status = ioread8(base_addr + 164*06e1d1d7SOliver Hartkopp (i * KVASER_PCI_PORT_BYTES) + SJA1000_MOD); 1653878fb6fSWolfgang Grandegger /* check reset bit */ 1663878fb6fSWolfgang Grandegger if (!(status & MOD_RM)) 1673878fb6fSWolfgang Grandegger break; 1683878fb6fSWolfgang Grandegger } 1693878fb6fSWolfgang Grandegger 1703878fb6fSWolfgang Grandegger return i; 1713878fb6fSWolfgang Grandegger } 1723878fb6fSWolfgang Grandegger 1733878fb6fSWolfgang Grandegger static void kvaser_pci_del_chan(struct net_device *dev) 1743878fb6fSWolfgang Grandegger { 1753878fb6fSWolfgang Grandegger struct sja1000_priv *priv; 1763878fb6fSWolfgang Grandegger struct kvaser_pci *board; 1773878fb6fSWolfgang Grandegger int i; 1783878fb6fSWolfgang Grandegger 1793878fb6fSWolfgang Grandegger if (!dev) 1803878fb6fSWolfgang Grandegger return; 1813878fb6fSWolfgang Grandegger priv = netdev_priv(dev); 1823878fb6fSWolfgang Grandegger board = priv->priv; 1833878fb6fSWolfgang Grandegger if (!board) 1843878fb6fSWolfgang Grandegger return; 1853878fb6fSWolfgang Grandegger 1863878fb6fSWolfgang Grandegger dev_info(&board->pci_dev->dev, "Removing device %s\n", 1873878fb6fSWolfgang Grandegger dev->name); 1883878fb6fSWolfgang Grandegger 1893878fb6fSWolfgang Grandegger /* Disable PCI interrupts */ 1903878fb6fSWolfgang Grandegger kvaser_pci_disable_irq(dev); 1913878fb6fSWolfgang Grandegger 1923878fb6fSWolfgang Grandegger for (i = 0; i < board->no_channels - 1; i++) { 1933878fb6fSWolfgang Grandegger if (board->slave_dev[i]) { 1943878fb6fSWolfgang Grandegger dev_info(&board->pci_dev->dev, "Removing device %s\n", 1953878fb6fSWolfgang Grandegger board->slave_dev[i]->name); 1963878fb6fSWolfgang Grandegger unregister_sja1000dev(board->slave_dev[i]); 1973878fb6fSWolfgang Grandegger free_sja1000dev(board->slave_dev[i]); 1983878fb6fSWolfgang Grandegger } 1993878fb6fSWolfgang Grandegger } 2003878fb6fSWolfgang Grandegger unregister_sja1000dev(dev); 2013878fb6fSWolfgang Grandegger 202255a9154SWolfgang Grandegger pci_iounmap(board->pci_dev, priv->reg_base); 2033878fb6fSWolfgang Grandegger pci_iounmap(board->pci_dev, board->conf_addr); 2043878fb6fSWolfgang Grandegger pci_iounmap(board->pci_dev, board->res_addr); 2053878fb6fSWolfgang Grandegger 2063878fb6fSWolfgang Grandegger free_sja1000dev(dev); 2073878fb6fSWolfgang Grandegger } 2083878fb6fSWolfgang Grandegger 2093878fb6fSWolfgang Grandegger static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel, 2103878fb6fSWolfgang Grandegger struct net_device **master_dev, 2113878fb6fSWolfgang Grandegger void __iomem *conf_addr, 2123878fb6fSWolfgang Grandegger void __iomem *res_addr, 213255a9154SWolfgang Grandegger void __iomem *base_addr) 2143878fb6fSWolfgang Grandegger { 2153878fb6fSWolfgang Grandegger struct net_device *dev; 2163878fb6fSWolfgang Grandegger struct sja1000_priv *priv; 2173878fb6fSWolfgang Grandegger struct kvaser_pci *board; 2183878fb6fSWolfgang Grandegger int err, init_step; 2193878fb6fSWolfgang Grandegger 2203878fb6fSWolfgang Grandegger dev = alloc_sja1000dev(sizeof(struct kvaser_pci)); 2213878fb6fSWolfgang Grandegger if (dev == NULL) 2223878fb6fSWolfgang Grandegger return -ENOMEM; 2233878fb6fSWolfgang Grandegger 2243878fb6fSWolfgang Grandegger priv = netdev_priv(dev); 2253878fb6fSWolfgang Grandegger board = priv->priv; 2263878fb6fSWolfgang Grandegger 2273878fb6fSWolfgang Grandegger board->pci_dev = pdev; 2283878fb6fSWolfgang Grandegger board->channel = channel; 2293878fb6fSWolfgang Grandegger 2303878fb6fSWolfgang Grandegger /* S5920 */ 2313878fb6fSWolfgang Grandegger board->conf_addr = conf_addr; 2323878fb6fSWolfgang Grandegger 2333878fb6fSWolfgang Grandegger /* XILINX board wide address */ 2343878fb6fSWolfgang Grandegger board->res_addr = res_addr; 2353878fb6fSWolfgang Grandegger 2363878fb6fSWolfgang Grandegger if (channel == 0) { 2373878fb6fSWolfgang Grandegger board->xilinx_ver = 2383878fb6fSWolfgang Grandegger ioread8(board->res_addr + XILINX_VERINT) >> 4; 2393878fb6fSWolfgang Grandegger init_step = 2; 2403878fb6fSWolfgang Grandegger 2413878fb6fSWolfgang Grandegger /* Assert PTADR# - we're in passive mode so the other bits are 2423878fb6fSWolfgang Grandegger not important */ 2433878fb6fSWolfgang Grandegger iowrite32(0x80808080UL, board->conf_addr + S5920_PTCR); 2443878fb6fSWolfgang Grandegger 2453878fb6fSWolfgang Grandegger /* Enable interrupts from card */ 2463878fb6fSWolfgang Grandegger kvaser_pci_enable_irq(dev); 2473878fb6fSWolfgang Grandegger } else { 2483878fb6fSWolfgang Grandegger struct sja1000_priv *master_priv = netdev_priv(*master_dev); 2493878fb6fSWolfgang Grandegger struct kvaser_pci *master_board = master_priv->priv; 2503878fb6fSWolfgang Grandegger master_board->slave_dev[channel - 1] = dev; 2513878fb6fSWolfgang Grandegger master_board->no_channels = channel + 1; 2523878fb6fSWolfgang Grandegger board->xilinx_ver = master_board->xilinx_ver; 2533878fb6fSWolfgang Grandegger } 2543878fb6fSWolfgang Grandegger 255255a9154SWolfgang Grandegger priv->reg_base = base_addr + channel * KVASER_PCI_PORT_BYTES; 2563878fb6fSWolfgang Grandegger 2573878fb6fSWolfgang Grandegger priv->read_reg = kvaser_pci_read_reg; 2583878fb6fSWolfgang Grandegger priv->write_reg = kvaser_pci_write_reg; 2593878fb6fSWolfgang Grandegger 2603878fb6fSWolfgang Grandegger priv->can.clock.freq = KVASER_PCI_CAN_CLOCK; 2613878fb6fSWolfgang Grandegger 2623878fb6fSWolfgang Grandegger priv->ocr = KVASER_PCI_OCR; 2633878fb6fSWolfgang Grandegger priv->cdr = KVASER_PCI_CDR; 2643878fb6fSWolfgang Grandegger 2653878fb6fSWolfgang Grandegger priv->irq_flags = IRQF_SHARED; 2663878fb6fSWolfgang Grandegger dev->irq = pdev->irq; 2673878fb6fSWolfgang Grandegger 2683878fb6fSWolfgang Grandegger init_step = 4; 2693878fb6fSWolfgang Grandegger 270255a9154SWolfgang Grandegger dev_info(&pdev->dev, "reg_base=%p conf_addr=%p irq=%d\n", 271255a9154SWolfgang Grandegger priv->reg_base, board->conf_addr, dev->irq); 2723878fb6fSWolfgang Grandegger 2733878fb6fSWolfgang Grandegger SET_NETDEV_DEV(dev, &pdev->dev); 2743878fb6fSWolfgang Grandegger 2753878fb6fSWolfgang Grandegger /* Register SJA1000 device */ 2763878fb6fSWolfgang Grandegger err = register_sja1000dev(dev); 2773878fb6fSWolfgang Grandegger if (err) { 2783878fb6fSWolfgang Grandegger dev_err(&pdev->dev, "Registering device failed (err=%d)\n", 2793878fb6fSWolfgang Grandegger err); 2803878fb6fSWolfgang Grandegger goto failure; 2813878fb6fSWolfgang Grandegger } 2823878fb6fSWolfgang Grandegger 2833878fb6fSWolfgang Grandegger if (channel == 0) 2843878fb6fSWolfgang Grandegger *master_dev = dev; 2853878fb6fSWolfgang Grandegger 2863878fb6fSWolfgang Grandegger return 0; 2873878fb6fSWolfgang Grandegger 2883878fb6fSWolfgang Grandegger failure: 2893878fb6fSWolfgang Grandegger kvaser_pci_del_chan(dev); 2903878fb6fSWolfgang Grandegger return err; 2913878fb6fSWolfgang Grandegger } 2923878fb6fSWolfgang Grandegger 2933c8ac0f2SBill Pemberton static int kvaser_pci_init_one(struct pci_dev *pdev, 2943878fb6fSWolfgang Grandegger const struct pci_device_id *ent) 2953878fb6fSWolfgang Grandegger { 2963878fb6fSWolfgang Grandegger int err; 2973878fb6fSWolfgang Grandegger struct net_device *master_dev = NULL; 2983878fb6fSWolfgang Grandegger struct sja1000_priv *priv; 2993878fb6fSWolfgang Grandegger struct kvaser_pci *board; 3003878fb6fSWolfgang Grandegger int no_channels; 3013878fb6fSWolfgang Grandegger void __iomem *base_addr = NULL; 3023878fb6fSWolfgang Grandegger void __iomem *conf_addr = NULL; 3033878fb6fSWolfgang Grandegger void __iomem *res_addr = NULL; 3043878fb6fSWolfgang Grandegger int i; 3053878fb6fSWolfgang Grandegger 3063878fb6fSWolfgang Grandegger dev_info(&pdev->dev, "initializing device %04x:%04x\n", 3073878fb6fSWolfgang Grandegger pdev->vendor, pdev->device); 3083878fb6fSWolfgang Grandegger 3093878fb6fSWolfgang Grandegger err = pci_enable_device(pdev); 3103878fb6fSWolfgang Grandegger if (err) 3113878fb6fSWolfgang Grandegger goto failure; 3123878fb6fSWolfgang Grandegger 3133878fb6fSWolfgang Grandegger err = pci_request_regions(pdev, DRV_NAME); 3143878fb6fSWolfgang Grandegger if (err) 3153878fb6fSWolfgang Grandegger goto failure_release_pci; 3163878fb6fSWolfgang Grandegger 3173878fb6fSWolfgang Grandegger /* S5920 */ 3183878fb6fSWolfgang Grandegger conf_addr = pci_iomap(pdev, 0, PCI_CONFIG_PORT_SIZE); 3193878fb6fSWolfgang Grandegger if (conf_addr == NULL) { 3203878fb6fSWolfgang Grandegger err = -ENODEV; 3213878fb6fSWolfgang Grandegger goto failure_release_regions; 3223878fb6fSWolfgang Grandegger } 3233878fb6fSWolfgang Grandegger 3243878fb6fSWolfgang Grandegger /* XILINX board wide address */ 3253878fb6fSWolfgang Grandegger res_addr = pci_iomap(pdev, 2, PCI_PORT_XILINX_SIZE); 3263878fb6fSWolfgang Grandegger if (res_addr == NULL) { 3273878fb6fSWolfgang Grandegger err = -ENOMEM; 3283878fb6fSWolfgang Grandegger goto failure_iounmap; 3293878fb6fSWolfgang Grandegger } 3303878fb6fSWolfgang Grandegger 3313878fb6fSWolfgang Grandegger base_addr = pci_iomap(pdev, 1, PCI_PORT_SIZE); 3323878fb6fSWolfgang Grandegger if (base_addr == NULL) { 3333878fb6fSWolfgang Grandegger err = -ENOMEM; 3343878fb6fSWolfgang Grandegger goto failure_iounmap; 3353878fb6fSWolfgang Grandegger } 3363878fb6fSWolfgang Grandegger 3373878fb6fSWolfgang Grandegger no_channels = number_of_sja1000_chip(base_addr); 3383878fb6fSWolfgang Grandegger if (no_channels == 0) { 3393878fb6fSWolfgang Grandegger err = -ENOMEM; 3403878fb6fSWolfgang Grandegger goto failure_iounmap; 3413878fb6fSWolfgang Grandegger } 3423878fb6fSWolfgang Grandegger 3433878fb6fSWolfgang Grandegger for (i = 0; i < no_channels; i++) { 3443878fb6fSWolfgang Grandegger err = kvaser_pci_add_chan(pdev, i, &master_dev, 3453878fb6fSWolfgang Grandegger conf_addr, res_addr, 346255a9154SWolfgang Grandegger base_addr); 3473878fb6fSWolfgang Grandegger if (err) 3483878fb6fSWolfgang Grandegger goto failure_cleanup; 3493878fb6fSWolfgang Grandegger } 3503878fb6fSWolfgang Grandegger 3513878fb6fSWolfgang Grandegger priv = netdev_priv(master_dev); 3523878fb6fSWolfgang Grandegger board = priv->priv; 3533878fb6fSWolfgang Grandegger 3543878fb6fSWolfgang Grandegger dev_info(&pdev->dev, "xilinx version=%d number of channels=%d\n", 3553878fb6fSWolfgang Grandegger board->xilinx_ver, board->no_channels); 3563878fb6fSWolfgang Grandegger 3573878fb6fSWolfgang Grandegger pci_set_drvdata(pdev, master_dev); 3583878fb6fSWolfgang Grandegger return 0; 3593878fb6fSWolfgang Grandegger 3603878fb6fSWolfgang Grandegger failure_cleanup: 3613878fb6fSWolfgang Grandegger kvaser_pci_del_chan(master_dev); 3623878fb6fSWolfgang Grandegger 3633878fb6fSWolfgang Grandegger failure_iounmap: 3643878fb6fSWolfgang Grandegger if (conf_addr != NULL) 3653878fb6fSWolfgang Grandegger pci_iounmap(pdev, conf_addr); 3663878fb6fSWolfgang Grandegger if (res_addr != NULL) 3673878fb6fSWolfgang Grandegger pci_iounmap(pdev, res_addr); 3683878fb6fSWolfgang Grandegger if (base_addr != NULL) 3693878fb6fSWolfgang Grandegger pci_iounmap(pdev, base_addr); 3703878fb6fSWolfgang Grandegger 3713878fb6fSWolfgang Grandegger failure_release_regions: 3723878fb6fSWolfgang Grandegger pci_release_regions(pdev); 3733878fb6fSWolfgang Grandegger 3743878fb6fSWolfgang Grandegger failure_release_pci: 3753878fb6fSWolfgang Grandegger pci_disable_device(pdev); 3763878fb6fSWolfgang Grandegger 3773878fb6fSWolfgang Grandegger failure: 3783878fb6fSWolfgang Grandegger return err; 3793878fb6fSWolfgang Grandegger 3803878fb6fSWolfgang Grandegger } 3813878fb6fSWolfgang Grandegger 3823c8ac0f2SBill Pemberton static void kvaser_pci_remove_one(struct pci_dev *pdev) 3833878fb6fSWolfgang Grandegger { 3843878fb6fSWolfgang Grandegger struct net_device *dev = pci_get_drvdata(pdev); 3853878fb6fSWolfgang Grandegger 3863878fb6fSWolfgang Grandegger kvaser_pci_del_chan(dev); 3873878fb6fSWolfgang Grandegger 3883878fb6fSWolfgang Grandegger pci_release_regions(pdev); 3893878fb6fSWolfgang Grandegger pci_disable_device(pdev); 3903878fb6fSWolfgang Grandegger pci_set_drvdata(pdev, NULL); 3913878fb6fSWolfgang Grandegger } 3923878fb6fSWolfgang Grandegger 3933878fb6fSWolfgang Grandegger static struct pci_driver kvaser_pci_driver = { 3943878fb6fSWolfgang Grandegger .name = DRV_NAME, 3953878fb6fSWolfgang Grandegger .id_table = kvaser_pci_tbl, 3963878fb6fSWolfgang Grandegger .probe = kvaser_pci_init_one, 3973c8ac0f2SBill Pemberton .remove = kvaser_pci_remove_one, 3983878fb6fSWolfgang Grandegger }; 3993878fb6fSWolfgang Grandegger 400fb7944b3SAxel Lin module_pci_driver(kvaser_pci_driver); 401