示例#1
0
static int __devinit ddb_probe(struct pci_dev *pdev,
			       const struct pci_device_id *id)
{
	struct ddb *dev;
	int stat = 0;
	int irq_flag = IRQF_SHARED;

	if (pci_enable_device(pdev) < 0)
		return -ENODEV;

	dev = vzalloc(sizeof(struct ddb));
	if (dev == NULL)
		return -ENOMEM;

	dev->has_dma = 1;
	dev->pdev = pdev;
	dev->dev = &pdev->dev;
	pci_set_drvdata(pdev, dev);

	dev->ids.vendor = id->vendor;
	dev->ids.device = id->device;
	dev->ids.subvendor = id->subvendor;
	dev->ids.subdevice = id->subdevice;

	dev->info = (struct ddb_info *) id->driver_data;
	pr_info("DDBridge driver detected: %s\n", dev->info->name);

	dev->regs_len = pci_resource_len(dev->pdev, 0);
	dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
			    pci_resource_len(dev->pdev, 0));
	if (!dev->regs) {
		pr_err("DDBridge: not enough memory for register map\n");
		stat = -ENOMEM;
		goto fail;
	}
	if (ddbreadl(dev, 0) == 0xffffffff) {
		pr_err("DDBridge: cannot read registers\n");
		stat = -ENODEV;
		goto fail;
	}

	dev->ids.hwid = ddbreadl(dev, 0);
	dev->ids.regmapid = ddbreadl(dev, 4);

	pr_info("HW %08x REGMAP %08x\n",
		dev->ids.hwid, dev->ids.regmapid);

	ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
	ddbwritel(dev, 0x00000000, MSI1_ENABLE);
	ddbwritel(dev, 0x00000000, MSI2_ENABLE);
	ddbwritel(dev, 0x00000000, MSI3_ENABLE);
	ddbwritel(dev, 0x00000000, MSI4_ENABLE);
	ddbwritel(dev, 0x00000000, MSI5_ENABLE);
	ddbwritel(dev, 0x00000000, MSI6_ENABLE);
	ddbwritel(dev, 0x00000000, MSI7_ENABLE);

#ifdef CONFIG_PCI_MSI
	if (msi && pci_msi_enabled()) {
		stat = pci_enable_msi_block(dev->pdev, 2);
		if (stat == 0) {
			dev->msi = 1;
			pr_info("DDBrige using 2 MSI interrupts\n");
		}
		if (stat == 1)
			stat = pci_enable_msi(dev->pdev);
		if (stat < 0) {
			pr_info(": MSI not available.\n");
		} else {
			irq_flag = 0;
			dev->msi++;
		}
	}
	if (dev->msi == 2) {
		stat = request_irq(dev->pdev->irq, irq_handler0,
				   irq_flag, "ddbridge", (void *) dev);
		if (stat < 0)
			goto fail0;
		stat = request_irq(dev->pdev->irq + 1, irq_handler1,
				   irq_flag, "ddbridge", (void *) dev);
		if (stat < 0) {
			free_irq(dev->pdev->irq, dev);
			goto fail0;
		}
	} else
#endif
	{
#ifdef DDB_TEST_THREADED
		stat = request_threaded_irq(dev->pdev->irq, irq_handler,
					    irq_thread,
					    irq_flag,
					    "ddbridge", (void *) dev);
#else
		stat = request_irq(dev->pdev->irq, irq_handler,
				   irq_flag, "ddbridge", (void *) dev);
#endif
		if (stat < 0)
			goto fail0;
	}
	ddbwritel(dev, 0, DMA_BASE_READ);
	if (dev->info->type != DDB_MOD)
		ddbwritel(dev, 0, DMA_BASE_WRITE);

	/*ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);*/
	if (dev->msi == 2) {
		ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE);
		ddbwritel(dev, 0x0000000f, MSI1_ENABLE);
	} else {
		ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);
		ddbwritel(dev, 0x00000000, MSI1_ENABLE);
	}
	if (ddb_i2c_init(dev) < 0)
		goto fail1;
	ddb_ports_init(dev);
	if (ddb_buffers_alloc(dev) < 0) {
		pr_info(": Could not allocate buffer memory\n");
		goto fail2;
	}
	if (ddb_ports_attach(dev) < 0)
		goto fail3;

	/* ignore if this fails */
	ddb_device_create(dev);

	if (dev->info->fan_num)	{
		ddbwritel(dev, 1, GPIO_DIRECTION);
		ddbwritel(dev, 1, GPIO_OUTPUT);
	}
	if (dev->info->type == DDB_MOD)
		ddbridge_mod_init(dev);

	return 0;

fail3:
	ddb_ports_detach(dev);
	pr_err("fail3\n");
	ddb_ports_release(dev);
fail2:
	pr_err("fail2\n");
	ddb_buffers_free(dev);
	ddb_i2c_release(dev);
fail1:
	pr_err("fail1\n");
	ddbwritel(dev, 0, INTERRUPT_ENABLE);
	ddbwritel(dev, 0, MSI1_ENABLE);
	free_irq(dev->pdev->irq, dev);
	if (dev->msi == 2)
		free_irq(dev->pdev->irq + 1, dev);
fail0:
	pr_err("fail0\n");
	if (dev->msi)
		pci_disable_msi(dev->pdev);
fail:
	pr_err("fail\n");
	ddb_unmap(dev);
	pci_set_drvdata(pdev, 0);
	pci_disable_device(pdev);
	return -1;
}
示例#2
0
文件: octonet.c 项目: cesbo/dddvb
static int __init octonet_probe(struct platform_device *pdev)
{
	struct ddb *dev;
	struct resource *regs;
	int irq;

	dev = vzalloc(sizeof(struct ddb));
	if (!dev)
		return -ENOMEM;
	platform_set_drvdata(pdev, dev);
	dev->dev = &pdev->dev;
	dev->pfdev = pdev;

	mutex_init(&dev->mutex);
	regs = platform_get_resource(dev->pfdev, IORESOURCE_MEM, 0);
	if (!regs)
		return -ENXIO;
	dev->regs_len = (regs->end - regs->start) + 1;
	dev_info(dev->dev, "regs_start=%08x regs_len=%08x\n",
		 (u32) regs->start, (u32) dev->regs_len);
	dev->regs = ioremap(regs->start, dev->regs_len);

	if (!dev->regs) {
		dev_err(dev->dev, "ioremap failed\n");
		return -ENOMEM;
	}

	dev->link[0].ids.hwid = ddbreadl(dev, 0);
	dev->link[0].ids.regmapid = ddbreadl(dev, 4);
	dev->link[0].ids.devid = ddbreadl(dev, 8);
	dev->link[0].ids.mac = ddbreadl(dev, 12);

	dev->link[0].ids.vendor = dev->link[0].ids.devid & 0xffff;
	dev->link[0].ids.device = dev->link[0].ids.devid >> 16;
	dev->link[0].ids.subvendor = dev->link[0].ids.devid & 0xffff;
	dev->link[0].ids.subdevice = dev->link[0].ids.devid >> 16;

	dev->link[0].dev = dev;
	if (dev->link[0].ids.devid == 0x0300dd01)
		dev->link[0].info = &ddb_octonet;
	else if (dev->link[0].ids.devid == 0x0301dd01)
		dev->link[0].info = &ddb_octonet_jse;
	else if (dev->link[0].ids.devid == 0x0307dd01)
		dev->link[0].info = &ddb_octonet_gtl;
	else
		dev->link[0].info = &ddb_octonet_tbd;

	pr_info("HW  %08x REGMAP %08x\n",
		dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
	pr_info("MAC %08x DEVID  %08x\n",
		dev->link[0].ids.mac, dev->link[0].ids.devid);

	ddbwritel(dev, 0, ETHER_CONTROL);
	ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
	ddbwritel(dev, 0xffffffff, INTERRUPT_STATUS);
	ddb_reset_ios(dev);

	irq = platform_get_irq(dev->pfdev, 0);
	if (irq < 0)
		goto fail;
	if (request_irq(irq, irq_handler,
			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
			"octonet-dvb", (void *) dev) < 0)
		goto fail;
	ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);

	if (ddb_init(dev) == 0)
		return 0;

fail:
	dev_err(dev->dev, "fail\n");
	ddbwritel(dev, 0, ETHER_CONTROL);
	ddbwritel(dev, 0, INTERRUPT_ENABLE);
	octonet_unmap(dev);
	platform_set_drvdata(pdev, 0);
	return -1;
}