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 2905780d98SJeff Kirsher * along with this program; if not, see <http://www.gnu.org/licenses/>. 303878fb6fSWolfgang Grandegger */ 313878fb6fSWolfgang Grandegger 323878fb6fSWolfgang Grandegger #include <linux/kernel.h> 333878fb6fSWolfgang Grandegger #include <linux/module.h> 343878fb6fSWolfgang Grandegger #include <linux/interrupt.h> 353878fb6fSWolfgang Grandegger #include <linux/netdevice.h> 363878fb6fSWolfgang Grandegger #include <linux/delay.h> 373878fb6fSWolfgang Grandegger #include <linux/pci.h> 383878fb6fSWolfgang Grandegger #include <linux/can/dev.h> 393878fb6fSWolfgang Grandegger #include <linux/io.h> 403878fb6fSWolfgang Grandegger 413878fb6fSWolfgang Grandegger #include "sja1000.h" 423878fb6fSWolfgang Grandegger 433878fb6fSWolfgang Grandegger #define DRV_NAME "kvaser_pci" 443878fb6fSWolfgang Grandegger 453878fb6fSWolfgang Grandegger MODULE_AUTHOR("Per Dalen <per.dalen@cnw.se>"); 463878fb6fSWolfgang Grandegger MODULE_DESCRIPTION("Socket-CAN driver for KVASER PCAN PCI cards"); 473878fb6fSWolfgang Grandegger MODULE_SUPPORTED_DEVICE("KVASER PCAN PCI CAN card"); 483878fb6fSWolfgang Grandegger MODULE_LICENSE("GPL v2"); 493878fb6fSWolfgang Grandegger 503878fb6fSWolfgang Grandegger #define MAX_NO_OF_CHANNELS 4 /* max no of channels on a single card */ 513878fb6fSWolfgang Grandegger 523878fb6fSWolfgang Grandegger struct kvaser_pci { 533878fb6fSWolfgang Grandegger int channel; 543878fb6fSWolfgang Grandegger struct pci_dev *pci_dev; 553878fb6fSWolfgang Grandegger struct net_device *slave_dev[MAX_NO_OF_CHANNELS-1]; 563878fb6fSWolfgang Grandegger void __iomem *conf_addr; 573878fb6fSWolfgang Grandegger void __iomem *res_addr; 583878fb6fSWolfgang Grandegger int no_channels; 593878fb6fSWolfgang Grandegger u8 xilinx_ver; 603878fb6fSWolfgang Grandegger }; 613878fb6fSWolfgang Grandegger 623878fb6fSWolfgang Grandegger #define KVASER_PCI_CAN_CLOCK (16000000 / 2) 633878fb6fSWolfgang Grandegger 643878fb6fSWolfgang Grandegger /* 653878fb6fSWolfgang Grandegger * The board configuration is probably following: 663878fb6fSWolfgang Grandegger * RX1 is connected to ground. 673878fb6fSWolfgang Grandegger * TX1 is not connected. 683878fb6fSWolfgang Grandegger * CLKO is not connected. 693878fb6fSWolfgang Grandegger * Setting the OCR register to 0xDA is a good idea. 703878fb6fSWolfgang Grandegger * This means normal output mode , push-pull and the correct polarity. 713878fb6fSWolfgang Grandegger */ 723878fb6fSWolfgang Grandegger #define KVASER_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) 733878fb6fSWolfgang Grandegger 743878fb6fSWolfgang Grandegger /* 753878fb6fSWolfgang Grandegger * In the CDR register, you should set CBP to 1. 763878fb6fSWolfgang Grandegger * You will probably also want to set the clock divider value to 0 773878fb6fSWolfgang Grandegger * (meaning divide-by-2), the Pelican bit, and the clock-off bit 783878fb6fSWolfgang Grandegger * (you will have no need for CLKOUT anyway). 793878fb6fSWolfgang Grandegger */ 803878fb6fSWolfgang Grandegger #define KVASER_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) 813878fb6fSWolfgang Grandegger 823878fb6fSWolfgang Grandegger /* 833878fb6fSWolfgang Grandegger * These register values are valid for revision 14 of the Xilinx logic. 843878fb6fSWolfgang Grandegger */ 853878fb6fSWolfgang Grandegger #define XILINX_VERINT 7 /* Lower nibble simulate interrupts, 863878fb6fSWolfgang Grandegger high nibble version number. */ 873878fb6fSWolfgang Grandegger 883878fb6fSWolfgang Grandegger #define XILINX_PRESUMED_VERSION 14 893878fb6fSWolfgang Grandegger 903878fb6fSWolfgang Grandegger /* 913878fb6fSWolfgang Grandegger * Important S5920 registers 923878fb6fSWolfgang Grandegger */ 933878fb6fSWolfgang Grandegger #define S5920_INTCSR 0x38 943878fb6fSWolfgang Grandegger #define S5920_PTCR 0x60 953878fb6fSWolfgang Grandegger #define INTCSR_ADDON_INTENABLE_M 0x2000 963878fb6fSWolfgang Grandegger 973878fb6fSWolfgang Grandegger 983878fb6fSWolfgang Grandegger #define KVASER_PCI_PORT_BYTES 0x20 993878fb6fSWolfgang Grandegger 1003878fb6fSWolfgang Grandegger #define PCI_CONFIG_PORT_SIZE 0x80 /* size of the config io-memory */ 1013878fb6fSWolfgang Grandegger #define PCI_PORT_SIZE 0x80 /* size of a channel io-memory */ 1023878fb6fSWolfgang Grandegger #define PCI_PORT_XILINX_SIZE 0x08 /* size of a xilinx io-memory */ 1033878fb6fSWolfgang Grandegger 1043878fb6fSWolfgang Grandegger #define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */ 1053878fb6fSWolfgang Grandegger #define KVASER_PCI_DEVICE_ID1 0x8406 1063878fb6fSWolfgang Grandegger 1073878fb6fSWolfgang Grandegger #define KVASER_PCI_VENDOR_ID2 0x1a07 /* the PCI device and vendor IDs */ 1083878fb6fSWolfgang Grandegger #define KVASER_PCI_DEVICE_ID2 0x0008 1093878fb6fSWolfgang Grandegger 1109baa3c34SBenoit Taine static const struct pci_device_id kvaser_pci_tbl[] = { 1113878fb6fSWolfgang Grandegger {KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,}, 1123878fb6fSWolfgang Grandegger {KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,}, 1133878fb6fSWolfgang Grandegger { 0,} 1143878fb6fSWolfgang Grandegger }; 1153878fb6fSWolfgang Grandegger 1163878fb6fSWolfgang Grandegger MODULE_DEVICE_TABLE(pci, kvaser_pci_tbl); 1173878fb6fSWolfgang Grandegger 118255a9154SWolfgang Grandegger static u8 kvaser_pci_read_reg(const struct sja1000_priv *priv, int port) 1193878fb6fSWolfgang Grandegger { 120255a9154SWolfgang Grandegger return ioread8(priv->reg_base + port); 1213878fb6fSWolfgang Grandegger } 1223878fb6fSWolfgang Grandegger 123255a9154SWolfgang Grandegger static void kvaser_pci_write_reg(const struct sja1000_priv *priv, 124255a9154SWolfgang Grandegger int port, u8 val) 1253878fb6fSWolfgang Grandegger { 126255a9154SWolfgang Grandegger iowrite8(val, priv->reg_base + port); 1273878fb6fSWolfgang Grandegger } 1283878fb6fSWolfgang Grandegger 1293878fb6fSWolfgang Grandegger static void kvaser_pci_disable_irq(struct net_device *dev) 1303878fb6fSWolfgang Grandegger { 1313878fb6fSWolfgang Grandegger struct sja1000_priv *priv = netdev_priv(dev); 1323878fb6fSWolfgang Grandegger struct kvaser_pci *board = priv->priv; 1333878fb6fSWolfgang Grandegger u32 intcsr; 1343878fb6fSWolfgang Grandegger 1353878fb6fSWolfgang Grandegger /* Disable interrupts from card */ 1363878fb6fSWolfgang Grandegger intcsr = ioread32(board->conf_addr + S5920_INTCSR); 1373878fb6fSWolfgang Grandegger intcsr &= ~INTCSR_ADDON_INTENABLE_M; 1383878fb6fSWolfgang Grandegger iowrite32(intcsr, board->conf_addr + S5920_INTCSR); 1393878fb6fSWolfgang Grandegger } 1403878fb6fSWolfgang Grandegger 1413878fb6fSWolfgang Grandegger static void kvaser_pci_enable_irq(struct net_device *dev) 1423878fb6fSWolfgang Grandegger { 1433878fb6fSWolfgang Grandegger struct sja1000_priv *priv = netdev_priv(dev); 1443878fb6fSWolfgang Grandegger struct kvaser_pci *board = priv->priv; 1453878fb6fSWolfgang Grandegger u32 tmp_en_io; 1463878fb6fSWolfgang Grandegger 1473878fb6fSWolfgang Grandegger /* Enable interrupts from card */ 1483878fb6fSWolfgang Grandegger tmp_en_io = ioread32(board->conf_addr + S5920_INTCSR); 1493878fb6fSWolfgang Grandegger tmp_en_io |= INTCSR_ADDON_INTENABLE_M; 1503878fb6fSWolfgang Grandegger iowrite32(tmp_en_io, board->conf_addr + S5920_INTCSR); 1513878fb6fSWolfgang Grandegger } 1523878fb6fSWolfgang Grandegger 1533878fb6fSWolfgang Grandegger static int number_of_sja1000_chip(void __iomem *base_addr) 1543878fb6fSWolfgang Grandegger { 1553878fb6fSWolfgang Grandegger u8 status; 1563878fb6fSWolfgang Grandegger int i; 1573878fb6fSWolfgang Grandegger 1583878fb6fSWolfgang Grandegger for (i = 0; i < MAX_NO_OF_CHANNELS; i++) { 1593878fb6fSWolfgang Grandegger /* reset chip */ 1603878fb6fSWolfgang Grandegger iowrite8(MOD_RM, base_addr + 16106e1d1d7SOliver Hartkopp (i * KVASER_PCI_PORT_BYTES) + SJA1000_MOD); 1623878fb6fSWolfgang Grandegger status = ioread8(base_addr + 16306e1d1d7SOliver Hartkopp (i * KVASER_PCI_PORT_BYTES) + SJA1000_MOD); 1643878fb6fSWolfgang Grandegger /* check reset bit */ 1653878fb6fSWolfgang Grandegger if (!(status & MOD_RM)) 1663878fb6fSWolfgang Grandegger break; 1673878fb6fSWolfgang Grandegger } 1683878fb6fSWolfgang Grandegger 1693878fb6fSWolfgang Grandegger return i; 1703878fb6fSWolfgang Grandegger } 1713878fb6fSWolfgang Grandegger 1723878fb6fSWolfgang Grandegger static void kvaser_pci_del_chan(struct net_device *dev) 1733878fb6fSWolfgang Grandegger { 1743878fb6fSWolfgang Grandegger struct sja1000_priv *priv; 1753878fb6fSWolfgang Grandegger struct kvaser_pci *board; 1763878fb6fSWolfgang Grandegger int i; 1773878fb6fSWolfgang Grandegger 1783878fb6fSWolfgang Grandegger if (!dev) 1793878fb6fSWolfgang Grandegger return; 1803878fb6fSWolfgang Grandegger priv = netdev_priv(dev); 1813878fb6fSWolfgang Grandegger board = priv->priv; 1823878fb6fSWolfgang Grandegger if (!board) 1833878fb6fSWolfgang Grandegger return; 1843878fb6fSWolfgang Grandegger 1853878fb6fSWolfgang Grandegger dev_info(&board->pci_dev->dev, "Removing device %s\n", 1863878fb6fSWolfgang Grandegger dev->name); 1873878fb6fSWolfgang Grandegger 1883878fb6fSWolfgang Grandegger /* Disable PCI interrupts */ 1893878fb6fSWolfgang Grandegger kvaser_pci_disable_irq(dev); 1903878fb6fSWolfgang Grandegger 1913878fb6fSWolfgang Grandegger for (i = 0; i < board->no_channels - 1; i++) { 1923878fb6fSWolfgang Grandegger if (board->slave_dev[i]) { 1933878fb6fSWolfgang Grandegger dev_info(&board->pci_dev->dev, "Removing device %s\n", 1943878fb6fSWolfgang Grandegger board->slave_dev[i]->name); 1953878fb6fSWolfgang Grandegger unregister_sja1000dev(board->slave_dev[i]); 1963878fb6fSWolfgang Grandegger free_sja1000dev(board->slave_dev[i]); 1973878fb6fSWolfgang Grandegger } 1983878fb6fSWolfgang Grandegger } 1993878fb6fSWolfgang Grandegger unregister_sja1000dev(dev); 2003878fb6fSWolfgang Grandegger 201255a9154SWolfgang Grandegger pci_iounmap(board->pci_dev, priv->reg_base); 2023878fb6fSWolfgang Grandegger pci_iounmap(board->pci_dev, board->conf_addr); 2033878fb6fSWolfgang Grandegger pci_iounmap(board->pci_dev, board->res_addr); 2043878fb6fSWolfgang Grandegger 2053878fb6fSWolfgang Grandegger free_sja1000dev(dev); 2063878fb6fSWolfgang Grandegger } 2073878fb6fSWolfgang Grandegger 2083878fb6fSWolfgang Grandegger static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel, 2093878fb6fSWolfgang Grandegger struct net_device **master_dev, 2103878fb6fSWolfgang Grandegger void __iomem *conf_addr, 2113878fb6fSWolfgang Grandegger void __iomem *res_addr, 212255a9154SWolfgang Grandegger void __iomem *base_addr) 2133878fb6fSWolfgang Grandegger { 2143878fb6fSWolfgang Grandegger struct net_device *dev; 2153878fb6fSWolfgang Grandegger struct sja1000_priv *priv; 2163878fb6fSWolfgang Grandegger struct kvaser_pci *board; 217*4e2061b1SSudip Mukherjee int err; 2183878fb6fSWolfgang Grandegger 2193878fb6fSWolfgang Grandegger dev = alloc_sja1000dev(sizeof(struct kvaser_pci)); 2203878fb6fSWolfgang Grandegger if (dev == NULL) 2213878fb6fSWolfgang Grandegger return -ENOMEM; 2223878fb6fSWolfgang Grandegger 2233878fb6fSWolfgang Grandegger priv = netdev_priv(dev); 2243878fb6fSWolfgang Grandegger board = priv->priv; 2253878fb6fSWolfgang Grandegger 2263878fb6fSWolfgang Grandegger board->pci_dev = pdev; 2273878fb6fSWolfgang Grandegger board->channel = channel; 2283878fb6fSWolfgang Grandegger 2293878fb6fSWolfgang Grandegger /* S5920 */ 2303878fb6fSWolfgang Grandegger board->conf_addr = conf_addr; 2313878fb6fSWolfgang Grandegger 2323878fb6fSWolfgang Grandegger /* XILINX board wide address */ 2333878fb6fSWolfgang Grandegger board->res_addr = res_addr; 2343878fb6fSWolfgang Grandegger 2353878fb6fSWolfgang Grandegger if (channel == 0) { 2363878fb6fSWolfgang Grandegger board->xilinx_ver = 2373878fb6fSWolfgang Grandegger ioread8(board->res_addr + XILINX_VERINT) >> 4; 2383878fb6fSWolfgang Grandegger 2393878fb6fSWolfgang Grandegger /* Assert PTADR# - we're in passive mode so the other bits are 2403878fb6fSWolfgang Grandegger not important */ 2413878fb6fSWolfgang Grandegger iowrite32(0x80808080UL, board->conf_addr + S5920_PTCR); 2423878fb6fSWolfgang Grandegger 2433878fb6fSWolfgang Grandegger /* Enable interrupts from card */ 2443878fb6fSWolfgang Grandegger kvaser_pci_enable_irq(dev); 2453878fb6fSWolfgang Grandegger } else { 2463878fb6fSWolfgang Grandegger struct sja1000_priv *master_priv = netdev_priv(*master_dev); 2473878fb6fSWolfgang Grandegger struct kvaser_pci *master_board = master_priv->priv; 2483878fb6fSWolfgang Grandegger master_board->slave_dev[channel - 1] = dev; 2493878fb6fSWolfgang Grandegger master_board->no_channels = channel + 1; 2503878fb6fSWolfgang Grandegger board->xilinx_ver = master_board->xilinx_ver; 2513878fb6fSWolfgang Grandegger } 2523878fb6fSWolfgang Grandegger 253255a9154SWolfgang Grandegger priv->reg_base = base_addr + channel * KVASER_PCI_PORT_BYTES; 2543878fb6fSWolfgang Grandegger 2553878fb6fSWolfgang Grandegger priv->read_reg = kvaser_pci_read_reg; 2563878fb6fSWolfgang Grandegger priv->write_reg = kvaser_pci_write_reg; 2573878fb6fSWolfgang Grandegger 2583878fb6fSWolfgang Grandegger priv->can.clock.freq = KVASER_PCI_CAN_CLOCK; 2593878fb6fSWolfgang Grandegger 2603878fb6fSWolfgang Grandegger priv->ocr = KVASER_PCI_OCR; 2613878fb6fSWolfgang Grandegger priv->cdr = KVASER_PCI_CDR; 2623878fb6fSWolfgang Grandegger 2633878fb6fSWolfgang Grandegger priv->irq_flags = IRQF_SHARED; 2643878fb6fSWolfgang Grandegger dev->irq = pdev->irq; 2653878fb6fSWolfgang Grandegger 266255a9154SWolfgang Grandegger dev_info(&pdev->dev, "reg_base=%p conf_addr=%p irq=%d\n", 267255a9154SWolfgang Grandegger priv->reg_base, board->conf_addr, dev->irq); 2683878fb6fSWolfgang Grandegger 2693878fb6fSWolfgang Grandegger SET_NETDEV_DEV(dev, &pdev->dev); 2703e66d013SChristopher R. Baker dev->dev_id = channel; 2713878fb6fSWolfgang Grandegger 2723878fb6fSWolfgang Grandegger /* Register SJA1000 device */ 2733878fb6fSWolfgang Grandegger err = register_sja1000dev(dev); 2743878fb6fSWolfgang Grandegger if (err) { 2753878fb6fSWolfgang Grandegger dev_err(&pdev->dev, "Registering device failed (err=%d)\n", 2763878fb6fSWolfgang Grandegger err); 2773878fb6fSWolfgang Grandegger goto failure; 2783878fb6fSWolfgang Grandegger } 2793878fb6fSWolfgang Grandegger 2803878fb6fSWolfgang Grandegger if (channel == 0) 2813878fb6fSWolfgang Grandegger *master_dev = dev; 2823878fb6fSWolfgang Grandegger 2833878fb6fSWolfgang Grandegger return 0; 2843878fb6fSWolfgang Grandegger 2853878fb6fSWolfgang Grandegger failure: 2863878fb6fSWolfgang Grandegger kvaser_pci_del_chan(dev); 2873878fb6fSWolfgang Grandegger return err; 2883878fb6fSWolfgang Grandegger } 2893878fb6fSWolfgang Grandegger 2903c8ac0f2SBill Pemberton static int kvaser_pci_init_one(struct pci_dev *pdev, 2913878fb6fSWolfgang Grandegger const struct pci_device_id *ent) 2923878fb6fSWolfgang Grandegger { 2933878fb6fSWolfgang Grandegger int err; 2943878fb6fSWolfgang Grandegger struct net_device *master_dev = NULL; 2953878fb6fSWolfgang Grandegger struct sja1000_priv *priv; 2963878fb6fSWolfgang Grandegger struct kvaser_pci *board; 2973878fb6fSWolfgang Grandegger int no_channels; 2983878fb6fSWolfgang Grandegger void __iomem *base_addr = NULL; 2993878fb6fSWolfgang Grandegger void __iomem *conf_addr = NULL; 3003878fb6fSWolfgang Grandegger void __iomem *res_addr = NULL; 3013878fb6fSWolfgang Grandegger int i; 3023878fb6fSWolfgang Grandegger 3033878fb6fSWolfgang Grandegger dev_info(&pdev->dev, "initializing device %04x:%04x\n", 3043878fb6fSWolfgang Grandegger pdev->vendor, pdev->device); 3053878fb6fSWolfgang Grandegger 3063878fb6fSWolfgang Grandegger err = pci_enable_device(pdev); 3073878fb6fSWolfgang Grandegger if (err) 3083878fb6fSWolfgang Grandegger goto failure; 3093878fb6fSWolfgang Grandegger 3103878fb6fSWolfgang Grandegger err = pci_request_regions(pdev, DRV_NAME); 3113878fb6fSWolfgang Grandegger if (err) 3123878fb6fSWolfgang Grandegger goto failure_release_pci; 3133878fb6fSWolfgang Grandegger 3143878fb6fSWolfgang Grandegger /* S5920 */ 3153878fb6fSWolfgang Grandegger conf_addr = pci_iomap(pdev, 0, PCI_CONFIG_PORT_SIZE); 3163878fb6fSWolfgang Grandegger if (conf_addr == NULL) { 3173878fb6fSWolfgang Grandegger err = -ENODEV; 3183878fb6fSWolfgang Grandegger goto failure_release_regions; 3193878fb6fSWolfgang Grandegger } 3203878fb6fSWolfgang Grandegger 3213878fb6fSWolfgang Grandegger /* XILINX board wide address */ 3223878fb6fSWolfgang Grandegger res_addr = pci_iomap(pdev, 2, PCI_PORT_XILINX_SIZE); 3233878fb6fSWolfgang Grandegger if (res_addr == NULL) { 3243878fb6fSWolfgang Grandegger err = -ENOMEM; 3253878fb6fSWolfgang Grandegger goto failure_iounmap; 3263878fb6fSWolfgang Grandegger } 3273878fb6fSWolfgang Grandegger 3283878fb6fSWolfgang Grandegger base_addr = pci_iomap(pdev, 1, PCI_PORT_SIZE); 3293878fb6fSWolfgang Grandegger if (base_addr == NULL) { 3303878fb6fSWolfgang Grandegger err = -ENOMEM; 3313878fb6fSWolfgang Grandegger goto failure_iounmap; 3323878fb6fSWolfgang Grandegger } 3333878fb6fSWolfgang Grandegger 3343878fb6fSWolfgang Grandegger no_channels = number_of_sja1000_chip(base_addr); 3353878fb6fSWolfgang Grandegger if (no_channels == 0) { 3363878fb6fSWolfgang Grandegger err = -ENOMEM; 3373878fb6fSWolfgang Grandegger goto failure_iounmap; 3383878fb6fSWolfgang Grandegger } 3393878fb6fSWolfgang Grandegger 3403878fb6fSWolfgang Grandegger for (i = 0; i < no_channels; i++) { 3413878fb6fSWolfgang Grandegger err = kvaser_pci_add_chan(pdev, i, &master_dev, 3423878fb6fSWolfgang Grandegger conf_addr, res_addr, 343255a9154SWolfgang Grandegger base_addr); 3443878fb6fSWolfgang Grandegger if (err) 3453878fb6fSWolfgang Grandegger goto failure_cleanup; 3463878fb6fSWolfgang Grandegger } 3473878fb6fSWolfgang Grandegger 3483878fb6fSWolfgang Grandegger priv = netdev_priv(master_dev); 3493878fb6fSWolfgang Grandegger board = priv->priv; 3503878fb6fSWolfgang Grandegger 3513878fb6fSWolfgang Grandegger dev_info(&pdev->dev, "xilinx version=%d number of channels=%d\n", 3523878fb6fSWolfgang Grandegger board->xilinx_ver, board->no_channels); 3533878fb6fSWolfgang Grandegger 3543878fb6fSWolfgang Grandegger pci_set_drvdata(pdev, master_dev); 3553878fb6fSWolfgang Grandegger return 0; 3563878fb6fSWolfgang Grandegger 3573878fb6fSWolfgang Grandegger failure_cleanup: 3583878fb6fSWolfgang Grandegger kvaser_pci_del_chan(master_dev); 3593878fb6fSWolfgang Grandegger 3603878fb6fSWolfgang Grandegger failure_iounmap: 3613878fb6fSWolfgang Grandegger if (conf_addr != NULL) 3623878fb6fSWolfgang Grandegger pci_iounmap(pdev, conf_addr); 3633878fb6fSWolfgang Grandegger if (res_addr != NULL) 3643878fb6fSWolfgang Grandegger pci_iounmap(pdev, res_addr); 3653878fb6fSWolfgang Grandegger if (base_addr != NULL) 3663878fb6fSWolfgang Grandegger pci_iounmap(pdev, base_addr); 3673878fb6fSWolfgang Grandegger 3683878fb6fSWolfgang Grandegger failure_release_regions: 3693878fb6fSWolfgang Grandegger pci_release_regions(pdev); 3703878fb6fSWolfgang Grandegger 3713878fb6fSWolfgang Grandegger failure_release_pci: 3723878fb6fSWolfgang Grandegger pci_disable_device(pdev); 3733878fb6fSWolfgang Grandegger 3743878fb6fSWolfgang Grandegger failure: 3753878fb6fSWolfgang Grandegger return err; 3763878fb6fSWolfgang Grandegger 3773878fb6fSWolfgang Grandegger } 3783878fb6fSWolfgang Grandegger 3793c8ac0f2SBill Pemberton static void kvaser_pci_remove_one(struct pci_dev *pdev) 3803878fb6fSWolfgang Grandegger { 3813878fb6fSWolfgang Grandegger struct net_device *dev = pci_get_drvdata(pdev); 3823878fb6fSWolfgang Grandegger 3833878fb6fSWolfgang Grandegger kvaser_pci_del_chan(dev); 3843878fb6fSWolfgang Grandegger 3853878fb6fSWolfgang Grandegger pci_release_regions(pdev); 3863878fb6fSWolfgang Grandegger pci_disable_device(pdev); 3873878fb6fSWolfgang Grandegger } 3883878fb6fSWolfgang Grandegger 3893878fb6fSWolfgang Grandegger static struct pci_driver kvaser_pci_driver = { 3903878fb6fSWolfgang Grandegger .name = DRV_NAME, 3913878fb6fSWolfgang Grandegger .id_table = kvaser_pci_tbl, 3923878fb6fSWolfgang Grandegger .probe = kvaser_pci_init_one, 3933c8ac0f2SBill Pemberton .remove = kvaser_pci_remove_one, 3943878fb6fSWolfgang Grandegger }; 3953878fb6fSWolfgang Grandegger 396fb7944b3SAxel Lin module_pci_driver(kvaser_pci_driver); 397