Esempio n. 1
0
static int __devinit generic_onenand_probe(struct device *dev)
{
	struct onenand_info *info;
	struct platform_device *pdev = to_platform_device(dev);
	struct flash_platform_data *pdata = pdev->dev.platform_data;
	struct resource *res = pdev->resource;
	unsigned long size = res->end - res->start + 1;
	int err;

	info = kmalloc(sizeof(struct onenand_info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	memset(info, 0, sizeof(struct onenand_info));

	if (!request_mem_region(res->start, size, dev->driver->name)) {
		err = -EBUSY;
		goto out_free_info;
	}

	info->onenand.base = ioremap(res->start, size);
	if (!info->onenand.base) {
		err = -ENOMEM;
		goto out_release_mem_region;
	}

	info->onenand.mmcontrol = pdata->mmcontrol;

	info->mtd.name = pdev->dev.bus_id;
	info->mtd.priv = &info->onenand;
	info->mtd.owner = THIS_MODULE;

	if (onenand_scan(&info->mtd, 1)) {
		err = -ENXIO;
		goto out_iounmap;
	}

#ifdef CONFIG_MTD_PARTITIONS
	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
	if (err > 0)
		add_mtd_partitions(&info->mtd, info->parts, err);
	else if (err < 0 && pdata->parts)
		add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
	else
#endif
		err = add_mtd_device(&info->mtd);

	dev_set_drvdata(&pdev->dev, info);

	return 0;

out_iounmap:
	iounmap(info->onenand.base);
out_release_mem_region:
	release_mem_region(res->start, size);
out_free_info:
	kfree(info);

	return err;
}
Esempio n. 2
0
static int __init lpc32xx_add_partitions(struct lpc32xx_nand_host *host)
{
#ifdef CONFIG_MTD_PARTITIONS
	struct mtd_info *mtd = &host->mtd;
	struct mtd_partition *partitions = NULL;
	int num_partitions = 0;

#ifdef CONFIG_MTD_CMDLINE_PARTS
	static const char *part_probes[] = { "cmdlinepart", NULL };

	mtd->name = LPC32XX_MODNAME;
	num_partitions = parse_mtd_partitions(mtd, part_probes,
					      &partitions, 0);
#endif
	if ((num_partitions <= 0) && (host->ncfg->partition_info))
		partitions = host->ncfg->partition_info(mtd->size,
			&num_partitions);

	if ((!partitions) || (num_partitions == 0)) {
		dev_err(mtd->dev.parent,"No parititions defined,"
			" or unsupported device.\n");
		return ENXIO;
	}

	return add_mtd_partitions(mtd, partitions, num_partitions);
#else
	return add_mtd_device(mtd);
#endif
}
static int rknand_add_partitions(struct rknand_info *nand_info)
{
#ifdef CONFIG_MTD_CMDLINE_PARTS
    int num_partitions = 0; 

	// 从命令行解析分区的信息
    num_partitions = parse_mtd_partitions(&(rknand_mtd), part_probes, &rknand_parts, 0); 
    NAND_DEBUG(NAND_DEBUG_LEVEL0,"num_partitions = %d\n",num_partitions);
    if(num_partitions > 0) { 
    	int i;
    	for (i = 0; i < num_partitions; i++) 
        {
            rknand_parts[i].offset *= 0x200;
            rknand_parts[i].size   *=0x200;
    	}
        rknand_parts[num_partitions - 1].size = rknand_mtd.size - rknand_parts[num_partitions - 1].offset;
        
		g_num_partitions = num_partitions;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
		return mtd_device_register(&rknand_mtd, rknand_parts, num_partitions);
#else
		return add_mtd_partitions(&(rknand_mtd), rknand_parts, num_partitions);
#endif
    } 
#endif 
    g_num_partitions = 0;
	return 0;
}
/*
 * Initialize FLASH support
 */
static int __init h720x_mtd_init(void)
{

	char	*part_type = NULL;

	h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);

	if (!h720x_map.virt) {
		printk(KERN_ERR "H720x-MTD: ioremap failed\n");
		return -EIO;
	}

	simple_map_init(&h720x_map);

	// Probe for flash bankwidth 4
	printk (KERN_INFO "H720x-MTD probing 32bit FLASH\n");
	mymtd = do_map_probe("cfi_probe", &h720x_map);
	if (!mymtd) {
		printk (KERN_INFO "H720x-MTD probing 16bit FLASH\n");
	    // Probe for bankwidth 2
	    h720x_map.bankwidth = 2;
	    mymtd = do_map_probe("cfi_probe", &h720x_map);
	}

	if (mymtd) {
		mymtd->owner = THIS_MODULE;

<<<<<<< HEAD
		nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
		if (nr_mtd_parts > 0)
			part_type = "command line";
=======
Esempio n. 5
0
static int __init omapflash_probe(struct platform_device *pdev)
{
	int err;
	struct omapflash_info *info;
	struct flash_platform_data *pdata = pdev->dev.platform_data;
	struct resource *res = pdev->resource;
	unsigned long size = res->end - res->start + 1;

	info = kzalloc(sizeof(struct omapflash_info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	if (!request_mem_region(res->start, size, "flash")) {
		err = -EBUSY;
		goto out_free_info;
	}

	info->map.virt		= ioremap(res->start, size);
	if (!info->map.virt) {
		err = -ENOMEM;
		goto out_release_mem_region;
	}
	info->map.name		= pdev->dev.bus_id;
	info->map.phys		= res->start;
	info->map.size		= size;
	info->map.bankwidth	= pdata->width;
	info->map.set_vpp	= omap_set_vpp;

	simple_map_init(&info->map);
	info->mtd = do_map_probe(pdata->map_name, &info->map);
	if (!info->mtd) {
		err = -EIO;
		goto out_iounmap;
	}
	info->mtd->owner = THIS_MODULE;

#ifdef CONFIG_MTD_PARTITIONS
	err = parse_mtd_partitions(info->mtd, part_probes, &info->parts, 0);
	if (err > 0)
		add_mtd_partitions(info->mtd, info->parts, err);
	else if (err <= 0 && pdata->parts)
		add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
	else
#endif
		add_mtd_device(info->mtd);

	platform_set_drvdata(pdev, info);

	return 0;

out_iounmap:
	iounmap(info->map.virt);
out_release_mem_region:
	release_mem_region(res->start, size);
out_free_info:
	kfree(info);

	return err;
}
Esempio n. 6
0
static int __init cs553x_init(void)
{
	int err = -ENXIO;
	int i;
	uint64_t val;

#ifdef CONFIG_MTD_PARTITIONS
	int mtd_parts_nb = 0;
	struct mtd_partition *mtd_parts = NULL;
#endif

	/* If the CPU isn't a Geode GX or LX, abort */
	if (!is_geode())
		return -ENXIO;

	/* If it doesn't have the CS553[56], abort */
	rdmsrl(MSR_DIVIL_GLD_CAP, val);
	val &= ~0xFFULL;
	if (val != CAP_CS5535 && val != CAP_CS5536)
		return -ENXIO;

	/* If it doesn't have the NAND controller enabled, abort */
	rdmsrl(MSR_DIVIL_BALL_OPTS, val);
	if (val & PIN_OPT_IDE) {
		printk(KERN_INFO "CS553x NAND controller: Flash I/O not enabled in MSR_DIVIL_BALL_OPTS.\n");
		return -ENXIO;
	}

	for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
		rdmsrl(MSR_DIVIL_LBAR_FLSH0 + i, val);

		if ((val & (FLSH_LBAR_EN|FLSH_NOR_NAND)) == (FLSH_LBAR_EN|FLSH_NOR_NAND))
			err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF);
	}

	/* Register all devices together here. This means we can easily hack it to
	   do mtdconcat etc. if we want to. */
	for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
		if (cs553x_mtd[i]) {

			/* If any devices registered, return success. Else the last error. */
#ifdef CONFIG_MTD_PARTITIONS
			mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], part_probes, &mtd_parts, 0);
			if (mtd_parts_nb > 0) {
				printk(KERN_NOTICE "Using command line partition definition\n");
				add_mtd_partitions(cs553x_mtd[i], mtd_parts, mtd_parts_nb);
			} else {
				add_mtd_device(cs553x_mtd[i]);
			}
#else
			add_mtd_device(cs553x_mtd[i]);
#endif
			err = 0;
		}
	}

	return err;
}
Esempio n. 7
0
static int __devinit bfin_flash_probe(struct platform_device *pdev)
{
	int ret;
	struct physmap_flash_data *pdata = pdev->dev.platform_data;
	struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	struct resource *flash_ambctl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	struct async_state *state;

	state = kzalloc(sizeof(*state), GFP_KERNEL);
	if (!state)
		return -ENOMEM;

	state->map.name       = DRIVER_NAME;
	state->map.read       = bfin_flash_read;
	state->map.copy_from  = bfin_flash_copy_from;
	state->map.write      = bfin_flash_write;
	state->map.copy_to    = bfin_flash_copy_to;
	state->map.bankwidth  = pdata->width;
	state->map.size       = resource_size(memory);
	state->map.virt       = (void __iomem *)memory->start;
	state->map.phys       = memory->start;
	state->map.map_priv_1 = (unsigned long)state;
	state->enet_flash_pin = platform_get_irq(pdev, 0);
	state->flash_ambctl0  = flash_ambctl->start;
	state->flash_ambctl1  = flash_ambctl->end;

	if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) {
		pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin);
		kfree(state);
		return -EBUSY;
	}
	gpio_direction_output(state->enet_flash_pin, 1);

	pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
	state->mtd = do_map_probe(memory->name, &state->map);
	if (!state->mtd) {
		gpio_free(state->enet_flash_pin);
		kfree(state);
		return -ENXIO;
	}

	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
	if (ret > 0) {
		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
		mtd_device_register(state->mtd, pdata->parts, ret);
		state->parts = pdata->parts;
	} else if (pdata->nr_parts) {
		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
		mtd_device_register(state->mtd, pdata->parts, pdata->nr_parts);
	} else {
		pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
		mtd_device_register(state->mtd, NULL, 0);
	}

	platform_set_drvdata(pdev, state);

	return 0;
}
Esempio n. 8
0
static int __init
dm270_init_flash (void)   
{
	struct mtd_partition *parts;
	int nb_parts = 0;
	int parsed_nr_parts = 0;
	const char *part_type;
 
	/*
	 * Static partition definition selection
	 */
	part_type = "static";

 	parts = dm270_partitions;
	nb_parts = ARRAY_SIZE(dm270_partitions);
	dm270_map_flash.virt = phys_to_virt(dm270_map_flash.phys);

	simple_map_init(&dm270_map_flash);
	/*
	 * Now let's probe for the actual flash.  Do it here since
	 * specific machine settings might have been set above.
	 */
	printk(KERN_NOTICE "DM270 flash: probing %d-bit flash bus\n",
		dm270_map_flash.bankwidth*8);
	dm270_flash_mtd = do_map_probe("cfi_probe", &dm270_map_flash);
	if (!dm270_flash_mtd) {
		return -ENXIO;
	}
	dm270_flash_mtd->owner = THIS_MODULE;
 
	/*
	 * Dynamic partition selection stuff (might override the static ones)
	 */
	if (dm270_partition_types[0]) {
		parsed_nr_parts = parse_mtd_partitions(dm270_flash_mtd,
				dm270_partition_types, &parsed_parts,
				CONFIG_FLASH_MEM_BASE);
	}
 	if (parsed_nr_parts > 0) {
		part_type = "dynamic";
		parts = parsed_parts;
		nb_parts = parsed_nr_parts;
	}

	if (nb_parts == 0) {
		printk(KERN_NOTICE "DM270 flash: no partition info available,"
			"registering whole flash at once\n");
		if (add_mtd_device(dm270_flash_mtd)) {
			return -ENXIO;
		}
	} else {
		printk(KERN_NOTICE "Using %s partition definition\n",
			part_type);
		return add_mtd_partitions(dm270_flash_mtd, parts, nb_parts);
	}
	return 0;
}
Esempio n. 9
0
static int __init init_soleng_maps(void)
{
	int nr_parts = 0;

	/* First probe at offset 0 */
	soleng_flash_map.phys = 0;
	soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0);
	soleng_eprom_map.phys = 0x01000000;
	soleng_eprom_map.virt = (void __iomem *)P1SEGADDR(0x01000000);
	simple_map_init(&soleng_eprom_map);
	simple_map_init(&soleng_flash_map);

	printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n");
	flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map);
	if (!flash_mtd) {
		/* Not there. Try swapping */
		printk(KERN_NOTICE "Probing for flash chips at 0x01000000:\n");
		soleng_flash_map.phys = 0x01000000;
		soleng_flash_map.virt = P2SEGADDR(0x01000000);
		soleng_eprom_map.phys = 0;
		soleng_eprom_map.virt = P1SEGADDR(0);
		flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map);
		if (!flash_mtd) {
			/* Eep. */
			printk(KERN_NOTICE "Flash chips not detected at either possible location.\n");
			return -ENXIO;
		}
	}
	printk(KERN_NOTICE "Solution Engine: Flash at 0x%08lx, EPROM at 0x%08lx\n",
	       soleng_flash_map.phys & 0x1fffffff,
	       soleng_eprom_map.phys & 0x1fffffff);
	flash_mtd->owner = THIS_MODULE;

	eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map);
	if (eprom_mtd) {
		eprom_mtd->owner = THIS_MODULE;
		add_mtd_device(eprom_mtd);
	}

	nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);

#ifdef CONFIG_MTD_SUPERH_RESERVE
	if (nr_parts <= 0) {
		printk(KERN_NOTICE "Using configured partition at 0x%08x.\n",
		       CONFIG_MTD_SUPERH_RESERVE);
		parsed_parts = superh_se_partitions;
		nr_parts = sizeof(superh_se_partitions)/sizeof(*parsed_parts);
	}
#endif /* CONFIG_MTD_SUPERH_RESERVE */

	if (nr_parts > 0)
		add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
	else
		add_mtd_device(flash_mtd);

	return 0;
}
Esempio n. 10
0
static int __devinit generic_onenand_probe(struct platform_device *pdev)
{
	struct onenand_info *info;
	struct onenand_platform_data *pdata = pdev->dev.platform_data;
	struct resource *res = pdev->resource;
	unsigned long size = resource_size(res);
	int err;

	info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	if (!request_mem_region(res->start, size, dev_name(&pdev->dev))) {
		err = -EBUSY;
		goto out_free_info;
	}

	info->onenand.base = ioremap(res->start, size);
	if (!info->onenand.base) {
		err = -ENOMEM;
		goto out_release_mem_region;
	}

	info->onenand.mmcontrol = pdata ? pdata->mmcontrol : 0;
	info->onenand.irq = platform_get_irq(pdev, 0);

	info->mtd.name = dev_name(&pdev->dev);
	info->mtd.priv = &info->onenand;
	info->mtd.owner = THIS_MODULE;

	if (onenand_scan(&info->mtd, 1)) {
		err = -ENXIO;
		goto out_iounmap;
	}

	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
	if (err > 0)
		mtd_device_register(&info->mtd, info->parts, err);
	else if (err <= 0 && pdata && pdata->parts)
		mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
	else
		err = mtd_device_register(&info->mtd, NULL, 0);

	platform_set_drvdata(pdev, info);

	return 0;

out_iounmap:
	iounmap(info->onenand.base);
out_release_mem_region:
	release_mem_region(res->start, size);
out_free_info:
	kfree(info);

	return err;
}
Esempio n. 11
0
int mtdsf_init_device(struct mtd_info *mtd, unsigned long size, char *name)
{
	int nr_parts, cut_parts = 0;
	char *part_type = NULL;

	mtd->name = name;
	mtd->type = MTD_NORFLASH;
	mtd->flags = MTD_CAP_NORFLASH;
	mtd->size = size;
	mtd->erasesize = MTDSF_ERASE_SIZE;
	mtd->owner = THIS_MODULE;
	mtd->erase = sf_erase;
	mtd->read = sf_read;
	mtd->write = sf_write;
	mtd->writesize = 1;


	boot_partitions[5].offset = size - boot_partitions[5].size;
	boot_partitions[4].offset = boot_partitions[5].offset - boot_partitions[4].size;
	boot_partitions[3].offset = boot_partitions[4].offset - boot_partitions[3].size;
	boot_partitions[2].offset = boot_partitions[3].offset - boot_partitions[2].size;
	if (boot_partitions[2].offset > 0x00280000) {
		boot_partitions[1].offset = boot_partitions[2].offset - boot_partitions[1].size;
		if (boot_partitions[1].offset > 0)
			boot_partitions[0].size = boot_partitions[1].offset;
		else {
			shift_partition_content(1);
			cut_parts = 1;
		}
	} else if (boot_partitions[2].offset > 0) {
		boot_partitions[1].size = boot_partitions[2].offset;
		boot_partitions[1].offset = 0;
		shift_partition_content(1);
		cut_parts = 1;
	} else {
		shift_partition_content(2);
		cut_parts = 2;
	}
	

	nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
	if (nr_parts > 0) {
		part_type = "command line";
		cut_parts = 0;
	}
	if (nr_parts <= 0) {
		parts = boot_partitions;
		nr_parts = NUM_SF_PARTITIONS;
		part_type = "builtin";
	}
	printk(KERN_INFO "SF Using %s partition table count=%d\n", part_type, nr_parts - cut_parts);
	mtd_device_register(mtd, parts, nr_parts - cut_parts);
	//add_mtd_partitions(mtd, boot_partitions, ARRAY_SIZE(boot_partitions));

	return 0;
}
Esempio n. 12
0
static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
{
	struct mtd_partition *parts;
	static const char *part_probes[] = { "cmdlinepart", NULL };

	/* register the flash bank */
	/* partition the flash bank */
	p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0);
	return mtd_device_register(p->info, parts, p->nr_parts);
}
Esempio n. 13
0
int __init init_s3c2410nor(void)
{
  static const char *rom_probe_types[] = PROBETYPES;
  const char **type;
  const char *part_type = 0;

  printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", WINDOW_SIZE, WINDOW_ADDR);
  s3c2410nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);//物理->虚拟地址

  if (!s3c2410nor_map.virt)
  {
    printk(MSG_PREFIX "failed to ioremap\n");
    return  - EIO;
  }

  simple_map_init(&s3c2410nor_map);

  mymtd = 0;
  type = rom_probe_types;
  for (; !mymtd &&  *type; type++)
  {
    mymtd = do_map_probe(*type, &s3c2410nor_map);//探测NOR FLASH
  }
  if (mymtd)
  {
    mymtd->owner = THIS_MODULE;

    #ifdef CONFIG_MTD_PARTITIONS
      mtd_parts_nb = parse_mtd_partitions(mymtd, NULL, &mtd_parts, MTDID);//探测分区信息
      if (mtd_parts_nb > 0)
        part_type = "detected";

      if (mtd_parts_nb == 0) //未探测到,使用数组定义的分区信息
      {
        mtd_parts = static_partitions;
        mtd_parts_nb = ARRAY_SIZE(static_partitions);
        part_type = "static";
      }
    #endif
    add_mtd_device(mymtd);
    if (mtd_parts_nb == 0)
      printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
    else
    {
      printk(KERN_NOTICE MSG_PREFIX "using %s partition definition\n",
        part_type);
      add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb);//添加分区信息
    }
    return 0;
  }

  iounmap((void*)s3c2410nor_map.virt);
  return  - ENXIO;
}
Esempio n. 14
0
static int __init epxa_mtd_init(void)
{
	int i;
	
	printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);

	epxa_map.virt = (void __iomem *)ioremap(FLASH_START, FLASH_SIZE);
	if (!epxa_map.virt) {
		printk("Failed to ioremap %s flash\n",BOARD_NAME);
		return -EIO;
	}
	simple_map_init(&epxa_map);

	mymtd = do_map_probe("cfi_probe", &epxa_map);
	if (!mymtd) {
		iounmap((void *)epxa_map.virt);
		return -ENXIO;
	}

	mymtd->owner = THIS_MODULE;

	/* Unlock the flash device. */
	if(mymtd->unlock){
		for (i=0; i<mymtd->numeraseregions;i++){
			int j;
			for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
				mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
			}
		}
	}

#ifdef CONFIG_MTD_PARTITIONS
	nr_parts = parse_mtd_partitions(mymtd, probes, &parts, 0);

	if (nr_parts > 0) {
		add_mtd_partitions(mymtd, parts, nr_parts);
		return 0;
	}
#endif
	/* No recognised partitioning schemes found - use defaults */
	nr_parts = epxa_default_partitions(mymtd, &parts);
	if (nr_parts > 0) {
		add_mtd_partitions(mymtd, parts, nr_parts);
		return 0;
	}

	/* If all else fails... */
	add_mtd_device(mymtd);
	return 0;
}
Esempio n. 15
0
int __init init_physmap(void)
{
	static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", 0 };
	const char **type;

       	printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys);
	physmap_map.virt = (unsigned long)ioremap(physmap_map.phys, physmap_map.size);

	if (!physmap_map.virt) {
		printk("Failed to ioremap\n");
		return -EIO;
	}

	simple_map_init(&physmap_map);

	mymtd = 0;
	type = rom_probe_types;
	for(; !mymtd && *type; type++) {
		mymtd = do_map_probe(*type, &physmap_map);
	}
	if (mymtd) {
		mymtd->owner = THIS_MODULE;

#ifdef CONFIG_MTD_PARTITIONS
		mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes, 
						    &mtd_parts, 0);

		if (mtd_parts_nb > 0)
		{
			add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
			return 0;
		}

		if (num_physmap_partitions != 0) 
		{
			printk(KERN_NOTICE 
			       "Using physmap partition definition\n");
			add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions);
			return 0;
		}

#endif
		add_mtd_device(mymtd);

		return 0;
	}

	iounmap((void *)physmap_map.virt);
	return -ENXIO;
}
Esempio n. 16
0
static int __init armflash_cfi_init(void *base, u_int size)
{
	int ret;

	armflash_flash_init();
	armflash_flash_wp(1);

	/*
	 * look for CFI based flash parts fitted to this board
	 */
	armflash_map.size       = size;
	armflash_map.buswidth   = 4;
	armflash_map.virt = (unsigned long) base;

	simple_map_init(&armflash_map);

	/*
	 * The CFI layer automatically works out what size chips we have
	 * and does the necessary identification for us automatically.
	 */
	mtd = do_map_probe("cfi_probe", &armflash_map);
	if (!mtd)
		return -ENXIO;

	mtd->owner = THIS_MODULE;

	ret = parse_mtd_partitions(mtd, probes, &parts, (void *)0);
	if (ret <= 0) {
		/*
		 * Use default static MTD partition definition:
		 */
		parts = integrator_partitions;
		ret = ARRAY_SIZE(integrator_partitions);
	}

	ret = add_mtd_partitions(mtd, parts, ret);
	if (ret)
		printk(KERN_ERR "mtd partition registration failed: %d\n", ret);

	/*
	 * If we got an error, free all resources.
	 */
	if (ret < 0) {
		del_mtd_partitions(mtd);
		map_destroy(mtd);
	}

	return ret;
}
Esempio n. 17
0
static int rk29xxnand_add_partitions(struct rknand_info *nand_info)
{
#ifdef CONFIG_MTD_CMDLINE_PARTS
    int num_partitions = 0; 

	// 从命令行解析分区的信息
    num_partitions = parse_mtd_partitions(&(rknand_mtd), part_probes, &rknand_parts, 0); 
    NAND_DEBUG(NAND_DEBUG_LEVEL0,"num_partitions = %d\n",num_partitions);
    if(num_partitions > 0) { 
    	int i;
		g_num_partitions = num_partitions;
		return add_mtd_partitions(&(rknand_mtd), rknand_parts, num_partitions);
    } 
#endif 
	return 0;
}
Esempio n. 18
0
static void __init set_mtd_partitions(void)
{
	int nr_parts = 0;

	simple_map_init(&rsk_flash_map);
	flash_mtd = do_map_probe("cfi_probe", &rsk_flash_map);
	nr_parts = parse_mtd_partitions(flash_mtd, probes,
					&parsed_partitions, 0);
	/* If there is no partition table, used the hard coded table */
	if (nr_parts <= 0) {
		flash_data.parts = rsk_partitions;
		flash_data.nr_parts = ARRAY_SIZE(rsk_partitions);
	} else {
		flash_data.nr_parts = nr_parts;
		flash_data.parts = parsed_partitions;
	}
}
Esempio n. 19
0
int __init init_alteramap(void)
{
	static const char *rom_probe_types[] = {"cfi_probe", "jedec_probe", 0 };
	const char **type;

 	ndk_amd_map.virt = (unsigned long *)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
/*
	if (!ndk_amd_map.virt) {
		printk("Failed to ioremap\n");
		return -EIO;
	}
*/
	simple_map_init(&ndk_amd_map);

	mymtd = 0;
	type = rom_probe_types;
	for(; !mymtd && *type; type++) {
		mymtd = do_map_probe(*type, &ndk_amd_map);
	}
	if (mymtd) {
		mymtd->owner = THIS_MODULE;

		mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes, 
						    &mtd_parts, 0);

		if (mtd_parts_nb > 0)
		{
			mtd_device_register(mymtd, mtd_parts, mtd_parts_nb);
			return 0;
		}

		if (NUM_PARTITIONS != 0) 
		{
			printk(KERN_NOTICE 
			       "Using Altera NDK partition definition\n");
			mtd_device_register(mymtd, alteramap_partitions, NUM_PARTITIONS);
			return 0;
		}

		return 0;
	}

	iounmap((void *)ndk_amd_map.virt);
	return -ENXIO;
}
Esempio n. 20
0
static int __init armflash_cfi_init(void *base, u_int size)
{
	int ret;

	armflash_flash_init();
	armflash_flash_wp(1);

	/*
	 * look for CFI based flash parts fitted to this board
	 */
	armflash_map.size       = size;
	armflash_map.bankwidth   = 4;
	armflash_map.virt = (void __iomem *) base;

	simple_map_init(&armflash_map);

	/*
	 * Also, the CFI layer automatically works out what size
	 * of chips we have, and does the necessary identification
	 * for us automatically.
	 */
	mtd = do_map_probe("cfi_probe", &armflash_map);
	if (!mtd)
		return -ENXIO;

	mtd->owner = THIS_MODULE;

	ret = parse_mtd_partitions(mtd, probes, &parts, (void *)0);
	if (ret > 0) {
		ret = add_mtd_partitions(mtd, parts, ret);
		if (ret)
			printk(KERN_ERR "mtd partition registration "
				"failed: %d\n", ret);
	}

	/*
	 * If we got an error, free all resources.
	 */
	if (ret < 0) {
		del_mtd_partitions(mtd);
		map_destroy(mtd);
	}

	return ret;
}
static int __init flash_init(void)
{
	/*
	 * Read the bootbus region 0 setup to determine the base
	 * address of the flash.
	 */
	union cvmx_mio_boot_reg_cfgx region_cfg;
	region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(0));
	if (region_cfg.s.en) {
		/*
		 * The bootloader always takes the flash and sets its
		 * address so the entire flash fits below
		 * 0x1fc00000. This way the flash aliases to
		 * 0x1fc00000 for booting. Software can access the
		 * full flash at the true address, while core boot can
		 * access 4MB.
		 */
		/* Use this name so old part lines work */
		flash_map.name = "phys_mapped_flash";
		flash_map.phys = region_cfg.s.base << 16;
		flash_map.size = 0x1fc00000 - flash_map.phys;
		flash_map.bankwidth = 1;
		flash_map.virt = ioremap(flash_map.phys, flash_map.size);
		pr_notice("Bootbus flash: Setting flash for %luMB flash at "
			  "0x%08llx\n", flash_map.size >> 20, flash_map.phys);
		simple_map_init(&flash_map);
		mymtd = do_map_probe("cfi_probe", &flash_map);
		if (mymtd) {
			mymtd->owner = THIS_MODULE;

#ifdef CONFIG_MTD_PARTITIONS
			nr_parts = parse_mtd_partitions(mymtd,
							part_probe_types,
							&parts, 0);
			if (nr_parts > 0)
				add_mtd_partitions(mymtd, parts, nr_parts);
			else
				add_mtd_device(mymtd);
#else
			add_mtd_device(mymtd);
#endif
		} else {
			pr_err("Failed to register MTD device for flash\n");
		}
	}
Esempio n. 22
0
/*
 * Initialize FLASH support
 */
int __init h720x_mtd_init(void)
{

	char	*part_type = NULL;

	h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE);

	if (!h720x_map.virt) {
		printk(KERN_ERR "H720x-MTD: ioremap failed\n");
		return -EIO;
	}

	simple_map_init(&h720x_map);

	// Probe for flash bankwidth 4
	printk (KERN_INFO "H720x-MTD probing 32bit FLASH\n");
	mymtd = do_map_probe("cfi_probe", &h720x_map);
	if (!mymtd) {
		printk (KERN_INFO "H720x-MTD probing 16bit FLASH\n");
	    // Probe for bankwidth 2
	    h720x_map.bankwidth = 2;
	    mymtd = do_map_probe("cfi_probe", &h720x_map);
	}

	if (mymtd) {
		mymtd->owner = THIS_MODULE;

#ifdef CONFIG_MTD_PARTITIONS
		nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
		if (nr_mtd_parts > 0)
			part_type = "command line";
#endif
		if (nr_mtd_parts <= 0) {
			mtd_parts = h720x_partitions;
			nr_mtd_parts = NUM_PARTITIONS;
			part_type = "builtin";
		}
		printk(KERN_INFO "Using %s partition table\n", part_type);
		add_mtd_partitions(mymtd, mtd_parts, nr_mtd_parts);
		return 0;
	}

	iounmap((void *)h720x_map.virt);
	return -ENXIO;
}
Esempio n. 23
0
static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
{
	int err = 0;
#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
	struct mtd_partition *parts;
	static const char *part_probes[] = { "cmdlinepart", NULL };
#endif

	/* register the flash bank */
#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
	/* partition the flash bank */
	p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0);
	if (p->nr_parts > 0)
		err = add_mtd_partitions(p->info, parts, p->nr_parts);
#endif
	if (p->nr_parts <= 0)
		err = add_mtd_device(p->info);

	return err;
}
Esempio n. 24
0
static int __init init_iq80310(void)
{
	struct mtd_partition *parts;
	int nb_parts = 0;
	int parsed_nr_parts = 0;
	int ret;

	iq80310_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
	if (!iq80310_map.virt) {
		printk("Failed to ioremap\n");
		return -EIO;
	}
	simple_map_init(&iq80310_map);

	mymtd = do_map_probe("cfi_probe", &iq80310_map);
	if (!mymtd) {
		iounmap((void *)iq80310_map.virt);
		return -ENXIO;
	}
	mymtd->owner = THIS_MODULE;

	ret = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);

	if (ret > 0)
		parsed_nr_parts = ret;

	if (parsed_nr_parts > 0) {
		parts = parsed_parts;
		nb_parts = parsed_nr_parts;
	} else {
		parts = iq80310_partitions;
		nb_parts = ARRAY_SIZE(iq80310_partitions);
	}
	add_mtd_partitions(mymtd, parts, nb_parts);
	return 0;
}
Esempio n. 25
0
/*
 * Probe for the NAND device.
 */
static int __init plat_nand_probe(struct platform_device *pdev)
{
	struct platform_nand_data *pdata = pdev->dev.platform_data;
	struct plat_nand_data *data;
	int res = 0;

	/* Allocate memory for the device structure (and zero it) */
	data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL);
	if (!data) {
		dev_err(&pdev->dev, "failed to allocate device structure.\n");
		return -ENOMEM;
	}

	data->io_base = ioremap(pdev->resource[0].start,
				pdev->resource[0].end - pdev->resource[0].start + 1);
	if (data->io_base == NULL) {
		dev_err(&pdev->dev, "ioremap failed\n");
		kfree(data);
		return -EIO;
	}

	data->chip.priv = &data;
	data->mtd.priv = &data->chip;
	data->mtd.owner = THIS_MODULE;
	data->mtd.name = dev_name(&pdev->dev);

	data->chip.IO_ADDR_R = data->io_base;
	data->chip.IO_ADDR_W = data->io_base;
	data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl;
	data->chip.dev_ready = pdata->ctrl.dev_ready;
	data->chip.select_chip = pdata->ctrl.select_chip;
	data->chip.chip_delay = pdata->chip.chip_delay;
	data->chip.options |= pdata->chip.options;

	data->chip.ecc.hwctl = pdata->ctrl.hwcontrol;
	data->chip.ecc.layout = pdata->chip.ecclayout;
	data->chip.ecc.mode = NAND_ECC_SOFT;

	platform_set_drvdata(pdev, data);

	/* Scan to find existance of the device */
	if (nand_scan(&data->mtd, 1)) {
		res = -ENXIO;
		goto out;
	}

#ifdef CONFIG_MTD_PARTITIONS
	if (pdata->chip.part_probe_types) {
		res = parse_mtd_partitions(&data->mtd,
					pdata->chip.part_probe_types,
					&data->parts, 0);
		if (res > 0) {
			add_mtd_partitions(&data->mtd, data->parts, res);
			return 0;
		}
	}
	if (pdata->chip.partitions) {
		data->parts = pdata->chip.partitions;
		res = add_mtd_partitions(&data->mtd, data->parts,
			pdata->chip.nr_partitions);
	} else
#endif
	res = add_mtd_device(&data->mtd);

	if (!res)
		return res;

	nand_release(&data->mtd);
out:
	platform_set_drvdata(pdev, NULL);
	iounmap(data->io_base);
	kfree(data);
	return res;
}
Esempio n. 26
0
static int __init pxa2xx_flash_probe(struct platform_device *pdev)
{
	struct flash_platform_data *flash = pdev->dev.platform_data;
	struct pxa2xx_flash_info *info;
	struct mtd_partition *parts;
	struct resource *res;
	int ret = 0;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENODEV;

	info = kmalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	memset(info, 0, sizeof(struct pxa2xx_flash_info));
	info->map.name = (char *) flash->name;
	info->map.bankwidth = flash->width;
	info->map.phys = res->start;
	info->map.size = res->end - res->start + 1;
	info->parts = flash->parts;
	info->nr_parts = flash->nr_parts;

	info->map.virt = ioremap(info->map.phys, info->map.size);
	if (!info->map.virt) {
		printk(KERN_WARNING "Failed to ioremap %s\n",
		       info->map.name);
		return -ENOMEM;
	}
	info->map.cached =
		ioremap_cached(info->map.phys, info->map.size);
	if (!info->map.cached)
		printk(KERN_WARNING "Failed to ioremap cached %s\n",
		       info->map.name);
	info->map.inval_cache = pxa2xx_map_inval_cache;
	simple_map_init(&info->map);

	printk(KERN_NOTICE
	       "Probing %s at physical address 0x%08lx"
	       " (%d-bit bankwidth)\n",
	       info->map.name, (unsigned long)info->map.phys,
	       info->map.bankwidth * 8);

	info->mtd = do_map_probe(flash->map_name, &info->map);

	if (!info->mtd) {
		iounmap((void *)info->map.virt);
		if (info->map.cached)
			iounmap(info->map.cached);
		return -EIO;
	}
	info->mtd->owner = THIS_MODULE;

#ifdef CONFIG_MTD_PARTITIONS
	ret = parse_mtd_partitions(info->mtd, probes, &parts, 0);

	if (ret > 0) {
		info->nr_parts = ret;
		info->parts = parts;
	}
#endif

	if (info->nr_parts) {
		add_mtd_partitions(info->mtd, info->parts,
				   info->nr_parts);
	} else {
		printk("Registering %s as whole device\n",
		       info->map.name);
		add_mtd_device(info->mtd);
	}

	platform_set_drvdata(pdev, info);
	return 0;
}
Esempio n. 27
0
static int ixp2000_flash_probe(struct platform_device *dev)
{
	static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
	struct ixp2000_flash_data *ixp_data = dev->dev.platform_data;
	struct flash_platform_data *plat;
	struct ixp2000_flash_info *info;
	unsigned long window_size;
	int err = -1;

	if (!ixp_data)
		return -ENODEV;

	plat = ixp_data->platform_data;
	if (!plat)
		return -ENODEV;

	window_size = dev->resource->end - dev->resource->start + 1;
	dev_info(&dev->dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n",
		 ixp_data->nr_banks, ((u32)window_size >> 20));

	if (plat->width != 1) {
		dev_err(&dev->dev, "IXP2000 MTD map only supports 8-bit mode, asking for %d\n",
			plat->width * 8);
		return -EIO;
	}

	info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
	if(!info) {
		err = -ENOMEM;
		goto Error;
	}
	memzero(info, sizeof(struct ixp2000_flash_info));

	platform_set_drvdata(dev, info);

	/*
	 * Tell the MTD layer we're not 1:1 mapped so that it does
	 * not attempt to do a direct access on us.
	 */
	info->map.phys = NO_XIP;

	info->map.size = ixp_data->nr_banks * window_size;
	info->map.bankwidth = 1;

	/*
 	 * map_priv_2 is used to store a ptr to to the bank_setup routine
 	 */
	info->map.map_priv_2 = (unsigned long) ixp_data->bank_setup;

	info->map.name = dev->dev.bus_id;
	info->map.read = ixp2000_flash_read8;
	info->map.write = ixp2000_flash_write8;
	info->map.copy_from = ixp2000_flash_copy_from;
	info->map.copy_to = ixp2000_flash_copy_to;

	info->res = request_mem_region(dev->resource->start,
			dev->resource->end - dev->resource->start + 1,
			dev->dev.bus_id);
	if (!info->res) {
		dev_err(&dev->dev, "Could not reserve memory region\n");
		err = -ENOMEM;
		goto Error;
	}

	info->map.map_priv_1 = (unsigned long) ioremap(dev->resource->start,
			    	dev->resource->end - dev->resource->start + 1);
	if (!info->map.map_priv_1) {
		dev_err(&dev->dev, "Failed to ioremap flash region\n");
		err = -EIO;
		goto Error;
	}

#if defined(__ARMEB__)
	/*
	 * Enable erratum 44 workaround for NPUs with broken slowport
	 */

	erratum44_workaround = ixp2000_has_broken_slowport();
	dev_info(&dev->dev, "Erratum 44 workaround %s\n",
	       erratum44_workaround ? "enabled" : "disabled");
#endif

	info->mtd = do_map_probe(plat->map_name, &info->map);
	if (!info->mtd) {
		dev_err(&dev->dev, "map_probe failed\n");
		err = -ENXIO;
		goto Error;
	}
	info->mtd->owner = THIS_MODULE;

	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
	if (err > 0) {
		err = add_mtd_partitions(info->mtd, info->partitions, err);
		if(err)
			dev_err(&dev->dev, "Could not parse partitions\n");
	}

	if (err)
		goto Error;

	return 0;

Error:
	ixp2000_flash_remove(dev);
	return err;
}
Esempio n. 28
0
/*
 * board specific setup should have ensured the SPI clock used here
 * matches what the READ command supports, at least until this driver
 * understands FAST_READ (for clocks over 25 MHz).
 */
static int __devinit m25p_probe(struct spi_device *spi)
{
	struct flash_platform_data	*data;
	struct m25p			*flash;
	struct flash_info		*info;
	unsigned			i;
	uint64_t tmpdiv;

	/* Platform data helps sort out which chip type we have, as
	 * well as how this board partitions it.  If we don't have
	 * a chip ID, try the JEDEC id commands; they'll work for most
	 * newer chips, even if we don't recognize the particular chip.
	 */
	data = spi->dev.platform_data;

	if (data && data->type) {
		for (i = 0, info = m25p_data;
				i < ARRAY_SIZE(m25p_data);
				i++, info++) {
			if (strcmp(data->type, info->name) == 0)
				break;
		}

		/* unrecognized chip? */
		if (i == ARRAY_SIZE(m25p_data)) {
			DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
					spi->dev.bus_id, data->type);
			info = NULL;

		/* recognized; is that chip really what's there? */
		} else if (info->jedec_id) {
			struct flash_info	*chip = jedec_probe(spi);

			if (!chip || chip != info) {
				dev_warn(&spi->dev, "found %s, expected %s\n",
						chip ? chip->name : "UNKNOWN",
						info->name);
				info = NULL;
			}
		}
	} else
		info = jedec_probe(spi);

	if (!info)
		return -ENODEV;

	flash = kzalloc(sizeof *flash, GFP_KERNEL);
	if (!flash)
		return -ENOMEM;

	flash->spi = spi;
	mutex_init(&flash->lock);
	dev_set_drvdata(&spi->dev, flash);

	if (data && data->name)
		flash->mtd.name = data->name;
	else
		flash->mtd.name = spi->dev.bus_id;

	flash->mtd.type = MTD_NORFLASH;
	flash->mtd.writesize = 1;
	flash->mtd.flags = MTD_CAP_NORFLASH;
	flash->mtd.size = info->sector_size * info->n_sectors;
	flash->mtd.erase = m25p80_erase;
	flash->mtd.read = m25p80_read;
	flash->mtd.write = m25p80_write;

	/* prefer "small sector" erase if possible */
	if (info->flags & SECT_4K) {
		flash->erase_opcode = OPCODE_BE_4K;
		flash->mtd.erasesize = 4096;
	} else {
		flash->erase_opcode = OPCODE_SE;
		flash->mtd.erasesize = info->sector_size;
	}
	tmpdiv = (uint64_t) info->sector_size * info->n_sectors;
	do_div(tmpdiv, flash->mtd.erasesize);
	flash->mtd.num_eraseblocks = tmpdiv;

	dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
			device_size(&(flash->mtd)) >> (ffs(1024)-1));

	DEBUG(MTD_DEBUG_LEVEL2,
		"mtd .name = %s, .size = 0x%.8x (%uMiB) "
			".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
		flash->mtd.name,
		flash->mtd.size, flash->mtd.size / (1024*1024),
		flash->mtd.erasesize, flash->mtd.erasesize / 1024,
		flash->mtd.numeraseregions);

	if (flash->mtd.numeraseregions)
		for (i = 0; i < flash->mtd.numeraseregions; i++)
			DEBUG(MTD_DEBUG_LEVEL2,
				"mtd.eraseregions[%d] = { .offset = 0x%.8x, "
				".erasesize = 0x%.8x (%uKiB), "
				".numblocks = %d }\n",
				i, flash->mtd.eraseregions[i].offset,
				flash->mtd.eraseregions[i].erasesize,
				flash->mtd.eraseregions[i].erasesize / 1024,
				flash->mtd.eraseregions[i].numblocks);


	/* partitions should match sector boundaries; and it may be good to
	 * use readonly partitions for writeprotected sectors (BP2..BP0).
	 */
	if (mtd_has_partitions()) {
		struct mtd_partition	*parts = NULL;
		int			nr_parts = 0;

#ifdef CONFIG_MTD_CMDLINE_PARTS
		static const char *part_probes[] = { "cmdlinepart", NULL, };

		nr_parts = parse_mtd_partitions(&flash->mtd,
				part_probes, &parts, 0);
#endif

		if (nr_parts <= 0 && data && data->parts) {
			parts = data->parts;
			nr_parts = data->nr_parts;
		}

		if (nr_parts > 0) {
			for (i = 0; i < nr_parts; i++) {
				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
					"{.name = %s, .offset = 0x%.8x, "
						".size = 0x%.8x (%uKiB) }\n",
					i, parts[i].name,
					parts[i].offset,
					parts[i].size,
					parts[i].size / 1024);
			}
			flash->partitioned = 1;
			return add_mtd_partitions(&flash->mtd, parts, nr_parts);
		}
	} else if (data->nr_parts)
		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
				data->nr_parts, data->name);

	return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
}
Esempio n. 29
0
static int __devinit omap_nand_probe(struct platform_device *pdev)
{
	struct omap_nand_info		*info;
	struct omap_nand_platform_data	*pdata = pdev->dev.platform_data;
	struct resource			*res = pdev->resource;
	unsigned long			size = res->end - res->start + 1;
	int				err;

	info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	if (!request_mem_region(res->start, size, pdev->dev.driver->name)) {
		err = -EBUSY;
		goto out_free_info;
	}

	info->nand.IO_ADDR_R = ioremap(res->start, size);
	if (!info->nand.IO_ADDR_R) {
		err = -ENOMEM;
		goto out_release_mem_region;
	}
	info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
	info->nand.cmd_ctrl = omap_nand_hwcontrol;
	info->nand.ecc.mode = NAND_ECC_SOFT;
	info->nand.options = pdata->options;
	if (pdata->dev_ready)
		info->nand.dev_ready = omap_nand_dev_ready;
	else
		info->nand.chip_delay = 20;

	info->mtd.name = pdev->dev.bus_id;
	info->mtd.priv = &info->nand;

	info->pdata = pdata;

	/* DIP switches on H2 and some other boards change between 8 and 16 bit
	 * bus widths for flash.  Try the other width if the first try fails.
	 */
	if (nand_scan(&info->mtd, 1)) {
		info->nand.options ^= NAND_BUSWIDTH_16;
		if (nand_scan(&info->mtd, 1)) {
			err = -ENXIO;
			goto out_iounmap;
		}
	}
	info->mtd.owner = THIS_MODULE;

#ifdef CONFIG_MTD_PARTITIONS
	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
	if (err > 0)
		add_mtd_partitions(&info->mtd, info->parts, err);
	else if (err < 0 && pdata->parts)
		add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
	else
#endif
		add_mtd_device(&info->mtd);

	platform_set_drvdata(pdev, info);

	return 0;

out_iounmap:
	iounmap(info->nand.IO_ADDR_R);
out_release_mem_region:
	release_mem_region(res->start, size);
out_free_info:
	kfree(info);

	return err;
}
Esempio n. 30
0
static int __init init_lubbock(void)
{
	int flashboot = (LUB_CONF_SWITCHES & 1);
	int ret = 0, i;

	lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth =
		(BOOT_DEF & 1) ? 2 : 4;

	/* Compensate for the nROMBT switch which swaps the flash banks */
	printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n",
	       flashboot?"Flash":"ROM", flashboot);

	lubbock_maps[flashboot^1].name = "Lubbock Application Flash";
	lubbock_maps[flashboot].name = "Lubbock Boot ROM";

	for (i = 0; i < 2; i++) {
		lubbock_maps[i].virt = ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
		if (!lubbock_maps[i].virt) {
			printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name);
			if (!ret)
				ret = -ENOMEM;
			continue;
		}
		lubbock_maps[i].cached = ioremap_cached(lubbock_maps[i].phys, WINDOW_SIZE);
		if (!lubbock_maps[i].cached)
			printk(KERN_WARNING "Failed to ioremap cached %s\n", lubbock_maps[i].name);
		simple_map_init(&lubbock_maps[i]);

		printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit bankwidth)\n",
		       lubbock_maps[i].name, lubbock_maps[i].phys,
		       lubbock_maps[i].bankwidth * 8);

		mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]);

		if (!mymtds[i]) {
			iounmap((void *)lubbock_maps[i].virt);
			if (lubbock_maps[i].cached)
				iounmap(lubbock_maps[i].cached);
			if (!ret)
				ret = -EIO;
			continue;
		}
		mymtds[i]->owner = THIS_MODULE;

		ret = parse_mtd_partitions(mymtds[i], probes,
					   &parsed_parts[i], 0);

		if (ret > 0)
			nr_parsed_parts[i] = ret;
	}

	if (!mymtds[0] && !mymtds[1])
		return ret;

	for (i = 0; i < 2; i++) {
		if (!mymtds[i]) {
			printk(KERN_WARNING "%s is absent. Skipping\n", lubbock_maps[i].name);
		} else if (nr_parsed_parts[i]) {
			add_mtd_partitions(mymtds[i], parsed_parts[i], nr_parsed_parts[i]);
		} else if (!i) {
			printk("Using static partitions on %s\n", lubbock_maps[i].name);
			add_mtd_partitions(mymtds[i], lubbock_partitions, ARRAY_SIZE(lubbock_partitions));
		} else {
			printk("Registering %s as whole device\n", lubbock_maps[i].name);
			add_mtd_device(mymtds[i]);
		}
	}
	return 0;
}