aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/onenand/omap-onenand.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/onenand/omap-onenand.c')
-rw-r--r--drivers/mtd/onenand/omap-onenand.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c
new file mode 100644
index 000000000000..56e1aec6b835
--- /dev/null
+++ b/drivers/mtd/onenand/omap-onenand.c
@@ -0,0 +1,178 @@
1/*
2 * linux/drivers/mtd/onenand/omap-onenand.c
3 *
4 * Copyright (c) 2005 Samsung Electronics
5 * Kyungmin Park <kyungmin.park@samsung.com>
6 *
7 * Derived from linux/drivers/mtd/nand/omap-nand-flash.c
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * Overview:
14 * This is a device driver for the OneNAND flash device for TI OMAP boards.
15 */
16
17#include <linux/slab.h>
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/onenand.h>
22#include <linux/mtd/partitions.h>
23
24#include <asm/io.h>
25#include <asm/arch/hardware.h>
26#include <asm/arch/tc.h>
27#include <asm/sizes.h>
28
29#define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS
30#define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS
31/*
32 * MTD structure for OMAP board
33 */
34static struct mtd_info *omap_onenand_mtd = NULL;
35
36/*
37 * Define partitions for flash devices
38 */
39
40#ifdef CONFIG_MTD_PARTITIONS
41static struct mtd_partition static_partition[] = {
42 {
43 .name = "X-Loader + U-Boot",
44 .offset = 0,
45 .size = SZ_128K,
46 .mask_flags = MTD_WRITEABLE /* force read-only */
47 },
48 {
49 .name = "U-Boot Environment",
50 .offset = MTDPART_OFS_APPEND,
51 .size = SZ_128K,
52 .mask_flags = MTD_WRITEABLE /* force read-only */
53 },
54 {
55 .name = "kernel",
56 .offset = MTDPART_OFS_APPEND,
57 .size = 2 * SZ_1M
58 },
59 {
60 .name = "filesystem0",
61 .offset = MTDPART_OFS_APPEND,
62 .size = SZ_16M,
63 },
64 {
65 .name = "filesystem1",
66 .offset = MTDPART_OFS_APPEND,
67 .size = MTDPART_SIZ_FULL,
68 },
69};
70
71const char *part_probes[] = { "cmdlinepart", NULL, };
72
73#endif
74
75/* Scan to find existance of the device at base.
76 This also allocates oob and data internal buffers */
77static char onenand_name[] = "onenand";
78
79/*
80 * Main initialization routine
81 */
82static int __init omap_onenand_init (void)
83{
84 struct onenand_chip *this;
85 struct mtd_partition *dynamic_partition = 0;
86 int err = 0;
87
88 /* Allocate memory for MTD device structure and private data */
89 omap_onenand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct onenand_chip),
90 GFP_KERNEL);
91 if (!omap_onenand_mtd) {
92 printk (KERN_WARNING "Unable to allocate OneNAND MTD device structure.\n");
93 err = -ENOMEM;
94 goto out;
95 }
96
97 /* Get pointer to private data */
98 this = (struct onenand_chip *) (&omap_onenand_mtd[1]);
99
100 /* Initialize structures */
101 memset((char *) omap_onenand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct onenand_chip));
102
103 /* Link the private data with the MTD structure */
104 omap_onenand_mtd->priv = this;
105
106 /* try the first address */
107 this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K);
108 omap_onenand_mtd->name = onenand_name;
109 if (onenand_scan(omap_onenand_mtd, 1)){
110 /* try the second address */
111 iounmap(this->base);
112 this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K);
113 if (onenand_scan(omap_onenand_mtd, 1)) {
114 iounmap(this->base);
115 err = -ENXIO;
116 goto out_mtd;
117 }
118 }
119
120 /* Register the partitions */
121 switch (omap_onenand_mtd->size) {
122 case SZ_128M:
123 case SZ_64M:
124 case SZ_32M:
125#ifdef CONFIG_MTD_PARTITIONS
126 err = parse_mtd_partitions(omap_onenand_mtd, part_probes,
127 &dynamic_partition, 0);
128 if (err > 0)
129 err = add_mtd_partitions(omap_onenand_mtd,
130 dynamic_partition, err);
131 else if (1)
132 err = add_mtd_partitions(omap_onenand_mtd,
133 static_partition,
134 ARRAY_SIZE(static_partition));
135 else
136#endif
137 err = add_mtd_device(omap_onenand_mtd);
138 if (err)
139 goto out_buf;
140 break;
141
142 default:
143 printk(KERN_WARNING "Unsupported OneNAND device\n");
144 err = -ENXIO;
145 goto out_buf;
146 }
147
148 return 0;
149
150out_buf:
151 onenand_release(omap_onenand_mtd);
152 iounmap(this->base);
153out_mtd:
154 kfree(omap_onenand_mtd);
155out:
156 return err;
157}
158
159/*
160 * Clean up routine
161 */
162static void __exit omap_onenand_cleanup (void)
163{
164 struct onenand_chip *this = omap_onenand_mtd->priv;
165
166 /* onenand_release frees MTD partitions, MTD structure
167 and onenand internal buffers */
168 onenand_release(omap_onenand_mtd);
169 iounmap(this->base);
170 kfree(omap_onenand_mtd);
171}
172
173module_init(omap_onenand_init);
174module_exit(omap_onenand_cleanup);
175
176MODULE_LICENSE("GPL");
177MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
178MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP boards");