static int __init init_pmc551()

in devices/pmc551.c [651:815]


static int __init init_pmc551(void)
{
	struct pci_dev *PCI_Device = NULL;
	struct mypriv *priv;
	int found = 0;
	struct mtd_info *mtd;
	int length = 0;

	if (msize) {
		msize = (1 << (ffs(msize) - 1)) << 20;
		if (msize > (1 << 30)) {
			printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n",
				msize);
			return -EINVAL;
		}
	}

	if (asize) {
		asize = (1 << (ffs(asize) - 1)) << 20;
		if (asize > (1 << 30)) {
			printk(KERN_NOTICE "pmc551: Invalid aperture size "
				"[%d]\n", asize);
			return -EINVAL;
		}
	}

	printk(KERN_INFO PMC551_VERSION);

	/*
	 * PCU-bus chipset probe.
	 */
	for (;;) {

		if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI,
						  PCI_DEVICE_ID_V3_SEMI_V370PDC,
						  PCI_Device)) == NULL) {
			break;
		}

		printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n",
			(unsigned long long)pci_resource_start(PCI_Device, 0));

		/*
		 * The PMC551 device acts VERY weird if you don't init it
		 * first.  i.e. it will not correctly report devsel.  If for
		 * some reason the sdram is in a wrote-protected state the
		 * device will DEVSEL when it is written to causing problems
		 * with the oldproc.c driver in
		 * some kernels (2.2.*)
		 */
		if ((length = fixup_pmc551(PCI_Device)) <= 0) {
			printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
			break;
		}

		/*
		 * This is needed until the driver is capable of reading the
		 * onboard I2C SROM to discover the "real" memory size.
		 */
		if (msize) {
			length = msize;
			printk(KERN_NOTICE "pmc551: Using specified memory "
				"size 0x%x\n", length);
		} else {
			msize = length;
		}

		mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
		if (!mtd)
			break;

		priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL);
		if (!priv) {
			kfree(mtd);
			break;
		}
		mtd->priv = priv;
		priv->dev = PCI_Device;

		if (asize > length) {
			printk(KERN_NOTICE "pmc551: reducing aperture size to "
				"fit %dM\n", length >> 20);
			priv->asize = asize = length;
		} else if (asize == 0 || asize == length) {
			printk(KERN_NOTICE "pmc551: Using existing aperture "
				"size %dM\n", length >> 20);
			priv->asize = asize = length;
		} else {
			printk(KERN_NOTICE "pmc551: Using specified aperture "
				"size %dM\n", asize >> 20);
			priv->asize = asize;
		}
		priv->start = pci_iomap(PCI_Device, 0, priv->asize);

		if (!priv->start) {
			printk(KERN_NOTICE "pmc551: Unable to map IO space\n");
			kfree(mtd->priv);
			kfree(mtd);
			break;
		}
#ifdef CONFIG_MTD_PMC551_DEBUG
		printk(KERN_DEBUG "pmc551: setting aperture to %d\n",
			ffs(priv->asize >> 20) - 1);
#endif

		priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN
				   | PMC551_PCI_MEM_MAP_ENABLE
				   | (ffs(priv->asize >> 20) - 1) << 4);
		priv->curr_map0 = priv->base_map0;
		pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0,
					priv->curr_map0);

#ifdef CONFIG_MTD_PMC551_DEBUG
		printk(KERN_DEBUG "pmc551: aperture set to %d\n",
			(priv->base_map0 & 0xF0) >> 4);
#endif

		mtd->size = msize;
		mtd->flags = MTD_CAP_RAM;
		mtd->_erase = pmc551_erase;
		mtd->_read = pmc551_read;
		mtd->_write = pmc551_write;
		mtd->_point = pmc551_point;
		mtd->_unpoint = pmc551_unpoint;
		mtd->type = MTD_RAM;
		mtd->name = "PMC551 RAM board";
		mtd->erasesize = 0x10000;
		mtd->writesize = 1;
		mtd->owner = THIS_MODULE;

		if (mtd_device_register(mtd, NULL, 0)) {
			printk(KERN_NOTICE "pmc551: Failed to register new device\n");
			pci_iounmap(PCI_Device, priv->start);
			kfree(mtd->priv);
			kfree(mtd);
			break;
		}

		/* Keep a reference as the mtd_device_register worked */
		pci_dev_get(PCI_Device);

		printk(KERN_NOTICE "Registered pmc551 memory device.\n");
		printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
			priv->asize >> 20,
			priv->start, priv->start + priv->asize);
		printk(KERN_NOTICE "Total memory is %d%sB\n",
			(length < 1024) ? length :
			(length < 1048576) ? length >> 10 : length >> 20,
			(length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
		priv->nextpmc551 = pmc551list;
		pmc551list = mtd;
		found++;
	}

	/* Exited early, reference left over */
	pci_dev_put(PCI_Device);

	if (!pmc551list) {
		printk(KERN_NOTICE "pmc551: not detected\n");
		return -ENODEV;
	} else {
		printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
		return 0;
	}
}