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.
12 #include <linux/err.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/slab.h>
17 #include <linux/mtd/mtd.h>
18 #include <linux/mtd/nand.h>
19 #include <linux/mtd/partitions.h>
21 struct plat_nand_data
{
22 struct nand_chip chip
;
24 void __iomem
*io_base
;
27 static const char *part_probe_types
[] = { "cmdlinepart", NULL
};
30 * Probe for the NAND device.
32 static int plat_nand_probe(struct platform_device
*pdev
)
34 struct platform_nand_data
*pdata
= dev_get_platdata(&pdev
->dev
);
35 struct mtd_part_parser_data ppdata
;
36 struct plat_nand_data
*data
;
38 const char **part_types
;
42 dev_err(&pdev
->dev
, "platform_nand_data is missing\n");
46 if (pdata
->chip
.nr_chips
< 1) {
47 dev_err(&pdev
->dev
, "invalid number of chips specified\n");
51 /* Allocate memory for the device structure (and zero it) */
52 data
= devm_kzalloc(&pdev
->dev
, sizeof(struct plat_nand_data
),
57 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
58 data
->io_base
= devm_ioremap_resource(&pdev
->dev
, res
);
59 if (IS_ERR(data
->io_base
))
60 return PTR_ERR(data
->io_base
);
62 data
->chip
.priv
= &data
;
63 data
->mtd
.priv
= &data
->chip
;
64 data
->mtd
.owner
= THIS_MODULE
;
65 data
->mtd
.name
= dev_name(&pdev
->dev
);
67 data
->chip
.IO_ADDR_R
= data
->io_base
;
68 data
->chip
.IO_ADDR_W
= data
->io_base
;
69 data
->chip
.cmd_ctrl
= pdata
->ctrl
.cmd_ctrl
;
70 data
->chip
.dev_ready
= pdata
->ctrl
.dev_ready
;
71 data
->chip
.select_chip
= pdata
->ctrl
.select_chip
;
72 data
->chip
.write_buf
= pdata
->ctrl
.write_buf
;
73 data
->chip
.read_buf
= pdata
->ctrl
.read_buf
;
74 data
->chip
.read_byte
= pdata
->ctrl
.read_byte
;
75 data
->chip
.chip_delay
= pdata
->chip
.chip_delay
;
76 data
->chip
.options
|= pdata
->chip
.options
;
77 data
->chip
.bbt_options
|= pdata
->chip
.bbt_options
;
79 data
->chip
.ecc
.hwctl
= pdata
->ctrl
.hwcontrol
;
80 data
->chip
.ecc
.layout
= pdata
->chip
.ecclayout
;
81 data
->chip
.ecc
.mode
= NAND_ECC_SOFT
;
83 platform_set_drvdata(pdev
, data
);
85 /* Handle any platform specific setup */
86 if (pdata
->ctrl
.probe
) {
87 err
= pdata
->ctrl
.probe(pdev
);
92 /* Scan to find existence of the device */
93 if (nand_scan(&data
->mtd
, pdata
->chip
.nr_chips
)) {
98 part_types
= pdata
->chip
.part_probe_types
? : part_probe_types
;
100 ppdata
.of_node
= pdev
->dev
.of_node
;
101 err
= mtd_device_parse_register(&data
->mtd
, part_types
, &ppdata
,
102 pdata
->chip
.partitions
,
103 pdata
->chip
.nr_partitions
);
108 nand_release(&data
->mtd
);
110 if (pdata
->ctrl
.remove
)
111 pdata
->ctrl
.remove(pdev
);
116 * Remove a NAND device.
118 static int plat_nand_remove(struct platform_device
*pdev
)
120 struct plat_nand_data
*data
= platform_get_drvdata(pdev
);
121 struct platform_nand_data
*pdata
= dev_get_platdata(&pdev
->dev
);
123 nand_release(&data
->mtd
);
124 if (pdata
->ctrl
.remove
)
125 pdata
->ctrl
.remove(pdev
);
130 static const struct of_device_id plat_nand_match
[] = {
131 { .compatible
= "gen_nand" },
134 MODULE_DEVICE_TABLE(of
, plat_nand_match
);
136 static struct platform_driver plat_nand_driver
= {
137 .probe
= plat_nand_probe
,
138 .remove
= plat_nand_remove
,
141 .owner
= THIS_MODULE
,
142 .of_match_table
= plat_nand_match
,
146 module_platform_driver(plat_nand_driver
);
148 MODULE_LICENSE("GPL");
149 MODULE_AUTHOR("Vitaly Wool");
150 MODULE_DESCRIPTION("Simple generic NAND driver");
151 MODULE_ALIAS("platform:gen_nand");