static void rtcan_ems_pci_del_chan(struct rtcan_device *dev, int init_step) { struct rtcan_ems_pci *board; if (!dev) return; board = (struct rtcan_ems_pci *)dev->board_priv; switch (init_step) { case 0: /* Full cleanup */ RTCAN_DBG("Removing %s %s device %s\n", ems_pci_board_name, dev->ctrl_name, dev->name); rtcan_sja1000_unregister(dev); case 5: case 4: iounmap((void *)board->base_addr); case 3: if (board->channel != EMS_PCI_SLAVE) iounmap((void *)board->conf_addr); case 2: rtcan_dev_free(dev); case 1: break; } }
static int __devinit ems_pci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { struct rtcan_device *master_dev = NULL; int err; RTCAN_DBG("%s: initializing device %04x:%04x\n", RTCAN_DRV_NAME, pdev->vendor, pdev->device); if ((err = pci_enable_device (pdev))) goto failure; if ((err = pci_request_regions(pdev, RTCAN_DRV_NAME))) goto failure; if ((err = pci_write_config_word(pdev, 0x04, 2))) goto failure_cleanup; if ((err = rtcan_ems_pci_add_chan(pdev, EMS_PCI_MASTER, &master_dev))) goto failure_cleanup; if ((err = rtcan_ems_pci_add_chan(pdev, EMS_PCI_SLAVE, &master_dev))) goto failure_cleanup; pci_set_drvdata(pdev, master_dev); return 0; failure_cleanup: if (master_dev) rtcan_ems_pci_del_chan(master_dev, 0); pci_release_regions(pdev); failure: return err; }
static int __devinit adv_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int ret, channel; unsigned int nb_ports = 0; unsigned int bar = 0; unsigned int bar_flag = 0; unsigned int offset = 0; unsigned int ix; struct rtcan_device *master_dev = NULL; dev_info(&pdev->dev, "RTCAN Registering card"); ret = pci_enable_device(pdev); if (ret) goto failure; dev_info(&pdev->dev, "RTCAN detected Advantech PCI card at slot #%i\n", PCI_SLOT(pdev->devfn)); ret = pci_request_regions(pdev, RTCAN_DRV_NAME); if (ret) goto failure_device; switch (pdev->device) { case 0xc001: case 0xc002: case 0xc004: case 0xc101: case 0xc102: case 0xc104: nb_ports = pdev->device & 0x7; offset = 0x100; bar = 0; break; case 0x1680: case 0x2052: nb_ports = 2; bar = 2; bar_flag = 1; break; case 0x1681: nb_ports = 1; bar = 2; bar_flag = 1; break; default: goto failure_regions; } if (nb_ports > 1) channel = CHANNEL_MASTER; else channel = CHANNEL_SINGLE; RTCAN_DBG("%s: Initializing device %04x:%04x:%04x\n", RTCAN_DRV_NAME, pdev->vendor, pdev->device, pdev->subsystem_device); ret = rtcan_adv_pci_add_chan(pdev, channel, bar, offset, &master_dev); if (ret) goto failure_iounmap; /* register slave channel, if any */ for (ix = 1; ix < nb_ports; ix++) { ret = rtcan_adv_pci_add_chan(pdev, CHANNEL_SLAVE, bar + (bar_flag ? ix : 0), offset * ix, &master_dev); if (ret) goto failure_iounmap; } pci_set_drvdata(pdev, master_dev); return 0; failure_iounmap: if (master_dev) rtcan_adv_pci_del_chan(pdev, master_dev); failure_regions: pci_release_regions(pdev); failure_device: pci_disable_device(pdev); failure: return ret; }
static int rtcan_adv_pci_add_chan(struct pci_dev *pdev, int channel, unsigned int bar, unsigned int offset, struct rtcan_device **master_dev) { struct rtcan_device *dev; struct rtcan_sja1000 *chip; struct rtcan_adv_pci *board; void __iomem *base_addr; int ret; dev = rtcan_dev_alloc(sizeof(struct rtcan_sja1000), sizeof(struct rtcan_adv_pci)); if (dev == NULL) return -ENOMEM; chip = (struct rtcan_sja1000 *)dev->priv; board = (struct rtcan_adv_pci *)dev->board_priv; if (channel == CHANNEL_SLAVE) { struct rtcan_adv_pci *master_board = (struct rtcan_adv_pci *)(*master_dev)->board_priv; master_board->slave_dev = dev; if (offset) base_addr = master_board->base_addr+offset; else base_addr = pci_iomap(pdev, bar, ADV_PCI_BASE_SIZE); if (!base_addr) { ret = -EIO; goto failure; } } else { base_addr = pci_iomap(pdev, bar, ADV_PCI_BASE_SIZE) + offset; if (!base_addr) { ret = -EIO; goto failure; } } board->pci_dev = pdev; board->conf_addr = NULL; board->base_addr = base_addr; dev->board_name = adv_pci_board_name; chip->read_reg = rtcan_adv_pci_read_reg; chip->write_reg = rtcan_adv_pci_write_reg; /* Clock frequency in Hz */ dev->can_sys_clock = ADV_PCI_CAN_CLOCK; /* Output control register */ chip->ocr = ADV_PCI_OCR; /* Clock divider register */ chip->cdr = ADV_PCI_CDR; strncpy(dev->name, RTCAN_DEV_NAME, IFNAMSIZ); /* Make sure SJA1000 is in reset mode */ chip->write_reg(dev, SJA_MOD, SJA_MOD_RM); /* Set PeliCAN mode */ chip->write_reg(dev, SJA_CDR, SJA_CDR_CAN_MODE); /* check if mode is set */ ret = chip->read_reg(dev, SJA_CDR); if (ret != SJA_CDR_CAN_MODE) { ret = -EIO; goto failure_iounmap; } /* Register and setup interrupt handling */ chip->irq_flags = RTDM_IRQTYPE_SHARED; chip->irq_num = pdev->irq; RTCAN_DBG("%s: base_addr=%p conf_addr=%p irq=%d ocr=%#x cdr=%#x\n", RTCAN_DRV_NAME, board->base_addr, board->conf_addr, chip->irq_num, chip->ocr, chip->cdr); /* Register SJA1000 device */ ret = rtcan_sja1000_register(dev); if (ret) { printk(KERN_ERR "ERROR %d while trying to register SJA1000 device!\n", ret); goto failure_iounmap; } if (channel != CHANNEL_SLAVE) *master_dev = dev; return 0; failure_iounmap: if (channel != CHANNEL_SLAVE || !offset) pci_iounmap(pdev, base_addr); failure: rtcan_dev_free(dev); return ret; }
static int ixxat_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int ret, channel, conf_addr; unsigned long addr; void __iomem *base_addr; struct rtcan_device *master_dev = NULL; if ((ret = pci_enable_device (pdev))) goto failure; if ((ret = pci_request_regions(pdev, RTCAN_DRV_NAME))) goto failure; RTCAN_DBG("%s: Initializing device %04x:%04x:%04x\n", RTCAN_DRV_NAME, pdev->vendor, pdev->device, pdev->subsystem_device); /* Enable memory and I/O space */ if ((ret = pci_write_config_word(pdev, 0x04, 0x3))) goto failure_release_pci; conf_addr = pci_resource_start(pdev, 1); addr = pci_resource_start(pdev, 2); base_addr = ioremap(addr, IXXAT_BASE_PORT_SIZE); if (base_addr == 0) { ret = -ENODEV; goto failure_release_pci; } /* Check if second channel is available after reset */ writeb(0x1, base_addr + CHANNEL_MASTER_RESET); writeb(0x1, base_addr + CHANNEL_SLAVE_RESET); udelay(100); if ( (readb(base_addr + CHANNEL_OFFSET + SJA_MOD) & IXXAT_SJA_MOD_MASK ) != 0x21 || readb(base_addr + CHANNEL_OFFSET + SJA_SR ) != 0x0c || readb(base_addr + CHANNEL_OFFSET + SJA_IR ) != 0xe0) channel = CHANNEL_SINGLE; else channel = CHANNEL_MASTER; if ((ret = rtcan_ixxat_pci_add_chan(pdev, channel, &master_dev, conf_addr, base_addr))) goto failure_iounmap; if (channel != CHANNEL_SINGLE) { channel = CHANNEL_SLAVE; if ((ret = rtcan_ixxat_pci_add_chan(pdev, channel, &master_dev, conf_addr, base_addr + CHANNEL_OFFSET))) goto failure_iounmap; } pci_set_drvdata(pdev, master_dev); return 0; failure_iounmap: if (master_dev) rtcan_ixxat_pci_del_chan(master_dev); iounmap(base_addr); failure_release_pci: pci_release_regions(pdev); failure: return ret; }
static int rtcan_ixxat_pci_add_chan(struct pci_dev *pdev, int channel, struct rtcan_device **master_dev, int conf_addr, void __iomem *base_addr) { struct rtcan_device *dev; struct rtcan_sja1000 *chip; struct rtcan_ixxat_pci *board; u8 intcsr; int ret; dev = rtcan_dev_alloc(sizeof(struct rtcan_sja1000), sizeof(struct rtcan_ixxat_pci)); if (dev == NULL) return -ENOMEM; chip = (struct rtcan_sja1000 *)dev->priv; board = (struct rtcan_ixxat_pci *)dev->board_priv; board->pci_dev = pdev; board->conf_addr = conf_addr; board->base_addr = base_addr; if (channel == CHANNEL_SLAVE) { struct rtcan_ixxat_pci *master_board = (struct rtcan_ixxat_pci *)(*master_dev)->board_priv; master_board->slave_dev = dev; } dev->board_name = ixxat_pci_board_name; chip->read_reg = rtcan_ixxat_pci_read_reg; chip->write_reg = rtcan_ixxat_pci_write_reg; /* Clock frequency in Hz */ dev->can_sys_clock = IXXAT_PCI_CAN_SYS_CLOCK; /* Output control register */ chip->ocr = (SJA_OCR_MODE_NORMAL | SJA_OCR_TX0_INVERT | SJA_OCR_TX0_PUSHPULL | SJA_OCR_TX1_PUSHPULL); /* Clock divider register */ chip->cdr = SJA_CDR_CAN_MODE; strncpy(dev->name, RTCAN_DEV_NAME, IFNAMSIZ); /* Enable PCI interrupts */ intcsr = inb(board->conf_addr + IXXAT_INTCSR_OFFSET); if (channel == CHANNEL_SLAVE) intcsr |= IXXAT_INTCSR_SLAVE; else intcsr |= IXXAT_INTCSR_MASTER; outb(intcsr, board->conf_addr + IXXAT_INTCSR_OFFSET); /* Register and setup interrupt handling */ chip->irq_flags = RTDM_IRQTYPE_SHARED; chip->irq_num = pdev->irq; RTCAN_DBG("%s: base_addr=0x%p conf_addr=%#x irq=%d ocr=%#x cdr=%#x\n", RTCAN_DRV_NAME, board->base_addr, board->conf_addr, chip->irq_num, chip->ocr, chip->cdr); /* Register SJA1000 device */ ret = rtcan_sja1000_register(dev); if (ret) { printk(KERN_ERR "ERROR %d while trying to register SJA1000 device!\n", ret); goto failure; } if (channel != CHANNEL_SLAVE) *master_dev = dev; return 0; failure: rtcan_dev_free(dev); return ret; }