diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 13:10:11 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 13:10:11 -0700 |
commit | ba7cc09c9c9e29a57045dc5bbf843ac1cfad3283 (patch) | |
tree | 7e2d39269803b53ba048f3bad11cd6a1a38b35b9 /drivers/mtd/nand/plat_nand.c | |
parent | d84c4124c4b6611301b402e8611b7e36de3bd351 (diff) | |
parent | b7aa48be1e7a11e36448a7db58931bbf735d2718 (diff) |
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (21 commits)
[MTD] [CHIPS] Remove MTD_OBSOLETE_CHIPS (jedec, amd_flash, sharp)
[MTD] Delete allegedly obsolete "bank_size" field of mtd_info.
[MTD] Remove unnecessary user space check from mtd.h.
[MTD] [MAPS] Remove flash maps for no longer supported 405LP boards
[MTD] [MAPS] Fix missing printk() parameter in physmap_of.c MTD driver
[MTD] [NAND] platform NAND driver: add driver
[MTD] [NAND] platform NAND driver: update header
[JFFS2] Simplify and clean up jffs2_add_tn_to_tree() some more.
[JFFS2] Remove another bogus optimisation in jffs2_add_tn_to_tree()
[JFFS2] Remove broken insert_point optimisation in jffs2_add_tn_to_tree()
[JFFS2] Remember to calculate overlap on nodes which replace older nodes
[JFFS2] Don't advance c->wbuf_ofs to next eraseblock after wbuf flush
[MTD] [NAND] at91_nand.c: CMDLINE_PARTS support
[MTD] [NAND] Tidy up handling of page number in nand_block_bad()
[MTD] block2mtd_paramline[] mustn't be __initdata
[MTD] [NAND] Support multiple chips in CAFÉ driver
[MTD] [NAND] Rename cafe.c to cafe_nand.c and remove the multi-obj magic
[MTD] [NAND] Use rslib for CAFÉ ECC
[RSLIB] Support non-canonical GF representations
[JFFS2] Remove dead file histo_mips.h
...
Diffstat (limited to 'drivers/mtd/nand/plat_nand.c')
-rw-r--r-- | drivers/mtd/nand/plat_nand.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c new file mode 100644 index 00000000000..cd725fc5e81 --- /dev/null +++ b/drivers/mtd/nand/plat_nand.c @@ -0,0 +1,150 @@ +/* + * Generic NAND driver + * + * Author: Vitaly Wool <vitalywool@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> + +struct plat_nand_data { + struct nand_chip chip; + struct mtd_info mtd; + void __iomem *io_base; +#ifdef CONFIG_MTD_PARTITIONS + int nr_parts; + struct mtd_partition *parts; +#endif +}; + +/* + * 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->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; +} + +/* + * Remove a NAND device. + */ +static int __devexit plat_nand_remove(struct platform_device *pdev) +{ + struct plat_nand_data *data = platform_get_drvdata(pdev); + struct platform_nand_data *pdata = pdev->dev.platform_data; + + nand_release(&data->mtd); +#ifdef CONFIG_MTD_PARTITIONS + if (data->parts && data->parts != pdata->chip.partitions) + kfree(data->parts); +#endif + iounmap(data->io_base); + kfree(data); + + return 0; +} + +static struct platform_driver plat_nand_driver = { + .probe = plat_nand_probe, + .remove = plat_nand_remove, + .driver = { + .name = "gen_nand", + .owner = THIS_MODULE, + }, +}; + +static int __init plat_nand_init(void) +{ + return platform_driver_register(&plat_nand_driver); +} + +static void __exit plat_nand_exit(void) +{ + platform_driver_unregister(&plat_nand_driver); +} + +module_init(plat_nand_init); +module_exit(plat_nand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Vitaly Wool"); +MODULE_DESCRIPTION("Simple generic NAND driver"); |