예제 #1
0
/*
 * Main initialization routine
 */
static int __init h1910_init (void)
{
	struct nand_chip *this;
	const char *part_type = 0;
	int mtd_parts_nb = 0;
	struct mtd_partition *mtd_parts = 0;
	void __iomem *nandaddr;
	
	if (!machine_is_h1900())
		return -ENODEV;
		
	nandaddr = __ioremap(0x08000000, 0x1000, 0, 1);
	if (!nandaddr) {
		printk("Failed to ioremap nand flash.\n");
		return -ENOMEM;
	}
	
	/* Allocate memory for MTD device structure and private data */
	h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + 
			     sizeof(struct nand_chip),
			     GFP_KERNEL);
	if (!h1910_nand_mtd) {
		printk("Unable to allocate h1910 NAND MTD device structure.\n");
		iounmap ((void *) nandaddr);
		return -ENOMEM;
	}
	
	/* Get pointer to private data */
	this = (struct nand_chip *) (&h1910_nand_mtd[1]);
	
	/* Initialize structures */
	memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info));
	memset((char *) this, 0, sizeof(struct nand_chip));
	
	/* Link the private data with the MTD structure */
	h1910_nand_mtd->priv = this;
	
	/*
	 * Enable VPEN
	 */
	GPSR(37) = GPIO_bit(37);
	
	/* insert callbacks */
	this->IO_ADDR_R = nandaddr;
	this->IO_ADDR_W = nandaddr;
	this->hwcontrol = h1910_hwcontrol;
	this->dev_ready = NULL;	/* unknown whether that was correct or not so we will just do it like this */
	/* 15 us command delay time */
	this->chip_delay = 50;
	this->eccmode = NAND_ECC_SOFT;
	this->options = NAND_NO_AUTOINCR;
	
	/* Scan to find existence of the device */
	if (nand_scan (h1910_nand_mtd, 1)) {
		printk(KERN_NOTICE "No NAND device - returning -ENXIO\n");
		kfree (h1910_nand_mtd);
		iounmap ((void *) nandaddr);
		return -ENXIO;
	}
	
#ifdef CONFIG_MTD_CMDLINE_PARTS
	mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, 
						"h1910-nand");
	if (mtd_parts_nb > 0)
	  part_type = "command line";
	else
	  mtd_parts_nb = 0;
#endif
	if (mtd_parts_nb == 0)
	{
		mtd_parts = partition_info;
		mtd_parts_nb = NUM_PARTITIONS;
		part_type = "static";
	}
	
	/* Register the partitions */
	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
	add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb);
	
	/* Return happy */
	return 0;
}
예제 #2
0
static int hinfc504_os_probe(struct platform_device * pltdev)
{
	int size;
	int result = 0;
	struct hinfc_host *host;
	struct nand_chip *chip;
	struct mtd_info *mtd;
	struct resource *res;

	size = sizeof(struct hinfc_host) + sizeof(struct nand_chip)
		+ sizeof(struct mtd_info);
	host = kmalloc(size, GFP_KERNEL);
	if (!host) {
		PR_BUG("failed to allocate device structure.\n");
		return -ENOMEM;
	}
	memset((char *)host, 0, size);
	platform_set_drvdata(pltdev, host);

	host->dev  = &pltdev->dev;
	host->chip = chip = (struct nand_chip *)&host[1];
	host->mtd  = mtd  = (struct mtd_info *)&chip[1];

	res = platform_get_resource_byname(pltdev, IORESOURCE_MEM, "base");
	if (!res) {
		PR_BUG("Can't get resource.\n");
		return -EIO;
	}

	host->iobase = ioremap(res->start, res->end - res->start + 1);
	if (!host->iobase) {
		PR_BUG("ioremap failed\n");
		kfree(host);
		return -EIO;
	}

	mtd->priv  = chip;
	mtd->owner = THIS_MODULE;
	mtd->name  = (char*)(pltdev->name);

	res = platform_get_resource_byname(pltdev, IORESOURCE_MEM, "buffer");
	if (!res) {
		PR_BUG("Can't get resource.\n");
		return -EIO;
	}

	chip->IO_ADDR_R = chip->IO_ADDR_W = ioremap_nocache(res->start,
		res->end - res->start + 1);
	if (!chip->IO_ADDR_R) {
		PR_BUG("ioremap failed\n");
		return -EIO;
	}

	host->buffer = dma_alloc_coherent(host->dev,
		(NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE),
		&host->dma_buffer, GFP_KERNEL);
	if (!host->buffer) {
		PR_BUG("Can't malloc memory for NAND driver.");
		return -EIO;
	}

	chip->priv        = host;
	host->chip        = chip;
	chip->cmd_ctrl    = hinfc504_cmd_ctrl;
	chip->dev_ready   = hinfc504_dev_ready;
	chip->select_chip = hinfc504_select_chip;
	chip->read_byte   = hinfc504_read_byte;
	chip->read_word   = hinfc504_read_word;
	chip->write_buf   = hinfc504_write_buf;
	chip->read_buf    = hinfc504_read_buf;

	chip->chip_delay = HINFC504_CHIP_DELAY;
	chip->options    = NAND_NO_AUTOINCR | NAND_SKIP_BBTSCAN;
	chip->ecc.layout = NULL;
	chip->ecc.mode   = NAND_ECC_NONE;

	host->clk = clk_get_sys("hinfc504", NULL);
	if (IS_ERR(host->clk)) {
		PR_BUG("hinfc504 clock not found.\n");
		return -EIO;
	}
	host->enable = hinfc504_os_enable;

	if (hinfc504_nand_init(host, chip)) {
		PR_BUG("failed to allocate device buffer.\n");
		return -EIO;
	}

	if (nand_otp_len) {
		PR_MSG("Copy Nand read retry parameter from boot,"
		       " parameter length %d.\n", nand_otp_len);
		memcpy(host->rr_data, nand_otp, nand_otp_len);
	}

	if (nand_scan(mtd, CONFIG_HINFC504_MAX_CHIP)) {
		result = -ENXIO;
		goto fail;
	}

	register_mtd_partdev(host->mtd);

	if (!mtd_device_parse_register(mtd, part_probes_type,
		NULL, ptn_info.parts, ptn_info.parts_num))
		return 0;

	unregister_mtd_partdev(host->mtd);

	result = -ENODEV;
	nand_release(mtd);

fail:
	if (host->buffer) {
		dma_free_coherent(host->dev,
			(NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE),
			host->buffer,
			host->dma_buffer);
		host->buffer = NULL;
	}
	iounmap(chip->IO_ADDR_W);
	iounmap(host->iobase);
	kfree(host);
	platform_set_drvdata(pltdev, NULL);

	return result;
}
예제 #3
0
/*
 * Main initialization routine
 */
static int __devinit ams_delta_init(struct platform_device *pdev)
{
	struct nand_chip *this;
	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	void __iomem *io_base;
	int err = 0;

	if (!res)
		return -ENXIO;

	/* Allocate memory for MTD device structure and private data */
	ams_delta_mtd = kmalloc(sizeof(struct mtd_info) +
				sizeof(struct nand_chip), GFP_KERNEL);
	if (!ams_delta_mtd) {
		printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
		err = -ENOMEM;
		goto out;
	}

	ams_delta_mtd->owner = THIS_MODULE;

	/* Get pointer to private data */
	this = (struct nand_chip *) (&ams_delta_mtd[1]);

	/* Initialize structures */
	memset(ams_delta_mtd, 0, sizeof(struct mtd_info));
	memset(this, 0, sizeof(struct nand_chip));

	/* Link the private data with the MTD structure */
	ams_delta_mtd->priv = this;

	if (!request_mem_region(res->start, resource_size(res),
			dev_name(&pdev->dev))) {
		dev_err(&pdev->dev, "request_mem_region failed\n");
		err = -EBUSY;
		goto out_free;
	}

	io_base = ioremap(res->start, resource_size(res));
	if (io_base == NULL) {
		dev_err(&pdev->dev, "ioremap failed\n");
		err = -EIO;
		goto out_release_io;
	}

	this->priv = io_base;

	/* Set address of NAND IO lines */
	this->IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH;
	this->IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT;
	this->read_byte = ams_delta_read_byte;
	this->write_buf = ams_delta_write_buf;
	this->read_buf = ams_delta_read_buf;
	this->verify_buf = ams_delta_verify_buf;
	this->cmd_ctrl = ams_delta_hwcontrol;
	if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
		this->dev_ready = ams_delta_nand_ready;
	} else {
		this->dev_ready = NULL;
;
	}
	/* 25 us command delay time */
	this->chip_delay = 30;
	this->ecc.mode = NAND_ECC_SOFT;

	platform_set_drvdata(pdev, io_base);

	/* Set chip enabled, but  */
	ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
					  AMS_DELTA_LATCH2_NAND_NWE |
					  AMS_DELTA_LATCH2_NAND_NCE |
					  AMS_DELTA_LATCH2_NAND_NWP);

	/* Scan to find existence of the device */
	if (nand_scan(ams_delta_mtd, 1)) {
		err = -ENXIO;
		goto out_mtd;
	}

	/* Register the partitions */
	mtd_device_register(ams_delta_mtd, partition_info,
			    ARRAY_SIZE(partition_info));

	goto out;

 out_mtd:
	platform_set_drvdata(pdev, NULL);
	iounmap(io_base);
out_release_io:
	release_mem_region(res->start, resource_size(res));
out_free:
	kfree(ams_delta_mtd);
 out:
	return err;
}
예제 #4
0
파일: ndfc.c 프로젝트: AppEngine/linux-2.6
/*
 * Initialize chip structure
 */
static int ndfc_chip_init(struct ndfc_controller *ndfc,
			  struct device_node *node)
{
#ifdef CONFIG_MTD_PARTITIONS
#ifdef CONFIG_MTD_CMDLINE_PARTS
	static const char *part_types[] = { "cmdlinepart", NULL };
#else
	static const char *part_types[] = { NULL };
#endif
#endif
	struct device_node *flash_np;
	struct nand_chip *chip = &ndfc->chip;
	int ret;

	chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
	chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
	chip->cmd_ctrl = ndfc_hwcontrol;
	chip->dev_ready = ndfc_ready;
	chip->select_chip = ndfc_select_chip;
	chip->chip_delay = 50;
	chip->controller = &ndfc->ndfc_control;
	chip->read_buf = ndfc_read_buf;
	chip->write_buf = ndfc_write_buf;
	chip->verify_buf = ndfc_verify_buf;
	chip->ecc.correct = nand_correct_data;
	chip->ecc.hwctl = ndfc_enable_hwecc;
	chip->ecc.calculate = ndfc_calculate_ecc;
	chip->ecc.mode = NAND_ECC_HW;
	chip->ecc.size = 256;
	chip->ecc.bytes = 3;

	ndfc->mtd.priv = chip;
	ndfc->mtd.owner = THIS_MODULE;

	flash_np = of_get_next_child(node, NULL);
	if (!flash_np)
		return -ENODEV;

	ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
			dev_name(&ndfc->ofdev->dev), flash_np->name);
	if (!ndfc->mtd.name) {
		ret = -ENOMEM;
		goto err;
	}

	ret = nand_scan(&ndfc->mtd, 1);
	if (ret)
		goto err;

#ifdef CONFIG_MTD_PARTITIONS
	ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0);
	if (ret < 0)
		goto err;

#ifdef CONFIG_MTD_OF_PARTS
	if (ret == 0) {
		ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
					      &ndfc->parts);
		if (ret < 0)
			goto err;
	}
#endif

	if (ret > 0)
		ret = add_mtd_partitions(&ndfc->mtd, ndfc->parts, ret);
	else
#endif
		ret = add_mtd_device(&ndfc->mtd);

err:
	of_node_put(flash_np);
	if (ret)
		kfree(ndfc->mtd.name);
	return ret;
}
예제 #5
0
/*
 * Probe for the NAND device.
 */
static int __init at91_nand_probe(struct platform_device *pdev)
{
	struct at91_nand_host *host;
	struct mtd_info *mtd;
	struct nand_chip *nand_chip;
	int res;

#ifdef CONFIG_MTD_PARTITIONS
	struct mtd_partition *partitions = NULL;
	int num_partitions = 0;
#endif

	/* Allocate memory for the device structure (and zero it) */
	host = kzalloc(sizeof(struct at91_nand_host), GFP_KERNEL);
	if (!host) {
		printk(KERN_ERR "at91_nand: failed to allocate device structure.\n");
		return -ENOMEM;
	}

	host->io_base = ioremap(pdev->resource[0].start,
				pdev->resource[0].end - pdev->resource[0].start + 1);
	if (host->io_base == NULL) {
		printk(KERN_ERR "at91_nand: ioremap failed\n");
		kfree(host);
		return -EIO;
	}

	mtd = &host->mtd;
	nand_chip = &host->nand_chip;
	host->board = pdev->dev.platform_data;

	nand_chip->priv = host;		/* link the private data structures */
	mtd->priv = nand_chip;
	mtd->owner = THIS_MODULE;

	/* Set address of NAND IO lines */
	nand_chip->IO_ADDR_R = host->io_base;
	nand_chip->IO_ADDR_W = host->io_base;
	nand_chip->cmd_ctrl = at91_nand_cmd_ctrl;
	nand_chip->dev_ready = at91_nand_device_ready;
	nand_chip->ecc.mode = NAND_ECC_SOFT;	/* enable ECC */
	nand_chip->chip_delay = 20;		/* 20us command delay time */

	if (host->board->bus_width_16)		/* 16-bit bus width */
		nand_chip->options |= NAND_BUSWIDTH_16;

	platform_set_drvdata(pdev, host);
	at91_nand_enable(host);

	if (host->board->det_pin) {
		if (at91_get_gpio_value(host->board->det_pin)) {
			printk ("No SmartMedia card inserted.\n");
			res = ENXIO;
			goto out;
		}
	}

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

#ifdef CONFIG_MTD_PARTITIONS
	if (host->board->partition_info)
		partitions = host->board->partition_info(mtd->size, &num_partitions);

	if ((!partitions) || (num_partitions == 0)) {
		printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
		res = ENXIO;
		goto release;
	}

	res = add_mtd_partitions(mtd, partitions, num_partitions);
#else
	res = add_mtd_device(mtd);
#endif

	if (!res)
		return res;

release:
	nand_release(mtd);
out:
	at91_nand_disable(host);
	platform_set_drvdata(pdev, NULL);
	iounmap(host->io_base);
	kfree(host);
	return res;
}
예제 #6
0
/*
 * Main initialization routine
 */
static int __init ppchameleonevb_init(void)
{
	struct nand_chip *this;
	void __iomem *ppchameleon_fio_base;
	void __iomem *ppchameleonevb_fio_base;

	/*********************************
	* Processor module NAND (if any) *
	*********************************/
	/* Allocate memory for MTD device structure and private data */
	ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
	if (!ppchameleon_mtd) {
		printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
		return -ENOMEM;
	}

	/* map physical address */
	ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M);
	if (!ppchameleon_fio_base) {
		printk("ioremap PPChameleon NAND flash failed\n");
		kfree(ppchameleon_mtd);
		return -EIO;
	}

	/* Get pointer to private data */
	this = (struct nand_chip *)(&ppchameleon_mtd[1]);

	/* Initialize structures */
	memset(ppchameleon_mtd, 0, sizeof(struct mtd_info));
	memset(this, 0, sizeof(struct nand_chip));

	/* Link the private data with the MTD structure */
	ppchameleon_mtd->priv = this;
	ppchameleon_mtd->owner = THIS_MODULE;

	/* Initialize GPIOs */
	/* Pin mapping for NAND chip */
	/*
	   CE   GPIO_01
	   CLE  GPIO_02
	   ALE  GPIO_03
	   R/B  GPIO_04
	 */
	/* output select */
	out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xC0FFFFFF);
	/* three-state select */
	out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xC0FFFFFF);
	/* enable output driver */
	out_be32((volatile unsigned *)GPIO0_TCR,
		 in_be32((volatile unsigned *)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
#ifdef USE_READY_BUSY_PIN
	/* three-state select */
	out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFF3FFFFF);
	/* high-impedecence */
	out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
	/* input select */
	out_be32((volatile unsigned *)GPIO0_ISR1H,
		 (in_be32((volatile unsigned *)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
#endif

	/* insert callbacks */
	this->IO_ADDR_R = ppchameleon_fio_base;
	this->IO_ADDR_W = ppchameleon_fio_base;
	this->cmd_ctrl = ppchameleon_hwcontrol;
#ifdef USE_READY_BUSY_PIN
	this->dev_ready = ppchameleon_device_ready;
#endif
	this->chip_delay = NAND_BIG_DELAY_US;
	/* ECC mode */
	this->ecc.mode = NAND_ECC_SOFT;

	/* Scan to find existence of the device (it could not be mounted) */
	if (nand_scan(ppchameleon_mtd, 1)) {
		iounmap((void *)ppchameleon_fio_base);
		ppchameleon_fio_base = NULL;
		kfree(ppchameleon_mtd);
		goto nand_evb_init;
	}
#ifndef USE_READY_BUSY_PIN
	/* Adjust delay if necessary */
	if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
		this->chip_delay = NAND_SMALL_DELAY_US;
#endif

	ppchameleon_mtd->name = "ppchameleon-nand";

	/* Register the partitions */
	mtd_device_parse_register(ppchameleon_mtd, NULL, 0,
			ppchameleon_mtd->size == NAND_SMALL_SIZE ?
				partition_info_me :
				partition_info_hi,
			NUM_PARTITIONS);

 nand_evb_init:
	/****************************
	* EVB NAND (always present) *
	****************************/
	/* Allocate memory for MTD device structure and private data */
	ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
	if (!ppchameleonevb_mtd) {
		printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
		if (ppchameleon_fio_base)
			iounmap(ppchameleon_fio_base);
		return -ENOMEM;
	}

	/* map physical address */
	ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M);
	if (!ppchameleonevb_fio_base) {
		printk("ioremap PPChameleonEVB NAND flash failed\n");
		kfree(ppchameleonevb_mtd);
		if (ppchameleon_fio_base)
			iounmap(ppchameleon_fio_base);
		return -EIO;
	}

	/* Get pointer to private data */
	this = (struct nand_chip *)(&ppchameleonevb_mtd[1]);

	/* Initialize structures */
	memset(ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
	memset(this, 0, sizeof(struct nand_chip));

	/* Link the private data with the MTD structure */
	ppchameleonevb_mtd->priv = this;

	/* Initialize GPIOs */
	/* Pin mapping for NAND chip */
	/*
	   CE   GPIO_14
	   CLE  GPIO_15
	   ALE  GPIO_16
	   R/B  GPIO_31
	 */
	/* output select */
	out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xFFFFFFF0);
	out_be32((volatile unsigned *)GPIO0_OSRL, in_be32((volatile unsigned *)GPIO0_OSRL) & 0x3FFFFFFF);
	/* three-state select */
	out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFFFFFFF0);
	out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0x3FFFFFFF);
	/* enable output driver */
	out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
		 NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
#ifdef USE_READY_BUSY_PIN
	/* three-state select */
	out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0xFFFFFFFC);
	/* high-impedecence */
	out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
	/* input select */
	out_be32((volatile unsigned *)GPIO0_ISR1L,
		 (in_be32((volatile unsigned *)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
#endif

	/* insert callbacks */
	this->IO_ADDR_R = ppchameleonevb_fio_base;
	this->IO_ADDR_W = ppchameleonevb_fio_base;
	this->cmd_ctrl = ppchameleonevb_hwcontrol;
#ifdef USE_READY_BUSY_PIN
	this->dev_ready = ppchameleonevb_device_ready;
#endif
	this->chip_delay = NAND_SMALL_DELAY_US;

	/* ECC mode */
	this->ecc.mode = NAND_ECC_SOFT;

	/* Scan to find existence of the device */
	if (nand_scan(ppchameleonevb_mtd, 1)) {
		iounmap((void *)ppchameleonevb_fio_base);
		kfree(ppchameleonevb_mtd);
		if (ppchameleon_fio_base)
			iounmap(ppchameleon_fio_base);
		return -ENXIO;
	}

	ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;

	/* Register the partitions */
	mtd_device_parse_register(ppchameleonevb_mtd, NULL, 0,
			ppchameleon_mtd->size == NAND_SMALL_SIZE ?
				partition_info_me :
				partition_info_hi,
			NUM_PARTITIONS);

	/* Return happy */
	return 0;
}
static int __init ams_delta_init(void)
{
	struct nand_chip *this;
	int err = 0;

	/* Allocate memory for MTD device structure and private data */
	ams_delta_mtd = kmalloc(sizeof(struct mtd_info) +
				sizeof(struct nand_chip), GFP_KERNEL);
	if (!ams_delta_mtd) {
		printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
		err = -ENOMEM;
		goto out;
	}

	ams_delta_mtd->owner = THIS_MODULE;

	/* Get pointer to private data */
	this = (struct nand_chip *) (&ams_delta_mtd[1]);

	/* Initialize structures */
	memset(ams_delta_mtd, 0, sizeof(struct mtd_info));
	memset(this, 0, sizeof(struct nand_chip));

	/* Link the private data with the MTD structure */
	ams_delta_mtd->priv = this;

	/* Set address of NAND IO lines */
	this->IO_ADDR_R = (OMAP1_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH);
	this->IO_ADDR_W = (OMAP1_MPUIO_BASE + OMAP_MPUIO_OUTPUT);
	this->read_byte = ams_delta_read_byte;
	this->write_buf = ams_delta_write_buf;
	this->read_buf = ams_delta_read_buf;
	this->verify_buf = ams_delta_verify_buf;
	this->cmd_ctrl = ams_delta_hwcontrol;
	if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
		this->dev_ready = ams_delta_nand_ready;
	} else {
		this->dev_ready = NULL;
		printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n");
	}
	/* 25 us command delay time */
	this->chip_delay = 30;
	this->ecc.mode = NAND_ECC_SOFT;

	/* Set chip enabled, but  */
	ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
					  AMS_DELTA_LATCH2_NAND_NWE |
					  AMS_DELTA_LATCH2_NAND_NCE |
					  AMS_DELTA_LATCH2_NAND_NWP);

	/* Scan to find existance of the device */
	if (nand_scan(ams_delta_mtd, 1)) {
		err = -ENXIO;
		goto out_mtd;
	}

	/* Register the partitions */
	add_mtd_partitions(ams_delta_mtd, partition_info,
			   ARRAY_SIZE(partition_info));

	goto out;

 out_mtd:
	kfree(ams_delta_mtd);
 out:
	return err;
}
예제 #8
0
static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
{
	int err = 0;
	struct nand_chip *this;
	struct mtd_info *new_mtd;

	printk(KERN_NOTICE "Probing CS553x NAND controller CS#%d at %sIO 0x%08lx\n", cs, mmio?"MM":"P", adr);

	if (!mmio) {
		printk(KERN_NOTICE "PIO mode not yet implemented for CS553X NAND controller\n");
		return -ENXIO;
	}

	/* Allocate memory for MTD device structure and private data */
	new_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
	if (!new_mtd) {
		err = -ENOMEM;
		goto out;
	}

	/* Get pointer to private data */
	this = (struct nand_chip *)(&new_mtd[1]);

	/* Link the private data with the MTD structure */
	new_mtd->priv = this;
	new_mtd->owner = THIS_MODULE;

	/* map physical address */
	this->IO_ADDR_R = this->IO_ADDR_W = ioremap(adr, 4096);
	if (!this->IO_ADDR_R) {
		printk(KERN_WARNING "ioremap cs553x NAND @0x%08lx failed\n", adr);
		err = -EIO;
		goto out_mtd;
	}

	this->cmd_ctrl = cs553x_hwcontrol;
	this->dev_ready = cs553x_device_ready;
	this->read_byte = cs553x_read_byte;
	this->read_buf = cs553x_read_buf;
	this->write_buf = cs553x_write_buf;

	this->chip_delay = 0;

	this->ecc.mode = NAND_ECC_HW;
	this->ecc.size = 256;
	this->ecc.bytes = 3;
	this->ecc.hwctl  = cs_enable_hwecc;
	this->ecc.calculate = cs_calculate_ecc;
	this->ecc.correct  = nand_correct_data;
	this->ecc.strength = 1;

	/* Enable the following for a flash based bad block table */
	this->bbt_options = NAND_BBT_USE_FLASH;

	new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs);
	if (!new_mtd->name) {
		err = -ENOMEM;
		goto out_ior;
	}

	/* Scan to find existence of the device */
	if (nand_scan(new_mtd, 1)) {
		err = -ENXIO;
		goto out_free;
	}

	cs553x_mtd[cs] = new_mtd;
	goto out;

out_free:
	kfree(new_mtd->name);
out_ior:
	iounmap(this->IO_ADDR_R);
out_mtd:
	kfree(new_mtd);
out:
	return err;
}
예제 #9
0
static int __devinit pasemi_nand_probe(struct platform_device *ofdev,
				      const struct of_device_id *match)
{
	struct pci_dev *pdev;
	struct device_node *np = ofdev->dev.of_node;
	struct resource res;
	struct nand_chip *chip;
	int err = 0;

	err = of_address_to_resource(np, 0, &res);

	if (err)
		return -EINVAL;

	/* We only support one device at the moment */
	if (pasemi_nand_mtd)
		return -ENODEV;

	pr_debug("pasemi_nand at %llx-%llx\n", res.start, res.end);

	/* Allocate memory for MTD device structure and private data */
	pasemi_nand_mtd = kzalloc(sizeof(struct mtd_info) +
				  sizeof(struct nand_chip), GFP_KERNEL);
	if (!pasemi_nand_mtd) {
		printk(KERN_WARNING
		       "Unable to allocate PASEMI NAND MTD device structure\n");
		err = -ENOMEM;
		goto out;
	}

	/* Get pointer to private data */
	chip = (struct nand_chip *)&pasemi_nand_mtd[1];

	/* Link the private data with the MTD structure */
	pasemi_nand_mtd->priv = chip;
	pasemi_nand_mtd->owner = THIS_MODULE;

	chip->IO_ADDR_R = of_iomap(np, 0);
	chip->IO_ADDR_W = chip->IO_ADDR_R;

	if (!chip->IO_ADDR_R) {
		err = -EIO;
		goto out_mtd;
	}

	pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa008, NULL);
	if (!pdev) {
		err = -ENODEV;
		goto out_ior;
	}

	lpcctl = pci_resource_start(pdev, 0);
	pci_dev_put(pdev);

	if (!request_region(lpcctl, 4, driver_name)) {
		err = -EBUSY;
		goto out_ior;
	}

	chip->cmd_ctrl = pasemi_hwcontrol;
	chip->dev_ready = pasemi_device_ready;
	chip->read_buf = pasemi_read_buf;
	chip->write_buf = pasemi_write_buf;
	chip->chip_delay = 0;
	chip->ecc.mode = NAND_ECC_SOFT;

	/* Enable the following for a flash based bad block table */
	chip->options = NAND_NO_AUTOINCR;
	chip->bbt_options = NAND_BBT_USE_FLASH;

	/* Scan to find existance of the device */
	if (nand_scan(pasemi_nand_mtd, 1)) {
		err = -ENXIO;
		goto out_lpc;
	}

	if (add_mtd_device(pasemi_nand_mtd)) {
		printk(KERN_ERR "pasemi_nand: Unable to register MTD device\n");
		err = -ENODEV;
		goto out_lpc;
	}

	printk(KERN_INFO "PA Semi NAND flash at %08llx, control at I/O %x\n",
	       res.start, lpcctl);

	return 0;

 out_lpc:
	release_region(lpcctl, 4);
 out_ior:
	iounmap(chip->IO_ADDR_R);
 out_mtd:
	kfree(pasemi_nand_mtd);
 out:
	return err;
}
예제 #10
0
static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
{
	struct nand_chip *this;
#ifdef CONFIG_MTD_PARTITIONS
	struct mtd_partition *sharpsl_partition_info;
	int nr_partitions;
#endif
	struct resource *r;
	int err = 0;
	struct sharpsl_nand *sharpsl;
	struct sharpsl_nand_platform_data *data = pdev->dev.platform_data;

	if (!data) {
		dev_err(&pdev->dev, "no platform data!\n");
		return -EINVAL;
	}

	/* Allocate memory for MTD device structure and private data */
	sharpsl = kzalloc(sizeof(struct sharpsl_nand), GFP_KERNEL);
	if (!sharpsl) {
		printk("Unable to allocate SharpSL NAND MTD device structure.\n");
		return -ENOMEM;
	}

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!r) {
		dev_err(&pdev->dev, "no io memory resource defined!\n");
		err = -ENODEV;
		goto err_get_res;
	}

	/* map physical address */
	sharpsl->io = ioremap(r->start, resource_size(r));
	if (!sharpsl->io) {
		printk("ioremap to access Sharp SL NAND chip failed\n");
		err = -EIO;
		goto err_ioremap;
	}

	/* Get pointer to private data */
	this = (struct nand_chip *)(&sharpsl->chip);

	/* Link the private data with the MTD structure */
	sharpsl->mtd.priv = this;
	sharpsl->mtd.owner = THIS_MODULE;

	platform_set_drvdata(pdev, sharpsl);

	/*
	 * PXA initialize
	 */
	writeb(readb(sharpsl->io + FLASHCTL) | FLWP, sharpsl->io + FLASHCTL);

	/* Set address of NAND IO lines */
	this->IO_ADDR_R = sharpsl->io + FLASHIO;
	this->IO_ADDR_W = sharpsl->io + FLASHIO;
	/* Set address of hardware control function */
	this->cmd_ctrl = sharpsl_nand_hwcontrol;
	this->dev_ready = sharpsl_nand_dev_ready;
	/* 15 us command delay time */
	this->chip_delay = 15;
	/* set eccmode using hardware ECC */
	this->ecc.mode = NAND_ECC_HW;
	this->ecc.size = 256;
	this->ecc.bytes = 3;
	this->badblock_pattern = data->badblock_pattern;
	this->ecc.layout = data->ecc_layout;
	this->ecc.hwctl = sharpsl_nand_enable_hwecc;
	this->ecc.calculate = sharpsl_nand_calculate_ecc;
	this->ecc.correct = nand_correct_data;

	/* Scan to find existence of the device */
	err = nand_scan(&sharpsl->mtd, 1);
	if (err)
		goto err_scan;

	/* Register the partitions */
	sharpsl->mtd.name = "sharpsl-nand";
#ifdef CONFIG_MTD_PARTITIONS
	nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0);
	if (nr_partitions <= 0) {
		nr_partitions = data->nr_partitions;
		sharpsl_partition_info = data->partitions;
	}

	if (nr_partitions > 0)
		err = add_mtd_partitions(&sharpsl->mtd, sharpsl_partition_info, nr_partitions);
	else
#endif
	err = add_mtd_device(&sharpsl->mtd);
	if (err)
		goto err_add;

	/* Return happy */
	return 0;

err_add:
	nand_release(&sharpsl->mtd);

err_scan:
	platform_set_drvdata(pdev, NULL);
	iounmap(sharpsl->io);
err_ioremap:
err_get_res:
	kfree(sharpsl);
	return err;
}