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;
}
}