aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/chips/gen_probe.c6
-rw-r--r--drivers/mtd/devices/docprobe.c47
-rw-r--r--drivers/mtd/nand/Kconfig6
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/ams-delta.c238
5 files changed, 253 insertions, 45 deletions
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index 00ca6f591202..cdb0f590b40c 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -207,14 +207,14 @@ static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
207 struct cfi_private *cfi = map->fldrv_priv; 207 struct cfi_private *cfi = map->fldrv_priv;
208 __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID; 208 __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
209#ifdef CONFIG_MODULES 209#ifdef CONFIG_MODULES
210 char probename[32]; 210 char probename[16+sizeof(MODULE_SYMBOL_PREFIX)];
211 cfi_cmdset_fn_t *probe_function; 211 cfi_cmdset_fn_t *probe_function;
212 212
213 sprintf(probename, "cfi_cmdset_%4.4X", type); 213 sprintf(probename, MODULE_SYMBOL_PREFIX "cfi_cmdset_%4.4X", type);
214 214
215 probe_function = __symbol_get(probename); 215 probe_function = __symbol_get(probename);
216 if (!probe_function) { 216 if (!probe_function) {
217 request_module(probename); 217 request_module(probename + sizeof(MODULE_SYMBOL_PREFIX) - 1);
218 probe_function = __symbol_get(probename); 218 probe_function = __symbol_get(probename);
219 } 219 }
220 220
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index dce4c904b636..593bb033a3fa 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -231,26 +231,9 @@ static inline int __init doccheck(void __iomem *potential, unsigned long physadr
231 231
232static int docfound; 232static int docfound;
233 233
234#ifdef CONFIG_MTD_DOC2000
235extern void DoC2k_init(struct mtd_info *); 234extern void DoC2k_init(struct mtd_info *);
236#define doc2k_initfunc (&DoC2k_init)
237#else
238#define doc2k_initfunc NULL
239#endif
240
241#ifdef CONFIG_MTD_DOC2001
242extern void DoCMil_init(struct mtd_info *); 235extern void DoCMil_init(struct mtd_info *);
243#define docmil_initfunc (&DoCMil_init)
244#else
245#define docmil_initfunc NULL
246#endif
247
248#ifdef CONFIG_MTD_DOC2001PLUS
249extern void DoCMilPlus_init(struct mtd_info *); 236extern void DoCMilPlus_init(struct mtd_info *);
250#define docmplus_initfunc (&DoCMilPlus_init)
251#else
252#define docmplus_initfunc NULL
253#endif
254 237
255static void __init DoC_Probe(unsigned long physadr) 238static void __init DoC_Probe(unsigned long physadr)
256{ 239{
@@ -260,8 +243,6 @@ static void __init DoC_Probe(unsigned long physadr)
260 int ChipID; 243 int ChipID;
261 char namebuf[15]; 244 char namebuf[15];
262 char *name = namebuf; 245 char *name = namebuf;
263 char *im_funcname = NULL;
264 char *im_modname = NULL;
265 void (*initroutine)(struct mtd_info *) = NULL; 246 void (*initroutine)(struct mtd_info *) = NULL;
266 247
267 docptr = ioremap(physadr, DOC_IOREMAP_LEN); 248 docptr = ioremap(physadr, DOC_IOREMAP_LEN);
@@ -299,48 +280,30 @@ static void __init DoC_Probe(unsigned long physadr)
299 switch(ChipID) { 280 switch(ChipID) {
300 case DOC_ChipID_Doc2kTSOP: 281 case DOC_ChipID_Doc2kTSOP:
301 name="2000 TSOP"; 282 name="2000 TSOP";
302 im_funcname = "DoC2k_init"; 283 initroutine = symbol_request(DoC2k_init);
303 im_modname = "doc2000";
304 initroutine = doc2k_initfunc;
305 break; 284 break;
306 285
307 case DOC_ChipID_Doc2k: 286 case DOC_ChipID_Doc2k:
308 name="2000"; 287 name="2000";
309 im_funcname = "DoC2k_init"; 288 initroutine = symbol_request(DoC2k_init);
310 im_modname = "doc2000";
311 initroutine = doc2k_initfunc;
312 break; 289 break;
313 290
314 case DOC_ChipID_DocMil: 291 case DOC_ChipID_DocMil:
315 name="Millennium"; 292 name="Millennium";
316#ifdef DOC_SINGLE_DRIVER 293#ifdef DOC_SINGLE_DRIVER
317 im_funcname = "DoC2k_init"; 294 initroutine = symbol_request(DoC2k_init);
318 im_modname = "doc2000";
319 initroutine = doc2k_initfunc;
320#else 295#else
321 im_funcname = "DoCMil_init"; 296 initroutine = symbol_request(DoCMil_init);
322 im_modname = "doc2001";
323 initroutine = docmil_initfunc;
324#endif /* DOC_SINGLE_DRIVER */ 297#endif /* DOC_SINGLE_DRIVER */
325 break; 298 break;
326 299
327 case DOC_ChipID_DocMilPlus16: 300 case DOC_ChipID_DocMilPlus16:
328 case DOC_ChipID_DocMilPlus32: 301 case DOC_ChipID_DocMilPlus32:
329 name="MillenniumPlus"; 302 name="MillenniumPlus";
330 im_funcname = "DoCMilPlus_init"; 303 initroutine = symbol_request(DoCMilPlus_init);
331 im_modname = "doc2001plus";
332 initroutine = docmplus_initfunc;
333 break; 304 break;
334 } 305 }
335 306
336#ifdef CONFIG_MODULES
337 if (im_funcname && !initroutine)
338 initroutine = __symbol_get(im_funcname);
339 if (im_funcname && !initroutine) {
340 request_module(im_modname);
341 initroutine = __symbol_get(im_funcname);
342 }
343#endif
344 if (initroutine) { 307 if (initroutine) {
345 (*initroutine)(mtd); 308 (*initroutine)(mtd);
346 symbol_put_addr(initroutine); 309 symbol_put_addr(initroutine);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index b1f807980b79..2d0ebad55a49 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -49,6 +49,12 @@ config MTD_NAND_SPIA
49 help 49 help
50 If you had to ask, you don't have one. Say 'N'. 50 If you had to ask, you don't have one. Say 'N'.
51 51
52config MTD_NAND_AMS_DELTA
53 tristate "NAND Flash device on Amstrad E3"
54 depends on MACH_AMS_DELTA && MTD_NAND
55 help
56 Support for NAND flash on Amstrad E3 (Delta).
57
52config MTD_NAND_TOTO 58config MTD_NAND_TOTO
53 tristate "NAND Flash device on TOTO board" 59 tristate "NAND Flash device on TOTO board"
54 depends on ARCH_OMAP && MTD_NAND 60 depends on ARCH_OMAP && MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 0741d739cb87..33475087dbff 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o
7obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o 7obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
8 8
9obj-$(CONFIG_MTD_NAND_SPIA) += spia.o 9obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
10obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
10obj-$(CONFIG_MTD_NAND_TOTO) += toto.o 11obj-$(CONFIG_MTD_NAND_TOTO) += toto.o
11obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o 12obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
12obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o 13obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
new file mode 100644
index 000000000000..5a349eb316f5
--- /dev/null
+++ b/drivers/mtd/nand/ams-delta.c
@@ -0,0 +1,238 @@
1/*
2 * drivers/mtd/nand/ams-delta.c
3 *
4 * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
5 *
6 * Derived from drivers/mtd/toto.c
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Overview:
13 * This is a device driver for the NAND flash device found on the
14 * Amstrad E3 (Delta).
15 */
16
17#include <linux/slab.h>
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/delay.h>
21#include <linux/mtd/mtd.h>
22#include <linux/mtd/nand.h>
23#include <linux/mtd/partitions.h>
24#include <asm/io.h>
25#include <asm/arch/hardware.h>
26#include <asm/sizes.h>
27#include <asm/arch/gpio.h>
28#include <asm/arch/board-ams-delta.h>
29
30/*
31 * MTD structure for E3 (Delta)
32 */
33static struct mtd_info *ams_delta_mtd = NULL;
34
35#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP)
36
37#define T_NAND_CTL_CLRALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, 0)
38#define T_NAND_CTL_SETALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, AMS_DELTA_LATCH2_NAND_ALE)
39#define T_NAND_CTL_CLRCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, 0)
40#define T_NAND_CTL_SETCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, AMS_DELTA_LATCH2_NAND_CLE)
41#define T_NAND_CTL_SETNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, 0)
42#define T_NAND_CTL_CLRNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, AMS_DELTA_LATCH2_NAND_NCE)
43
44/*
45 * Define partitions for flash devices
46 */
47
48static struct mtd_partition partition_info[] = {
49 { .name = "Kernel",
50 .offset = 0,
51 .size = 3 * SZ_1M + SZ_512K },
52 { .name = "u-boot",
53 .offset = 3 * SZ_1M + SZ_512K,
54 .size = SZ_256K },
55 { .name = "u-boot params",
56 .offset = 3 * SZ_1M + SZ_512K + SZ_256K,
57 .size = SZ_256K },
58 { .name = "Amstrad LDR",
59 .offset = 4 * SZ_1M,
60 .size = SZ_256K },
61 { .name = "File system",
62 .offset = 4 * SZ_1M + 1 * SZ_256K,
63 .size = 27 * SZ_1M },
64 { .name = "PBL reserved",
65 .offset = 32 * SZ_1M - 3 * SZ_256K,
66 .size = 3 * SZ_256K },
67};
68
69/*
70 * hardware specific access to control-lines
71*/
72
73static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd)
74{
75 switch (cmd) {
76
77 case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
78 case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
79
80 case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
81 case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
82
83 case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
84 case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
85 }
86}
87
88static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
89{
90 struct nand_chip *this = mtd->priv;
91
92 omap_writew(0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
93 omap_writew(byte, this->IO_ADDR_W);
94 ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0);
95 ndelay(40);
96 ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE,
97 AMS_DELTA_LATCH2_NAND_NWE);
98}
99
100static u_char ams_delta_read_byte(struct mtd_info *mtd)
101{
102 u_char res;
103 struct nand_chip *this = mtd->priv;
104
105 ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0);
106 ndelay(40);
107 omap_writew(~0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
108 res = omap_readw(this->IO_ADDR_R);
109 ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE,
110 AMS_DELTA_LATCH2_NAND_NRE);
111
112 return res;
113}
114
115static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
116 int len)
117{
118 int i;
119
120 for (i=0; i<len; i++)
121 ams_delta_write_byte(mtd, buf[i]);
122}
123
124static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
125{
126 int i;
127
128 for (i=0; i<len; i++)
129 buf[i] = ams_delta_read_byte(mtd);
130}
131
132static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
133 int len)
134{
135 int i;
136
137 for (i=0; i<len; i++)
138 if (buf[i] != ams_delta_read_byte(mtd))
139 return -EFAULT;
140
141 return 0;
142}
143
144static int ams_delta_nand_ready(struct mtd_info *mtd)
145{
146 return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB);
147}
148
149/*
150 * Main initialization routine
151 */
152static int __init ams_delta_init(void)
153{
154 struct nand_chip *this;
155 int err = 0;
156
157 /* Allocate memory for MTD device structure and private data */
158 ams_delta_mtd = kmalloc(sizeof(struct mtd_info) +
159 sizeof(struct nand_chip), GFP_KERNEL);
160 if (!ams_delta_mtd) {
161 printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
162 err = -ENOMEM;
163 goto out;
164 }
165
166 ams_delta_mtd->owner = THIS_MODULE;
167
168 /* Get pointer to private data */
169 this = (struct nand_chip *) (&ams_delta_mtd[1]);
170
171 /* Initialize structures */
172 memset(ams_delta_mtd, 0, sizeof(struct mtd_info));
173 memset(this, 0, sizeof(struct nand_chip));
174
175 /* Link the private data with the MTD structure */
176 ams_delta_mtd->priv = this;
177
178 /* Set address of NAND IO lines */
179 this->IO_ADDR_R = (OMAP_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH);
180 this->IO_ADDR_W = (OMAP_MPUIO_BASE + OMAP_MPUIO_OUTPUT);
181 this->read_byte = ams_delta_read_byte;
182 this->write_byte = ams_delta_write_byte;
183 this->write_buf = ams_delta_write_buf;
184 this->read_buf = ams_delta_read_buf;
185 this->verify_buf = ams_delta_verify_buf;
186 this->hwcontrol = ams_delta_hwcontrol;
187 if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) {
188 this->dev_ready = ams_delta_nand_ready;
189 } else {
190 this->dev_ready = NULL;
191 printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n");
192 }
193 /* 25 us command delay time */
194 this->chip_delay = 30;
195 this->eccmode = NAND_ECC_SOFT;
196
197 /* Set chip enabled, but */
198 ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
199 AMS_DELTA_LATCH2_NAND_NWE |
200 AMS_DELTA_LATCH2_NAND_NCE |
201 AMS_DELTA_LATCH2_NAND_NWP);
202
203 /* Scan to find existance of the device */
204 if (nand_scan(ams_delta_mtd, 1)) {
205 err = -ENXIO;
206 goto out_mtd;
207 }
208
209 /* Register the partitions */
210 add_mtd_partitions(ams_delta_mtd, partition_info,
211 ARRAY_SIZE(partition_info));
212
213 goto out;
214
215 out_mtd:
216 kfree(ams_delta_mtd);
217 out:
218 return err;
219}
220
221module_init(ams_delta_init);
222
223/*
224 * Clean up routine
225 */
226static void __exit ams_delta_cleanup(void)
227{
228 /* Release resources, unregister device */
229 nand_release(ams_delta_mtd);
230
231 /* Free the MTD device structure */
232 kfree(ams_delta_mtd);
233}
234module_exit(ams_delta_cleanup);
235
236MODULE_LICENSE("GPL");
237MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
238MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)");