4 * Author: Vitaly Wool <vitalywool@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/slab.h>
16 #include <linux/mtd/mtd.h>
17 #include <linux/mtd/nand.h>
18 #include <linux/mtd/partitions.h>
20 struct plat_nand_data
{
21 struct nand_chip chip
;
23 void __iomem
*io_base
;
24 #ifdef CONFIG_MTD_PARTITIONS
26 struct mtd_partition
*parts
;
31 * Probe for the NAND device.
33 static int __init
plat_nand_probe(struct platform_device
*pdev
)
35 struct platform_nand_data
*pdata
= pdev
->dev
.platform_data
;
36 struct plat_nand_data
*data
;
39 /* Allocate memory for the device structure (and zero it) */
40 data
= kzalloc(sizeof(struct plat_nand_data
), GFP_KERNEL
);
42 dev_err(&pdev
->dev
, "failed to allocate device structure.\n");
46 data
->io_base
= ioremap(pdev
->resource
[0].start
,
47 pdev
->resource
[0].end
- pdev
->resource
[0].start
+ 1);
48 if (data
->io_base
== NULL
) {
49 dev_err(&pdev
->dev
, "ioremap failed\n");
54 data
->chip
.priv
= &data
;
55 data
->mtd
.priv
= &data
->chip
;
56 data
->mtd
.owner
= THIS_MODULE
;
58 data
->chip
.IO_ADDR_R
= data
->io_base
;
59 data
->chip
.IO_ADDR_W
= data
->io_base
;
60 data
->chip
.cmd_ctrl
= pdata
->ctrl
.cmd_ctrl
;
61 data
->chip
.dev_ready
= pdata
->ctrl
.dev_ready
;
62 data
->chip
.select_chip
= pdata
->ctrl
.select_chip
;
63 data
->chip
.chip_delay
= pdata
->chip
.chip_delay
;
64 data
->chip
.options
|= pdata
->chip
.options
;
66 data
->chip
.ecc
.hwctl
= pdata
->ctrl
.hwcontrol
;
67 data
->chip
.ecc
.layout
= pdata
->chip
.ecclayout
;
68 data
->chip
.ecc
.mode
= NAND_ECC_SOFT
;
70 platform_set_drvdata(pdev
, data
);
72 /* Scan to find existance of the device */
73 if (nand_scan(&data
->mtd
, 1)) {
78 #ifdef CONFIG_MTD_PARTITIONS
79 if (pdata
->chip
.part_probe_types
) {
80 res
= parse_mtd_partitions(&data
->mtd
,
81 pdata
->chip
.part_probe_types
,
84 add_mtd_partitions(&data
->mtd
, data
->parts
, res
);
88 if (pdata
->chip
.partitions
) {
89 data
->parts
= pdata
->chip
.partitions
;
90 res
= add_mtd_partitions(&data
->mtd
, data
->parts
,
91 pdata
->chip
.nr_partitions
);
94 res
= add_mtd_device(&data
->mtd
);
99 nand_release(&data
->mtd
);
101 platform_set_drvdata(pdev
, NULL
);
102 iounmap(data
->io_base
);
108 * Remove a NAND device.
110 static int __devexit
plat_nand_remove(struct platform_device
*pdev
)
112 struct plat_nand_data
*data
= platform_get_drvdata(pdev
);
113 struct platform_nand_data
*pdata
= pdev
->dev
.platform_data
;
115 nand_release(&data
->mtd
);
116 #ifdef CONFIG_MTD_PARTITIONS
117 if (data
->parts
&& data
->parts
!= pdata
->chip
.partitions
)
120 iounmap(data
->io_base
);
126 static struct platform_driver plat_nand_driver
= {
127 .probe
= plat_nand_probe
,
128 .remove
= plat_nand_remove
,
131 .owner
= THIS_MODULE
,
135 static int __init
plat_nand_init(void)
137 return platform_driver_register(&plat_nand_driver
);
140 static void __exit
plat_nand_exit(void)
142 platform_driver_unregister(&plat_nand_driver
);
145 module_init(plat_nand_init
);
146 module_exit(plat_nand_exit
);
148 MODULE_LICENSE("GPL");
149 MODULE_AUTHOR("Vitaly Wool");
150 MODULE_DESCRIPTION("Simple generic NAND driver");