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
;
25 struct mtd_partition
*parts
;
29 * Probe for the NAND device.
31 static int __devinit
plat_nand_probe(struct platform_device
*pdev
)
33 struct platform_nand_data
*pdata
= pdev
->dev
.platform_data
;
34 struct plat_nand_data
*data
;
38 if (pdata
->chip
.nr_chips
< 1) {
39 dev_err(&pdev
->dev
, "invalid number of chips specified\n");
43 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
47 /* Allocate memory for the device structure (and zero it) */
48 data
= kzalloc(sizeof(struct plat_nand_data
), GFP_KERNEL
);
50 dev_err(&pdev
->dev
, "failed to allocate device structure.\n");
54 if (!request_mem_region(res
->start
, resource_size(res
),
55 dev_name(&pdev
->dev
))) {
56 dev_err(&pdev
->dev
, "request_mem_region failed\n");
61 data
->io_base
= ioremap(res
->start
, resource_size(res
));
62 if (data
->io_base
== NULL
) {
63 dev_err(&pdev
->dev
, "ioremap failed\n");
68 data
->chip
.priv
= &data
;
69 data
->mtd
.priv
= &data
->chip
;
70 data
->mtd
.owner
= THIS_MODULE
;
71 data
->mtd
.name
= dev_name(&pdev
->dev
);
73 data
->chip
.IO_ADDR_R
= data
->io_base
;
74 data
->chip
.IO_ADDR_W
= data
->io_base
;
75 data
->chip
.cmd_ctrl
= pdata
->ctrl
.cmd_ctrl
;
76 data
->chip
.dev_ready
= pdata
->ctrl
.dev_ready
;
77 data
->chip
.select_chip
= pdata
->ctrl
.select_chip
;
78 data
->chip
.write_buf
= pdata
->ctrl
.write_buf
;
79 data
->chip
.read_buf
= pdata
->ctrl
.read_buf
;
80 data
->chip
.chip_delay
= pdata
->chip
.chip_delay
;
81 data
->chip
.options
|= pdata
->chip
.options
;
83 data
->chip
.ecc
.hwctl
= pdata
->ctrl
.hwcontrol
;
84 data
->chip
.ecc
.layout
= pdata
->chip
.ecclayout
;
85 data
->chip
.ecc
.mode
= NAND_ECC_SOFT
;
87 platform_set_drvdata(pdev
, data
);
89 /* Handle any platform specific setup */
90 if (pdata
->ctrl
.probe
) {
91 err
= pdata
->ctrl
.probe(pdev
);
96 /* Scan to find existence of the device */
97 if (nand_scan(&data
->mtd
, pdata
->chip
.nr_chips
)) {
102 if (pdata
->chip
.part_probe_types
) {
103 err
= parse_mtd_partitions(&data
->mtd
,
104 pdata
->chip
.part_probe_types
,
107 mtd_device_register(&data
->mtd
, data
->parts
, err
);
111 if (pdata
->chip
.set_parts
)
112 pdata
->chip
.set_parts(data
->mtd
.size
, &pdata
->chip
);
113 if (pdata
->chip
.partitions
) {
114 data
->parts
= pdata
->chip
.partitions
;
115 err
= mtd_device_register(&data
->mtd
, data
->parts
,
116 pdata
->chip
.nr_partitions
);
118 err
= mtd_device_register(&data
->mtd
, NULL
, 0);
123 nand_release(&data
->mtd
);
125 if (pdata
->ctrl
.remove
)
126 pdata
->ctrl
.remove(pdev
);
127 platform_set_drvdata(pdev
, NULL
);
128 iounmap(data
->io_base
);
130 release_mem_region(res
->start
, resource_size(res
));
137 * Remove a NAND device.
139 static int __devexit
plat_nand_remove(struct platform_device
*pdev
)
141 struct plat_nand_data
*data
= platform_get_drvdata(pdev
);
142 struct platform_nand_data
*pdata
= pdev
->dev
.platform_data
;
143 struct resource
*res
;
145 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
147 nand_release(&data
->mtd
);
148 if (data
->parts
&& data
->parts
!= pdata
->chip
.partitions
)
150 if (pdata
->ctrl
.remove
)
151 pdata
->ctrl
.remove(pdev
);
152 iounmap(data
->io_base
);
153 release_mem_region(res
->start
, resource_size(res
));
159 static struct platform_driver plat_nand_driver
= {
160 .probe
= plat_nand_probe
,
161 .remove
= __devexit_p(plat_nand_remove
),
164 .owner
= THIS_MODULE
,
168 static int __init
plat_nand_init(void)
170 return platform_driver_register(&plat_nand_driver
);
173 static void __exit
plat_nand_exit(void)
175 platform_driver_unregister(&plat_nand_driver
);
178 module_init(plat_nand_init
);
179 module_exit(plat_nand_exit
);
181 MODULE_LICENSE("GPL");
182 MODULE_AUTHOR("Vitaly Wool");
183 MODULE_DESCRIPTION("Simple generic NAND driver");
184 MODULE_ALIAS("platform:gen_nand");