static int chameleon_parse_gdd()

in mcb-parse.c [36:114]


static int chameleon_parse_gdd(struct mcb_bus *bus,
			struct chameleon_bar *cb,
			void __iomem *base, int bar_count)
{
	struct chameleon_gdd __iomem *gdd =
		(struct chameleon_gdd __iomem *) base;
	struct mcb_device *mdev;
	u32 dev_mapbase;
	u32 offset;
	u32 size;
	int ret;
	__le32 reg1;
	__le32 reg2;

	mdev = mcb_alloc_dev(bus);
	if (!mdev)
		return -ENOMEM;

	reg1 = readl(&gdd->reg1);
	reg2 = readl(&gdd->reg2);
	offset = readl(&gdd->offset);
	size = readl(&gdd->size);

	mdev->id = GDD_DEV(reg1);
	mdev->rev = GDD_REV(reg1);
	mdev->var = GDD_VAR(reg1);
	mdev->bar = GDD_BAR(reg2);
	mdev->group = GDD_GRP(reg2);
	mdev->inst = GDD_INS(reg2);

	/*
	 * If the BAR is missing, dev_mapbase is zero, or if the
	 * device is IO mapped we just print a warning and go on with the
	 * next device, instead of completely stop the gdd parser
	 */
	if (mdev->bar > bar_count - 1) {
		pr_info("No BAR for 16z%03d\n", mdev->id);
		ret = 0;
		goto err;
	}

	dev_mapbase = cb[mdev->bar].addr;
	if (!dev_mapbase) {
		pr_info("BAR not assigned for 16z%03d\n", mdev->id);
		ret = 0;
		goto err;
	}

	if (dev_mapbase & 0x01) {
		pr_info("IO mapped Device (16z%03d) not yet supported\n",
			mdev->id);
		ret = 0;
		goto err;
	}

	pr_debug("Found a 16z%03d\n", mdev->id);

	mdev->irq.start = GDD_IRQ(reg1);
	mdev->irq.end = GDD_IRQ(reg1);
	mdev->irq.flags = IORESOURCE_IRQ;

	mdev->mem.start = dev_mapbase + offset;

	mdev->mem.end = mdev->mem.start + size - 1;
	mdev->mem.flags = IORESOURCE_MEM;

	mdev->is_added = false;

	ret = mcb_device_register(bus, mdev);
	if (ret < 0)
		goto err;

	return 0;

err:
	mcb_free_dev(mdev);

	return ret;
}