in maps/pcmciamtd.c [462:632]
static int pcmciamtd_config(struct pcmcia_device *link)
{
struct pcmciamtd_dev *dev = link->priv;
struct mtd_info *mtd = NULL;
int ret;
int i, j = 0;
static char *probes[] = { "jedec_probe", "cfi_probe" };
int new_name = 0;
pr_debug("link=0x%p\n", link);
card_settings(dev, link, &new_name);
dev->pcmcia_map.phys = NO_XIP;
dev->pcmcia_map.copy_from = pcmcia_copy_from_remap;
dev->pcmcia_map.copy_to = pcmcia_copy_to_remap;
if (dev->pcmcia_map.bankwidth == 1) {
dev->pcmcia_map.read = pcmcia_read8_remap;
dev->pcmcia_map.write = pcmcia_write8_remap;
} else {
dev->pcmcia_map.read = pcmcia_read16_remap;
dev->pcmcia_map.write = pcmcia_write16_remap;
}
if(setvpp == 1)
dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
/* Request a memory window for PCMCIA. Some architeures can map windows
* up to the maximum that PCMCIA can support (64MiB) - this is ideal and
* we aim for a window the size of the whole card - otherwise we try
* smaller windows until we succeed
*/
link->resource[2]->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE;
link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ?
WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
link->resource[2]->start = 0;
link->resource[2]->end = (force_size) ? force_size << 20 :
MAX_PCMCIA_ADDR;
dev->win_size = 0;
do {
int ret;
pr_debug("requesting window with size = %luKiB memspeed = %d\n",
(unsigned long) resource_size(link->resource[2]) >> 10,
mem_speed);
ret = pcmcia_request_window(link, link->resource[2], mem_speed);
pr_debug("ret = %d dev->win_size = %d\n", ret, dev->win_size);
if(ret) {
j++;
link->resource[2]->start = 0;
link->resource[2]->end = (force_size) ?
force_size << 20 : MAX_PCMCIA_ADDR;
link->resource[2]->end >>= j;
} else {
pr_debug("Got window of size %luKiB\n", (unsigned long)
resource_size(link->resource[2]) >> 10);
dev->win_size = resource_size(link->resource[2]);
break;
}
} while (link->resource[2]->end >= 0x1000);
pr_debug("dev->win_size = %d\n", dev->win_size);
if(!dev->win_size) {
dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
pcmciamtd_release(link);
return -ENODEV;
}
pr_debug("Allocated a window of %dKiB\n", dev->win_size >> 10);
/* Get write protect status */
dev->win_base = ioremap(link->resource[2]->start,
resource_size(link->resource[2]));
if(!dev->win_base) {
dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n",
link->resource[2]);
pcmciamtd_release(link);
return -ENODEV;
}
pr_debug("mapped window dev = %p @ %pR, base = %p\n",
dev, link->resource[2], dev->win_base);
dev->offset = 0;
dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2];
dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
if(setvpp == 2) {
link->vpp = dev->vpp;
} else {
link->vpp = 0;
}
link->config_index = 0;
pr_debug("Setting Configuration\n");
ret = pcmcia_enable_device(link);
if (ret != 0) {
if (dev->win_base) {
iounmap(dev->win_base);
dev->win_base = NULL;
}
return -ENODEV;
}
if(mem_type == 1) {
mtd = do_map_probe("map_ram", &dev->pcmcia_map);
} else if(mem_type == 2) {
mtd = do_map_probe("map_rom", &dev->pcmcia_map);
} else {
for(i = 0; i < ARRAY_SIZE(probes); i++) {
pr_debug("Trying %s\n", probes[i]);
mtd = do_map_probe(probes[i], &dev->pcmcia_map);
if(mtd)
break;
pr_debug("FAILED: %s\n", probes[i]);
}
}
if(!mtd) {
pr_debug("Can not find an MTD\n");
pcmciamtd_release(link);
return -ENODEV;
}
dev->mtd_info = mtd;
mtd->owner = THIS_MODULE;
if(new_name) {
int size = 0;
char unit = ' ';
/* Since we are using a default name, make it better by adding
* in the size
*/
if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */
size = mtd->size >> 10;
unit = 'K';
} else {
size = mtd->size >> 20;
unit = 'M';
}
snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card");
}
/* If the memory found is fits completely into the mapped PCMCIA window,
use the faster non-remapping read/write functions */
if(mtd->size <= dev->win_size) {
pr_debug("Using non remapping memory functions\n");
dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
if (dev->pcmcia_map.bankwidth == 1) {
dev->pcmcia_map.read = pcmcia_read8;
dev->pcmcia_map.write = pcmcia_write8;
} else {
dev->pcmcia_map.read = pcmcia_read16;
dev->pcmcia_map.write = pcmcia_write16;
}
dev->pcmcia_map.copy_from = pcmcia_copy_from;
dev->pcmcia_map.copy_to = pcmcia_copy_to;
}
if (mtd_device_register(mtd, NULL, 0)) {
map_destroy(mtd);
dev->mtd_info = NULL;
dev_err(&dev->p_dev->dev,
"Could not register the MTD device\n");
pcmciamtd_release(link);
return -ENODEV;
}
dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name);
return 0;
}