コード例 #1
0
static void kvaser_pci_del_chan(struct net_device *dev)
{
	struct sja1000_priv *priv;
	struct kvaser_pci *board;
	int i;

	if (!dev)
		return;
	priv = netdev_priv(dev);
	board = priv->priv;
	if (!board)
		return;

	dev_info(&board->pci_dev->dev, "Removing device %s\n",
		 dev->name);

	/* Disable PCI interrupts */
	kvaser_pci_disable_irq(dev);

	for (i = 0; i < board->no_channels - 1; i++) {
		if (board->slave_dev[i]) {
			dev_info(&board->pci_dev->dev, "Removing device %s\n",
				 board->slave_dev[i]->name);
			unregister_sja1000dev(board->slave_dev[i]);
			free_sja1000dev(board->slave_dev[i]);
		}
	}
	unregister_sja1000dev(dev);

	pci_iounmap(board->pci_dev, priv->reg_base);
	pci_iounmap(board->pci_dev, board->conf_addr);
	pci_iounmap(board->pci_dev, board->res_addr);

	free_sja1000dev(dev);
}
コード例 #2
0
static void ems_pci_del_card(struct pci_dev *pdev)
{
	struct ems_pci_card *card = pci_get_drvdata(pdev);
	struct net_device *dev;
	int i = 0;

	for (i = 0; i < card->channels; i++) {
		dev = card->net_dev[i];

		if (!dev)
			continue;

		dev_info(&pdev->dev, "Removing %s.\n", dev->name);
		unregister_sja1000dev(dev);
		free_sja1000dev(dev);
	}

	if (card->base_addr != NULL)
		pci_iounmap(card->pci_dev, card->base_addr);

	if (card->conf_addr != NULL)
		pci_iounmap(card->pci_dev, card->conf_addr);

	kfree(card);

	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);
}
コード例 #3
0
/*
 * Release claimed resources
 */
static int __devexit ems_104m_remove(struct device *pdev, unsigned int idx)
{
	struct ems_104m_card *card = dev_get_drvdata(pdev);
	struct net_device *dev;
	int i = 0;

	if (!card)
		return 0;

	free_irq(card->irq, card);

	for (i = 0; i < card->channels; i++) {
		dev = card->net_dev[i];

		if (!dev)
			continue;

		dev_info(pdev, "removing %s on channel #%d\n", dev->name, i);
		unregister_sja1000dev(dev);
		free_sja1000dev(dev);
	}

	writeb(EMS_CMD_UMAP, card->base);

	if (card->base != NULL)
		iounmap(card->base);

	kfree(card);

	dev_set_drvdata(pdev, NULL);

	return 0;
}
コード例 #4
0
/*
 * free all resources used by the channels and switch off leds and can power
 */
static void pcan_free_channels(struct pcan_pccard *card)
{
	int i;
	u8 led_mask = 0;

	for (i = 0; i < card->chan_count; i++) {
		struct net_device *netdev;
		char name[IFNAMSIZ];

		led_mask |= PCC_LED(i);

		netdev = card->channel[i].netdev;
		if (!netdev)
			continue;

		strncpy(name, netdev->name, IFNAMSIZ);

		unregister_sja1000dev(netdev);

		free_sja1000dev(netdev);

		dev_info(&card->pdev->dev, "%s removed\n", name);
	}

	/* do it only if device not removed */
	if (pcan_pccard_present(card)) {
		pcan_set_leds(card, led_mask, PCC_LED_OFF);
		pcan_set_can_power(card, 0);
	}
}
コード例 #5
0
static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
{
	struct ems_pcmcia_card *card = pdev->priv;
	struct net_device *dev;
	int i;

	free_irq(pdev->irq, card);

	for (i = 0; i < card->channels; i++) {
		dev = card->net_dev[i];
		if (!dev)
			continue;

		printk(KERN_INFO "%s: removing %s on channel #%d\n",
		       DRV_NAME, dev->name, i);
		unregister_sja1000dev(dev);
		free_sja1000dev(dev);
	}

	writeb(EMS_CMD_UMAP, card->base_addr);
	iounmap(card->base_addr);
	kfree(card);

	pdev->priv = NULL;
}
コード例 #6
0
ファイル: peak_pci.c プロジェクト: 020gzh/linux
static void peak_pci_remove(struct pci_dev *pdev)
{
	struct net_device *dev = pci_get_drvdata(pdev); /* Last device */
	struct sja1000_priv *priv = netdev_priv(dev);
	struct peak_pci_chan *chan = priv->priv;
	void __iomem *cfg_base = chan->cfg_base;
	void __iomem *reg_base = priv->reg_base;

	/* Disable interrupts */
	writew(0x0, cfg_base + PITA_ICR + 2);

	/* Loop over all registered devices */
	while (1) {
		struct net_device *prev_dev = chan->prev_dev;

		dev_info(&pdev->dev, "removing device %s\n", dev->name);
		unregister_sja1000dev(dev);
		free_sja1000dev(dev);
		dev = prev_dev;

		if (!dev) {
			/* do that only for first channel */
			if (chan->pciec_card)
				peak_pciec_remove(chan->pciec_card);
			break;
		}
		priv = netdev_priv(dev);
		chan = priv->priv;
	}

	pci_iounmap(pdev, reg_base);
	pci_iounmap(pdev, cfg_base);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
}
コード例 #7
0
static int pcm027_remove (struct platform_device *pdev)
{
	struct net_device *dev = dev_get_drvdata(&pdev->dev);
	struct resource *res;

	dev_set_drvdata(&pdev->dev, NULL);
	unregister_sja1000dev(dev);
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	release_mem_region(res->start, res->end - res->start + 1);

	if (dev->base_addr)
		iounmap ((void *)dev->base_addr);

	free_sja1000dev(dev);

	return 0;
}
コード例 #8
0
ファイル: sja1000_of_platform.c プロジェクト: 03199618/linux
static int sja1000_ofp_remove(struct platform_device *ofdev)
{
	struct net_device *dev = platform_get_drvdata(ofdev);
	struct sja1000_priv *priv = netdev_priv(dev);
	struct device_node *np = ofdev->dev.of_node;
	struct resource res;

	unregister_sja1000dev(dev);
	free_sja1000dev(dev);
	iounmap(priv->reg_base);
	irq_dispose_mapping(dev->irq);

	of_address_to_resource(np, 0, &res);
	release_mem_region(res.start, resource_size(&res));

	return 0;
}
コード例 #9
0
static int sp_remove(struct platform_device *pdev)
{
	struct net_device *dev = dev_get_drvdata(&pdev->dev);
	struct sja1000_priv *priv = netdev_priv(dev);
	struct resource *res;

	unregister_sja1000dev(dev);
	dev_set_drvdata(&pdev->dev, NULL);

	if (priv->reg_base)
		iounmap(priv->reg_base);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	release_mem_region(res->start, resource_size(res));

	free_sja1000dev(dev);

	return 0;
}
コード例 #10
0
ファイル: plx_pci.c プロジェクト: 12rafael/jellytimekernel
static void plx_pci_del_card(struct pci_dev *pdev)
{
	struct plx_pci_card *card = pci_get_drvdata(pdev);
	struct net_device *dev;
	struct sja1000_priv *priv;
	int i = 0;

	for (i = 0; i < card->channels; i++) {
		dev = card->net_dev[i];
		if (!dev)
			continue;

		dev_info(&pdev->dev, "Removing %s\n", dev->name);
		unregister_sja1000dev(dev);
		priv = netdev_priv(dev);
		if (priv->reg_base)
			pci_iounmap(pdev, priv->reg_base);
		free_sja1000dev(dev);
	}

	card->reset_func(pdev);

	/*
	 * Disable interrupts from PCI-card and disable local
	 * interrupts
	 */
	if (pdev->device != PCI_DEVICE_ID_PLX_9056)
		iowrite32(0x0, card->conf_addr + PLX_INTCSR);
	else
		iowrite32(0x0, card->conf_addr + PLX9056_INTCSR);

	if (card->conf_addr)
		pci_iounmap(pdev, card->conf_addr);

	kfree(card);

	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);
}
コード例 #11
0
static int __devexit sja1000_isa_remove(struct platform_device *pdev)
{
	struct net_device *dev = dev_get_drvdata(&pdev->dev);
	struct sja1000_priv *priv = netdev_priv(dev);
	int idx = pdev->id;

	unregister_sja1000dev(dev);
	dev_set_drvdata(&pdev->dev, NULL);

	if (mem[idx]) {
		iounmap(priv->reg_base);
		release_mem_region(mem[idx], SJA1000_IOSIZE);
	} else {
		if (priv->read_reg == sja1000_isa_port_read_reg_indirect)
			release_region(port[idx], SJA1000_IOSIZE_INDIRECT);
		else
			release_region(port[idx], SJA1000_IOSIZE);
	}
	free_sja1000dev(dev);

	return 0;
}
コード例 #12
0
ファイル: tscan1.c プロジェクト: avagin/linux
static int tscan1_remove(struct device *dev, unsigned id /*unused*/)
{
	struct net_device *netdev;
	struct sja1000_priv *priv;
	unsigned long pld_base, sja1000_base;

	netdev = dev_get_drvdata(dev);
	unregister_sja1000dev(netdev);
	dev_set_drvdata(dev, NULL);

	priv = netdev_priv(netdev);
	pld_base = netdev->base_addr;
	sja1000_base = (unsigned long)priv->reg_base;

	outb(0, pld_base + TSCAN1_MODE);	/* disable SJA1000 IO space */

	release_region(sja1000_base, TSCAN1_SJA1000_SIZE);
	release_region(pld_base, TSCAN1_PLD_SIZE);

	free_sja1000dev(netdev);

	return 0;
}
コード例 #13
0
static int pcan_add_channels(struct pcan_pccard *card)
{
	struct pcmcia_device *pdev = card->pdev;
	int i, err = 0;
	u8 ccr = PCC_CCR_INIT;

	/* init common registers (reset channels and leds off) */
	card->ccr = ~ccr;
	pcan_write_reg(card, PCC_CCR, ccr);

	/* wait 2ms before unresetting channels */
	mdelay(2);

	ccr &= ~PCC_CCR_RST_ALL;
	pcan_write_reg(card, PCC_CCR, ccr);

	/* create one network device per channel detected */
	for (i = 0; i < ARRAY_SIZE(card->channel); i++) {
		struct net_device *netdev;
		struct sja1000_priv *priv;

		netdev = alloc_sja1000dev(0);
		if (!netdev) {
			err = -ENOMEM;
			break;
		}

		/* update linkages */
		priv = netdev_priv(netdev);
		priv->priv = card;
		SET_NETDEV_DEV(netdev, &pdev->dev);

		priv->irq_flags = IRQF_SHARED;
		netdev->irq = pdev->irq;
		priv->reg_base = card->ioport_addr + PCC_CHAN_OFF(i);

		/* check if channel is present */
		if (!pcan_channel_present(priv)) {
			dev_err(&pdev->dev, "channel %d not present\n", i);
			free_sja1000dev(netdev);
			continue;
		}

		priv->read_reg  = pcan_read_canreg;
		priv->write_reg = pcan_write_canreg;
		priv->can.clock.freq = PCC_CAN_CLOCK;
		priv->ocr = PCC_OCR;
		priv->cdr = PCC_CDR;

		/* Neither a slave device distributes the clock */
		if (i > 0)
			priv->cdr |= CDR_CLK_OFF;

		priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;

		/* register SJA1000 device */
		err = register_sja1000dev(netdev);
		if (err) {
			free_sja1000dev(netdev);
			continue;
		}

		card->channel[i].netdev = netdev;
		card->chan_count++;

		/* set corresponding led on in the new ccr */
		ccr &= ~PCC_CCR_LED_OFF_CHAN(i);

		dev_info(&pdev->dev,
			"%s on channel %d at 0x%p irq %d\n",
			netdev->name, i, priv->reg_base, pdev->irq);
	}

	/* write new ccr (change leds state) */
	pcan_write_reg(card, PCC_CCR, ccr);

	return err;
}
コード例 #14
0
static int __devinit sja1000_ofp_probe(struct of_device *ofdev,
				       const struct of_device_id *id)
{
	struct device_node *np = ofdev->node;
	struct net_device *dev;
	struct sja1000_priv *priv;
	struct resource res;
	const u32 *prop;
	int err, irq, res_size, prop_size;
	void __iomem *base;

	err = of_address_to_resource(np, 0, &res);
	if (err) {
		dev_err(&ofdev->dev, "invalid address\n");
		return err;
	}

	res_size = resource_size(&res);

	if (!request_mem_region(res.start, res_size, DRV_NAME)) {
		dev_err(&ofdev->dev, "couldn't request %#llx..%#llx\n",
			(unsigned long long)res.start,
			(unsigned long long)res.end);
		return -EBUSY;
	}

	base = ioremap_nocache(res.start, res_size);
	if (!base) {
		dev_err(&ofdev->dev, "couldn't ioremap %#llx..%#llx\n",
			(unsigned long long)res.start,
			(unsigned long long)res.end);
		err = -ENOMEM;
		goto exit_release_mem;
	}

	irq = irq_of_parse_and_map(np, 0);
	if (irq == NO_IRQ) {
		dev_err(&ofdev->dev, "no irq found\n");
		err = -ENODEV;
		goto exit_unmap_mem;
	}

	dev = alloc_sja1000dev(0);
	if (!dev) {
		err = -ENOMEM;
		goto exit_dispose_irq;
	}

	priv = netdev_priv(dev);

	priv->read_reg = sja1000_ofp_read_reg;
	priv->write_reg = sja1000_ofp_write_reg;

	prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size);
	if (prop && (prop_size ==  sizeof(u32)))
		priv->can.clock.freq = *prop / 2;
	else
		priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */

	prop = of_get_property(np, "nxp,tx-output-mode", &prop_size);
	if (prop && (prop_size == sizeof(u32)))
		priv->ocr |= *prop & OCR_MODE_MASK;
	else
		priv->ocr |= OCR_MODE_NORMAL; /* default */

	prop = of_get_property(np, "nxp,tx-output-config", &prop_size);
	if (prop && (prop_size == sizeof(u32)))
		priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK;
	else
		priv->ocr |= OCR_TX0_PULLDOWN; /* default */

	prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size);
	if (prop && (prop_size == sizeof(u32)) && *prop) {
		u32 divider = priv->can.clock.freq * 2 / *prop;

		if (divider > 1)
			priv->cdr |= divider / 2 - 1;
		else
			priv->cdr |= CDR_CLKOUT_MASK;
	} else {
		priv->cdr |= CDR_CLK_OFF; /* default */
	}

	prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
	if (!prop)
		priv->cdr |= CDR_CBP; /* default */

	priv->irq_flags = IRQF_SHARED;
	priv->reg_base = base;

	dev->irq = irq;

	dev_info(&ofdev->dev,
		 "reg_base=0x%p irq=%d clock=%d ocr=0x%02x cdr=0x%02x\n",
		 priv->reg_base, dev->irq, priv->can.clock.freq,
		 priv->ocr, priv->cdr);

	dev_set_drvdata(&ofdev->dev, dev);
	SET_NETDEV_DEV(dev, &ofdev->dev);

	err = register_sja1000dev(dev);
	if (err) {
		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
			DRV_NAME, err);
		goto exit_free_sja1000;
	}

	return 0;

exit_free_sja1000:
	free_sja1000dev(dev);
exit_dispose_irq:
	irq_dispose_mapping(irq);
exit_unmap_mem:
	iounmap(base);
exit_release_mem:
	release_mem_region(res.start, res_size);

	return err;
}
コード例 #15
0
static int pcm027_probe(struct platform_device *pdev)
{
	int err, irq;
	void __iomem *addr = 0;
	struct net_device *dev;
	struct sja1000_priv *priv;
	struct resource *res;

	err = -ENODEV;
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	irq = platform_get_irq(pdev, 0);
	if (!res || !irq)
		goto exit;

	err = -EBUSY;
	if (!request_mem_region(res->start, res->end - res->start + 1,
				DRV_NAME)) {
		goto exit;
	}

	err = -ENOMEM;
	addr = ioremap_nocache(res->start, res->end - res->start + 1);
	if (!addr) {
		goto exit_release;
	}

	dev = alloc_sja1000dev(0);
	if (!dev)
		goto exit_iounmap;

	priv = netdev_priv(dev);

	priv->read_reg = pcm027_read_reg;
	priv->write_reg = pcm027_write_reg;
	priv->can.can_sys_clock = PCM027_CAN_CLOCK;
	priv->ocr = PCM027_OCR;
	priv->cdr = PCM027_CDR;

	dev->irq = irq;
	dev->base_addr = (unsigned long)addr;

	dev_set_drvdata(&pdev->dev, dev);

	err = register_sja1000dev(dev);
	if (err) {
		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
			DRV_NAME, err);
		goto exit_free;
	}

	printk("%s: %s device registered (base_addr=%#lx, irq=%d)\n",
	       dev->name, DRV_NAME, dev->base_addr, dev->irq);
	return 0;

exit_free:
	free_sja1000dev(dev);
exit_iounmap:
	iounmap(addr);
exit_release:
	release_mem_region(res->start, res->end - res->start + 1);
exit:
	return err;
}
コード例 #16
0
static int __devinit ems_pcmcia_add_card(struct pcmcia_device *pdev,
					 unsigned long base)
{
	struct sja1000_priv *priv;
	struct net_device *dev;
	struct ems_pcmcia_card *card;
	int err, i;

	/*                                                   */
	card = kzalloc(sizeof(struct ems_pcmcia_card), GFP_KERNEL);
	if (!card)
		return -ENOMEM;

	pdev->priv = card;
	card->channels = 0;

	card->base_addr = ioremap(base, EMS_PCMCIA_MEM_SIZE);
	if (!card->base_addr) {
		err = -ENOMEM;
		goto failure_cleanup;
	}

	/*                                    */
	if (readw(card->base_addr) != 0xAA55) {
		err = -ENODEV;
		goto failure_cleanup;
	}

	/*                     */
	writeb(EMS_CMD_RESET, card->base_addr);

	/*                                                               */
	writeb(EMS_CMD_MAP, card->base_addr);

	/*                           */
	for (i = 0; i < EMS_PCMCIA_MAX_CHAN; i++) {
		dev = alloc_sja1000dev(0);
		if (!dev) {
			err = -ENOMEM;
			goto failure_cleanup;
		}

		card->net_dev[i] = dev;
		priv = netdev_priv(dev);
		priv->priv = card;
		SET_NETDEV_DEV(dev, &pdev->dev);

		priv->irq_flags = IRQF_SHARED;
		dev->irq = pdev->irq;
		priv->reg_base = card->base_addr + EMS_PCMCIA_CAN_BASE_OFFSET +
			(i * EMS_PCMCIA_CAN_CTRL_SIZE);

		/*                             */
		if (ems_pcmcia_check_chan(priv)) {
			priv->read_reg  = ems_pcmcia_read_reg;
			priv->write_reg = ems_pcmcia_write_reg;
			priv->can.clock.freq = EMS_PCMCIA_CAN_CLOCK;
			priv->ocr = EMS_PCMCIA_OCR;
			priv->cdr = EMS_PCMCIA_CDR;
			priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;

			/*                         */
			err = register_sja1000dev(dev);
			if (err) {
				free_sja1000dev(dev);
				goto failure_cleanup;
			}

			card->channels++;

			printk(KERN_INFO "%s: registered %s on channel "
			       "#%d at 0x%p, irq %d\n", DRV_NAME, dev->name,
			       i, priv->reg_base, dev->irq);
		} else
			free_sja1000dev(dev);
	}

	err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
			  DRV_NAME, card);
	if (!err)
		return 0;

failure_cleanup:
	ems_pcmcia_del_card(pdev);
	return err;
}
コード例 #17
0
/*
 * Probe ISA device for EMS CAN signature and register each available
 * CAN channel to SJA1000 Socket-CAN subsystem.
 */
static int __devinit ems_104m_probe(struct device *pdev, unsigned int idx)
{
	struct sja1000_priv *priv;
	struct net_device *dev;
	struct ems_104m_card *card;

	int err, i;

	/* Allocating card structures to hold addresses, ... */
	card = kzalloc(sizeof(struct ems_104m_card), GFP_KERNEL);
	if (card == NULL) {
		dev_err(pdev, "couldn't allocate memory\n");
		return -ENOMEM;
	}

	dev_set_drvdata(pdev, card);

	card->channels = 0;
	card->irq = irq[idx];

	card->base = ioremap_nocache(mem[idx], EMS_104M_MEM_SIZE);
	if (card->base == NULL) {
		dev_err(pdev, "couldn't map memory\n");
		err = -ENOMEM;
		goto failure_cleanup;
	}

	/* Check for unique EMS CAN signature */
	if (readw(card->base) != 0xAA55) {
		dev_err(pdev, "No EMS CPC Card hardware found.\n");

		err = -ENODEV;
		goto failure_cleanup;
	}

	writeb(EMS_CMD_RESET, card->base);

	/* Wait for reset to finish */
	i = 0;
	while (readb(card->base + EMS_104M_CARD_REG_STATUS) == 0x01) {
		/* Check for timeout (50ms.) */
		if (i >= 50) {
			dev_err(pdev, "couldn't reset card.\n");

			err = -EBUSY;
			goto failure_cleanup;
		}

		msleep(1);
	}

	/* Make sure CAN controllers are mapped into card's memory space */
	writeb(EMS_CMD_MAP, card->base);
	writeb(EMS_CMD_MAP, card->base); /* Second call to workaround bug */

	/* Detect available channels */
	for (i = 0; i < EMS_104M_MAX_CHAN; i++) {
		dev = alloc_sja1000dev(0);
		if (dev == NULL) {
			err = -ENOMEM;
			goto failure_cleanup;
		}

		card->net_dev[i] = dev;
		priv = netdev_priv(dev);
		priv->priv = card;
		SET_NETDEV_DEV(dev, pdev);

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
		priv->irq_flags = SA_SHIRQ;
#else
		priv->irq_flags = IRQF_SHARED;
#endif
		dev->irq = irq[idx];
		priv->reg_base = card->base + EMS_104M_CAN_BASE_OFFSET
					+ (i * EMS_104M_CAN_CTRL_SIZE);

		/* Check if channel is present */
		if (ems_104m_check_chan(priv)) {
			priv->read_reg  = ems_104m_read_reg;
			priv->write_reg = ems_104m_write_reg;
			priv->can.clock.freq = EMS_104M_CAN_CLOCK;
			priv->ocr = EMS_104M_OCR;
			priv->cdr = EMS_104M_CDR;
			priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;

			/* Register SJA1000 device */
			err = register_sja1000dev(dev);
			if (err) {
				dev_err(pdev, "registering device failed"
				    " (err=%d)\n", err);
				free_sja1000dev(dev);
				goto failure_cleanup;
			}

			/* Enable interrupts of this channel */
			writeb(0x3 << (i * 2),
			    card->base + EMS_104M_CARD_REG_IRQ_CTRL);

			card->channels++;

			dev_info(pdev, "registered %s on channel at 0x%p,"
			    " irq %d\n", dev->name, priv->reg_base, dev->irq);
		} else {
			free_sja1000dev(dev);
		}
	}

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
	err = request_irq(card->irq, &ems_104m_interrupt, SA_SHIRQ,
		DRV_NAME, (void *)card);
#else
	err = request_irq(card->irq, &ems_104m_interrupt, IRQF_SHARED,
		DRV_NAME, (void *)card);
#endif

	if (err) {
		dev_err(pdev, "registering device failed (err=%d)\n", err);
		goto failure_cleanup;
	}

	return 0;

failure_cleanup:
	dev_err(pdev, "error: %d. Cleaning Up.\n", err);

	if (card->base)
		iounmap(card->base);

	kfree(card);

	return err;
}
コード例 #18
0
ファイル: plx_pci.c プロジェクト: 12rafael/jellytimekernel
/*
 * Probe PLX90xx based device for the SJA1000 chips and register each
 * available CAN channel to SJA1000 Socket-CAN subsystem.
 */
static int __devinit plx_pci_add_card(struct pci_dev *pdev,
				      const struct pci_device_id *ent)
{
	struct sja1000_priv *priv;
	struct net_device *dev;
	struct plx_pci_card *card;
	struct plx_pci_card_info *ci;
	int err, i;
	u32 val;
	void __iomem *addr;

	ci = (struct plx_pci_card_info *)ent->driver_data;

	if (pci_enable_device(pdev) < 0) {
		dev_err(&pdev->dev, "Failed to enable PCI device\n");
		return -ENODEV;
	}

	dev_info(&pdev->dev, "Detected \"%s\" card at slot #%i\n",
		 ci->name, PCI_SLOT(pdev->devfn));

	/* Allocate card structures to hold addresses, ... */
	card = kzalloc(sizeof(*card), GFP_KERNEL);
	if (!card) {
		dev_err(&pdev->dev, "Unable to allocate memory\n");
		pci_disable_device(pdev);
		return -ENOMEM;
	}

	pci_set_drvdata(pdev, card);

	card->channels = 0;

	/* Remap PLX90xx configuration space */
	addr = pci_iomap(pdev, ci->conf_map.bar, ci->conf_map.size);
	if (!addr) {
		err = -ENOMEM;
		dev_err(&pdev->dev, "Failed to remap configuration space "
			"(BAR%d)\n", ci->conf_map.bar);
		goto failure_cleanup;
	}
	card->conf_addr = addr + ci->conf_map.offset;

	ci->reset_func(pdev);
	card->reset_func = ci->reset_func;

	/* Detect available channels */
	for (i = 0; i < ci->channel_count; i++) {
		struct plx_pci_channel_map *cm = &ci->chan_map_tbl[i];

		dev = alloc_sja1000dev(0);
		if (!dev) {
			err = -ENOMEM;
			goto failure_cleanup;
		}

		card->net_dev[i] = dev;
		priv = netdev_priv(dev);
		priv->priv = card;
		priv->irq_flags = IRQF_SHARED;

		dev->irq = pdev->irq;

		/*
		 * Remap IO space of the SJA1000 chips
		 * This is device-dependent mapping
		 */
		addr = pci_iomap(pdev, cm->bar, cm->size);
		if (!addr) {
			err = -ENOMEM;
			dev_err(&pdev->dev, "Failed to remap BAR%d\n", cm->bar);
			goto failure_cleanup;
		}

		priv->reg_base = addr + cm->offset;
		priv->read_reg = plx_pci_read_reg;
		priv->write_reg = plx_pci_write_reg;

		/* Check if channel is present */
		if (plx_pci_check_sja1000(priv)) {
			priv->can.clock.freq = ci->can_clock;
			priv->ocr = ci->ocr;
			priv->cdr = ci->cdr;

			SET_NETDEV_DEV(dev, &pdev->dev);

			/* Register SJA1000 device */
			err = register_sja1000dev(dev);
			if (err) {
				dev_err(&pdev->dev, "Registering device failed "
					"(err=%d)\n", err);
				free_sja1000dev(dev);
				goto failure_cleanup;
			}

			card->channels++;

			dev_info(&pdev->dev, "Channel #%d at 0x%p, irq %d "
				 "registered as %s\n", i + 1, priv->reg_base,
				 dev->irq, dev->name);
		} else {
			dev_err(&pdev->dev, "Channel #%d not detected\n",
				i + 1);
			free_sja1000dev(dev);
		}
	}

	if (!card->channels) {
		err = -ENODEV;
		goto failure_cleanup;
	}

	/*
	 * Enable interrupts from PCI-card (PLX90xx) and enable Local_1,
	 * Local_2 interrupts from the SJA1000 chips
	 */
	if (pdev->device != PCI_DEVICE_ID_PLX_9056) {
		val = ioread32(card->conf_addr + PLX_INTCSR);
		if (pdev->subsystem_vendor == PCI_VENDOR_ID_ESDGMBH)
			val |= PLX_LINT1_EN | PLX_PCI_INT_EN;
		else
			val |= PLX_LINT1_EN | PLX_LINT2_EN | PLX_PCI_INT_EN;
		iowrite32(val, card->conf_addr + PLX_INTCSR);
	} else {
		iowrite32(PLX9056_LINTI | PLX9056_PCI_INT_EN,
			  card->conf_addr + PLX9056_INTCSR);
	}
	return 0;

failure_cleanup:
	dev_err(&pdev->dev, "Error: %d. Cleaning Up.\n", err);

	plx_pci_del_card(pdev);

	return err;
}
コード例 #19
0
/*
 * Probe PCI device for EMS CAN signature and register each available
 * CAN channel to SJA1000 Socket-CAN subsystem.
 */
static int __devinit ems_pci_add_card(struct pci_dev *pdev,
					const struct pci_device_id *ent)
{
	struct sja1000_priv *priv;
	struct net_device *dev;
	struct ems_pci_card *card;
	int max_chan, conf_size, base_bar;
	int err, i;

	/* Enabling PCI device */
	if (pci_enable_device(pdev) < 0) {
		dev_err(&pdev->dev, "Enabling PCI device failed\n");
		return -ENODEV;
	}

	/* Allocating card structures to hold addresses, ... */
	card = kzalloc(sizeof(struct ems_pci_card), GFP_KERNEL);
	if (card == NULL) {
		dev_err(&pdev->dev, "Unable to allocate memory\n");
		pci_disable_device(pdev);
		return -ENOMEM;
	}

	pci_set_drvdata(pdev, card);

	card->pci_dev = pdev;

	card->channels = 0;

	if (pdev->vendor == PCI_VENDOR_ID_PLX) {
		card->version = 2; /* CPC-PCI v2 */
		max_chan = EMS_PCI_V2_MAX_CHAN;
		base_bar = EMS_PCI_V2_BASE_BAR;
		conf_size = EMS_PCI_V2_CONF_SIZE;
	} else {
		card->version = 1; /* CPC-PCI v1 */
		max_chan = EMS_PCI_V1_MAX_CHAN;
		base_bar = EMS_PCI_V1_BASE_BAR;
		conf_size = EMS_PCI_V1_CONF_SIZE;
	}

	/* Remap configuration space and controller memory area */
	card->conf_addr = pci_iomap(pdev, 0, conf_size);
	if (card->conf_addr == NULL) {
		err = -ENOMEM;
		goto failure_cleanup;
	}

	card->base_addr = pci_iomap(pdev, base_bar, EMS_PCI_BASE_SIZE);
	if (card->base_addr == NULL) {
		err = -ENOMEM;
		goto failure_cleanup;
	}

	if (card->version == 1) {
		/* Configure PITA-2 parallel interface (enable MUX) */
		writel(PITA2_MISC_CONFIG, card->conf_addr + PITA2_MISC);

		/* Check for unique EMS CAN signature */
		if (ems_pci_v1_readb(card, 0) != 0x55 ||
		    ems_pci_v1_readb(card, 1) != 0xAA ||
		    ems_pci_v1_readb(card, 2) != 0x01 ||
		    ems_pci_v1_readb(card, 3) != 0xCB ||
		    ems_pci_v1_readb(card, 4) != 0x11) {
			dev_err(&pdev->dev,
				"Not EMS Dr. Thomas Wuensche interface\n");
			err = -ENODEV;
			goto failure_cleanup;
		}
	}

	ems_pci_card_reset(card);

	/* Detect available channels */
	for (i = 0; i < max_chan; i++) {
		dev = alloc_sja1000dev(0);
		if (dev == NULL) {
			err = -ENOMEM;
			goto failure_cleanup;
		}

		card->net_dev[i] = dev;
		priv = netdev_priv(dev);
		priv->priv = card;
		priv->irq_flags = IRQF_SHARED;

		dev->irq = pdev->irq;
		priv->reg_base = card->base_addr + EMS_PCI_CAN_BASE_OFFSET
					+ (i * EMS_PCI_CAN_CTRL_SIZE);
		if (card->version == 1) {
			priv->read_reg  = ems_pci_v1_read_reg;
			priv->write_reg = ems_pci_v1_write_reg;
			priv->post_irq  = ems_pci_v1_post_irq;
		} else {
			priv->read_reg  = ems_pci_v2_read_reg;
			priv->write_reg = ems_pci_v2_write_reg;
			priv->post_irq  = ems_pci_v2_post_irq;
		}

		/* Check if channel is present */
		if (ems_pci_check_chan(priv)) {
			priv->can.clock.freq = EMS_PCI_CAN_CLOCK;
			priv->ocr = EMS_PCI_OCR;
			priv->cdr = EMS_PCI_CDR;

			SET_NETDEV_DEV(dev, &pdev->dev);

			if (card->version == 1)
				/* reset int flag of pita */
				writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0,
				       card->conf_addr + PITA2_ICR);
			else
				/* enable IRQ in PLX 9030 */
				writel(PLX_ICSR_ENA_CLR,
				       card->conf_addr + PLX_ICSR);

			/* Register SJA1000 device */
			err = register_sja1000dev(dev);
			if (err) {
				dev_err(&pdev->dev, "Registering device failed "
							"(err=%d)\n", err);
				free_sja1000dev(dev);
				goto failure_cleanup;
			}

			card->channels++;

			dev_info(&pdev->dev, "Channel #%d at 0x%p, irq %d\n",
					i + 1, priv->reg_base, dev->irq);
		} else {
			free_sja1000dev(dev);
		}
	}

	return 0;

failure_cleanup:
	dev_err(&pdev->dev, "Error: %d. Cleaning Up.\n", err);

	ems_pci_del_card(pdev);

	return err;
}
コード例 #20
0
static int sp_probe(struct platform_device *pdev)
{
	int err;
	void __iomem *addr;
	struct net_device *dev;
	struct sja1000_priv *priv;
	struct resource *res_mem, *res_irq;
	struct sja1000_platform_data *pdata;

	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "No platform data provided!\n");
		err = -ENODEV;
		goto exit;
	}

	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res_mem || !res_irq) {
		err = -ENODEV;
		goto exit;
	}

	if (!request_mem_region(res_mem->start, resource_size(res_mem),
				DRV_NAME)) {
		err = -EBUSY;
		goto exit;
	}

	addr = ioremap_nocache(res_mem->start, resource_size(res_mem));
	if (!addr) {
		err = -ENOMEM;
		goto exit_release;
	}

	dev = alloc_sja1000dev(0);
	if (!dev) {
		err = -ENOMEM;
		goto exit_iounmap;
	}
	priv = netdev_priv(dev);

	dev->irq = res_irq->start;
	priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
	priv->reg_base = addr;
	priv->read_reg = sp_read_reg;
	priv->write_reg = sp_write_reg;
	priv->can.clock.freq = pdata->clock;
	priv->ocr = pdata->ocr;
	priv->cdr = pdata->cdr;

	dev_set_drvdata(&pdev->dev, dev);
	SET_NETDEV_DEV(dev, &pdev->dev);

	err = register_sja1000dev(dev);
	if (err) {
		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
			DRV_NAME, err);
		goto exit_free;
	}

	dev_info(&pdev->dev, "%s device registered (reg_base=%p, irq=%d)\n",
		 DRV_NAME, priv->reg_base, dev->irq);
	return 0;

 exit_free:
	free_sja1000dev(dev);
 exit_iounmap:
	iounmap(addr);
 exit_release:
	release_mem_region(res_mem->start, resource_size(res_mem));
 exit:
	return err;
}
コード例 #21
0
static int pcan_add_channels(struct pcan_pccard *card)
{
	struct pcmcia_device *pdev = card->pdev;
	int i, err = 0;
	u8 ccr = PCC_CCR_INIT;

	
	card->ccr = ~ccr;
	pcan_write_reg(card, PCC_CCR, ccr);

	
	mdelay(2);

	ccr &= ~PCC_CCR_RST_ALL;
	pcan_write_reg(card, PCC_CCR, ccr);

	
	for (i = 0; i < ARRAY_SIZE(card->channel); i++) {
		struct net_device *netdev;
		struct sja1000_priv *priv;

		netdev = alloc_sja1000dev(0);
		if (!netdev) {
			err = -ENOMEM;
			break;
		}

		
		priv = netdev_priv(netdev);
		priv->priv = card;
		SET_NETDEV_DEV(netdev, &pdev->dev);

		priv->irq_flags = IRQF_SHARED;
		netdev->irq = pdev->irq;
		priv->reg_base = card->ioport_addr + PCC_CHAN_OFF(i);

		
		if (!pcan_channel_present(priv)) {
			dev_err(&pdev->dev, "channel %d not present\n", i);
			free_sja1000dev(netdev);
			continue;
		}

		priv->read_reg  = pcan_read_canreg;
		priv->write_reg = pcan_write_canreg;
		priv->can.clock.freq = PCC_CAN_CLOCK;
		priv->ocr = PCC_OCR;
		priv->cdr = PCC_CDR;

		
		if (i > 0)
			priv->cdr |= CDR_CLK_OFF;

		priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;

		
		err = register_sja1000dev(netdev);
		if (err) {
			free_sja1000dev(netdev);
			continue;
		}

		card->channel[i].netdev = netdev;
		card->chan_count++;

		
		ccr &= ~PCC_CCR_LED_OFF_CHAN(i);

		dev_info(&pdev->dev,
			"%s on channel %d at 0x%p irq %d\n",
			netdev->name, i, priv->reg_base, pdev->irq);
	}

	
	pcan_write_reg(card, PCC_CCR, ccr);

	return err;
}
コード例 #22
0
ファイル: tscan1.c プロジェクト: avagin/linux
/* Probe for a TS-CAN1 board with JP2:JP1 jumper setting ID */
static int tscan1_probe(struct device *dev, unsigned id)
{
	struct net_device *netdev;
	struct sja1000_priv *priv;
	unsigned long pld_base, sja1000_base;
	int irq, i;

	pld_base = TSCAN1_PLD_ADDRESS + id * TSCAN1_PLD_SIZE;
	if (!request_region(pld_base, TSCAN1_PLD_SIZE, dev_name(dev)))
		return -EBUSY;

	if (inb(pld_base + TSCAN1_ID1) != TSCAN1_ID1_VALUE ||
	    inb(pld_base + TSCAN1_ID2) != TSCAN1_ID2_VALUE) {
		release_region(pld_base, TSCAN1_PLD_SIZE);
		return -ENODEV;
	}

	switch (inb(pld_base + TSCAN1_JUMPERS) & (TSCAN1_JP4 | TSCAN1_JP5)) {
	case TSCAN1_JP4:
		irq = 6;
		break;
	case TSCAN1_JP5:
		irq = 7;
		break;
	case TSCAN1_JP4 | TSCAN1_JP5:
		irq = 5;
		break;
	default:
		dev_err(dev, "invalid JP4:JP5 setting (no IRQ)\n");
		release_region(pld_base, TSCAN1_PLD_SIZE);
		return -EINVAL;
	}

	netdev = alloc_sja1000dev(0);
	if (!netdev) {
		release_region(pld_base, TSCAN1_PLD_SIZE);
		return -ENOMEM;
	}

	dev_set_drvdata(dev, netdev);
	SET_NETDEV_DEV(netdev, dev);

	netdev->base_addr = pld_base;
	netdev->irq = irq;

	priv = netdev_priv(netdev);
	priv->read_reg = tscan1_read;
	priv->write_reg = tscan1_write;
	priv->can.clock.freq = TSCAN1_SJA1000_XTAL / 2;
	priv->cdr = CDR_CBP | CDR_CLK_OFF;
	priv->ocr = OCR_TX0_PUSHPULL;

	/* Select the first SJA1000 IO address that is free and that works */
	for (i = 0; i < ARRAY_SIZE(tscan1_sja1000_addresses); i++) {
		sja1000_base = tscan1_sja1000_addresses[i];
		if (!request_region(sja1000_base, TSCAN1_SJA1000_SIZE,
								dev_name(dev)))
			continue;

		/* Set SJA1000 IO base address and enable it */
		outb(TSCAN1_MODE_ENABLE | i, pld_base + TSCAN1_MODE);

		priv->reg_base = (void __iomem *)sja1000_base;
		if (!register_sja1000dev(netdev)) {
			/* SJA1000 probe succeeded; turn LED off and return */
			outb(0, pld_base + TSCAN1_LED);
			netdev_info(netdev, "TS-CAN1 at 0x%lx 0x%lx irq %d\n",
						pld_base, sja1000_base, irq);
			return 0;
		}

		/* SJA1000 probe failed; release and try next address */
		outb(0, pld_base + TSCAN1_MODE);
		release_region(sja1000_base, TSCAN1_SJA1000_SIZE);
	}

	dev_err(dev, "failed to assign SJA1000 IO address\n");
	dev_set_drvdata(dev, NULL);
	free_sja1000dev(netdev);
	release_region(pld_base, TSCAN1_PLD_SIZE);
	return -ENXIO;
}
コード例 #23
0
ファイル: peak_pci.c プロジェクト: 020gzh/linux
static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct sja1000_priv *priv;
	struct peak_pci_chan *chan;
	struct net_device *dev, *prev_dev;
	void __iomem *cfg_base, *reg_base;
	u16 sub_sys_id, icr;
	int i, err, channels;

	err = pci_enable_device(pdev);
	if (err)
		return err;

	err = pci_request_regions(pdev, DRV_NAME);
	if (err)
		goto failure_disable_pci;

	err = pci_read_config_word(pdev, 0x2e, &sub_sys_id);
	if (err)
		goto failure_release_regions;

	dev_dbg(&pdev->dev, "probing device %04x:%04x:%04x\n",
		pdev->vendor, pdev->device, sub_sys_id);

	err = pci_write_config_word(pdev, 0x44, 0);
	if (err)
		goto failure_release_regions;

	if (sub_sys_id >= 12)
		channels = 4;
	else if (sub_sys_id >= 10)
		channels = 3;
	else if (sub_sys_id >= 4)
		channels = 2;
	else
		channels = 1;

	cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE);
	if (!cfg_base) {
		dev_err(&pdev->dev, "failed to map PCI resource #0\n");
		err = -ENOMEM;
		goto failure_release_regions;
	}

	reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels);
	if (!reg_base) {
		dev_err(&pdev->dev, "failed to map PCI resource #1\n");
		err = -ENOMEM;
		goto failure_unmap_cfg_base;
	}

	/* Set GPIO control register */
	writew(0x0005, cfg_base + PITA_GPIOICR + 2);
	/* Enable all channels of this card */
	writeb(0x00, cfg_base + PITA_GPIOICR);
	/* Toggle reset */
	writeb(0x05, cfg_base + PITA_MISC + 3);
	mdelay(5);
	/* Leave parport mux mode */
	writeb(0x04, cfg_base + PITA_MISC + 3);

	icr = readw(cfg_base + PITA_ICR + 2);

	for (i = 0; i < channels; i++) {
		dev = alloc_sja1000dev(sizeof(struct peak_pci_chan));
		if (!dev) {
			err = -ENOMEM;
			goto failure_remove_channels;
		}

		priv = netdev_priv(dev);
		chan = priv->priv;

		chan->cfg_base = cfg_base;
		priv->reg_base = reg_base + i * PEAK_PCI_CHAN_SIZE;

		priv->read_reg = peak_pci_read_reg;
		priv->write_reg = peak_pci_write_reg;
		priv->post_irq = peak_pci_post_irq;

		priv->can.clock.freq = PEAK_PCI_CAN_CLOCK;
		priv->ocr = PEAK_PCI_OCR;
		priv->cdr = PEAK_PCI_CDR;
		/* Neither a slave nor a single device distributes the clock */
		if (channels == 1 || i > 0)
			priv->cdr |= CDR_CLK_OFF;

		/* Setup interrupt handling */
		priv->irq_flags = IRQF_SHARED;
		dev->irq = pdev->irq;

		chan->icr_mask = peak_pci_icr_masks[i];
		icr |= chan->icr_mask;

		SET_NETDEV_DEV(dev, &pdev->dev);
		dev->dev_id = i;

		/* Create chain of SJA1000 devices */
		chan->prev_dev = pci_get_drvdata(pdev);
		pci_set_drvdata(pdev, dev);

		/*
		 * PCAN-ExpressCard needs some additional i2c init.
		 * This must be done *before* register_sja1000dev() but
		 * *after* devices linkage
		 */
		if (pdev->device == PEAK_PCIEC_DEVICE_ID ||
		    pdev->device == PEAK_PCIEC34_DEVICE_ID) {
			err = peak_pciec_probe(pdev, dev);
			if (err) {
				dev_err(&pdev->dev,
					"failed to probe device (err %d)\n",
					err);
				goto failure_free_dev;
			}
		}

		err = register_sja1000dev(dev);
		if (err) {
			dev_err(&pdev->dev, "failed to register device\n");
			goto failure_free_dev;
		}

		dev_info(&pdev->dev,
			 "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",
			 dev->name, priv->reg_base, chan->cfg_base, dev->irq);
	}

	/* Enable interrupts */
	writew(icr, cfg_base + PITA_ICR + 2);

	return 0;

failure_free_dev:
	pci_set_drvdata(pdev, chan->prev_dev);
	free_sja1000dev(dev);

failure_remove_channels:
	/* Disable interrupts */
	writew(0x0, cfg_base + PITA_ICR + 2);

	chan = NULL;
	for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) {
		priv = netdev_priv(dev);
		chan = priv->priv;
		prev_dev = chan->prev_dev;

		unregister_sja1000dev(dev);
		free_sja1000dev(dev);
	}

	/* free any PCIeC resources too */
	if (chan && chan->pciec_card)
		peak_pciec_remove(chan->pciec_card);

	pci_iounmap(pdev, reg_base);

failure_unmap_cfg_base:
	pci_iounmap(pdev, cfg_base);

failure_release_regions:
	pci_release_regions(pdev);

failure_disable_pci:
	pci_disable_device(pdev);

	return err;
}