diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/mtd/nand |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/Kconfig | 207 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 24 | ||||
-rw-r--r-- | drivers/mtd/nand/au1550nd.c | 477 | ||||
-rw-r--r-- | drivers/mtd/nand/autcpu12.c | 225 | ||||
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 1782 | ||||
-rw-r--r-- | drivers/mtd/nand/edb7312.c | 218 | ||||
-rw-r--r-- | drivers/mtd/nand/h1910.c | 208 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 2563 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 1056 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_ecc.c | 250 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_ids.c | 129 | ||||
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 1613 | ||||
-rw-r--r-- | drivers/mtd/nand/ppchameleonevb.c | 420 | ||||
-rw-r--r-- | drivers/mtd/nand/rtc_from4.c | 559 | ||||
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 704 | ||||
-rwxr-xr-x | drivers/mtd/nand/sharpsl.c | 260 | ||||
-rw-r--r-- | drivers/mtd/nand/spia.c | 173 | ||||
-rw-r--r-- | drivers/mtd/nand/toto.c | 205 | ||||
-rw-r--r-- | drivers/mtd/nand/tx4925ndfmc.c | 416 | ||||
-rw-r--r-- | drivers/mtd/nand/tx4938ndfmc.c | 406 |
20 files changed, 11895 insertions, 0 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig new file mode 100644 index 000000000000..f7801eb730ce --- /dev/null +++ b/drivers/mtd/nand/Kconfig | |||
@@ -0,0 +1,207 @@ | |||
1 | # drivers/mtd/nand/Kconfig | ||
2 | # $Id: Kconfig,v 1.26 2005/01/05 12:42:24 dwmw2 Exp $ | ||
3 | |||
4 | menu "NAND Flash Device Drivers" | ||
5 | depends on MTD!=n | ||
6 | |||
7 | config MTD_NAND | ||
8 | tristate "NAND Device Support" | ||
9 | depends on MTD | ||
10 | select MTD_NAND_IDS | ||
11 | help | ||
12 | This enables support for accessing all type of NAND flash | ||
13 | devices. For further information see | ||
14 | <http://www.linux-mtd.infradead.org/tech/nand.html>. | ||
15 | |||
16 | config MTD_NAND_VERIFY_WRITE | ||
17 | bool "Verify NAND page writes" | ||
18 | depends on MTD_NAND | ||
19 | help | ||
20 | This adds an extra check when data is written to the flash. The | ||
21 | NAND flash device internally checks only bits transitioning | ||
22 | from 1 to 0. There is a rare possibility that even though the | ||
23 | device thinks the write was successful, a bit could have been | ||
24 | flipped accidentaly due to device wear or something else. | ||
25 | |||
26 | config MTD_NAND_AUTCPU12 | ||
27 | tristate "SmartMediaCard on autronix autcpu12 board" | ||
28 | depends on ARM && MTD_NAND && ARCH_AUTCPU12 | ||
29 | help | ||
30 | This enables the driver for the autronix autcpu12 board to | ||
31 | access the SmartMediaCard. | ||
32 | |||
33 | config MTD_NAND_EDB7312 | ||
34 | tristate "Support for Cirrus Logic EBD7312 evaluation board" | ||
35 | depends on ARM && MTD_NAND && ARCH_EDB7312 | ||
36 | help | ||
37 | This enables the driver for the Cirrus Logic EBD7312 evaluation | ||
38 | board to access the onboard NAND Flash. | ||
39 | |||
40 | config MTD_NAND_H1900 | ||
41 | tristate "iPAQ H1900 flash" | ||
42 | depends on ARM && MTD_NAND && ARCH_PXA && MTD_PARTITIONS | ||
43 | help | ||
44 | This enables the driver for the iPAQ h1900 flash. | ||
45 | |||
46 | config MTD_NAND_SPIA | ||
47 | tristate "NAND Flash device on SPIA board" | ||
48 | depends on ARM && ARCH_P720T && MTD_NAND | ||
49 | help | ||
50 | If you had to ask, you don't have one. Say 'N'. | ||
51 | |||
52 | config MTD_NAND_TOTO | ||
53 | tristate "NAND Flash device on TOTO board" | ||
54 | depends on ARM && ARCH_OMAP && MTD_NAND | ||
55 | help | ||
56 | Support for NAND flash on Texas Instruments Toto platform. | ||
57 | |||
58 | config MTD_NAND_IDS | ||
59 | tristate | ||
60 | |||
61 | config MTD_NAND_TX4925NDFMC | ||
62 | tristate "SmartMedia Card on Toshiba RBTX4925 reference board" | ||
63 | depends on TOSHIBA_RBTX4925 && MTD_NAND && TOSHIBA_RBTX4925_MPLEX_NAND | ||
64 | help | ||
65 | This enables the driver for the NAND flash device found on the | ||
66 | Toshiba RBTX4925 reference board, which is a SmartMediaCard. | ||
67 | |||
68 | config MTD_NAND_TX4938NDFMC | ||
69 | tristate "NAND Flash device on Toshiba RBTX4938 reference board" | ||
70 | depends on TOSHIBA_RBTX4938 && MTD_NAND && TOSHIBA_RBTX4938_MPLEX_NAND | ||
71 | help | ||
72 | This enables the driver for the NAND flash device found on the | ||
73 | Toshiba RBTX4938 reference board. | ||
74 | |||
75 | config MTD_NAND_AU1550 | ||
76 | tristate "Au1550 NAND support" | ||
77 | depends on SOC_AU1550 && MTD_NAND | ||
78 | help | ||
79 | This enables the driver for the NAND flash controller on the | ||
80 | AMD/Alchemy 1550 SOC. | ||
81 | |||
82 | config MTD_NAND_RTC_FROM4 | ||
83 | tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)" | ||
84 | depends on MTD_NAND && SH_SOLUTION_ENGINE | ||
85 | select REED_SOLOMON | ||
86 | select REED_SOLOMON_DEC8 | ||
87 | help | ||
88 | This enables the driver for the Renesas Technology AG-AND | ||
89 | flash interface board (FROM_BOARD4) | ||
90 | |||
91 | config MTD_NAND_PPCHAMELEONEVB | ||
92 | tristate "NAND Flash device on PPChameleonEVB board" | ||
93 | depends on PPCHAMELEONEVB && MTD_NAND | ||
94 | help | ||
95 | This enables the NAND flash driver on the PPChameleon EVB Board. | ||
96 | |||
97 | config MTD_NAND_S3C2410 | ||
98 | tristate "NAND Flash support for S3C2410 SoC" | ||
99 | depends on ARCH_S3C2410 && MTD_NAND | ||
100 | help | ||
101 | This enables the NAND flash controller on the S3C2410. | ||
102 | |||
103 | No board specfic support is done by this driver, each board | ||
104 | must advertise a platform_device for the driver to attach. | ||
105 | |||
106 | config MTD_NAND_S3C2410_DEBUG | ||
107 | bool "S3C2410 NAND driver debug" | ||
108 | depends on MTD_NAND_S3C2410 | ||
109 | help | ||
110 | Enable debugging of the S3C2410 NAND driver | ||
111 | |||
112 | config MTD_NAND_S3C2410_HWECC | ||
113 | bool "S3C2410 NAND Hardware ECC" | ||
114 | depends on MTD_NAND_S3C2410 | ||
115 | help | ||
116 | Enable the use of the S3C2410's internal ECC generator when | ||
117 | using NAND. Early versions of the chip have had problems with | ||
118 | incorrect ECC generation, and if using these, the default of | ||
119 | software ECC is preferable. | ||
120 | |||
121 | If you lay down a device with the hardware ECC, then you will | ||
122 | currently not be able to switch to software, as there is no | ||
123 | implementation for ECC method used by the S3C2410 | ||
124 | |||
125 | config MTD_NAND_DISKONCHIP | ||
126 | tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" | ||
127 | depends on MTD_NAND && EXPERIMENTAL | ||
128 | select REED_SOLOMON | ||
129 | select REED_SOLOMON_DEC16 | ||
130 | help | ||
131 | This is a reimplementation of M-Systems DiskOnChip 2000, | ||
132 | Millennium and Millennium Plus as a standard NAND device driver, | ||
133 | as opposed to the earlier self-contained MTD device drivers. | ||
134 | This should enable, among other things, proper JFFS2 operation on | ||
135 | these devices. | ||
136 | |||
137 | config MTD_NAND_DISKONCHIP_PROBE_ADVANCED | ||
138 | bool "Advanced detection options for DiskOnChip" | ||
139 | depends on MTD_NAND_DISKONCHIP | ||
140 | help | ||
141 | This option allows you to specify nonstandard address at which to | ||
142 | probe for a DiskOnChip, or to change the detection options. You | ||
143 | are unlikely to need any of this unless you are using LinuxBIOS. | ||
144 | Say 'N'. | ||
145 | |||
146 | config MTD_NAND_DISKONCHIP_PROBE_ADDRESS | ||
147 | hex "Physical address of DiskOnChip" if MTD_NAND_DISKONCHIP_PROBE_ADVANCED | ||
148 | depends on MTD_NAND_DISKONCHIP | ||
149 | default "0" | ||
150 | ---help--- | ||
151 | By default, the probe for DiskOnChip devices will look for a | ||
152 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | ||
153 | This option allows you to specify a single address at which to probe | ||
154 | for the device, which is useful if you have other devices in that | ||
155 | range which get upset when they are probed. | ||
156 | |||
157 | (Note that on PowerPC, the normal probe will only check at | ||
158 | 0xE4000000.) | ||
159 | |||
160 | Normally, you should leave this set to zero, to allow the probe at | ||
161 | the normal addresses. | ||
162 | |||
163 | config MTD_NAND_DISKONCHIP_PROBE_HIGH | ||
164 | bool "Probe high addresses" | ||
165 | depends on MTD_NAND_DISKONCHIP_PROBE_ADVANCED | ||
166 | help | ||
167 | By default, the probe for DiskOnChip devices will look for a | ||
168 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | ||
169 | This option changes to make it probe between 0xFFFC8000 and | ||
170 | 0xFFFEE000. Unless you are using LinuxBIOS, this is unlikely to be | ||
171 | useful to you. Say 'N'. | ||
172 | |||
173 | config MTD_NAND_DISKONCHIP_BBTWRITE | ||
174 | bool "Allow BBT writes on DiskOnChip Millennium and 2000TSOP" | ||
175 | depends on MTD_NAND_DISKONCHIP | ||
176 | help | ||
177 | On DiskOnChip devices shipped with the INFTL filesystem (Millennium | ||
178 | and 2000 TSOP/Alon), Linux reserves some space at the end of the | ||
179 | device for the Bad Block Table (BBT). If you have existing INFTL | ||
180 | data on your device (created by non-Linux tools such as M-Systems' | ||
181 | DOS drivers), your data might overlap the area Linux wants to use for | ||
182 | the BBT. If this is a concern for you, leave this option disabled and | ||
183 | Linux will not write BBT data into this area. | ||
184 | The downside of leaving this option disabled is that if bad blocks | ||
185 | are detected by Linux, they will not be recorded in the BBT, which | ||
186 | could cause future problems. | ||
187 | Once you enable this option, new filesystems (INFTL or others, created | ||
188 | in Linux or other operating systems) will not use the reserved area. | ||
189 | The only reason not to enable this option is to prevent damage to | ||
190 | preexisting filesystems. | ||
191 | Even if you leave this disabled, you can enable BBT writes at module | ||
192 | load time (assuming you build diskonchip as a module) with the module | ||
193 | parameter "inftl_bbt_write=1". | ||
194 | |||
195 | config MTD_NAND_SHARPSL | ||
196 | bool "Support for NAND Flash on Sharp SL Series (C7xx + others)" | ||
197 | depends on MTD_NAND && ARCH_PXA | ||
198 | |||
199 | config MTD_NAND_NANDSIM | ||
200 | bool "Support for NAND Flash Simulator" | ||
201 | depends on MTD_NAND && MTD_PARTITIONS | ||
202 | |||
203 | help | ||
204 | The simulator may simulate verious NAND flash chips for the | ||
205 | MTD nand layer. | ||
206 | |||
207 | endmenu | ||
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile new file mode 100644 index 000000000000..d9dc8cc2da8c --- /dev/null +++ b/drivers/mtd/nand/Makefile | |||
@@ -0,0 +1,24 @@ | |||
1 | # | ||
2 | # linux/drivers/nand/Makefile | ||
3 | # | ||
4 | # $Id: Makefile.common,v 1.15 2004/11/26 12:28:22 dedekind Exp $ | ||
5 | |||
6 | obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o | ||
7 | obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o | ||
8 | |||
9 | obj-$(CONFIG_MTD_NAND_SPIA) += spia.o | ||
10 | obj-$(CONFIG_MTD_NAND_TOTO) += toto.o | ||
11 | obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o | ||
12 | obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o | ||
13 | obj-$(CONFIG_MTD_NAND_TX4925NDFMC) += tx4925ndfmc.o | ||
14 | obj-$(CONFIG_MTD_NAND_TX4938NDFMC) += tx4938ndfmc.o | ||
15 | obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o | ||
16 | obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o | ||
17 | obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o | ||
18 | obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o | ||
19 | obj-$(CONFIG_MTD_NAND_H1900) += h1910.o | ||
20 | obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o | ||
21 | obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o | ||
22 | obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o | ||
23 | |||
24 | nand-objs = nand_base.o nand_bbt.o | ||
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c new file mode 100644 index 000000000000..4c7719ce3f48 --- /dev/null +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -0,0 +1,477 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/au1550nd.c | ||
3 | * | ||
4 | * Copyright (C) 2004 Embedded Edge, LLC | ||
5 | * | ||
6 | * $Id: au1550nd.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $ | ||
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 | */ | ||
13 | |||
14 | #include <linux/slab.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/mtd/mtd.h> | ||
18 | #include <linux/mtd/nand.h> | ||
19 | #include <linux/mtd/partitions.h> | ||
20 | #include <asm/io.h> | ||
21 | |||
22 | /* fixme: this is ugly */ | ||
23 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) | ||
24 | #include <asm/mach-au1x00/au1000.h> | ||
25 | #ifdef CONFIG_MIPS_PB1550 | ||
26 | #include <asm/mach-pb1x00/pb1550.h> | ||
27 | #endif | ||
28 | #ifdef CONFIG_MIPS_DB1550 | ||
29 | #include <asm/mach-db1x00/db1x00.h> | ||
30 | #endif | ||
31 | #else | ||
32 | #include <asm/au1000.h> | ||
33 | #ifdef CONFIG_MIPS_PB1550 | ||
34 | #include <asm/pb1550.h> | ||
35 | #endif | ||
36 | #ifdef CONFIG_MIPS_DB1550 | ||
37 | #include <asm/db1x00.h> | ||
38 | #endif | ||
39 | #endif | ||
40 | |||
41 | /* | ||
42 | * MTD structure for NAND controller | ||
43 | */ | ||
44 | static struct mtd_info *au1550_mtd = NULL; | ||
45 | static void __iomem *p_nand; | ||
46 | static int nand_width = 1; /* default x8*/ | ||
47 | |||
48 | #define NAND_CS 1 | ||
49 | |||
50 | /* | ||
51 | * Define partitions for flash device | ||
52 | */ | ||
53 | const static struct mtd_partition partition_info[] = { | ||
54 | #ifdef CONFIG_MIPS_PB1550 | ||
55 | #define NUM_PARTITIONS 2 | ||
56 | { | ||
57 | .name = "Pb1550 NAND FS 0", | ||
58 | .offset = 0, | ||
59 | .size = 8*1024*1024 | ||
60 | }, | ||
61 | { | ||
62 | .name = "Pb1550 NAND FS 1", | ||
63 | .offset = MTDPART_OFS_APPEND, | ||
64 | .size = MTDPART_SIZ_FULL | ||
65 | } | ||
66 | #endif | ||
67 | #ifdef CONFIG_MIPS_DB1550 | ||
68 | #define NUM_PARTITIONS 2 | ||
69 | { | ||
70 | .name = "Db1550 NAND FS 0", | ||
71 | .offset = 0, | ||
72 | .size = 8*1024*1024 | ||
73 | }, | ||
74 | { | ||
75 | .name = "Db1550 NAND FS 1", | ||
76 | .offset = MTDPART_OFS_APPEND, | ||
77 | .size = MTDPART_SIZ_FULL | ||
78 | } | ||
79 | #endif | ||
80 | }; | ||
81 | |||
82 | |||
83 | /** | ||
84 | * au_read_byte - read one byte from the chip | ||
85 | * @mtd: MTD device structure | ||
86 | * | ||
87 | * read function for 8bit buswith | ||
88 | */ | ||
89 | static u_char au_read_byte(struct mtd_info *mtd) | ||
90 | { | ||
91 | struct nand_chip *this = mtd->priv; | ||
92 | u_char ret = readb(this->IO_ADDR_R); | ||
93 | au_sync(); | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * au_write_byte - write one byte to the chip | ||
99 | * @mtd: MTD device structure | ||
100 | * @byte: pointer to data byte to write | ||
101 | * | ||
102 | * write function for 8it buswith | ||
103 | */ | ||
104 | static void au_write_byte(struct mtd_info *mtd, u_char byte) | ||
105 | { | ||
106 | struct nand_chip *this = mtd->priv; | ||
107 | writeb(byte, this->IO_ADDR_W); | ||
108 | au_sync(); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * au_read_byte16 - read one byte endianess aware from the chip | ||
113 | * @mtd: MTD device structure | ||
114 | * | ||
115 | * read function for 16bit buswith with | ||
116 | * endianess conversion | ||
117 | */ | ||
118 | static u_char au_read_byte16(struct mtd_info *mtd) | ||
119 | { | ||
120 | struct nand_chip *this = mtd->priv; | ||
121 | u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); | ||
122 | au_sync(); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * au_write_byte16 - write one byte endianess aware to the chip | ||
128 | * @mtd: MTD device structure | ||
129 | * @byte: pointer to data byte to write | ||
130 | * | ||
131 | * write function for 16bit buswith with | ||
132 | * endianess conversion | ||
133 | */ | ||
134 | static void au_write_byte16(struct mtd_info *mtd, u_char byte) | ||
135 | { | ||
136 | struct nand_chip *this = mtd->priv; | ||
137 | writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); | ||
138 | au_sync(); | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * au_read_word - read one word from the chip | ||
143 | * @mtd: MTD device structure | ||
144 | * | ||
145 | * read function for 16bit buswith without | ||
146 | * endianess conversion | ||
147 | */ | ||
148 | static u16 au_read_word(struct mtd_info *mtd) | ||
149 | { | ||
150 | struct nand_chip *this = mtd->priv; | ||
151 | u16 ret = readw(this->IO_ADDR_R); | ||
152 | au_sync(); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * au_write_word - write one word to the chip | ||
158 | * @mtd: MTD device structure | ||
159 | * @word: data word to write | ||
160 | * | ||
161 | * write function for 16bit buswith without | ||
162 | * endianess conversion | ||
163 | */ | ||
164 | static void au_write_word(struct mtd_info *mtd, u16 word) | ||
165 | { | ||
166 | struct nand_chip *this = mtd->priv; | ||
167 | writew(word, this->IO_ADDR_W); | ||
168 | au_sync(); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * au_write_buf - write buffer to chip | ||
173 | * @mtd: MTD device structure | ||
174 | * @buf: data buffer | ||
175 | * @len: number of bytes to write | ||
176 | * | ||
177 | * write function for 8bit buswith | ||
178 | */ | ||
179 | static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
180 | { | ||
181 | int i; | ||
182 | struct nand_chip *this = mtd->priv; | ||
183 | |||
184 | for (i=0; i<len; i++) { | ||
185 | writeb(buf[i], this->IO_ADDR_W); | ||
186 | au_sync(); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * au_read_buf - read chip data into buffer | ||
192 | * @mtd: MTD device structure | ||
193 | * @buf: buffer to store date | ||
194 | * @len: number of bytes to read | ||
195 | * | ||
196 | * read function for 8bit buswith | ||
197 | */ | ||
198 | static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len) | ||
199 | { | ||
200 | int i; | ||
201 | struct nand_chip *this = mtd->priv; | ||
202 | |||
203 | for (i=0; i<len; i++) { | ||
204 | buf[i] = readb(this->IO_ADDR_R); | ||
205 | au_sync(); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * au_verify_buf - Verify chip data against buffer | ||
211 | * @mtd: MTD device structure | ||
212 | * @buf: buffer containing the data to compare | ||
213 | * @len: number of bytes to compare | ||
214 | * | ||
215 | * verify function for 8bit buswith | ||
216 | */ | ||
217 | static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
218 | { | ||
219 | int i; | ||
220 | struct nand_chip *this = mtd->priv; | ||
221 | |||
222 | for (i=0; i<len; i++) { | ||
223 | if (buf[i] != readb(this->IO_ADDR_R)) | ||
224 | return -EFAULT; | ||
225 | au_sync(); | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * au_write_buf16 - write buffer to chip | ||
233 | * @mtd: MTD device structure | ||
234 | * @buf: data buffer | ||
235 | * @len: number of bytes to write | ||
236 | * | ||
237 | * write function for 16bit buswith | ||
238 | */ | ||
239 | static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) | ||
240 | { | ||
241 | int i; | ||
242 | struct nand_chip *this = mtd->priv; | ||
243 | u16 *p = (u16 *) buf; | ||
244 | len >>= 1; | ||
245 | |||
246 | for (i=0; i<len; i++) { | ||
247 | writew(p[i], this->IO_ADDR_W); | ||
248 | au_sync(); | ||
249 | } | ||
250 | |||
251 | } | ||
252 | |||
253 | /** | ||
254 | * au_read_buf16 - read chip data into buffer | ||
255 | * @mtd: MTD device structure | ||
256 | * @buf: buffer to store date | ||
257 | * @len: number of bytes to read | ||
258 | * | ||
259 | * read function for 16bit buswith | ||
260 | */ | ||
261 | static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len) | ||
262 | { | ||
263 | int i; | ||
264 | struct nand_chip *this = mtd->priv; | ||
265 | u16 *p = (u16 *) buf; | ||
266 | len >>= 1; | ||
267 | |||
268 | for (i=0; i<len; i++) { | ||
269 | p[i] = readw(this->IO_ADDR_R); | ||
270 | au_sync(); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * au_verify_buf16 - Verify chip data against buffer | ||
276 | * @mtd: MTD device structure | ||
277 | * @buf: buffer containing the data to compare | ||
278 | * @len: number of bytes to compare | ||
279 | * | ||
280 | * verify function for 16bit buswith | ||
281 | */ | ||
282 | static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) | ||
283 | { | ||
284 | int i; | ||
285 | struct nand_chip *this = mtd->priv; | ||
286 | u16 *p = (u16 *) buf; | ||
287 | len >>= 1; | ||
288 | |||
289 | for (i=0; i<len; i++) { | ||
290 | if (p[i] != readw(this->IO_ADDR_R)) | ||
291 | return -EFAULT; | ||
292 | au_sync(); | ||
293 | } | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | |||
298 | static void au1550_hwcontrol(struct mtd_info *mtd, int cmd) | ||
299 | { | ||
300 | register struct nand_chip *this = mtd->priv; | ||
301 | |||
302 | switch(cmd){ | ||
303 | |||
304 | case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break; | ||
305 | case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break; | ||
306 | |||
307 | case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break; | ||
308 | case NAND_CTL_CLRALE: | ||
309 | this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; | ||
310 | /* FIXME: Nobody knows why this is neccecary, | ||
311 | * but it works only that way */ | ||
312 | udelay(1); | ||
313 | break; | ||
314 | |||
315 | case NAND_CTL_SETNCE: | ||
316 | /* assert (force assert) chip enable */ | ||
317 | au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break; | ||
318 | break; | ||
319 | |||
320 | case NAND_CTL_CLRNCE: | ||
321 | /* deassert chip enable */ | ||
322 | au_writel(0, MEM_STNDCTL); break; | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | this->IO_ADDR_R = this->IO_ADDR_W; | ||
327 | |||
328 | /* Drain the writebuffer */ | ||
329 | au_sync(); | ||
330 | } | ||
331 | |||
332 | int au1550_device_ready(struct mtd_info *mtd) | ||
333 | { | ||
334 | int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0; | ||
335 | au_sync(); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * Main initialization routine | ||
341 | */ | ||
342 | int __init au1550_init (void) | ||
343 | { | ||
344 | struct nand_chip *this; | ||
345 | u16 boot_swapboot = 0; /* default value */ | ||
346 | int retval; | ||
347 | |||
348 | /* Allocate memory for MTD device structure and private data */ | ||
349 | au1550_mtd = kmalloc (sizeof(struct mtd_info) + | ||
350 | sizeof (struct nand_chip), GFP_KERNEL); | ||
351 | if (!au1550_mtd) { | ||
352 | printk ("Unable to allocate NAND MTD dev structure.\n"); | ||
353 | return -ENOMEM; | ||
354 | } | ||
355 | |||
356 | /* Get pointer to private data */ | ||
357 | this = (struct nand_chip *) (&au1550_mtd[1]); | ||
358 | |||
359 | /* Initialize structures */ | ||
360 | memset((char *) au1550_mtd, 0, sizeof(struct mtd_info)); | ||
361 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
362 | |||
363 | /* Link the private data with the MTD structure */ | ||
364 | au1550_mtd->priv = this; | ||
365 | |||
366 | |||
367 | /* MEM_STNDCTL: disable ints, disable nand boot */ | ||
368 | au_writel(0, MEM_STNDCTL); | ||
369 | |||
370 | #ifdef CONFIG_MIPS_PB1550 | ||
371 | /* set gpio206 high */ | ||
372 | au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR); | ||
373 | |||
374 | boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | | ||
375 | ((bcsr->status >> 6) & 0x1); | ||
376 | switch (boot_swapboot) { | ||
377 | case 0: | ||
378 | case 2: | ||
379 | case 8: | ||
380 | case 0xC: | ||
381 | case 0xD: | ||
382 | /* x16 NAND Flash */ | ||
383 | nand_width = 0; | ||
384 | break; | ||
385 | case 1: | ||
386 | case 9: | ||
387 | case 3: | ||
388 | case 0xE: | ||
389 | case 0xF: | ||
390 | /* x8 NAND Flash */ | ||
391 | nand_width = 1; | ||
392 | break; | ||
393 | default: | ||
394 | printk("Pb1550 NAND: bad boot:swap\n"); | ||
395 | retval = -EINVAL; | ||
396 | goto outmem; | ||
397 | } | ||
398 | #endif | ||
399 | |||
400 | /* Configure RCE1 - should be done by YAMON */ | ||
401 | au_writel(0x5 | (nand_width << 22), 0xB4001010); /* MEM_STCFG1 */ | ||
402 | au_writel(NAND_TIMING, 0xB4001014); /* MEM_STTIME1 */ | ||
403 | au_sync(); | ||
404 | |||
405 | /* setup and enable chip select, MEM_STADDR1 */ | ||
406 | /* we really need to decode offsets only up till 0x20 */ | ||
407 | au_writel((1<<28) | (NAND_PHYS_ADDR>>4) | | ||
408 | (((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18), | ||
409 | MEM_STADDR1); | ||
410 | au_sync(); | ||
411 | |||
412 | p_nand = ioremap(NAND_PHYS_ADDR, 0x1000); | ||
413 | |||
414 | /* Set address of hardware control function */ | ||
415 | this->hwcontrol = au1550_hwcontrol; | ||
416 | this->dev_ready = au1550_device_ready; | ||
417 | /* 30 us command delay time */ | ||
418 | this->chip_delay = 30; | ||
419 | this->eccmode = NAND_ECC_SOFT; | ||
420 | |||
421 | this->options = NAND_NO_AUTOINCR; | ||
422 | |||
423 | if (!nand_width) | ||
424 | this->options |= NAND_BUSWIDTH_16; | ||
425 | |||
426 | this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte; | ||
427 | this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte; | ||
428 | this->write_word = au_write_word; | ||
429 | this->read_word = au_read_word; | ||
430 | this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf; | ||
431 | this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf; | ||
432 | this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf; | ||
433 | |||
434 | /* Scan to find existence of the device */ | ||
435 | if (nand_scan (au1550_mtd, 1)) { | ||
436 | retval = -ENXIO; | ||
437 | goto outio; | ||
438 | } | ||
439 | |||
440 | /* Register the partitions */ | ||
441 | add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS); | ||
442 | |||
443 | return 0; | ||
444 | |||
445 | outio: | ||
446 | iounmap ((void *)p_nand); | ||
447 | |||
448 | outmem: | ||
449 | kfree (au1550_mtd); | ||
450 | return retval; | ||
451 | } | ||
452 | |||
453 | module_init(au1550_init); | ||
454 | |||
455 | /* | ||
456 | * Clean up routine | ||
457 | */ | ||
458 | #ifdef MODULE | ||
459 | static void __exit au1550_cleanup (void) | ||
460 | { | ||
461 | struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1]; | ||
462 | |||
463 | /* Release resources, unregister device */ | ||
464 | nand_release (au1550_mtd); | ||
465 | |||
466 | /* Free the MTD device structure */ | ||
467 | kfree (au1550_mtd); | ||
468 | |||
469 | /* Unmap */ | ||
470 | iounmap ((void *)p_nand); | ||
471 | } | ||
472 | module_exit(au1550_cleanup); | ||
473 | #endif | ||
474 | |||
475 | MODULE_LICENSE("GPL"); | ||
476 | MODULE_AUTHOR("Embedded Edge, LLC"); | ||
477 | MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board"); | ||
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c new file mode 100644 index 000000000000..4afa8ced05ad --- /dev/null +++ b/drivers/mtd/nand/autcpu12.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * drivers/mtd/autcpu12.c | ||
3 | * | ||
4 | * Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de> | ||
5 | * | ||
6 | * Derived from drivers/mtd/spia.c | ||
7 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | ||
8 | * | ||
9 | * $Id: autcpu12.c,v 1.22 2004/11/04 12:53:10 gleixner Exp $ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * Overview: | ||
16 | * This is a device driver for the NAND flash device found on the | ||
17 | * autronix autcpu12 board, which is a SmartMediaCard. It supports | ||
18 | * 16MiB, 32MiB and 64MiB cards. | ||
19 | * | ||
20 | * | ||
21 | * 02-12-2002 TG Cleanup of module params | ||
22 | * | ||
23 | * 02-20-2002 TG adjusted for different rd/wr adress support | ||
24 | * added support for read device ready/busy line | ||
25 | * added page_cache | ||
26 | * | ||
27 | * 10-06-2002 TG 128K card support added | ||
28 | */ | ||
29 | |||
30 | #include <linux/version.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/mtd/mtd.h> | ||
35 | #include <linux/mtd/nand.h> | ||
36 | #include <linux/mtd/partitions.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <asm/arch/hardware.h> | ||
39 | #include <asm/sizes.h> | ||
40 | #include <asm/arch/autcpu12.h> | ||
41 | |||
42 | /* | ||
43 | * MTD structure for AUTCPU12 board | ||
44 | */ | ||
45 | static struct mtd_info *autcpu12_mtd = NULL; | ||
46 | |||
47 | static int autcpu12_io_base = CS89712_VIRT_BASE; | ||
48 | static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC; | ||
49 | static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET; | ||
50 | static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET; | ||
51 | static void __iomem * autcpu12_fio_base; | ||
52 | |||
53 | /* | ||
54 | * Define partitions for flash devices | ||
55 | */ | ||
56 | static struct mtd_partition partition_info16k[] = { | ||
57 | { .name = "AUTCPU12 flash partition 1", | ||
58 | .offset = 0, | ||
59 | .size = 8 * SZ_1M }, | ||
60 | { .name = "AUTCPU12 flash partition 2", | ||
61 | .offset = 8 * SZ_1M, | ||
62 | .size = 8 * SZ_1M }, | ||
63 | }; | ||
64 | |||
65 | static struct mtd_partition partition_info32k[] = { | ||
66 | { .name = "AUTCPU12 flash partition 1", | ||
67 | .offset = 0, | ||
68 | .size = 8 * SZ_1M }, | ||
69 | { .name = "AUTCPU12 flash partition 2", | ||
70 | .offset = 8 * SZ_1M, | ||
71 | .size = 24 * SZ_1M }, | ||
72 | }; | ||
73 | |||
74 | static struct mtd_partition partition_info64k[] = { | ||
75 | { .name = "AUTCPU12 flash partition 1", | ||
76 | .offset = 0, | ||
77 | .size = 16 * SZ_1M }, | ||
78 | { .name = "AUTCPU12 flash partition 2", | ||
79 | .offset = 16 * SZ_1M, | ||
80 | .size = 48 * SZ_1M }, | ||
81 | }; | ||
82 | |||
83 | static struct mtd_partition partition_info128k[] = { | ||
84 | { .name = "AUTCPU12 flash partition 1", | ||
85 | .offset = 0, | ||
86 | .size = 16 * SZ_1M }, | ||
87 | { .name = "AUTCPU12 flash partition 2", | ||
88 | .offset = 16 * SZ_1M, | ||
89 | .size = 112 * SZ_1M }, | ||
90 | }; | ||
91 | |||
92 | #define NUM_PARTITIONS16K 2 | ||
93 | #define NUM_PARTITIONS32K 2 | ||
94 | #define NUM_PARTITIONS64K 2 | ||
95 | #define NUM_PARTITIONS128K 2 | ||
96 | /* | ||
97 | * hardware specific access to control-lines | ||
98 | */ | ||
99 | static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd) | ||
100 | { | ||
101 | |||
102 | switch(cmd){ | ||
103 | |||
104 | case NAND_CTL_SETCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_CLE; break; | ||
105 | case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_CLE; break; | ||
106 | |||
107 | case NAND_CTL_SETALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_ALE; break; | ||
108 | case NAND_CTL_CLRALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_ALE; break; | ||
109 | |||
110 | case NAND_CTL_SETNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x01; break; | ||
111 | case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x00; break; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * read device ready pin | ||
117 | */ | ||
118 | int autcpu12_device_ready(struct mtd_info *mtd) | ||
119 | { | ||
120 | |||
121 | return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0; | ||
122 | |||
123 | } | ||
124 | |||
125 | /* | ||
126 | * Main initialization routine | ||
127 | */ | ||
128 | int __init autcpu12_init (void) | ||
129 | { | ||
130 | struct nand_chip *this; | ||
131 | int err = 0; | ||
132 | |||
133 | /* Allocate memory for MTD device structure and private data */ | ||
134 | autcpu12_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), | ||
135 | GFP_KERNEL); | ||
136 | if (!autcpu12_mtd) { | ||
137 | printk ("Unable to allocate AUTCPU12 NAND MTD device structure.\n"); | ||
138 | err = -ENOMEM; | ||
139 | goto out; | ||
140 | } | ||
141 | |||
142 | /* map physical adress */ | ||
143 | autcpu12_fio_base = ioremap(autcpu12_fio_pbase,SZ_1K); | ||
144 | if(!autcpu12_fio_base){ | ||
145 | printk("Ioremap autcpu12 SmartMedia Card failed\n"); | ||
146 | err = -EIO; | ||
147 | goto out_mtd; | ||
148 | } | ||
149 | |||
150 | /* Get pointer to private data */ | ||
151 | this = (struct nand_chip *) (&autcpu12_mtd[1]); | ||
152 | |||
153 | /* Initialize structures */ | ||
154 | memset((char *) autcpu12_mtd, 0, sizeof(struct mtd_info)); | ||
155 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
156 | |||
157 | /* Link the private data with the MTD structure */ | ||
158 | autcpu12_mtd->priv = this; | ||
159 | |||
160 | /* Set address of NAND IO lines */ | ||
161 | this->IO_ADDR_R = autcpu12_fio_base; | ||
162 | this->IO_ADDR_W = autcpu12_fio_base; | ||
163 | this->hwcontrol = autcpu12_hwcontrol; | ||
164 | this->dev_ready = autcpu12_device_ready; | ||
165 | /* 20 us command delay time */ | ||
166 | this->chip_delay = 20; | ||
167 | this->eccmode = NAND_ECC_SOFT; | ||
168 | |||
169 | /* Enable the following for a flash based bad block table */ | ||
170 | /* | ||
171 | this->options = NAND_USE_FLASH_BBT; | ||
172 | */ | ||
173 | this->options = NAND_USE_FLASH_BBT; | ||
174 | |||
175 | /* Scan to find existance of the device */ | ||
176 | if (nand_scan (autcpu12_mtd, 1)) { | ||
177 | err = -ENXIO; | ||
178 | goto out_ior; | ||
179 | } | ||
180 | |||
181 | /* Register the partitions */ | ||
182 | switch(autcpu12_mtd->size){ | ||
183 | case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break; | ||
184 | case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break; | ||
185 | case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break; | ||
186 | case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break; | ||
187 | default: { | ||
188 | printk ("Unsupported SmartMedia device\n"); | ||
189 | err = -ENXIO; | ||
190 | goto out_ior; | ||
191 | } | ||
192 | } | ||
193 | goto out; | ||
194 | |||
195 | out_ior: | ||
196 | iounmap((void *)autcpu12_fio_base); | ||
197 | out_mtd: | ||
198 | kfree (autcpu12_mtd); | ||
199 | out: | ||
200 | return err; | ||
201 | } | ||
202 | |||
203 | module_init(autcpu12_init); | ||
204 | |||
205 | /* | ||
206 | * Clean up routine | ||
207 | */ | ||
208 | #ifdef MODULE | ||
209 | static void __exit autcpu12_cleanup (void) | ||
210 | { | ||
211 | /* Release resources, unregister device */ | ||
212 | nand_release (autcpu12_mtd); | ||
213 | |||
214 | /* unmap physical adress */ | ||
215 | iounmap((void *)autcpu12_fio_base); | ||
216 | |||
217 | /* Free the MTD device structure */ | ||
218 | kfree (autcpu12_mtd); | ||
219 | } | ||
220 | module_exit(autcpu12_cleanup); | ||
221 | #endif | ||
222 | |||
223 | MODULE_LICENSE("GPL"); | ||
224 | MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); | ||
225 | MODULE_DESCRIPTION("Glue layer for SmartMediaCard on autronix autcpu12"); | ||
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c new file mode 100644 index 000000000000..02135c3ac29a --- /dev/null +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -0,0 +1,1782 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/diskonchip.c | ||
3 | * | ||
4 | * (C) 2003 Red Hat, Inc. | ||
5 | * (C) 2004 Dan Brown <dan_brown@ieee.org> | ||
6 | * (C) 2004 Kalev Lember <kalev@smartlink.ee> | ||
7 | * | ||
8 | * Author: David Woodhouse <dwmw2@infradead.org> | ||
9 | * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org> | ||
10 | * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee> | ||
11 | * | ||
12 | * Error correction code lifted from the old docecc code | ||
13 | * Author: Fabrice Bellard (fabrice.bellard@netgem.com) | ||
14 | * Copyright (C) 2000 Netgem S.A. | ||
15 | * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de> | ||
16 | * | ||
17 | * Interface to generic NAND code for M-Systems DiskOnChip devices | ||
18 | * | ||
19 | * $Id: diskonchip.c,v 1.45 2005/01/05 18:05:14 dwmw2 Exp $ | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/rslib.h> | ||
27 | #include <linux/moduleparam.h> | ||
28 | #include <asm/io.h> | ||
29 | |||
30 | #include <linux/mtd/mtd.h> | ||
31 | #include <linux/mtd/nand.h> | ||
32 | #include <linux/mtd/doc2000.h> | ||
33 | #include <linux/mtd/compatmac.h> | ||
34 | #include <linux/mtd/partitions.h> | ||
35 | #include <linux/mtd/inftl.h> | ||
36 | |||
37 | /* Where to look for the devices? */ | ||
38 | #ifndef CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS | ||
39 | #define CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS 0 | ||
40 | #endif | ||
41 | |||
42 | static unsigned long __initdata doc_locations[] = { | ||
43 | #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) | ||
44 | #ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH | ||
45 | 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, | ||
46 | 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, | ||
47 | 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, | ||
48 | 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, | ||
49 | 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, | ||
50 | #else /* CONFIG_MTD_DOCPROBE_HIGH */ | ||
51 | 0xc8000, 0xca000, 0xcc000, 0xce000, | ||
52 | 0xd0000, 0xd2000, 0xd4000, 0xd6000, | ||
53 | 0xd8000, 0xda000, 0xdc000, 0xde000, | ||
54 | 0xe0000, 0xe2000, 0xe4000, 0xe6000, | ||
55 | 0xe8000, 0xea000, 0xec000, 0xee000, | ||
56 | #endif /* CONFIG_MTD_DOCPROBE_HIGH */ | ||
57 | #elif defined(__PPC__) | ||
58 | 0xe4000000, | ||
59 | #elif defined(CONFIG_MOMENCO_OCELOT) | ||
60 | 0x2f000000, | ||
61 | 0xff000000, | ||
62 | #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) | ||
63 | 0xff000000, | ||
64 | ##else | ||
65 | #warning Unknown architecture for DiskOnChip. No default probe locations defined | ||
66 | #endif | ||
67 | 0xffffffff }; | ||
68 | |||
69 | static struct mtd_info *doclist = NULL; | ||
70 | |||
71 | struct doc_priv { | ||
72 | void __iomem *virtadr; | ||
73 | unsigned long physadr; | ||
74 | u_char ChipID; | ||
75 | u_char CDSNControl; | ||
76 | int chips_per_floor; /* The number of chips detected on each floor */ | ||
77 | int curfloor; | ||
78 | int curchip; | ||
79 | int mh0_page; | ||
80 | int mh1_page; | ||
81 | struct mtd_info *nextdoc; | ||
82 | }; | ||
83 | |||
84 | /* Max number of eraseblocks to scan (from start of device) for the (I)NFTL | ||
85 | MediaHeader. The spec says to just keep going, I think, but that's just | ||
86 | silly. */ | ||
87 | #define MAX_MEDIAHEADER_SCAN 8 | ||
88 | |||
89 | /* This is the syndrome computed by the HW ecc generator upon reading an empty | ||
90 | page, one with all 0xff for data and stored ecc code. */ | ||
91 | static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; | ||
92 | /* This is the ecc value computed by the HW ecc generator upon writing an empty | ||
93 | page, one with all 0xff for data. */ | ||
94 | static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; | ||
95 | |||
96 | #define INFTL_BBT_RESERVED_BLOCKS 4 | ||
97 | |||
98 | #define DoC_is_MillenniumPlus(doc) ((doc)->ChipID == DOC_ChipID_DocMilPlus16 || (doc)->ChipID == DOC_ChipID_DocMilPlus32) | ||
99 | #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) | ||
100 | #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) | ||
101 | |||
102 | static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd); | ||
103 | static void doc200x_select_chip(struct mtd_info *mtd, int chip); | ||
104 | |||
105 | static int debug=0; | ||
106 | module_param(debug, int, 0); | ||
107 | |||
108 | static int try_dword=1; | ||
109 | module_param(try_dword, int, 0); | ||
110 | |||
111 | static int no_ecc_failures=0; | ||
112 | module_param(no_ecc_failures, int, 0); | ||
113 | |||
114 | #ifdef CONFIG_MTD_PARTITIONS | ||
115 | static int no_autopart=0; | ||
116 | module_param(no_autopart, int, 0); | ||
117 | #endif | ||
118 | |||
119 | #ifdef MTD_NAND_DISKONCHIP_BBTWRITE | ||
120 | static int inftl_bbt_write=1; | ||
121 | #else | ||
122 | static int inftl_bbt_write=0; | ||
123 | #endif | ||
124 | module_param(inftl_bbt_write, int, 0); | ||
125 | |||
126 | static unsigned long doc_config_location = CONFIG_MTD_DISKONCHIP_PROBE_ADDRESS; | ||
127 | module_param(doc_config_location, ulong, 0); | ||
128 | MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); | ||
129 | |||
130 | |||
131 | /* Sector size for HW ECC */ | ||
132 | #define SECTOR_SIZE 512 | ||
133 | /* The sector bytes are packed into NB_DATA 10 bit words */ | ||
134 | #define NB_DATA (((SECTOR_SIZE + 1) * 8 + 6) / 10) | ||
135 | /* Number of roots */ | ||
136 | #define NROOTS 4 | ||
137 | /* First consective root */ | ||
138 | #define FCR 510 | ||
139 | /* Number of symbols */ | ||
140 | #define NN 1023 | ||
141 | |||
142 | /* the Reed Solomon control structure */ | ||
143 | static struct rs_control *rs_decoder; | ||
144 | |||
145 | /* | ||
146 | * The HW decoder in the DoC ASIC's provides us a error syndrome, | ||
147 | * which we must convert to a standard syndrom usable by the generic | ||
148 | * Reed-Solomon library code. | ||
149 | * | ||
150 | * Fabrice Bellard figured this out in the old docecc code. I added | ||
151 | * some comments, improved a minor bit and converted it to make use | ||
152 | * of the generic Reed-Solomon libary. tglx | ||
153 | */ | ||
154 | static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | ||
155 | { | ||
156 | int i, j, nerr, errpos[8]; | ||
157 | uint8_t parity; | ||
158 | uint16_t ds[4], s[5], tmp, errval[8], syn[4]; | ||
159 | |||
160 | /* Convert the ecc bytes into words */ | ||
161 | ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); | ||
162 | ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); | ||
163 | ds[2] = ((ecc[2] & 0xf0) >> 4) | ((ecc[3] & 0x3f) << 4); | ||
164 | ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2); | ||
165 | parity = ecc[1]; | ||
166 | |||
167 | /* Initialize the syndrom buffer */ | ||
168 | for (i = 0; i < NROOTS; i++) | ||
169 | s[i] = ds[0]; | ||
170 | /* | ||
171 | * Evaluate | ||
172 | * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] | ||
173 | * where x = alpha^(FCR + i) | ||
174 | */ | ||
175 | for(j = 1; j < NROOTS; j++) { | ||
176 | if(ds[j] == 0) | ||
177 | continue; | ||
178 | tmp = rs->index_of[ds[j]]; | ||
179 | for(i = 0; i < NROOTS; i++) | ||
180 | s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; | ||
181 | } | ||
182 | |||
183 | /* Calc s[i] = s[i] / alpha^(v + i) */ | ||
184 | for (i = 0; i < NROOTS; i++) { | ||
185 | if (syn[i]) | ||
186 | syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); | ||
187 | } | ||
188 | /* Call the decoder library */ | ||
189 | nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval); | ||
190 | |||
191 | /* Incorrectable errors ? */ | ||
192 | if (nerr < 0) | ||
193 | return nerr; | ||
194 | |||
195 | /* | ||
196 | * Correct the errors. The bitpositions are a bit of magic, | ||
197 | * but they are given by the design of the de/encoder circuit | ||
198 | * in the DoC ASIC's. | ||
199 | */ | ||
200 | for(i = 0;i < nerr; i++) { | ||
201 | int index, bitpos, pos = 1015 - errpos[i]; | ||
202 | uint8_t val; | ||
203 | if (pos >= NB_DATA && pos < 1019) | ||
204 | continue; | ||
205 | if (pos < NB_DATA) { | ||
206 | /* extract bit position (MSB first) */ | ||
207 | pos = 10 * (NB_DATA - 1 - pos) - 6; | ||
208 | /* now correct the following 10 bits. At most two bytes | ||
209 | can be modified since pos is even */ | ||
210 | index = (pos >> 3) ^ 1; | ||
211 | bitpos = pos & 7; | ||
212 | if ((index >= 0 && index < SECTOR_SIZE) || | ||
213 | index == (SECTOR_SIZE + 1)) { | ||
214 | val = (uint8_t) (errval[i] >> (2 + bitpos)); | ||
215 | parity ^= val; | ||
216 | if (index < SECTOR_SIZE) | ||
217 | data[index] ^= val; | ||
218 | } | ||
219 | index = ((pos >> 3) + 1) ^ 1; | ||
220 | bitpos = (bitpos + 10) & 7; | ||
221 | if (bitpos == 0) | ||
222 | bitpos = 8; | ||
223 | if ((index >= 0 && index < SECTOR_SIZE) || | ||
224 | index == (SECTOR_SIZE + 1)) { | ||
225 | val = (uint8_t)(errval[i] << (8 - bitpos)); | ||
226 | parity ^= val; | ||
227 | if (index < SECTOR_SIZE) | ||
228 | data[index] ^= val; | ||
229 | } | ||
230 | } | ||
231 | } | ||
232 | /* If the parity is wrong, no rescue possible */ | ||
233 | return parity ? -1 : nerr; | ||
234 | } | ||
235 | |||
236 | static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) | ||
237 | { | ||
238 | volatile char dummy; | ||
239 | int i; | ||
240 | |||
241 | for (i = 0; i < cycles; i++) { | ||
242 | if (DoC_is_Millennium(doc)) | ||
243 | dummy = ReadDOC(doc->virtadr, NOP); | ||
244 | else if (DoC_is_MillenniumPlus(doc)) | ||
245 | dummy = ReadDOC(doc->virtadr, Mplus_NOP); | ||
246 | else | ||
247 | dummy = ReadDOC(doc->virtadr, DOCStatus); | ||
248 | } | ||
249 | |||
250 | } | ||
251 | |||
252 | #define CDSN_CTRL_FR_B_MASK (CDSN_CTRL_FR_B0 | CDSN_CTRL_FR_B1) | ||
253 | |||
254 | /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ | ||
255 | static int _DoC_WaitReady(struct doc_priv *doc) | ||
256 | { | ||
257 | void __iomem *docptr = doc->virtadr; | ||
258 | unsigned long timeo = jiffies + (HZ * 10); | ||
259 | |||
260 | if(debug) printk("_DoC_WaitReady...\n"); | ||
261 | /* Out-of-line routine to wait for chip response */ | ||
262 | if (DoC_is_MillenniumPlus(doc)) { | ||
263 | while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { | ||
264 | if (time_after(jiffies, timeo)) { | ||
265 | printk("_DoC_WaitReady timed out.\n"); | ||
266 | return -EIO; | ||
267 | } | ||
268 | udelay(1); | ||
269 | cond_resched(); | ||
270 | } | ||
271 | } else { | ||
272 | while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { | ||
273 | if (time_after(jiffies, timeo)) { | ||
274 | printk("_DoC_WaitReady timed out.\n"); | ||
275 | return -EIO; | ||
276 | } | ||
277 | udelay(1); | ||
278 | cond_resched(); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static inline int DoC_WaitReady(struct doc_priv *doc) | ||
286 | { | ||
287 | void __iomem *docptr = doc->virtadr; | ||
288 | int ret = 0; | ||
289 | |||
290 | if (DoC_is_MillenniumPlus(doc)) { | ||
291 | DoC_Delay(doc, 4); | ||
292 | |||
293 | if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) | ||
294 | /* Call the out-of-line routine to wait */ | ||
295 | ret = _DoC_WaitReady(doc); | ||
296 | } else { | ||
297 | DoC_Delay(doc, 4); | ||
298 | |||
299 | if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) | ||
300 | /* Call the out-of-line routine to wait */ | ||
301 | ret = _DoC_WaitReady(doc); | ||
302 | DoC_Delay(doc, 2); | ||
303 | } | ||
304 | |||
305 | if(debug) printk("DoC_WaitReady OK\n"); | ||
306 | return ret; | ||
307 | } | ||
308 | |||
309 | static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) | ||
310 | { | ||
311 | struct nand_chip *this = mtd->priv; | ||
312 | struct doc_priv *doc = this->priv; | ||
313 | void __iomem *docptr = doc->virtadr; | ||
314 | |||
315 | if(debug)printk("write_byte %02x\n", datum); | ||
316 | WriteDOC(datum, docptr, CDSNSlowIO); | ||
317 | WriteDOC(datum, docptr, 2k_CDSN_IO); | ||
318 | } | ||
319 | |||
320 | static u_char doc2000_read_byte(struct mtd_info *mtd) | ||
321 | { | ||
322 | struct nand_chip *this = mtd->priv; | ||
323 | struct doc_priv *doc = this->priv; | ||
324 | void __iomem *docptr = doc->virtadr; | ||
325 | u_char ret; | ||
326 | |||
327 | ReadDOC(docptr, CDSNSlowIO); | ||
328 | DoC_Delay(doc, 2); | ||
329 | ret = ReadDOC(docptr, 2k_CDSN_IO); | ||
330 | if (debug) printk("read_byte returns %02x\n", ret); | ||
331 | return ret; | ||
332 | } | ||
333 | |||
334 | static void doc2000_writebuf(struct mtd_info *mtd, | ||
335 | const u_char *buf, int len) | ||
336 | { | ||
337 | struct nand_chip *this = mtd->priv; | ||
338 | struct doc_priv *doc = this->priv; | ||
339 | void __iomem *docptr = doc->virtadr; | ||
340 | int i; | ||
341 | if (debug)printk("writebuf of %d bytes: ", len); | ||
342 | for (i=0; i < len; i++) { | ||
343 | WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i); | ||
344 | if (debug && i < 16) | ||
345 | printk("%02x ", buf[i]); | ||
346 | } | ||
347 | if (debug) printk("\n"); | ||
348 | } | ||
349 | |||
350 | static void doc2000_readbuf(struct mtd_info *mtd, | ||
351 | u_char *buf, int len) | ||
352 | { | ||
353 | struct nand_chip *this = mtd->priv; | ||
354 | struct doc_priv *doc = this->priv; | ||
355 | void __iomem *docptr = doc->virtadr; | ||
356 | int i; | ||
357 | |||
358 | if (debug)printk("readbuf of %d bytes: ", len); | ||
359 | |||
360 | for (i=0; i < len; i++) { | ||
361 | buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | static void doc2000_readbuf_dword(struct mtd_info *mtd, | ||
366 | u_char *buf, int len) | ||
367 | { | ||
368 | struct nand_chip *this = mtd->priv; | ||
369 | struct doc_priv *doc = this->priv; | ||
370 | void __iomem *docptr = doc->virtadr; | ||
371 | int i; | ||
372 | |||
373 | if (debug) printk("readbuf_dword of %d bytes: ", len); | ||
374 | |||
375 | if (unlikely((((unsigned long)buf)|len) & 3)) { | ||
376 | for (i=0; i < len; i++) { | ||
377 | *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); | ||
378 | } | ||
379 | } else { | ||
380 | for (i=0; i < len; i+=4) { | ||
381 | *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); | ||
382 | } | ||
383 | } | ||
384 | } | ||
385 | |||
386 | static int doc2000_verifybuf(struct mtd_info *mtd, | ||
387 | const u_char *buf, int len) | ||
388 | { | ||
389 | struct nand_chip *this = mtd->priv; | ||
390 | struct doc_priv *doc = this->priv; | ||
391 | void __iomem *docptr = doc->virtadr; | ||
392 | int i; | ||
393 | |||
394 | for (i=0; i < len; i++) | ||
395 | if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO)) | ||
396 | return -EFAULT; | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) | ||
401 | { | ||
402 | struct nand_chip *this = mtd->priv; | ||
403 | struct doc_priv *doc = this->priv; | ||
404 | uint16_t ret; | ||
405 | |||
406 | doc200x_select_chip(mtd, nr); | ||
407 | doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); | ||
408 | this->write_byte(mtd, NAND_CMD_READID); | ||
409 | doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
410 | doc200x_hwcontrol(mtd, NAND_CTL_SETALE); | ||
411 | this->write_byte(mtd, 0); | ||
412 | doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); | ||
413 | |||
414 | ret = this->read_byte(mtd) << 8; | ||
415 | ret |= this->read_byte(mtd); | ||
416 | |||
417 | if (doc->ChipID == DOC_ChipID_Doc2k && try_dword && !nr) { | ||
418 | /* First chip probe. See if we get same results by 32-bit access */ | ||
419 | union { | ||
420 | uint32_t dword; | ||
421 | uint8_t byte[4]; | ||
422 | } ident; | ||
423 | void __iomem *docptr = doc->virtadr; | ||
424 | |||
425 | doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); | ||
426 | doc2000_write_byte(mtd, NAND_CMD_READID); | ||
427 | doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
428 | doc200x_hwcontrol(mtd, NAND_CTL_SETALE); | ||
429 | doc2000_write_byte(mtd, 0); | ||
430 | doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); | ||
431 | |||
432 | ident.dword = readl(docptr + DoC_2k_CDSN_IO); | ||
433 | if (((ident.byte[0] << 8) | ident.byte[1]) == ret) { | ||
434 | printk(KERN_INFO "DiskOnChip 2000 responds to DWORD access\n"); | ||
435 | this->read_buf = &doc2000_readbuf_dword; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | static void __init doc2000_count_chips(struct mtd_info *mtd) | ||
443 | { | ||
444 | struct nand_chip *this = mtd->priv; | ||
445 | struct doc_priv *doc = this->priv; | ||
446 | uint16_t mfrid; | ||
447 | int i; | ||
448 | |||
449 | /* Max 4 chips per floor on DiskOnChip 2000 */ | ||
450 | doc->chips_per_floor = 4; | ||
451 | |||
452 | /* Find out what the first chip is */ | ||
453 | mfrid = doc200x_ident_chip(mtd, 0); | ||
454 | |||
455 | /* Find how many chips in each floor. */ | ||
456 | for (i = 1; i < 4; i++) { | ||
457 | if (doc200x_ident_chip(mtd, i) != mfrid) | ||
458 | break; | ||
459 | } | ||
460 | doc->chips_per_floor = i; | ||
461 | printk(KERN_DEBUG "Detected %d chips per floor.\n", i); | ||
462 | } | ||
463 | |||
464 | static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | ||
465 | { | ||
466 | struct doc_priv *doc = this->priv; | ||
467 | |||
468 | int status; | ||
469 | |||
470 | DoC_WaitReady(doc); | ||
471 | this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); | ||
472 | DoC_WaitReady(doc); | ||
473 | status = (int)this->read_byte(mtd); | ||
474 | |||
475 | return status; | ||
476 | } | ||
477 | |||
478 | static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) | ||
479 | { | ||
480 | struct nand_chip *this = mtd->priv; | ||
481 | struct doc_priv *doc = this->priv; | ||
482 | void __iomem *docptr = doc->virtadr; | ||
483 | |||
484 | WriteDOC(datum, docptr, CDSNSlowIO); | ||
485 | WriteDOC(datum, docptr, Mil_CDSN_IO); | ||
486 | WriteDOC(datum, docptr, WritePipeTerm); | ||
487 | } | ||
488 | |||
489 | static u_char doc2001_read_byte(struct mtd_info *mtd) | ||
490 | { | ||
491 | struct nand_chip *this = mtd->priv; | ||
492 | struct doc_priv *doc = this->priv; | ||
493 | void __iomem *docptr = doc->virtadr; | ||
494 | |||
495 | //ReadDOC(docptr, CDSNSlowIO); | ||
496 | /* 11.4.5 -- delay twice to allow extended length cycle */ | ||
497 | DoC_Delay(doc, 2); | ||
498 | ReadDOC(docptr, ReadPipeInit); | ||
499 | //return ReadDOC(docptr, Mil_CDSN_IO); | ||
500 | return ReadDOC(docptr, LastDataRead); | ||
501 | } | ||
502 | |||
503 | static void doc2001_writebuf(struct mtd_info *mtd, | ||
504 | const u_char *buf, int len) | ||
505 | { | ||
506 | struct nand_chip *this = mtd->priv; | ||
507 | struct doc_priv *doc = this->priv; | ||
508 | void __iomem *docptr = doc->virtadr; | ||
509 | int i; | ||
510 | |||
511 | for (i=0; i < len; i++) | ||
512 | WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); | ||
513 | /* Terminate write pipeline */ | ||
514 | WriteDOC(0x00, docptr, WritePipeTerm); | ||
515 | } | ||
516 | |||
517 | static void doc2001_readbuf(struct mtd_info *mtd, | ||
518 | u_char *buf, int len) | ||
519 | { | ||
520 | struct nand_chip *this = mtd->priv; | ||
521 | struct doc_priv *doc = this->priv; | ||
522 | void __iomem *docptr = doc->virtadr; | ||
523 | int i; | ||
524 | |||
525 | /* Start read pipeline */ | ||
526 | ReadDOC(docptr, ReadPipeInit); | ||
527 | |||
528 | for (i=0; i < len-1; i++) | ||
529 | buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); | ||
530 | |||
531 | /* Terminate read pipeline */ | ||
532 | buf[i] = ReadDOC(docptr, LastDataRead); | ||
533 | } | ||
534 | |||
535 | static int doc2001_verifybuf(struct mtd_info *mtd, | ||
536 | const u_char *buf, int len) | ||
537 | { | ||
538 | struct nand_chip *this = mtd->priv; | ||
539 | struct doc_priv *doc = this->priv; | ||
540 | void __iomem *docptr = doc->virtadr; | ||
541 | int i; | ||
542 | |||
543 | /* Start read pipeline */ | ||
544 | ReadDOC(docptr, ReadPipeInit); | ||
545 | |||
546 | for (i=0; i < len-1; i++) | ||
547 | if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { | ||
548 | ReadDOC(docptr, LastDataRead); | ||
549 | return i; | ||
550 | } | ||
551 | if (buf[i] != ReadDOC(docptr, LastDataRead)) | ||
552 | return i; | ||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | static u_char doc2001plus_read_byte(struct mtd_info *mtd) | ||
557 | { | ||
558 | struct nand_chip *this = mtd->priv; | ||
559 | struct doc_priv *doc = this->priv; | ||
560 | void __iomem *docptr = doc->virtadr; | ||
561 | u_char ret; | ||
562 | |||
563 | ReadDOC(docptr, Mplus_ReadPipeInit); | ||
564 | ReadDOC(docptr, Mplus_ReadPipeInit); | ||
565 | ret = ReadDOC(docptr, Mplus_LastDataRead); | ||
566 | if (debug) printk("read_byte returns %02x\n", ret); | ||
567 | return ret; | ||
568 | } | ||
569 | |||
570 | static void doc2001plus_writebuf(struct mtd_info *mtd, | ||
571 | const u_char *buf, int len) | ||
572 | { | ||
573 | struct nand_chip *this = mtd->priv; | ||
574 | struct doc_priv *doc = this->priv; | ||
575 | void __iomem *docptr = doc->virtadr; | ||
576 | int i; | ||
577 | |||
578 | if (debug)printk("writebuf of %d bytes: ", len); | ||
579 | for (i=0; i < len; i++) { | ||
580 | WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); | ||
581 | if (debug && i < 16) | ||
582 | printk("%02x ", buf[i]); | ||
583 | } | ||
584 | if (debug) printk("\n"); | ||
585 | } | ||
586 | |||
587 | static void doc2001plus_readbuf(struct mtd_info *mtd, | ||
588 | u_char *buf, int len) | ||
589 | { | ||
590 | struct nand_chip *this = mtd->priv; | ||
591 | struct doc_priv *doc = this->priv; | ||
592 | void __iomem *docptr = doc->virtadr; | ||
593 | int i; | ||
594 | |||
595 | if (debug)printk("readbuf of %d bytes: ", len); | ||
596 | |||
597 | /* Start read pipeline */ | ||
598 | ReadDOC(docptr, Mplus_ReadPipeInit); | ||
599 | ReadDOC(docptr, Mplus_ReadPipeInit); | ||
600 | |||
601 | for (i=0; i < len-2; i++) { | ||
602 | buf[i] = ReadDOC(docptr, Mil_CDSN_IO); | ||
603 | if (debug && i < 16) | ||
604 | printk("%02x ", buf[i]); | ||
605 | } | ||
606 | |||
607 | /* Terminate read pipeline */ | ||
608 | buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead); | ||
609 | if (debug && i < 16) | ||
610 | printk("%02x ", buf[len-2]); | ||
611 | buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead); | ||
612 | if (debug && i < 16) | ||
613 | printk("%02x ", buf[len-1]); | ||
614 | if (debug) printk("\n"); | ||
615 | } | ||
616 | |||
617 | static int doc2001plus_verifybuf(struct mtd_info *mtd, | ||
618 | const u_char *buf, int len) | ||
619 | { | ||
620 | struct nand_chip *this = mtd->priv; | ||
621 | struct doc_priv *doc = this->priv; | ||
622 | void __iomem *docptr = doc->virtadr; | ||
623 | int i; | ||
624 | |||
625 | if (debug)printk("verifybuf of %d bytes: ", len); | ||
626 | |||
627 | /* Start read pipeline */ | ||
628 | ReadDOC(docptr, Mplus_ReadPipeInit); | ||
629 | ReadDOC(docptr, Mplus_ReadPipeInit); | ||
630 | |||
631 | for (i=0; i < len-2; i++) | ||
632 | if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { | ||
633 | ReadDOC(docptr, Mplus_LastDataRead); | ||
634 | ReadDOC(docptr, Mplus_LastDataRead); | ||
635 | return i; | ||
636 | } | ||
637 | if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead)) | ||
638 | return len-2; | ||
639 | if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead)) | ||
640 | return len-1; | ||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) | ||
645 | { | ||
646 | struct nand_chip *this = mtd->priv; | ||
647 | struct doc_priv *doc = this->priv; | ||
648 | void __iomem *docptr = doc->virtadr; | ||
649 | int floor = 0; | ||
650 | |||
651 | if(debug)printk("select chip (%d)\n", chip); | ||
652 | |||
653 | if (chip == -1) { | ||
654 | /* Disable flash internally */ | ||
655 | WriteDOC(0, docptr, Mplus_FlashSelect); | ||
656 | return; | ||
657 | } | ||
658 | |||
659 | floor = chip / doc->chips_per_floor; | ||
660 | chip -= (floor * doc->chips_per_floor); | ||
661 | |||
662 | /* Assert ChipEnable and deassert WriteProtect */ | ||
663 | WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect); | ||
664 | this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | ||
665 | |||
666 | doc->curchip = chip; | ||
667 | doc->curfloor = floor; | ||
668 | } | ||
669 | |||
670 | static void doc200x_select_chip(struct mtd_info *mtd, int chip) | ||
671 | { | ||
672 | struct nand_chip *this = mtd->priv; | ||
673 | struct doc_priv *doc = this->priv; | ||
674 | void __iomem *docptr = doc->virtadr; | ||
675 | int floor = 0; | ||
676 | |||
677 | if(debug)printk("select chip (%d)\n", chip); | ||
678 | |||
679 | if (chip == -1) | ||
680 | return; | ||
681 | |||
682 | floor = chip / doc->chips_per_floor; | ||
683 | chip -= (floor * doc->chips_per_floor); | ||
684 | |||
685 | /* 11.4.4 -- deassert CE before changing chip */ | ||
686 | doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE); | ||
687 | |||
688 | WriteDOC(floor, docptr, FloorSelect); | ||
689 | WriteDOC(chip, docptr, CDSNDeviceSelect); | ||
690 | |||
691 | doc200x_hwcontrol(mtd, NAND_CTL_SETNCE); | ||
692 | |||
693 | doc->curchip = chip; | ||
694 | doc->curfloor = floor; | ||
695 | } | ||
696 | |||
697 | static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) | ||
698 | { | ||
699 | struct nand_chip *this = mtd->priv; | ||
700 | struct doc_priv *doc = this->priv; | ||
701 | void __iomem *docptr = doc->virtadr; | ||
702 | |||
703 | switch(cmd) { | ||
704 | case NAND_CTL_SETNCE: | ||
705 | doc->CDSNControl |= CDSN_CTRL_CE; | ||
706 | break; | ||
707 | case NAND_CTL_CLRNCE: | ||
708 | doc->CDSNControl &= ~CDSN_CTRL_CE; | ||
709 | break; | ||
710 | case NAND_CTL_SETCLE: | ||
711 | doc->CDSNControl |= CDSN_CTRL_CLE; | ||
712 | break; | ||
713 | case NAND_CTL_CLRCLE: | ||
714 | doc->CDSNControl &= ~CDSN_CTRL_CLE; | ||
715 | break; | ||
716 | case NAND_CTL_SETALE: | ||
717 | doc->CDSNControl |= CDSN_CTRL_ALE; | ||
718 | break; | ||
719 | case NAND_CTL_CLRALE: | ||
720 | doc->CDSNControl &= ~CDSN_CTRL_ALE; | ||
721 | break; | ||
722 | case NAND_CTL_SETWP: | ||
723 | doc->CDSNControl |= CDSN_CTRL_WP; | ||
724 | break; | ||
725 | case NAND_CTL_CLRWP: | ||
726 | doc->CDSNControl &= ~CDSN_CTRL_WP; | ||
727 | break; | ||
728 | } | ||
729 | if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); | ||
730 | WriteDOC(doc->CDSNControl, docptr, CDSNControl); | ||
731 | /* 11.4.3 -- 4 NOPs after CSDNControl write */ | ||
732 | DoC_Delay(doc, 4); | ||
733 | } | ||
734 | |||
735 | static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) | ||
736 | { | ||
737 | struct nand_chip *this = mtd->priv; | ||
738 | struct doc_priv *doc = this->priv; | ||
739 | void __iomem *docptr = doc->virtadr; | ||
740 | |||
741 | /* | ||
742 | * Must terminate write pipeline before sending any commands | ||
743 | * to the device. | ||
744 | */ | ||
745 | if (command == NAND_CMD_PAGEPROG) { | ||
746 | WriteDOC(0x00, docptr, Mplus_WritePipeTerm); | ||
747 | WriteDOC(0x00, docptr, Mplus_WritePipeTerm); | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | * Write out the command to the device. | ||
752 | */ | ||
753 | if (command == NAND_CMD_SEQIN) { | ||
754 | int readcmd; | ||
755 | |||
756 | if (column >= mtd->oobblock) { | ||
757 | /* OOB area */ | ||
758 | column -= mtd->oobblock; | ||
759 | readcmd = NAND_CMD_READOOB; | ||
760 | } else if (column < 256) { | ||
761 | /* First 256 bytes --> READ0 */ | ||
762 | readcmd = NAND_CMD_READ0; | ||
763 | } else { | ||
764 | column -= 256; | ||
765 | readcmd = NAND_CMD_READ1; | ||
766 | } | ||
767 | WriteDOC(readcmd, docptr, Mplus_FlashCmd); | ||
768 | } | ||
769 | WriteDOC(command, docptr, Mplus_FlashCmd); | ||
770 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | ||
771 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | ||
772 | |||
773 | if (column != -1 || page_addr != -1) { | ||
774 | /* Serially input address */ | ||
775 | if (column != -1) { | ||
776 | /* Adjust columns for 16 bit buswidth */ | ||
777 | if (this->options & NAND_BUSWIDTH_16) | ||
778 | column >>= 1; | ||
779 | WriteDOC(column, docptr, Mplus_FlashAddress); | ||
780 | } | ||
781 | if (page_addr != -1) { | ||
782 | WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress); | ||
783 | WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); | ||
784 | /* One more address cycle for higher density devices */ | ||
785 | if (this->chipsize & 0x0c000000) { | ||
786 | WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); | ||
787 | printk("high density\n"); | ||
788 | } | ||
789 | } | ||
790 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | ||
791 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | ||
792 | /* deassert ALE */ | ||
793 | if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID) | ||
794 | WriteDOC(0, docptr, Mplus_FlashControl); | ||
795 | } | ||
796 | |||
797 | /* | ||
798 | * program and erase have their own busy handlers | ||
799 | * status and sequential in needs no delay | ||
800 | */ | ||
801 | switch (command) { | ||
802 | |||
803 | case NAND_CMD_PAGEPROG: | ||
804 | case NAND_CMD_ERASE1: | ||
805 | case NAND_CMD_ERASE2: | ||
806 | case NAND_CMD_SEQIN: | ||
807 | case NAND_CMD_STATUS: | ||
808 | return; | ||
809 | |||
810 | case NAND_CMD_RESET: | ||
811 | if (this->dev_ready) | ||
812 | break; | ||
813 | udelay(this->chip_delay); | ||
814 | WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); | ||
815 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | ||
816 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | ||
817 | while ( !(this->read_byte(mtd) & 0x40)); | ||
818 | return; | ||
819 | |||
820 | /* This applies to read commands */ | ||
821 | default: | ||
822 | /* | ||
823 | * If we don't have access to the busy pin, we apply the given | ||
824 | * command delay | ||
825 | */ | ||
826 | if (!this->dev_ready) { | ||
827 | udelay (this->chip_delay); | ||
828 | return; | ||
829 | } | ||
830 | } | ||
831 | |||
832 | /* Apply this short delay always to ensure that we do wait tWB in | ||
833 | * any case on any machine. */ | ||
834 | ndelay (100); | ||
835 | /* wait until command is processed */ | ||
836 | while (!this->dev_ready(mtd)); | ||
837 | } | ||
838 | |||
839 | static int doc200x_dev_ready(struct mtd_info *mtd) | ||
840 | { | ||
841 | struct nand_chip *this = mtd->priv; | ||
842 | struct doc_priv *doc = this->priv; | ||
843 | void __iomem *docptr = doc->virtadr; | ||
844 | |||
845 | if (DoC_is_MillenniumPlus(doc)) { | ||
846 | /* 11.4.2 -- must NOP four times before checking FR/B# */ | ||
847 | DoC_Delay(doc, 4); | ||
848 | if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { | ||
849 | if(debug) | ||
850 | printk("not ready\n"); | ||
851 | return 0; | ||
852 | } | ||
853 | if (debug)printk("was ready\n"); | ||
854 | return 1; | ||
855 | } else { | ||
856 | /* 11.4.2 -- must NOP four times before checking FR/B# */ | ||
857 | DoC_Delay(doc, 4); | ||
858 | if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { | ||
859 | if(debug) | ||
860 | printk("not ready\n"); | ||
861 | return 0; | ||
862 | } | ||
863 | /* 11.4.2 -- Must NOP twice if it's ready */ | ||
864 | DoC_Delay(doc, 2); | ||
865 | if (debug)printk("was ready\n"); | ||
866 | return 1; | ||
867 | } | ||
868 | } | ||
869 | |||
870 | static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | ||
871 | { | ||
872 | /* This is our last resort if we couldn't find or create a BBT. Just | ||
873 | pretend all blocks are good. */ | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) | ||
878 | { | ||
879 | struct nand_chip *this = mtd->priv; | ||
880 | struct doc_priv *doc = this->priv; | ||
881 | void __iomem *docptr = doc->virtadr; | ||
882 | |||
883 | /* Prime the ECC engine */ | ||
884 | switch(mode) { | ||
885 | case NAND_ECC_READ: | ||
886 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); | ||
887 | WriteDOC(DOC_ECC_EN, docptr, ECCConf); | ||
888 | break; | ||
889 | case NAND_ECC_WRITE: | ||
890 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); | ||
891 | WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); | ||
892 | break; | ||
893 | } | ||
894 | } | ||
895 | |||
896 | static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) | ||
897 | { | ||
898 | struct nand_chip *this = mtd->priv; | ||
899 | struct doc_priv *doc = this->priv; | ||
900 | void __iomem *docptr = doc->virtadr; | ||
901 | |||
902 | /* Prime the ECC engine */ | ||
903 | switch(mode) { | ||
904 | case NAND_ECC_READ: | ||
905 | WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); | ||
906 | WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); | ||
907 | break; | ||
908 | case NAND_ECC_WRITE: | ||
909 | WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); | ||
910 | WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf); | ||
911 | break; | ||
912 | } | ||
913 | } | ||
914 | |||
915 | /* This code is only called on write */ | ||
916 | static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | ||
917 | unsigned char *ecc_code) | ||
918 | { | ||
919 | struct nand_chip *this = mtd->priv; | ||
920 | struct doc_priv *doc = this->priv; | ||
921 | void __iomem *docptr = doc->virtadr; | ||
922 | int i; | ||
923 | int emptymatch = 1; | ||
924 | |||
925 | /* flush the pipeline */ | ||
926 | if (DoC_is_2000(doc)) { | ||
927 | WriteDOC(doc->CDSNControl & ~CDSN_CTRL_FLASH_IO, docptr, CDSNControl); | ||
928 | WriteDOC(0, docptr, 2k_CDSN_IO); | ||
929 | WriteDOC(0, docptr, 2k_CDSN_IO); | ||
930 | WriteDOC(0, docptr, 2k_CDSN_IO); | ||
931 | WriteDOC(doc->CDSNControl, docptr, CDSNControl); | ||
932 | } else if (DoC_is_MillenniumPlus(doc)) { | ||
933 | WriteDOC(0, docptr, Mplus_NOP); | ||
934 | WriteDOC(0, docptr, Mplus_NOP); | ||
935 | WriteDOC(0, docptr, Mplus_NOP); | ||
936 | } else { | ||
937 | WriteDOC(0, docptr, NOP); | ||
938 | WriteDOC(0, docptr, NOP); | ||
939 | WriteDOC(0, docptr, NOP); | ||
940 | } | ||
941 | |||
942 | for (i = 0; i < 6; i++) { | ||
943 | if (DoC_is_MillenniumPlus(doc)) | ||
944 | ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i); | ||
945 | else | ||
946 | ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i); | ||
947 | if (ecc_code[i] != empty_write_ecc[i]) | ||
948 | emptymatch = 0; | ||
949 | } | ||
950 | if (DoC_is_MillenniumPlus(doc)) | ||
951 | WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); | ||
952 | else | ||
953 | WriteDOC(DOC_ECC_DIS, docptr, ECCConf); | ||
954 | #if 0 | ||
955 | /* If emptymatch=1, we might have an all-0xff data buffer. Check. */ | ||
956 | if (emptymatch) { | ||
957 | /* Note: this somewhat expensive test should not be triggered | ||
958 | often. It could be optimized away by examining the data in | ||
959 | the writebuf routine, and remembering the result. */ | ||
960 | for (i = 0; i < 512; i++) { | ||
961 | if (dat[i] == 0xff) continue; | ||
962 | emptymatch = 0; | ||
963 | break; | ||
964 | } | ||
965 | } | ||
966 | /* If emptymatch still =1, we do have an all-0xff data buffer. | ||
967 | Return all-0xff ecc value instead of the computed one, so | ||
968 | it'll look just like a freshly-erased page. */ | ||
969 | if (emptymatch) memset(ecc_code, 0xff, 6); | ||
970 | #endif | ||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) | ||
975 | { | ||
976 | int i, ret = 0; | ||
977 | struct nand_chip *this = mtd->priv; | ||
978 | struct doc_priv *doc = this->priv; | ||
979 | void __iomem *docptr = doc->virtadr; | ||
980 | volatile u_char dummy; | ||
981 | int emptymatch = 1; | ||
982 | |||
983 | /* flush the pipeline */ | ||
984 | if (DoC_is_2000(doc)) { | ||
985 | dummy = ReadDOC(docptr, 2k_ECCStatus); | ||
986 | dummy = ReadDOC(docptr, 2k_ECCStatus); | ||
987 | dummy = ReadDOC(docptr, 2k_ECCStatus); | ||
988 | } else if (DoC_is_MillenniumPlus(doc)) { | ||
989 | dummy = ReadDOC(docptr, Mplus_ECCConf); | ||
990 | dummy = ReadDOC(docptr, Mplus_ECCConf); | ||
991 | dummy = ReadDOC(docptr, Mplus_ECCConf); | ||
992 | } else { | ||
993 | dummy = ReadDOC(docptr, ECCConf); | ||
994 | dummy = ReadDOC(docptr, ECCConf); | ||
995 | dummy = ReadDOC(docptr, ECCConf); | ||
996 | } | ||
997 | |||
998 | /* Error occured ? */ | ||
999 | if (dummy & 0x80) { | ||
1000 | for (i = 0; i < 6; i++) { | ||
1001 | if (DoC_is_MillenniumPlus(doc)) | ||
1002 | calc_ecc[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i); | ||
1003 | else | ||
1004 | calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i); | ||
1005 | if (calc_ecc[i] != empty_read_syndrome[i]) | ||
1006 | emptymatch = 0; | ||
1007 | } | ||
1008 | /* If emptymatch=1, the read syndrome is consistent with an | ||
1009 | all-0xff data and stored ecc block. Check the stored ecc. */ | ||
1010 | if (emptymatch) { | ||
1011 | for (i = 0; i < 6; i++) { | ||
1012 | if (read_ecc[i] == 0xff) continue; | ||
1013 | emptymatch = 0; | ||
1014 | break; | ||
1015 | } | ||
1016 | } | ||
1017 | /* If emptymatch still =1, check the data block. */ | ||
1018 | if (emptymatch) { | ||
1019 | /* Note: this somewhat expensive test should not be triggered | ||
1020 | often. It could be optimized away by examining the data in | ||
1021 | the readbuf routine, and remembering the result. */ | ||
1022 | for (i = 0; i < 512; i++) { | ||
1023 | if (dat[i] == 0xff) continue; | ||
1024 | emptymatch = 0; | ||
1025 | break; | ||
1026 | } | ||
1027 | } | ||
1028 | /* If emptymatch still =1, this is almost certainly a freshly- | ||
1029 | erased block, in which case the ECC will not come out right. | ||
1030 | We'll suppress the error and tell the caller everything's | ||
1031 | OK. Because it is. */ | ||
1032 | if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); | ||
1033 | if (ret > 0) | ||
1034 | printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); | ||
1035 | } | ||
1036 | if (DoC_is_MillenniumPlus(doc)) | ||
1037 | WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); | ||
1038 | else | ||
1039 | WriteDOC(DOC_ECC_DIS, docptr, ECCConf); | ||
1040 | if (no_ecc_failures && (ret == -1)) { | ||
1041 | printk(KERN_ERR "suppressing ECC failure\n"); | ||
1042 | ret = 0; | ||
1043 | } | ||
1044 | return ret; | ||
1045 | } | ||
1046 | |||
1047 | //u_char mydatabuf[528]; | ||
1048 | |||
1049 | static struct nand_oobinfo doc200x_oobinfo = { | ||
1050 | .useecc = MTD_NANDECC_AUTOPLACE, | ||
1051 | .eccbytes = 6, | ||
1052 | .eccpos = {0, 1, 2, 3, 4, 5}, | ||
1053 | .oobfree = { {8, 8} } | ||
1054 | }; | ||
1055 | |||
1056 | /* Find the (I)NFTL Media Header, and optionally also the mirror media header. | ||
1057 | On sucessful return, buf will contain a copy of the media header for | ||
1058 | further processing. id is the string to scan for, and will presumably be | ||
1059 | either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media | ||
1060 | header. The page #s of the found media headers are placed in mh0_page and | ||
1061 | mh1_page in the DOC private structure. */ | ||
1062 | static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, | ||
1063 | const char *id, int findmirror) | ||
1064 | { | ||
1065 | struct nand_chip *this = mtd->priv; | ||
1066 | struct doc_priv *doc = this->priv; | ||
1067 | unsigned offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift); | ||
1068 | int ret; | ||
1069 | size_t retlen; | ||
1070 | |||
1071 | end = min(end, mtd->size); // paranoia | ||
1072 | for (offs = 0; offs < end; offs += mtd->erasesize) { | ||
1073 | ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); | ||
1074 | if (retlen != mtd->oobblock) continue; | ||
1075 | if (ret) { | ||
1076 | printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", | ||
1077 | offs); | ||
1078 | } | ||
1079 | if (memcmp(buf, id, 6)) continue; | ||
1080 | printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs); | ||
1081 | if (doc->mh0_page == -1) { | ||
1082 | doc->mh0_page = offs >> this->page_shift; | ||
1083 | if (!findmirror) return 1; | ||
1084 | continue; | ||
1085 | } | ||
1086 | doc->mh1_page = offs >> this->page_shift; | ||
1087 | return 2; | ||
1088 | } | ||
1089 | if (doc->mh0_page == -1) { | ||
1090 | printk(KERN_WARNING "DiskOnChip %s Media Header not found.\n", id); | ||
1091 | return 0; | ||
1092 | } | ||
1093 | /* Only one mediaheader was found. We want buf to contain a | ||
1094 | mediaheader on return, so we'll have to re-read the one we found. */ | ||
1095 | offs = doc->mh0_page << this->page_shift; | ||
1096 | ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); | ||
1097 | if (retlen != mtd->oobblock) { | ||
1098 | /* Insanity. Give up. */ | ||
1099 | printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n"); | ||
1100 | return 0; | ||
1101 | } | ||
1102 | return 1; | ||
1103 | } | ||
1104 | |||
1105 | static inline int __init nftl_partscan(struct mtd_info *mtd, | ||
1106 | struct mtd_partition *parts) | ||
1107 | { | ||
1108 | struct nand_chip *this = mtd->priv; | ||
1109 | struct doc_priv *doc = this->priv; | ||
1110 | int ret = 0; | ||
1111 | u_char *buf; | ||
1112 | struct NFTLMediaHeader *mh; | ||
1113 | const unsigned psize = 1 << this->page_shift; | ||
1114 | unsigned blocks, maxblocks; | ||
1115 | int offs, numheaders; | ||
1116 | |||
1117 | buf = kmalloc(mtd->oobblock, GFP_KERNEL); | ||
1118 | if (!buf) { | ||
1119 | printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); | ||
1120 | return 0; | ||
1121 | } | ||
1122 | if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out; | ||
1123 | mh = (struct NFTLMediaHeader *) buf; | ||
1124 | |||
1125 | //#ifdef CONFIG_MTD_DEBUG_VERBOSE | ||
1126 | // if (CONFIG_MTD_DEBUG_VERBOSE >= 2) | ||
1127 | printk(KERN_INFO " DataOrgID = %s\n" | ||
1128 | " NumEraseUnits = %d\n" | ||
1129 | " FirstPhysicalEUN = %d\n" | ||
1130 | " FormattedSize = %d\n" | ||
1131 | " UnitSizeFactor = %d\n", | ||
1132 | mh->DataOrgID, mh->NumEraseUnits, | ||
1133 | mh->FirstPhysicalEUN, mh->FormattedSize, | ||
1134 | mh->UnitSizeFactor); | ||
1135 | //#endif | ||
1136 | |||
1137 | blocks = mtd->size >> this->phys_erase_shift; | ||
1138 | maxblocks = min(32768U, mtd->erasesize - psize); | ||
1139 | |||
1140 | if (mh->UnitSizeFactor == 0x00) { | ||
1141 | /* Auto-determine UnitSizeFactor. The constraints are: | ||
1142 | - There can be at most 32768 virtual blocks. | ||
1143 | - There can be at most (virtual block size - page size) | ||
1144 | virtual blocks (because MediaHeader+BBT must fit in 1). | ||
1145 | */ | ||
1146 | mh->UnitSizeFactor = 0xff; | ||
1147 | while (blocks > maxblocks) { | ||
1148 | blocks >>= 1; | ||
1149 | maxblocks = min(32768U, (maxblocks << 1) + psize); | ||
1150 | mh->UnitSizeFactor--; | ||
1151 | } | ||
1152 | printk(KERN_WARNING "UnitSizeFactor=0x00 detected. Correct value is assumed to be 0x%02x.\n", mh->UnitSizeFactor); | ||
1153 | } | ||
1154 | |||
1155 | /* NOTE: The lines below modify internal variables of the NAND and MTD | ||
1156 | layers; variables with have already been configured by nand_scan. | ||
1157 | Unfortunately, we didn't know before this point what these values | ||
1158 | should be. Thus, this code is somewhat dependant on the exact | ||
1159 | implementation of the NAND layer. */ | ||
1160 | if (mh->UnitSizeFactor != 0xff) { | ||
1161 | this->bbt_erase_shift += (0xff - mh->UnitSizeFactor); | ||
1162 | mtd->erasesize <<= (0xff - mh->UnitSizeFactor); | ||
1163 | printk(KERN_INFO "Setting virtual erase size to %d\n", mtd->erasesize); | ||
1164 | blocks = mtd->size >> this->bbt_erase_shift; | ||
1165 | maxblocks = min(32768U, mtd->erasesize - psize); | ||
1166 | } | ||
1167 | |||
1168 | if (blocks > maxblocks) { | ||
1169 | printk(KERN_ERR "UnitSizeFactor of 0x%02x is inconsistent with device size. Aborting.\n", mh->UnitSizeFactor); | ||
1170 | goto out; | ||
1171 | } | ||
1172 | |||
1173 | /* Skip past the media headers. */ | ||
1174 | offs = max(doc->mh0_page, doc->mh1_page); | ||
1175 | offs <<= this->page_shift; | ||
1176 | offs += mtd->erasesize; | ||
1177 | |||
1178 | //parts[0].name = " DiskOnChip Boot / Media Header partition"; | ||
1179 | //parts[0].offset = 0; | ||
1180 | //parts[0].size = offs; | ||
1181 | |||
1182 | parts[0].name = " DiskOnChip BDTL partition"; | ||
1183 | parts[0].offset = offs; | ||
1184 | parts[0].size = (mh->NumEraseUnits - numheaders) << this->bbt_erase_shift; | ||
1185 | |||
1186 | offs += parts[0].size; | ||
1187 | if (offs < mtd->size) { | ||
1188 | parts[1].name = " DiskOnChip Remainder partition"; | ||
1189 | parts[1].offset = offs; | ||
1190 | parts[1].size = mtd->size - offs; | ||
1191 | ret = 2; | ||
1192 | goto out; | ||
1193 | } | ||
1194 | ret = 1; | ||
1195 | out: | ||
1196 | kfree(buf); | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1200 | /* This is a stripped-down copy of the code in inftlmount.c */ | ||
1201 | static inline int __init inftl_partscan(struct mtd_info *mtd, | ||
1202 | struct mtd_partition *parts) | ||
1203 | { | ||
1204 | struct nand_chip *this = mtd->priv; | ||
1205 | struct doc_priv *doc = this->priv; | ||
1206 | int ret = 0; | ||
1207 | u_char *buf; | ||
1208 | struct INFTLMediaHeader *mh; | ||
1209 | struct INFTLPartition *ip; | ||
1210 | int numparts = 0; | ||
1211 | int blocks; | ||
1212 | int vshift, lastvunit = 0; | ||
1213 | int i; | ||
1214 | int end = mtd->size; | ||
1215 | |||
1216 | if (inftl_bbt_write) | ||
1217 | end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift); | ||
1218 | |||
1219 | buf = kmalloc(mtd->oobblock, GFP_KERNEL); | ||
1220 | if (!buf) { | ||
1221 | printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); | ||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1225 | if (!find_media_headers(mtd, buf, "BNAND", 0)) goto out; | ||
1226 | doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift); | ||
1227 | mh = (struct INFTLMediaHeader *) buf; | ||
1228 | |||
1229 | mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks); | ||
1230 | mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions); | ||
1231 | mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions); | ||
1232 | mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits); | ||
1233 | mh->FormatFlags = le32_to_cpu(mh->FormatFlags); | ||
1234 | mh->PercentUsed = le32_to_cpu(mh->PercentUsed); | ||
1235 | |||
1236 | //#ifdef CONFIG_MTD_DEBUG_VERBOSE | ||
1237 | // if (CONFIG_MTD_DEBUG_VERBOSE >= 2) | ||
1238 | printk(KERN_INFO " bootRecordID = %s\n" | ||
1239 | " NoOfBootImageBlocks = %d\n" | ||
1240 | " NoOfBinaryPartitions = %d\n" | ||
1241 | " NoOfBDTLPartitions = %d\n" | ||
1242 | " BlockMultiplerBits = %d\n" | ||
1243 | " FormatFlgs = %d\n" | ||
1244 | " OsakVersion = %d.%d.%d.%d\n" | ||
1245 | " PercentUsed = %d\n", | ||
1246 | mh->bootRecordID, mh->NoOfBootImageBlocks, | ||
1247 | mh->NoOfBinaryPartitions, | ||
1248 | mh->NoOfBDTLPartitions, | ||
1249 | mh->BlockMultiplierBits, mh->FormatFlags, | ||
1250 | ((unsigned char *) &mh->OsakVersion)[0] & 0xf, | ||
1251 | ((unsigned char *) &mh->OsakVersion)[1] & 0xf, | ||
1252 | ((unsigned char *) &mh->OsakVersion)[2] & 0xf, | ||
1253 | ((unsigned char *) &mh->OsakVersion)[3] & 0xf, | ||
1254 | mh->PercentUsed); | ||
1255 | //#endif | ||
1256 | |||
1257 | vshift = this->phys_erase_shift + mh->BlockMultiplierBits; | ||
1258 | |||
1259 | blocks = mtd->size >> vshift; | ||
1260 | if (blocks > 32768) { | ||
1261 | printk(KERN_ERR "BlockMultiplierBits=%d is inconsistent with device size. Aborting.\n", mh->BlockMultiplierBits); | ||
1262 | goto out; | ||
1263 | } | ||
1264 | |||
1265 | blocks = doc->chips_per_floor << (this->chip_shift - this->phys_erase_shift); | ||
1266 | if (inftl_bbt_write && (blocks > mtd->erasesize)) { | ||
1267 | printk(KERN_ERR "Writeable BBTs spanning more than one erase block are not yet supported. FIX ME!\n"); | ||
1268 | goto out; | ||
1269 | } | ||
1270 | |||
1271 | /* Scan the partitions */ | ||
1272 | for (i = 0; (i < 4); i++) { | ||
1273 | ip = &(mh->Partitions[i]); | ||
1274 | ip->virtualUnits = le32_to_cpu(ip->virtualUnits); | ||
1275 | ip->firstUnit = le32_to_cpu(ip->firstUnit); | ||
1276 | ip->lastUnit = le32_to_cpu(ip->lastUnit); | ||
1277 | ip->flags = le32_to_cpu(ip->flags); | ||
1278 | ip->spareUnits = le32_to_cpu(ip->spareUnits); | ||
1279 | ip->Reserved0 = le32_to_cpu(ip->Reserved0); | ||
1280 | |||
1281 | //#ifdef CONFIG_MTD_DEBUG_VERBOSE | ||
1282 | // if (CONFIG_MTD_DEBUG_VERBOSE >= 2) | ||
1283 | printk(KERN_INFO " PARTITION[%d] ->\n" | ||
1284 | " virtualUnits = %d\n" | ||
1285 | " firstUnit = %d\n" | ||
1286 | " lastUnit = %d\n" | ||
1287 | " flags = 0x%x\n" | ||
1288 | " spareUnits = %d\n", | ||
1289 | i, ip->virtualUnits, ip->firstUnit, | ||
1290 | ip->lastUnit, ip->flags, | ||
1291 | ip->spareUnits); | ||
1292 | //#endif | ||
1293 | |||
1294 | /* | ||
1295 | if ((i == 0) && (ip->firstUnit > 0)) { | ||
1296 | parts[0].name = " DiskOnChip IPL / Media Header partition"; | ||
1297 | parts[0].offset = 0; | ||
1298 | parts[0].size = mtd->erasesize * ip->firstUnit; | ||
1299 | numparts = 1; | ||
1300 | } | ||
1301 | */ | ||
1302 | |||
1303 | if (ip->flags & INFTL_BINARY) | ||
1304 | parts[numparts].name = " DiskOnChip BDK partition"; | ||
1305 | else | ||
1306 | parts[numparts].name = " DiskOnChip BDTL partition"; | ||
1307 | parts[numparts].offset = ip->firstUnit << vshift; | ||
1308 | parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift; | ||
1309 | numparts++; | ||
1310 | if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit; | ||
1311 | if (ip->flags & INFTL_LAST) break; | ||
1312 | } | ||
1313 | lastvunit++; | ||
1314 | if ((lastvunit << vshift) < end) { | ||
1315 | parts[numparts].name = " DiskOnChip Remainder partition"; | ||
1316 | parts[numparts].offset = lastvunit << vshift; | ||
1317 | parts[numparts].size = end - parts[numparts].offset; | ||
1318 | numparts++; | ||
1319 | } | ||
1320 | ret = numparts; | ||
1321 | out: | ||
1322 | kfree(buf); | ||
1323 | return ret; | ||
1324 | } | ||
1325 | |||
1326 | static int __init nftl_scan_bbt(struct mtd_info *mtd) | ||
1327 | { | ||
1328 | int ret, numparts; | ||
1329 | struct nand_chip *this = mtd->priv; | ||
1330 | struct doc_priv *doc = this->priv; | ||
1331 | struct mtd_partition parts[2]; | ||
1332 | |||
1333 | memset((char *) parts, 0, sizeof(parts)); | ||
1334 | /* On NFTL, we have to find the media headers before we can read the | ||
1335 | BBTs, since they're stored in the media header eraseblocks. */ | ||
1336 | numparts = nftl_partscan(mtd, parts); | ||
1337 | if (!numparts) return -EIO; | ||
1338 | this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | | ||
1339 | NAND_BBT_SAVECONTENT | NAND_BBT_WRITE | | ||
1340 | NAND_BBT_VERSION; | ||
1341 | this->bbt_td->veroffs = 7; | ||
1342 | this->bbt_td->pages[0] = doc->mh0_page + 1; | ||
1343 | if (doc->mh1_page != -1) { | ||
1344 | this->bbt_md->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | | ||
1345 | NAND_BBT_SAVECONTENT | NAND_BBT_WRITE | | ||
1346 | NAND_BBT_VERSION; | ||
1347 | this->bbt_md->veroffs = 7; | ||
1348 | this->bbt_md->pages[0] = doc->mh1_page + 1; | ||
1349 | } else { | ||
1350 | this->bbt_md = NULL; | ||
1351 | } | ||
1352 | |||
1353 | /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set. | ||
1354 | At least as nand_bbt.c is currently written. */ | ||
1355 | if ((ret = nand_scan_bbt(mtd, NULL))) | ||
1356 | return ret; | ||
1357 | add_mtd_device(mtd); | ||
1358 | #ifdef CONFIG_MTD_PARTITIONS | ||
1359 | if (!no_autopart) | ||
1360 | add_mtd_partitions(mtd, parts, numparts); | ||
1361 | #endif | ||
1362 | return 0; | ||
1363 | } | ||
1364 | |||
1365 | static int __init inftl_scan_bbt(struct mtd_info *mtd) | ||
1366 | { | ||
1367 | int ret, numparts; | ||
1368 | struct nand_chip *this = mtd->priv; | ||
1369 | struct doc_priv *doc = this->priv; | ||
1370 | struct mtd_partition parts[5]; | ||
1371 | |||
1372 | if (this->numchips > doc->chips_per_floor) { | ||
1373 | printk(KERN_ERR "Multi-floor INFTL devices not yet supported.\n"); | ||
1374 | return -EIO; | ||
1375 | } | ||
1376 | |||
1377 | if (DoC_is_MillenniumPlus(doc)) { | ||
1378 | this->bbt_td->options = NAND_BBT_2BIT | NAND_BBT_ABSPAGE; | ||
1379 | if (inftl_bbt_write) | ||
1380 | this->bbt_td->options |= NAND_BBT_WRITE; | ||
1381 | this->bbt_td->pages[0] = 2; | ||
1382 | this->bbt_md = NULL; | ||
1383 | } else { | ||
1384 | this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | | ||
1385 | NAND_BBT_VERSION; | ||
1386 | if (inftl_bbt_write) | ||
1387 | this->bbt_td->options |= NAND_BBT_WRITE; | ||
1388 | this->bbt_td->offs = 8; | ||
1389 | this->bbt_td->len = 8; | ||
1390 | this->bbt_td->veroffs = 7; | ||
1391 | this->bbt_td->maxblocks = INFTL_BBT_RESERVED_BLOCKS; | ||
1392 | this->bbt_td->reserved_block_code = 0x01; | ||
1393 | this->bbt_td->pattern = "MSYS_BBT"; | ||
1394 | |||
1395 | this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | | ||
1396 | NAND_BBT_VERSION; | ||
1397 | if (inftl_bbt_write) | ||
1398 | this->bbt_md->options |= NAND_BBT_WRITE; | ||
1399 | this->bbt_md->offs = 8; | ||
1400 | this->bbt_md->len = 8; | ||
1401 | this->bbt_md->veroffs = 7; | ||
1402 | this->bbt_md->maxblocks = INFTL_BBT_RESERVED_BLOCKS; | ||
1403 | this->bbt_md->reserved_block_code = 0x01; | ||
1404 | this->bbt_md->pattern = "TBB_SYSM"; | ||
1405 | } | ||
1406 | |||
1407 | /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set. | ||
1408 | At least as nand_bbt.c is currently written. */ | ||
1409 | if ((ret = nand_scan_bbt(mtd, NULL))) | ||
1410 | return ret; | ||
1411 | memset((char *) parts, 0, sizeof(parts)); | ||
1412 | numparts = inftl_partscan(mtd, parts); | ||
1413 | /* At least for now, require the INFTL Media Header. We could probably | ||
1414 | do without it for non-INFTL use, since all it gives us is | ||
1415 | autopartitioning, but I want to give it more thought. */ | ||
1416 | if (!numparts) return -EIO; | ||
1417 | add_mtd_device(mtd); | ||
1418 | #ifdef CONFIG_MTD_PARTITIONS | ||
1419 | if (!no_autopart) | ||
1420 | add_mtd_partitions(mtd, parts, numparts); | ||
1421 | #endif | ||
1422 | return 0; | ||
1423 | } | ||
1424 | |||
1425 | static inline int __init doc2000_init(struct mtd_info *mtd) | ||
1426 | { | ||
1427 | struct nand_chip *this = mtd->priv; | ||
1428 | struct doc_priv *doc = this->priv; | ||
1429 | |||
1430 | this->write_byte = doc2000_write_byte; | ||
1431 | this->read_byte = doc2000_read_byte; | ||
1432 | this->write_buf = doc2000_writebuf; | ||
1433 | this->read_buf = doc2000_readbuf; | ||
1434 | this->verify_buf = doc2000_verifybuf; | ||
1435 | this->scan_bbt = nftl_scan_bbt; | ||
1436 | |||
1437 | doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO; | ||
1438 | doc2000_count_chips(mtd); | ||
1439 | mtd->name = "DiskOnChip 2000 (NFTL Model)"; | ||
1440 | return (4 * doc->chips_per_floor); | ||
1441 | } | ||
1442 | |||
1443 | static inline int __init doc2001_init(struct mtd_info *mtd) | ||
1444 | { | ||
1445 | struct nand_chip *this = mtd->priv; | ||
1446 | struct doc_priv *doc = this->priv; | ||
1447 | |||
1448 | this->write_byte = doc2001_write_byte; | ||
1449 | this->read_byte = doc2001_read_byte; | ||
1450 | this->write_buf = doc2001_writebuf; | ||
1451 | this->read_buf = doc2001_readbuf; | ||
1452 | this->verify_buf = doc2001_verifybuf; | ||
1453 | |||
1454 | ReadDOC(doc->virtadr, ChipID); | ||
1455 | ReadDOC(doc->virtadr, ChipID); | ||
1456 | ReadDOC(doc->virtadr, ChipID); | ||
1457 | if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) { | ||
1458 | /* It's not a Millennium; it's one of the newer | ||
1459 | DiskOnChip 2000 units with a similar ASIC. | ||
1460 | Treat it like a Millennium, except that it | ||
1461 | can have multiple chips. */ | ||
1462 | doc2000_count_chips(mtd); | ||
1463 | mtd->name = "DiskOnChip 2000 (INFTL Model)"; | ||
1464 | this->scan_bbt = inftl_scan_bbt; | ||
1465 | return (4 * doc->chips_per_floor); | ||
1466 | } else { | ||
1467 | /* Bog-standard Millennium */ | ||
1468 | doc->chips_per_floor = 1; | ||
1469 | mtd->name = "DiskOnChip Millennium"; | ||
1470 | this->scan_bbt = nftl_scan_bbt; | ||
1471 | return 1; | ||
1472 | } | ||
1473 | } | ||
1474 | |||
1475 | static inline int __init doc2001plus_init(struct mtd_info *mtd) | ||
1476 | { | ||
1477 | struct nand_chip *this = mtd->priv; | ||
1478 | struct doc_priv *doc = this->priv; | ||
1479 | |||
1480 | this->write_byte = NULL; | ||
1481 | this->read_byte = doc2001plus_read_byte; | ||
1482 | this->write_buf = doc2001plus_writebuf; | ||
1483 | this->read_buf = doc2001plus_readbuf; | ||
1484 | this->verify_buf = doc2001plus_verifybuf; | ||
1485 | this->scan_bbt = inftl_scan_bbt; | ||
1486 | this->hwcontrol = NULL; | ||
1487 | this->select_chip = doc2001plus_select_chip; | ||
1488 | this->cmdfunc = doc2001plus_command; | ||
1489 | this->enable_hwecc = doc2001plus_enable_hwecc; | ||
1490 | |||
1491 | doc->chips_per_floor = 1; | ||
1492 | mtd->name = "DiskOnChip Millennium Plus"; | ||
1493 | |||
1494 | return 1; | ||
1495 | } | ||
1496 | |||
1497 | static inline int __init doc_probe(unsigned long physadr) | ||
1498 | { | ||
1499 | unsigned char ChipID; | ||
1500 | struct mtd_info *mtd; | ||
1501 | struct nand_chip *nand; | ||
1502 | struct doc_priv *doc; | ||
1503 | void __iomem *virtadr; | ||
1504 | unsigned char save_control; | ||
1505 | unsigned char tmp, tmpb, tmpc; | ||
1506 | int reg, len, numchips; | ||
1507 | int ret = 0; | ||
1508 | |||
1509 | virtadr = ioremap(physadr, DOC_IOREMAP_LEN); | ||
1510 | if (!virtadr) { | ||
1511 | printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr); | ||
1512 | return -EIO; | ||
1513 | } | ||
1514 | |||
1515 | /* It's not possible to cleanly detect the DiskOnChip - the | ||
1516 | * bootup procedure will put the device into reset mode, and | ||
1517 | * it's not possible to talk to it without actually writing | ||
1518 | * to the DOCControl register. So we store the current contents | ||
1519 | * of the DOCControl register's location, in case we later decide | ||
1520 | * that it's not a DiskOnChip, and want to put it back how we | ||
1521 | * found it. | ||
1522 | */ | ||
1523 | save_control = ReadDOC(virtadr, DOCControl); | ||
1524 | |||
1525 | /* Reset the DiskOnChip ASIC */ | ||
1526 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, | ||
1527 | virtadr, DOCControl); | ||
1528 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, | ||
1529 | virtadr, DOCControl); | ||
1530 | |||
1531 | /* Enable the DiskOnChip ASIC */ | ||
1532 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, | ||
1533 | virtadr, DOCControl); | ||
1534 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, | ||
1535 | virtadr, DOCControl); | ||
1536 | |||
1537 | ChipID = ReadDOC(virtadr, ChipID); | ||
1538 | |||
1539 | switch(ChipID) { | ||
1540 | case DOC_ChipID_Doc2k: | ||
1541 | reg = DoC_2k_ECCStatus; | ||
1542 | break; | ||
1543 | case DOC_ChipID_DocMil: | ||
1544 | reg = DoC_ECCConf; | ||
1545 | break; | ||
1546 | case DOC_ChipID_DocMilPlus16: | ||
1547 | case DOC_ChipID_DocMilPlus32: | ||
1548 | case 0: | ||
1549 | /* Possible Millennium Plus, need to do more checks */ | ||
1550 | /* Possibly release from power down mode */ | ||
1551 | for (tmp = 0; (tmp < 4); tmp++) | ||
1552 | ReadDOC(virtadr, Mplus_Power); | ||
1553 | |||
1554 | /* Reset the Millennium Plus ASIC */ | ||
1555 | tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | | ||
1556 | DOC_MODE_BDECT; | ||
1557 | WriteDOC(tmp, virtadr, Mplus_DOCControl); | ||
1558 | WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); | ||
1559 | |||
1560 | mdelay(1); | ||
1561 | /* Enable the Millennium Plus ASIC */ | ||
1562 | tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | | ||
1563 | DOC_MODE_BDECT; | ||
1564 | WriteDOC(tmp, virtadr, Mplus_DOCControl); | ||
1565 | WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); | ||
1566 | mdelay(1); | ||
1567 | |||
1568 | ChipID = ReadDOC(virtadr, ChipID); | ||
1569 | |||
1570 | switch (ChipID) { | ||
1571 | case DOC_ChipID_DocMilPlus16: | ||
1572 | reg = DoC_Mplus_Toggle; | ||
1573 | break; | ||
1574 | case DOC_ChipID_DocMilPlus32: | ||
1575 | printk(KERN_ERR "DiskOnChip Millennium Plus 32MB is not supported, ignoring.\n"); | ||
1576 | default: | ||
1577 | ret = -ENODEV; | ||
1578 | goto notfound; | ||
1579 | } | ||
1580 | break; | ||
1581 | |||
1582 | default: | ||
1583 | ret = -ENODEV; | ||
1584 | goto notfound; | ||
1585 | } | ||
1586 | /* Check the TOGGLE bit in the ECC register */ | ||
1587 | tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; | ||
1588 | tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; | ||
1589 | tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; | ||
1590 | if ((tmp == tmpb) || (tmp != tmpc)) { | ||
1591 | printk(KERN_WARNING "Possible DiskOnChip at 0x%lx failed TOGGLE test, dropping.\n", physadr); | ||
1592 | ret = -ENODEV; | ||
1593 | goto notfound; | ||
1594 | } | ||
1595 | |||
1596 | for (mtd = doclist; mtd; mtd = doc->nextdoc) { | ||
1597 | unsigned char oldval; | ||
1598 | unsigned char newval; | ||
1599 | nand = mtd->priv; | ||
1600 | doc = nand->priv; | ||
1601 | /* Use the alias resolution register to determine if this is | ||
1602 | in fact the same DOC aliased to a new address. If writes | ||
1603 | to one chip's alias resolution register change the value on | ||
1604 | the other chip, they're the same chip. */ | ||
1605 | if (ChipID == DOC_ChipID_DocMilPlus16) { | ||
1606 | oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); | ||
1607 | newval = ReadDOC(virtadr, Mplus_AliasResolution); | ||
1608 | } else { | ||
1609 | oldval = ReadDOC(doc->virtadr, AliasResolution); | ||
1610 | newval = ReadDOC(virtadr, AliasResolution); | ||
1611 | } | ||
1612 | if (oldval != newval) | ||
1613 | continue; | ||
1614 | if (ChipID == DOC_ChipID_DocMilPlus16) { | ||
1615 | WriteDOC(~newval, virtadr, Mplus_AliasResolution); | ||
1616 | oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); | ||
1617 | WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it | ||
1618 | } else { | ||
1619 | WriteDOC(~newval, virtadr, AliasResolution); | ||
1620 | oldval = ReadDOC(doc->virtadr, AliasResolution); | ||
1621 | WriteDOC(newval, virtadr, AliasResolution); // restore it | ||
1622 | } | ||
1623 | newval = ~newval; | ||
1624 | if (oldval == newval) { | ||
1625 | printk(KERN_DEBUG "Found alias of DOC at 0x%lx to 0x%lx\n", doc->physadr, physadr); | ||
1626 | goto notfound; | ||
1627 | } | ||
1628 | } | ||
1629 | |||
1630 | printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr); | ||
1631 | |||
1632 | len = sizeof(struct mtd_info) + | ||
1633 | sizeof(struct nand_chip) + | ||
1634 | sizeof(struct doc_priv) + | ||
1635 | (2 * sizeof(struct nand_bbt_descr)); | ||
1636 | mtd = kmalloc(len, GFP_KERNEL); | ||
1637 | if (!mtd) { | ||
1638 | printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); | ||
1639 | ret = -ENOMEM; | ||
1640 | goto fail; | ||
1641 | } | ||
1642 | memset(mtd, 0, len); | ||
1643 | |||
1644 | nand = (struct nand_chip *) (mtd + 1); | ||
1645 | doc = (struct doc_priv *) (nand + 1); | ||
1646 | nand->bbt_td = (struct nand_bbt_descr *) (doc + 1); | ||
1647 | nand->bbt_md = nand->bbt_td + 1; | ||
1648 | |||
1649 | mtd->priv = nand; | ||
1650 | mtd->owner = THIS_MODULE; | ||
1651 | |||
1652 | nand->priv = doc; | ||
1653 | nand->select_chip = doc200x_select_chip; | ||
1654 | nand->hwcontrol = doc200x_hwcontrol; | ||
1655 | nand->dev_ready = doc200x_dev_ready; | ||
1656 | nand->waitfunc = doc200x_wait; | ||
1657 | nand->block_bad = doc200x_block_bad; | ||
1658 | nand->enable_hwecc = doc200x_enable_hwecc; | ||
1659 | nand->calculate_ecc = doc200x_calculate_ecc; | ||
1660 | nand->correct_data = doc200x_correct_data; | ||
1661 | |||
1662 | nand->autooob = &doc200x_oobinfo; | ||
1663 | nand->eccmode = NAND_ECC_HW6_512; | ||
1664 | nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; | ||
1665 | |||
1666 | doc->physadr = physadr; | ||
1667 | doc->virtadr = virtadr; | ||
1668 | doc->ChipID = ChipID; | ||
1669 | doc->curfloor = -1; | ||
1670 | doc->curchip = -1; | ||
1671 | doc->mh0_page = -1; | ||
1672 | doc->mh1_page = -1; | ||
1673 | doc->nextdoc = doclist; | ||
1674 | |||
1675 | if (ChipID == DOC_ChipID_Doc2k) | ||
1676 | numchips = doc2000_init(mtd); | ||
1677 | else if (ChipID == DOC_ChipID_DocMilPlus16) | ||
1678 | numchips = doc2001plus_init(mtd); | ||
1679 | else | ||
1680 | numchips = doc2001_init(mtd); | ||
1681 | |||
1682 | if ((ret = nand_scan(mtd, numchips))) { | ||
1683 | /* DBB note: i believe nand_release is necessary here, as | ||
1684 | buffers may have been allocated in nand_base. Check with | ||
1685 | Thomas. FIX ME! */ | ||
1686 | /* nand_release will call del_mtd_device, but we haven't yet | ||
1687 | added it. This is handled without incident by | ||
1688 | del_mtd_device, as far as I can tell. */ | ||
1689 | nand_release(mtd); | ||
1690 | kfree(mtd); | ||
1691 | goto fail; | ||
1692 | } | ||
1693 | |||
1694 | /* Success! */ | ||
1695 | doclist = mtd; | ||
1696 | return 0; | ||
1697 | |||
1698 | notfound: | ||
1699 | /* Put back the contents of the DOCControl register, in case it's not | ||
1700 | actually a DiskOnChip. */ | ||
1701 | WriteDOC(save_control, virtadr, DOCControl); | ||
1702 | fail: | ||
1703 | iounmap(virtadr); | ||
1704 | return ret; | ||
1705 | } | ||
1706 | |||
1707 | static void release_nanddoc(void) | ||
1708 | { | ||
1709 | struct mtd_info *mtd, *nextmtd; | ||
1710 | struct nand_chip *nand; | ||
1711 | struct doc_priv *doc; | ||
1712 | |||
1713 | for (mtd = doclist; mtd; mtd = nextmtd) { | ||
1714 | nand = mtd->priv; | ||
1715 | doc = nand->priv; | ||
1716 | |||
1717 | nextmtd = doc->nextdoc; | ||
1718 | nand_release(mtd); | ||
1719 | iounmap(doc->virtadr); | ||
1720 | kfree(mtd); | ||
1721 | } | ||
1722 | } | ||
1723 | |||
1724 | static int __init init_nanddoc(void) | ||
1725 | { | ||
1726 | int i, ret = 0; | ||
1727 | |||
1728 | /* We could create the decoder on demand, if memory is a concern. | ||
1729 | * This way we have it handy, if an error happens | ||
1730 | * | ||
1731 | * Symbolsize is 10 (bits) | ||
1732 | * Primitve polynomial is x^10+x^3+1 | ||
1733 | * first consecutive root is 510 | ||
1734 | * primitve element to generate roots = 1 | ||
1735 | * generator polinomial degree = 4 | ||
1736 | */ | ||
1737 | rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); | ||
1738 | if (!rs_decoder) { | ||
1739 | printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); | ||
1740 | return -ENOMEM; | ||
1741 | } | ||
1742 | |||
1743 | if (doc_config_location) { | ||
1744 | printk(KERN_INFO "Using configured DiskOnChip probe address 0x%lx\n", doc_config_location); | ||
1745 | ret = doc_probe(doc_config_location); | ||
1746 | if (ret < 0) | ||
1747 | goto outerr; | ||
1748 | } else { | ||
1749 | for (i=0; (doc_locations[i] != 0xffffffff); i++) { | ||
1750 | doc_probe(doc_locations[i]); | ||
1751 | } | ||
1752 | } | ||
1753 | /* No banner message any more. Print a message if no DiskOnChip | ||
1754 | found, so the user knows we at least tried. */ | ||
1755 | if (!doclist) { | ||
1756 | printk(KERN_INFO "No valid DiskOnChip devices found\n"); | ||
1757 | ret = -ENODEV; | ||
1758 | goto outerr; | ||
1759 | } | ||
1760 | return 0; | ||
1761 | outerr: | ||
1762 | free_rs(rs_decoder); | ||
1763 | return ret; | ||
1764 | } | ||
1765 | |||
1766 | static void __exit cleanup_nanddoc(void) | ||
1767 | { | ||
1768 | /* Cleanup the nand/DoC resources */ | ||
1769 | release_nanddoc(); | ||
1770 | |||
1771 | /* Free the reed solomon resources */ | ||
1772 | if (rs_decoder) { | ||
1773 | free_rs(rs_decoder); | ||
1774 | } | ||
1775 | } | ||
1776 | |||
1777 | module_init(init_nanddoc); | ||
1778 | module_exit(cleanup_nanddoc); | ||
1779 | |||
1780 | MODULE_LICENSE("GPL"); | ||
1781 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | ||
1782 | MODULE_DESCRIPTION("M-Systems DiskOnChip 2000, Millennium and Millennium Plus device driver\n"); | ||
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c new file mode 100644 index 000000000000..5549681ccdce --- /dev/null +++ b/drivers/mtd/nand/edb7312.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/edb7312.c | ||
3 | * | ||
4 | * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) | ||
5 | * | ||
6 | * Derived from drivers/mtd/nand/autcpu12.c | ||
7 | * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) | ||
8 | * | ||
9 | * $Id: edb7312.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * Overview: | ||
16 | * This is a device driver for the NAND flash device found on the | ||
17 | * CLEP7312 board which utilizes the Toshiba TC58V64AFT part. This is | ||
18 | * a 64Mibit (8MiB x 8 bits) NAND flash device. | ||
19 | */ | ||
20 | |||
21 | #include <linux/slab.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/mtd/mtd.h> | ||
25 | #include <linux/mtd/nand.h> | ||
26 | #include <linux/mtd/partitions.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */ | ||
29 | #include <asm/sizes.h> | ||
30 | #include <asm/hardware/clps7111.h> | ||
31 | |||
32 | /* | ||
33 | * MTD structure for EDB7312 board | ||
34 | */ | ||
35 | static struct mtd_info *ep7312_mtd = NULL; | ||
36 | |||
37 | /* | ||
38 | * Values specific to the EDB7312 board (used with EP7312 processor) | ||
39 | */ | ||
40 | #define EP7312_FIO_PBASE 0x10000000 /* Phys address of flash */ | ||
41 | #define EP7312_PXDR 0x0001 /* | ||
42 | * IO offset to Port B data register | ||
43 | * where the CLE, ALE and NCE pins | ||
44 | * are wired to. | ||
45 | */ | ||
46 | #define EP7312_PXDDR 0x0041 /* | ||
47 | * IO offset to Port B data direction | ||
48 | * register so we can control the IO | ||
49 | * lines. | ||
50 | */ | ||
51 | |||
52 | /* | ||
53 | * Module stuff | ||
54 | */ | ||
55 | |||
56 | static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE; | ||
57 | static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR; | ||
58 | static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR; | ||
59 | |||
60 | #ifdef CONFIG_MTD_PARTITIONS | ||
61 | /* | ||
62 | * Define static partitions for flash device | ||
63 | */ | ||
64 | static struct mtd_partition partition_info[] = { | ||
65 | { .name = "EP7312 Nand Flash", | ||
66 | .offset = 0, | ||
67 | .size = 8*1024*1024 } | ||
68 | }; | ||
69 | #define NUM_PARTITIONS 1 | ||
70 | |||
71 | #endif | ||
72 | |||
73 | |||
74 | /* | ||
75 | * hardware specific access to control-lines | ||
76 | */ | ||
77 | static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) | ||
78 | { | ||
79 | switch(cmd) { | ||
80 | |||
81 | case NAND_CTL_SETCLE: | ||
82 | clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr); | ||
83 | break; | ||
84 | case NAND_CTL_CLRCLE: | ||
85 | clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr); | ||
86 | break; | ||
87 | |||
88 | case NAND_CTL_SETALE: | ||
89 | clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr); | ||
90 | break; | ||
91 | case NAND_CTL_CLRALE: | ||
92 | clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr); | ||
93 | break; | ||
94 | |||
95 | case NAND_CTL_SETNCE: | ||
96 | clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr); | ||
97 | break; | ||
98 | case NAND_CTL_CLRNCE: | ||
99 | clps_writeb((clps_readb(ep7312_pxdr) | 0x80) | 0x40, ep7312_pxdr); | ||
100 | break; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * read device ready pin | ||
106 | */ | ||
107 | static int ep7312_device_ready(struct mtd_info *mtd) | ||
108 | { | ||
109 | return 1; | ||
110 | } | ||
111 | #ifdef CONFIG_MTD_PARTITIONS | ||
112 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
113 | #endif | ||
114 | |||
115 | /* | ||
116 | * Main initialization routine | ||
117 | */ | ||
118 | static int __init ep7312_init (void) | ||
119 | { | ||
120 | struct nand_chip *this; | ||
121 | const char *part_type = 0; | ||
122 | int mtd_parts_nb = 0; | ||
123 | struct mtd_partition *mtd_parts = 0; | ||
124 | void __iomem * ep7312_fio_base; | ||
125 | |||
126 | /* Allocate memory for MTD device structure and private data */ | ||
127 | ep7312_mtd = kmalloc(sizeof(struct mtd_info) + | ||
128 | sizeof(struct nand_chip), | ||
129 | GFP_KERNEL); | ||
130 | if (!ep7312_mtd) { | ||
131 | printk("Unable to allocate EDB7312 NAND MTD device structure.\n"); | ||
132 | return -ENOMEM; | ||
133 | } | ||
134 | |||
135 | /* map physical adress */ | ||
136 | ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K); | ||
137 | if(!ep7312_fio_base) { | ||
138 | printk("ioremap EDB7312 NAND flash failed\n"); | ||
139 | kfree(ep7312_mtd); | ||
140 | return -EIO; | ||
141 | } | ||
142 | |||
143 | /* Get pointer to private data */ | ||
144 | this = (struct nand_chip *) (&ep7312_mtd[1]); | ||
145 | |||
146 | /* Initialize structures */ | ||
147 | memset((char *) ep7312_mtd, 0, sizeof(struct mtd_info)); | ||
148 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
149 | |||
150 | /* Link the private data with the MTD structure */ | ||
151 | ep7312_mtd->priv = this; | ||
152 | |||
153 | /* | ||
154 | * Set GPIO Port B control register so that the pins are configured | ||
155 | * to be outputs for controlling the NAND flash. | ||
156 | */ | ||
157 | clps_writeb(0xf0, ep7312_pxddr); | ||
158 | |||
159 | /* insert callbacks */ | ||
160 | this->IO_ADDR_R = ep7312_fio_base; | ||
161 | this->IO_ADDR_W = ep7312_fio_base; | ||
162 | this->hwcontrol = ep7312_hwcontrol; | ||
163 | this->dev_ready = ep7312_device_ready; | ||
164 | /* 15 us command delay time */ | ||
165 | this->chip_delay = 15; | ||
166 | |||
167 | /* Scan to find existence of the device */ | ||
168 | if (nand_scan (ep7312_mtd, 1)) { | ||
169 | iounmap((void *)ep7312_fio_base); | ||
170 | kfree (ep7312_mtd); | ||
171 | return -ENXIO; | ||
172 | } | ||
173 | |||
174 | #ifdef CONFIG_MTD_PARTITIONS | ||
175 | ep7312_mtd->name = "edb7312-nand"; | ||
176 | mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, | ||
177 | &mtd_parts, 0); | ||
178 | if (mtd_parts_nb > 0) | ||
179 | part_type = "command line"; | ||
180 | else | ||
181 | mtd_parts_nb = 0; | ||
182 | #endif | ||
183 | if (mtd_parts_nb == 0) { | ||
184 | mtd_parts = partition_info; | ||
185 | mtd_parts_nb = NUM_PARTITIONS; | ||
186 | part_type = "static"; | ||
187 | } | ||
188 | |||
189 | /* Register the partitions */ | ||
190 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | ||
191 | add_mtd_partitions(ep7312_mtd, mtd_parts, mtd_parts_nb); | ||
192 | |||
193 | /* Return happy */ | ||
194 | return 0; | ||
195 | } | ||
196 | module_init(ep7312_init); | ||
197 | |||
198 | /* | ||
199 | * Clean up routine | ||
200 | */ | ||
201 | static void __exit ep7312_cleanup (void) | ||
202 | { | ||
203 | struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1]; | ||
204 | |||
205 | /* Release resources, unregister device */ | ||
206 | nand_release (ap7312_mtd); | ||
207 | |||
208 | /* Free internal data buffer */ | ||
209 | kfree (this->data_buf); | ||
210 | |||
211 | /* Free the MTD device structure */ | ||
212 | kfree (ep7312_mtd); | ||
213 | } | ||
214 | module_exit(ep7312_cleanup); | ||
215 | |||
216 | MODULE_LICENSE("GPL"); | ||
217 | MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>"); | ||
218 | MODULE_DESCRIPTION("MTD map driver for Cogent EDB7312 board"); | ||
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c new file mode 100644 index 000000000000..3825a7a0900c --- /dev/null +++ b/drivers/mtd/nand/h1910.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/h1910.c | ||
3 | * | ||
4 | * Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com) | ||
5 | * | ||
6 | * Derived from drivers/mtd/nand/edb7312.c | ||
7 | * Copyright (C) 2002 Marius Gröger (mag@sysgo.de) | ||
8 | * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) | ||
9 | * | ||
10 | * $Id: h1910.c,v 1.5 2004/11/04 12:53:10 gleixner Exp $ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | * Overview: | ||
17 | * This is a device driver for the NAND flash device found on the | ||
18 | * iPAQ h1910 board which utilizes the Samsung K9F2808 part. This is | ||
19 | * a 128Mibit (16MiB x 8 bits) NAND flash device. | ||
20 | */ | ||
21 | |||
22 | #include <linux/slab.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/mtd/mtd.h> | ||
26 | #include <linux/mtd/nand.h> | ||
27 | #include <linux/mtd/partitions.h> | ||
28 | #include <asm/io.h> | ||
29 | #include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */ | ||
30 | #include <asm/sizes.h> | ||
31 | #include <asm/arch/h1900-gpio.h> | ||
32 | #include <asm/arch/ipaq.h> | ||
33 | |||
34 | /* | ||
35 | * MTD structure for EDB7312 board | ||
36 | */ | ||
37 | static struct mtd_info *h1910_nand_mtd = NULL; | ||
38 | |||
39 | /* | ||
40 | * Module stuff | ||
41 | */ | ||
42 | |||
43 | #ifdef CONFIG_MTD_PARTITIONS | ||
44 | /* | ||
45 | * Define static partitions for flash device | ||
46 | */ | ||
47 | static struct mtd_partition partition_info[] = { | ||
48 | { name: "h1910 NAND Flash", | ||
49 | offset: 0, | ||
50 | size: 16*1024*1024 } | ||
51 | }; | ||
52 | #define NUM_PARTITIONS 1 | ||
53 | |||
54 | #endif | ||
55 | |||
56 | |||
57 | /* | ||
58 | * hardware specific access to control-lines | ||
59 | */ | ||
60 | static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) | ||
61 | { | ||
62 | struct nand_chip* this = (struct nand_chip *) (mtd->priv); | ||
63 | |||
64 | switch(cmd) { | ||
65 | |||
66 | case NAND_CTL_SETCLE: | ||
67 | this->IO_ADDR_R |= (1 << 2); | ||
68 | this->IO_ADDR_W |= (1 << 2); | ||
69 | break; | ||
70 | case NAND_CTL_CLRCLE: | ||
71 | this->IO_ADDR_R &= ~(1 << 2); | ||
72 | this->IO_ADDR_W &= ~(1 << 2); | ||
73 | break; | ||
74 | |||
75 | case NAND_CTL_SETALE: | ||
76 | this->IO_ADDR_R |= (1 << 3); | ||
77 | this->IO_ADDR_W |= (1 << 3); | ||
78 | break; | ||
79 | case NAND_CTL_CLRALE: | ||
80 | this->IO_ADDR_R &= ~(1 << 3); | ||
81 | this->IO_ADDR_W &= ~(1 << 3); | ||
82 | break; | ||
83 | |||
84 | case NAND_CTL_SETNCE: | ||
85 | break; | ||
86 | case NAND_CTL_CLRNCE: | ||
87 | break; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * read device ready pin | ||
93 | */ | ||
94 | #if 0 | ||
95 | static int h1910_device_ready(struct mtd_info *mtd) | ||
96 | { | ||
97 | return (GPLR(55) & GPIO_bit(55)); | ||
98 | } | ||
99 | #endif | ||
100 | |||
101 | /* | ||
102 | * Main initialization routine | ||
103 | */ | ||
104 | static int __init h1910_init (void) | ||
105 | { | ||
106 | struct nand_chip *this; | ||
107 | const char *part_type = 0; | ||
108 | int mtd_parts_nb = 0; | ||
109 | struct mtd_partition *mtd_parts = 0; | ||
110 | void __iomem *nandaddr; | ||
111 | |||
112 | if (!machine_is_h1900()) | ||
113 | return -ENODEV; | ||
114 | |||
115 | nandaddr = __ioremap(0x08000000, 0x1000, 0, 1); | ||
116 | if (!nandaddr) { | ||
117 | printk("Failed to ioremap nand flash.\n"); | ||
118 | return -ENOMEM; | ||
119 | } | ||
120 | |||
121 | /* Allocate memory for MTD device structure and private data */ | ||
122 | h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + | ||
123 | sizeof(struct nand_chip), | ||
124 | GFP_KERNEL); | ||
125 | if (!h1910_nand_mtd) { | ||
126 | printk("Unable to allocate h1910 NAND MTD device structure.\n"); | ||
127 | iounmap ((void *) nandaddr); | ||
128 | return -ENOMEM; | ||
129 | } | ||
130 | |||
131 | /* Get pointer to private data */ | ||
132 | this = (struct nand_chip *) (&h1910_nand_mtd[1]); | ||
133 | |||
134 | /* Initialize structures */ | ||
135 | memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info)); | ||
136 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
137 | |||
138 | /* Link the private data with the MTD structure */ | ||
139 | h1910_nand_mtd->priv = this; | ||
140 | |||
141 | /* | ||
142 | * Enable VPEN | ||
143 | */ | ||
144 | GPSR(37) = GPIO_bit(37); | ||
145 | |||
146 | /* insert callbacks */ | ||
147 | this->IO_ADDR_R = nandaddr; | ||
148 | this->IO_ADDR_W = nandaddr; | ||
149 | this->hwcontrol = h1910_hwcontrol; | ||
150 | this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */ | ||
151 | /* 15 us command delay time */ | ||
152 | this->chip_delay = 50; | ||
153 | this->eccmode = NAND_ECC_SOFT; | ||
154 | this->options = NAND_NO_AUTOINCR; | ||
155 | |||
156 | /* Scan to find existence of the device */ | ||
157 | if (nand_scan (h1910_nand_mtd, 1)) { | ||
158 | printk(KERN_NOTICE "No NAND device - returning -ENXIO\n"); | ||
159 | kfree (h1910_nand_mtd); | ||
160 | iounmap ((void *) nandaddr); | ||
161 | return -ENXIO; | ||
162 | } | ||
163 | |||
164 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
165 | mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, | ||
166 | "h1910-nand"); | ||
167 | if (mtd_parts_nb > 0) | ||
168 | part_type = "command line"; | ||
169 | else | ||
170 | mtd_parts_nb = 0; | ||
171 | #endif | ||
172 | if (mtd_parts_nb == 0) | ||
173 | { | ||
174 | mtd_parts = partition_info; | ||
175 | mtd_parts_nb = NUM_PARTITIONS; | ||
176 | part_type = "static"; | ||
177 | } | ||
178 | |||
179 | /* Register the partitions */ | ||
180 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | ||
181 | add_mtd_partitions(h1910_nand_mtd, mtd_parts, mtd_parts_nb); | ||
182 | |||
183 | /* Return happy */ | ||
184 | return 0; | ||
185 | } | ||
186 | module_init(h1910_init); | ||
187 | |||
188 | /* | ||
189 | * Clean up routine | ||
190 | */ | ||
191 | static void __exit h1910_cleanup (void) | ||
192 | { | ||
193 | struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1]; | ||
194 | |||
195 | /* Release resources, unregister device */ | ||
196 | nand_release (h1910_nand_mtd); | ||
197 | |||
198 | /* Release io resource */ | ||
199 | iounmap ((void *) this->IO_ADDR_W); | ||
200 | |||
201 | /* Free the MTD device structure */ | ||
202 | kfree (h1910_nand_mtd); | ||
203 | } | ||
204 | module_exit(h1910_cleanup); | ||
205 | |||
206 | MODULE_LICENSE("GPL"); | ||
207 | MODULE_AUTHOR("Joshua Wise <joshua at joshuawise dot com>"); | ||
208 | MODULE_DESCRIPTION("NAND flash driver for iPAQ h1910"); | ||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c new file mode 100644 index 000000000000..44d5b128911f --- /dev/null +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -0,0 +1,2563 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand.c | ||
3 | * | ||
4 | * Overview: | ||
5 | * This is the generic MTD driver for NAND flash devices. It should be | ||
6 | * capable of working with almost all NAND chips currently available. | ||
7 | * Basic support for AG-AND chips is provided. | ||
8 | * | ||
9 | * Additional technical information is available on | ||
10 | * http://www.linux-mtd.infradead.org/tech/nand.html | ||
11 | * | ||
12 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | ||
13 | * 2002 Thomas Gleixner (tglx@linutronix.de) | ||
14 | * | ||
15 | * 02-08-2004 tglx: support for strange chips, which cannot auto increment | ||
16 | * pages on read / read_oob | ||
17 | * | ||
18 | * 03-17-2004 tglx: Check ready before auto increment check. Simon Bayes | ||
19 | * pointed this out, as he marked an auto increment capable chip | ||
20 | * as NOAUTOINCR in the board driver. | ||
21 | * Make reads over block boundaries work too | ||
22 | * | ||
23 | * 04-14-2004 tglx: first working version for 2k page size chips | ||
24 | * | ||
25 | * 05-19-2004 tglx: Basic support for Renesas AG-AND chips | ||
26 | * | ||
27 | * 09-24-2004 tglx: add support for hardware controllers (e.g. ECC) shared | ||
28 | * among multiple independend devices. Suggestions and initial patch | ||
29 | * from Ben Dooks <ben-mtd@fluff.org> | ||
30 | * | ||
31 | * Credits: | ||
32 | * David Woodhouse for adding multichip support | ||
33 | * | ||
34 | * Aleph One Ltd. and Toby Churchill Ltd. for supporting the | ||
35 | * rework for 2K page size chips | ||
36 | * | ||
37 | * TODO: | ||
38 | * Enable cached programming for 2k page size chips | ||
39 | * Check, if mtd->ecctype should be set to MTD_ECC_HW | ||
40 | * if we have HW ecc support. | ||
41 | * The AG-AND chips have nice features for speed improvement, | ||
42 | * which are not supported yet. Read / program 4 pages in one go. | ||
43 | * | ||
44 | * $Id: nand_base.c,v 1.126 2004/12/13 11:22:25 lavinen Exp $ | ||
45 | * | ||
46 | * This program is free software; you can redistribute it and/or modify | ||
47 | * it under the terms of the GNU General Public License version 2 as | ||
48 | * published by the Free Software Foundation. | ||
49 | * | ||
50 | */ | ||
51 | |||
52 | #include <linux/delay.h> | ||
53 | #include <linux/errno.h> | ||
54 | #include <linux/sched.h> | ||
55 | #include <linux/slab.h> | ||
56 | #include <linux/types.h> | ||
57 | #include <linux/mtd/mtd.h> | ||
58 | #include <linux/mtd/nand.h> | ||
59 | #include <linux/mtd/nand_ecc.h> | ||
60 | #include <linux/mtd/compatmac.h> | ||
61 | #include <linux/interrupt.h> | ||
62 | #include <linux/bitops.h> | ||
63 | #include <asm/io.h> | ||
64 | |||
65 | #ifdef CONFIG_MTD_PARTITIONS | ||
66 | #include <linux/mtd/partitions.h> | ||
67 | #endif | ||
68 | |||
69 | /* Define default oob placement schemes for large and small page devices */ | ||
70 | static struct nand_oobinfo nand_oob_8 = { | ||
71 | .useecc = MTD_NANDECC_AUTOPLACE, | ||
72 | .eccbytes = 3, | ||
73 | .eccpos = {0, 1, 2}, | ||
74 | .oobfree = { {3, 2}, {6, 2} } | ||
75 | }; | ||
76 | |||
77 | static struct nand_oobinfo nand_oob_16 = { | ||
78 | .useecc = MTD_NANDECC_AUTOPLACE, | ||
79 | .eccbytes = 6, | ||
80 | .eccpos = {0, 1, 2, 3, 6, 7}, | ||
81 | .oobfree = { {8, 8} } | ||
82 | }; | ||
83 | |||
84 | static struct nand_oobinfo nand_oob_64 = { | ||
85 | .useecc = MTD_NANDECC_AUTOPLACE, | ||
86 | .eccbytes = 24, | ||
87 | .eccpos = { | ||
88 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
89 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
90 | 56, 57, 58, 59, 60, 61, 62, 63}, | ||
91 | .oobfree = { {2, 38} } | ||
92 | }; | ||
93 | |||
94 | /* This is used for padding purposes in nand_write_oob */ | ||
95 | static u_char ffchars[] = { | ||
96 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
97 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
98 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
99 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
100 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
101 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
102 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
103 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
104 | }; | ||
105 | |||
106 | /* | ||
107 | * NAND low-level MTD interface functions | ||
108 | */ | ||
109 | static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len); | ||
110 | static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len); | ||
111 | static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len); | ||
112 | |||
113 | static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); | ||
114 | static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | ||
115 | size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); | ||
116 | static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf); | ||
117 | static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf); | ||
118 | static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | ||
119 | size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel); | ||
120 | static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf); | ||
121 | static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, | ||
122 | unsigned long count, loff_t to, size_t * retlen); | ||
123 | static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, | ||
124 | unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); | ||
125 | static int nand_erase (struct mtd_info *mtd, struct erase_info *instr); | ||
126 | static void nand_sync (struct mtd_info *mtd); | ||
127 | |||
128 | /* Some internal functions */ | ||
129 | static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, | ||
130 | struct nand_oobinfo *oobsel, int mode); | ||
131 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE | ||
132 | static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, | ||
133 | u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode); | ||
134 | #else | ||
135 | #define nand_verify_pages(...) (0) | ||
136 | #endif | ||
137 | |||
138 | static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); | ||
139 | |||
140 | /** | ||
141 | * nand_release_device - [GENERIC] release chip | ||
142 | * @mtd: MTD device structure | ||
143 | * | ||
144 | * Deselect, release chip lock and wake up anyone waiting on the device | ||
145 | */ | ||
146 | static void nand_release_device (struct mtd_info *mtd) | ||
147 | { | ||
148 | struct nand_chip *this = mtd->priv; | ||
149 | |||
150 | /* De-select the NAND device */ | ||
151 | this->select_chip(mtd, -1); | ||
152 | /* Do we have a hardware controller ? */ | ||
153 | if (this->controller) { | ||
154 | spin_lock(&this->controller->lock); | ||
155 | this->controller->active = NULL; | ||
156 | spin_unlock(&this->controller->lock); | ||
157 | } | ||
158 | /* Release the chip */ | ||
159 | spin_lock (&this->chip_lock); | ||
160 | this->state = FL_READY; | ||
161 | wake_up (&this->wq); | ||
162 | spin_unlock (&this->chip_lock); | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * nand_read_byte - [DEFAULT] read one byte from the chip | ||
167 | * @mtd: MTD device structure | ||
168 | * | ||
169 | * Default read function for 8bit buswith | ||
170 | */ | ||
171 | static u_char nand_read_byte(struct mtd_info *mtd) | ||
172 | { | ||
173 | struct nand_chip *this = mtd->priv; | ||
174 | return readb(this->IO_ADDR_R); | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * nand_write_byte - [DEFAULT] write one byte to the chip | ||
179 | * @mtd: MTD device structure | ||
180 | * @byte: pointer to data byte to write | ||
181 | * | ||
182 | * Default write function for 8it buswith | ||
183 | */ | ||
184 | static void nand_write_byte(struct mtd_info *mtd, u_char byte) | ||
185 | { | ||
186 | struct nand_chip *this = mtd->priv; | ||
187 | writeb(byte, this->IO_ADDR_W); | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip | ||
192 | * @mtd: MTD device structure | ||
193 | * | ||
194 | * Default read function for 16bit buswith with | ||
195 | * endianess conversion | ||
196 | */ | ||
197 | static u_char nand_read_byte16(struct mtd_info *mtd) | ||
198 | { | ||
199 | struct nand_chip *this = mtd->priv; | ||
200 | return (u_char) cpu_to_le16(readw(this->IO_ADDR_R)); | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip | ||
205 | * @mtd: MTD device structure | ||
206 | * @byte: pointer to data byte to write | ||
207 | * | ||
208 | * Default write function for 16bit buswith with | ||
209 | * endianess conversion | ||
210 | */ | ||
211 | static void nand_write_byte16(struct mtd_info *mtd, u_char byte) | ||
212 | { | ||
213 | struct nand_chip *this = mtd->priv; | ||
214 | writew(le16_to_cpu((u16) byte), this->IO_ADDR_W); | ||
215 | } | ||
216 | |||
217 | /** | ||
218 | * nand_read_word - [DEFAULT] read one word from the chip | ||
219 | * @mtd: MTD device structure | ||
220 | * | ||
221 | * Default read function for 16bit buswith without | ||
222 | * endianess conversion | ||
223 | */ | ||
224 | static u16 nand_read_word(struct mtd_info *mtd) | ||
225 | { | ||
226 | struct nand_chip *this = mtd->priv; | ||
227 | return readw(this->IO_ADDR_R); | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * nand_write_word - [DEFAULT] write one word to the chip | ||
232 | * @mtd: MTD device structure | ||
233 | * @word: data word to write | ||
234 | * | ||
235 | * Default write function for 16bit buswith without | ||
236 | * endianess conversion | ||
237 | */ | ||
238 | static void nand_write_word(struct mtd_info *mtd, u16 word) | ||
239 | { | ||
240 | struct nand_chip *this = mtd->priv; | ||
241 | writew(word, this->IO_ADDR_W); | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * nand_select_chip - [DEFAULT] control CE line | ||
246 | * @mtd: MTD device structure | ||
247 | * @chip: chipnumber to select, -1 for deselect | ||
248 | * | ||
249 | * Default select function for 1 chip devices. | ||
250 | */ | ||
251 | static void nand_select_chip(struct mtd_info *mtd, int chip) | ||
252 | { | ||
253 | struct nand_chip *this = mtd->priv; | ||
254 | switch(chip) { | ||
255 | case -1: | ||
256 | this->hwcontrol(mtd, NAND_CTL_CLRNCE); | ||
257 | break; | ||
258 | case 0: | ||
259 | this->hwcontrol(mtd, NAND_CTL_SETNCE); | ||
260 | break; | ||
261 | |||
262 | default: | ||
263 | BUG(); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * nand_write_buf - [DEFAULT] write buffer to chip | ||
269 | * @mtd: MTD device structure | ||
270 | * @buf: data buffer | ||
271 | * @len: number of bytes to write | ||
272 | * | ||
273 | * Default write function for 8bit buswith | ||
274 | */ | ||
275 | static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
276 | { | ||
277 | int i; | ||
278 | struct nand_chip *this = mtd->priv; | ||
279 | |||
280 | for (i=0; i<len; i++) | ||
281 | writeb(buf[i], this->IO_ADDR_W); | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * nand_read_buf - [DEFAULT] read chip data into buffer | ||
286 | * @mtd: MTD device structure | ||
287 | * @buf: buffer to store date | ||
288 | * @len: number of bytes to read | ||
289 | * | ||
290 | * Default read function for 8bit buswith | ||
291 | */ | ||
292 | static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | ||
293 | { | ||
294 | int i; | ||
295 | struct nand_chip *this = mtd->priv; | ||
296 | |||
297 | for (i=0; i<len; i++) | ||
298 | buf[i] = readb(this->IO_ADDR_R); | ||
299 | } | ||
300 | |||
301 | /** | ||
302 | * nand_verify_buf - [DEFAULT] Verify chip data against buffer | ||
303 | * @mtd: MTD device structure | ||
304 | * @buf: buffer containing the data to compare | ||
305 | * @len: number of bytes to compare | ||
306 | * | ||
307 | * Default verify function for 8bit buswith | ||
308 | */ | ||
309 | static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
310 | { | ||
311 | int i; | ||
312 | struct nand_chip *this = mtd->priv; | ||
313 | |||
314 | for (i=0; i<len; i++) | ||
315 | if (buf[i] != readb(this->IO_ADDR_R)) | ||
316 | return -EFAULT; | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | /** | ||
322 | * nand_write_buf16 - [DEFAULT] write buffer to chip | ||
323 | * @mtd: MTD device structure | ||
324 | * @buf: data buffer | ||
325 | * @len: number of bytes to write | ||
326 | * | ||
327 | * Default write function for 16bit buswith | ||
328 | */ | ||
329 | static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len) | ||
330 | { | ||
331 | int i; | ||
332 | struct nand_chip *this = mtd->priv; | ||
333 | u16 *p = (u16 *) buf; | ||
334 | len >>= 1; | ||
335 | |||
336 | for (i=0; i<len; i++) | ||
337 | writew(p[i], this->IO_ADDR_W); | ||
338 | |||
339 | } | ||
340 | |||
341 | /** | ||
342 | * nand_read_buf16 - [DEFAULT] read chip data into buffer | ||
343 | * @mtd: MTD device structure | ||
344 | * @buf: buffer to store date | ||
345 | * @len: number of bytes to read | ||
346 | * | ||
347 | * Default read function for 16bit buswith | ||
348 | */ | ||
349 | static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len) | ||
350 | { | ||
351 | int i; | ||
352 | struct nand_chip *this = mtd->priv; | ||
353 | u16 *p = (u16 *) buf; | ||
354 | len >>= 1; | ||
355 | |||
356 | for (i=0; i<len; i++) | ||
357 | p[i] = readw(this->IO_ADDR_R); | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer | ||
362 | * @mtd: MTD device structure | ||
363 | * @buf: buffer containing the data to compare | ||
364 | * @len: number of bytes to compare | ||
365 | * | ||
366 | * Default verify function for 16bit buswith | ||
367 | */ | ||
368 | static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len) | ||
369 | { | ||
370 | int i; | ||
371 | struct nand_chip *this = mtd->priv; | ||
372 | u16 *p = (u16 *) buf; | ||
373 | len >>= 1; | ||
374 | |||
375 | for (i=0; i<len; i++) | ||
376 | if (p[i] != readw(this->IO_ADDR_R)) | ||
377 | return -EFAULT; | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | /** | ||
383 | * nand_block_bad - [DEFAULT] Read bad block marker from the chip | ||
384 | * @mtd: MTD device structure | ||
385 | * @ofs: offset from device start | ||
386 | * @getchip: 0, if the chip is already selected | ||
387 | * | ||
388 | * Check, if the block is bad. | ||
389 | */ | ||
390 | static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | ||
391 | { | ||
392 | int page, chipnr, res = 0; | ||
393 | struct nand_chip *this = mtd->priv; | ||
394 | u16 bad; | ||
395 | |||
396 | if (getchip) { | ||
397 | page = (int)(ofs >> this->page_shift); | ||
398 | chipnr = (int)(ofs >> this->chip_shift); | ||
399 | |||
400 | /* Grab the lock and see if the device is available */ | ||
401 | nand_get_device (this, mtd, FL_READING); | ||
402 | |||
403 | /* Select the NAND device */ | ||
404 | this->select_chip(mtd, chipnr); | ||
405 | } else | ||
406 | page = (int) ofs; | ||
407 | |||
408 | if (this->options & NAND_BUSWIDTH_16) { | ||
409 | this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); | ||
410 | bad = cpu_to_le16(this->read_word(mtd)); | ||
411 | if (this->badblockpos & 0x1) | ||
412 | bad >>= 1; | ||
413 | if ((bad & 0xFF) != 0xff) | ||
414 | res = 1; | ||
415 | } else { | ||
416 | this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask); | ||
417 | if (this->read_byte(mtd) != 0xff) | ||
418 | res = 1; | ||
419 | } | ||
420 | |||
421 | if (getchip) { | ||
422 | /* Deselect and wake up anyone waiting on the device */ | ||
423 | nand_release_device(mtd); | ||
424 | } | ||
425 | |||
426 | return res; | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * nand_default_block_markbad - [DEFAULT] mark a block bad | ||
431 | * @mtd: MTD device structure | ||
432 | * @ofs: offset from device start | ||
433 | * | ||
434 | * This is the default implementation, which can be overridden by | ||
435 | * a hardware specific driver. | ||
436 | */ | ||
437 | static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | ||
438 | { | ||
439 | struct nand_chip *this = mtd->priv; | ||
440 | u_char buf[2] = {0, 0}; | ||
441 | size_t retlen; | ||
442 | int block; | ||
443 | |||
444 | /* Get block number */ | ||
445 | block = ((int) ofs) >> this->bbt_erase_shift; | ||
446 | this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); | ||
447 | |||
448 | /* Do we have a flash based bad block table ? */ | ||
449 | if (this->options & NAND_USE_FLASH_BBT) | ||
450 | return nand_update_bbt (mtd, ofs); | ||
451 | |||
452 | /* We write two bytes, so we dont have to mess with 16 bit access */ | ||
453 | ofs += mtd->oobsize + (this->badblockpos & ~0x01); | ||
454 | return nand_write_oob (mtd, ofs , 2, &retlen, buf); | ||
455 | } | ||
456 | |||
457 | /** | ||
458 | * nand_check_wp - [GENERIC] check if the chip is write protected | ||
459 | * @mtd: MTD device structure | ||
460 | * Check, if the device is write protected | ||
461 | * | ||
462 | * The function expects, that the device is already selected | ||
463 | */ | ||
464 | static int nand_check_wp (struct mtd_info *mtd) | ||
465 | { | ||
466 | struct nand_chip *this = mtd->priv; | ||
467 | /* Check the WP bit */ | ||
468 | this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); | ||
469 | return (this->read_byte(mtd) & 0x80) ? 0 : 1; | ||
470 | } | ||
471 | |||
472 | /** | ||
473 | * nand_block_checkbad - [GENERIC] Check if a block is marked bad | ||
474 | * @mtd: MTD device structure | ||
475 | * @ofs: offset from device start | ||
476 | * @getchip: 0, if the chip is already selected | ||
477 | * @allowbbt: 1, if its allowed to access the bbt area | ||
478 | * | ||
479 | * Check, if the block is bad. Either by reading the bad block table or | ||
480 | * calling of the scan function. | ||
481 | */ | ||
482 | static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) | ||
483 | { | ||
484 | struct nand_chip *this = mtd->priv; | ||
485 | |||
486 | if (!this->bbt) | ||
487 | return this->block_bad(mtd, ofs, getchip); | ||
488 | |||
489 | /* Return info from the table */ | ||
490 | return nand_isbad_bbt (mtd, ofs, allowbbt); | ||
491 | } | ||
492 | |||
493 | /** | ||
494 | * nand_command - [DEFAULT] Send command to NAND device | ||
495 | * @mtd: MTD device structure | ||
496 | * @command: the command to be sent | ||
497 | * @column: the column address for this command, -1 if none | ||
498 | * @page_addr: the page address for this command, -1 if none | ||
499 | * | ||
500 | * Send command to NAND device. This function is used for small page | ||
501 | * devices (256/512 Bytes per page) | ||
502 | */ | ||
503 | static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) | ||
504 | { | ||
505 | register struct nand_chip *this = mtd->priv; | ||
506 | |||
507 | /* Begin command latch cycle */ | ||
508 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
509 | /* | ||
510 | * Write out the command to the device. | ||
511 | */ | ||
512 | if (command == NAND_CMD_SEQIN) { | ||
513 | int readcmd; | ||
514 | |||
515 | if (column >= mtd->oobblock) { | ||
516 | /* OOB area */ | ||
517 | column -= mtd->oobblock; | ||
518 | readcmd = NAND_CMD_READOOB; | ||
519 | } else if (column < 256) { | ||
520 | /* First 256 bytes --> READ0 */ | ||
521 | readcmd = NAND_CMD_READ0; | ||
522 | } else { | ||
523 | column -= 256; | ||
524 | readcmd = NAND_CMD_READ1; | ||
525 | } | ||
526 | this->write_byte(mtd, readcmd); | ||
527 | } | ||
528 | this->write_byte(mtd, command); | ||
529 | |||
530 | /* Set ALE and clear CLE to start address cycle */ | ||
531 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
532 | |||
533 | if (column != -1 || page_addr != -1) { | ||
534 | this->hwcontrol(mtd, NAND_CTL_SETALE); | ||
535 | |||
536 | /* Serially input address */ | ||
537 | if (column != -1) { | ||
538 | /* Adjust columns for 16 bit buswidth */ | ||
539 | if (this->options & NAND_BUSWIDTH_16) | ||
540 | column >>= 1; | ||
541 | this->write_byte(mtd, column); | ||
542 | } | ||
543 | if (page_addr != -1) { | ||
544 | this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); | ||
545 | this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); | ||
546 | /* One more address cycle for devices > 32MiB */ | ||
547 | if (this->chipsize > (32 << 20)) | ||
548 | this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); | ||
549 | } | ||
550 | /* Latch in address */ | ||
551 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | * program and erase have their own busy handlers | ||
556 | * status and sequential in needs no delay | ||
557 | */ | ||
558 | switch (command) { | ||
559 | |||
560 | case NAND_CMD_PAGEPROG: | ||
561 | case NAND_CMD_ERASE1: | ||
562 | case NAND_CMD_ERASE2: | ||
563 | case NAND_CMD_SEQIN: | ||
564 | case NAND_CMD_STATUS: | ||
565 | return; | ||
566 | |||
567 | case NAND_CMD_RESET: | ||
568 | if (this->dev_ready) | ||
569 | break; | ||
570 | udelay(this->chip_delay); | ||
571 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
572 | this->write_byte(mtd, NAND_CMD_STATUS); | ||
573 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
574 | while ( !(this->read_byte(mtd) & 0x40)); | ||
575 | return; | ||
576 | |||
577 | /* This applies to read commands */ | ||
578 | default: | ||
579 | /* | ||
580 | * If we don't have access to the busy pin, we apply the given | ||
581 | * command delay | ||
582 | */ | ||
583 | if (!this->dev_ready) { | ||
584 | udelay (this->chip_delay); | ||
585 | return; | ||
586 | } | ||
587 | } | ||
588 | |||
589 | /* Apply this short delay always to ensure that we do wait tWB in | ||
590 | * any case on any machine. */ | ||
591 | ndelay (100); | ||
592 | /* wait until command is processed */ | ||
593 | while (!this->dev_ready(mtd)); | ||
594 | } | ||
595 | |||
596 | /** | ||
597 | * nand_command_lp - [DEFAULT] Send command to NAND large page device | ||
598 | * @mtd: MTD device structure | ||
599 | * @command: the command to be sent | ||
600 | * @column: the column address for this command, -1 if none | ||
601 | * @page_addr: the page address for this command, -1 if none | ||
602 | * | ||
603 | * Send command to NAND device. This is the version for the new large page devices | ||
604 | * We dont have the seperate regions as we have in the small page devices. | ||
605 | * We must emulate NAND_CMD_READOOB to keep the code compatible. | ||
606 | * | ||
607 | */ | ||
608 | static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr) | ||
609 | { | ||
610 | register struct nand_chip *this = mtd->priv; | ||
611 | |||
612 | /* Emulate NAND_CMD_READOOB */ | ||
613 | if (command == NAND_CMD_READOOB) { | ||
614 | column += mtd->oobblock; | ||
615 | command = NAND_CMD_READ0; | ||
616 | } | ||
617 | |||
618 | |||
619 | /* Begin command latch cycle */ | ||
620 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
621 | /* Write out the command to the device. */ | ||
622 | this->write_byte(mtd, command); | ||
623 | /* End command latch cycle */ | ||
624 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
625 | |||
626 | if (column != -1 || page_addr != -1) { | ||
627 | this->hwcontrol(mtd, NAND_CTL_SETALE); | ||
628 | |||
629 | /* Serially input address */ | ||
630 | if (column != -1) { | ||
631 | /* Adjust columns for 16 bit buswidth */ | ||
632 | if (this->options & NAND_BUSWIDTH_16) | ||
633 | column >>= 1; | ||
634 | this->write_byte(mtd, column & 0xff); | ||
635 | this->write_byte(mtd, column >> 8); | ||
636 | } | ||
637 | if (page_addr != -1) { | ||
638 | this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); | ||
639 | this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); | ||
640 | /* One more address cycle for devices > 128MiB */ | ||
641 | if (this->chipsize > (128 << 20)) | ||
642 | this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0xff)); | ||
643 | } | ||
644 | /* Latch in address */ | ||
645 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | ||
646 | } | ||
647 | |||
648 | /* | ||
649 | * program and erase have their own busy handlers | ||
650 | * status and sequential in needs no delay | ||
651 | */ | ||
652 | switch (command) { | ||
653 | |||
654 | case NAND_CMD_CACHEDPROG: | ||
655 | case NAND_CMD_PAGEPROG: | ||
656 | case NAND_CMD_ERASE1: | ||
657 | case NAND_CMD_ERASE2: | ||
658 | case NAND_CMD_SEQIN: | ||
659 | case NAND_CMD_STATUS: | ||
660 | return; | ||
661 | |||
662 | |||
663 | case NAND_CMD_RESET: | ||
664 | if (this->dev_ready) | ||
665 | break; | ||
666 | udelay(this->chip_delay); | ||
667 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
668 | this->write_byte(mtd, NAND_CMD_STATUS); | ||
669 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
670 | while ( !(this->read_byte(mtd) & 0x40)); | ||
671 | return; | ||
672 | |||
673 | case NAND_CMD_READ0: | ||
674 | /* Begin command latch cycle */ | ||
675 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
676 | /* Write out the start read command */ | ||
677 | this->write_byte(mtd, NAND_CMD_READSTART); | ||
678 | /* End command latch cycle */ | ||
679 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
680 | /* Fall through into ready check */ | ||
681 | |||
682 | /* This applies to read commands */ | ||
683 | default: | ||
684 | /* | ||
685 | * If we don't have access to the busy pin, we apply the given | ||
686 | * command delay | ||
687 | */ | ||
688 | if (!this->dev_ready) { | ||
689 | udelay (this->chip_delay); | ||
690 | return; | ||
691 | } | ||
692 | } | ||
693 | |||
694 | /* Apply this short delay always to ensure that we do wait tWB in | ||
695 | * any case on any machine. */ | ||
696 | ndelay (100); | ||
697 | /* wait until command is processed */ | ||
698 | while (!this->dev_ready(mtd)); | ||
699 | } | ||
700 | |||
701 | /** | ||
702 | * nand_get_device - [GENERIC] Get chip for selected access | ||
703 | * @this: the nand chip descriptor | ||
704 | * @mtd: MTD device structure | ||
705 | * @new_state: the state which is requested | ||
706 | * | ||
707 | * Get the device and lock it for exclusive access | ||
708 | */ | ||
709 | static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) | ||
710 | { | ||
711 | struct nand_chip *active = this; | ||
712 | |||
713 | DECLARE_WAITQUEUE (wait, current); | ||
714 | |||
715 | /* | ||
716 | * Grab the lock and see if the device is available | ||
717 | */ | ||
718 | retry: | ||
719 | /* Hardware controller shared among independend devices */ | ||
720 | if (this->controller) { | ||
721 | spin_lock (&this->controller->lock); | ||
722 | if (this->controller->active) | ||
723 | active = this->controller->active; | ||
724 | else | ||
725 | this->controller->active = this; | ||
726 | spin_unlock (&this->controller->lock); | ||
727 | } | ||
728 | |||
729 | if (active == this) { | ||
730 | spin_lock (&this->chip_lock); | ||
731 | if (this->state == FL_READY) { | ||
732 | this->state = new_state; | ||
733 | spin_unlock (&this->chip_lock); | ||
734 | return; | ||
735 | } | ||
736 | } | ||
737 | set_current_state (TASK_UNINTERRUPTIBLE); | ||
738 | add_wait_queue (&active->wq, &wait); | ||
739 | spin_unlock (&active->chip_lock); | ||
740 | schedule (); | ||
741 | remove_wait_queue (&active->wq, &wait); | ||
742 | goto retry; | ||
743 | } | ||
744 | |||
745 | /** | ||
746 | * nand_wait - [DEFAULT] wait until the command is done | ||
747 | * @mtd: MTD device structure | ||
748 | * @this: NAND chip structure | ||
749 | * @state: state to select the max. timeout value | ||
750 | * | ||
751 | * Wait for command done. This applies to erase and program only | ||
752 | * Erase can take up to 400ms and program up to 20ms according to | ||
753 | * general NAND and SmartMedia specs | ||
754 | * | ||
755 | */ | ||
756 | static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | ||
757 | { | ||
758 | |||
759 | unsigned long timeo = jiffies; | ||
760 | int status; | ||
761 | |||
762 | if (state == FL_ERASING) | ||
763 | timeo += (HZ * 400) / 1000; | ||
764 | else | ||
765 | timeo += (HZ * 20) / 1000; | ||
766 | |||
767 | /* Apply this short delay always to ensure that we do wait tWB in | ||
768 | * any case on any machine. */ | ||
769 | ndelay (100); | ||
770 | |||
771 | if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) | ||
772 | this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); | ||
773 | else | ||
774 | this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); | ||
775 | |||
776 | while (time_before(jiffies, timeo)) { | ||
777 | /* Check, if we were interrupted */ | ||
778 | if (this->state != state) | ||
779 | return 0; | ||
780 | |||
781 | if (this->dev_ready) { | ||
782 | if (this->dev_ready(mtd)) | ||
783 | break; | ||
784 | } else { | ||
785 | if (this->read_byte(mtd) & NAND_STATUS_READY) | ||
786 | break; | ||
787 | } | ||
788 | yield (); | ||
789 | } | ||
790 | status = (int) this->read_byte(mtd); | ||
791 | return status; | ||
792 | } | ||
793 | |||
794 | /** | ||
795 | * nand_write_page - [GENERIC] write one page | ||
796 | * @mtd: MTD device structure | ||
797 | * @this: NAND chip structure | ||
798 | * @page: startpage inside the chip, must be called with (page & this->pagemask) | ||
799 | * @oob_buf: out of band data buffer | ||
800 | * @oobsel: out of band selecttion structre | ||
801 | * @cached: 1 = enable cached programming if supported by chip | ||
802 | * | ||
803 | * Nand_page_program function is used for write and writev ! | ||
804 | * This function will always program a full page of data | ||
805 | * If you call it with a non page aligned buffer, you're lost :) | ||
806 | * | ||
807 | * Cached programming is not supported yet. | ||
808 | */ | ||
809 | static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, | ||
810 | u_char *oob_buf, struct nand_oobinfo *oobsel, int cached) | ||
811 | { | ||
812 | int i, status; | ||
813 | u_char ecc_code[32]; | ||
814 | int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; | ||
815 | int *oob_config = oobsel->eccpos; | ||
816 | int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; | ||
817 | int eccbytes = 0; | ||
818 | |||
819 | /* FIXME: Enable cached programming */ | ||
820 | cached = 0; | ||
821 | |||
822 | /* Send command to begin auto page programming */ | ||
823 | this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); | ||
824 | |||
825 | /* Write out complete page of data, take care of eccmode */ | ||
826 | switch (eccmode) { | ||
827 | /* No ecc, write all */ | ||
828 | case NAND_ECC_NONE: | ||
829 | printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); | ||
830 | this->write_buf(mtd, this->data_poi, mtd->oobblock); | ||
831 | break; | ||
832 | |||
833 | /* Software ecc 3/256, write all */ | ||
834 | case NAND_ECC_SOFT: | ||
835 | for (; eccsteps; eccsteps--) { | ||
836 | this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); | ||
837 | for (i = 0; i < 3; i++, eccidx++) | ||
838 | oob_buf[oob_config[eccidx]] = ecc_code[i]; | ||
839 | datidx += this->eccsize; | ||
840 | } | ||
841 | this->write_buf(mtd, this->data_poi, mtd->oobblock); | ||
842 | break; | ||
843 | default: | ||
844 | eccbytes = this->eccbytes; | ||
845 | for (; eccsteps; eccsteps--) { | ||
846 | /* enable hardware ecc logic for write */ | ||
847 | this->enable_hwecc(mtd, NAND_ECC_WRITE); | ||
848 | this->write_buf(mtd, &this->data_poi[datidx], this->eccsize); | ||
849 | this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code); | ||
850 | for (i = 0; i < eccbytes; i++, eccidx++) | ||
851 | oob_buf[oob_config[eccidx]] = ecc_code[i]; | ||
852 | /* If the hardware ecc provides syndromes then | ||
853 | * the ecc code must be written immidiately after | ||
854 | * the data bytes (words) */ | ||
855 | if (this->options & NAND_HWECC_SYNDROME) | ||
856 | this->write_buf(mtd, ecc_code, eccbytes); | ||
857 | datidx += this->eccsize; | ||
858 | } | ||
859 | break; | ||
860 | } | ||
861 | |||
862 | /* Write out OOB data */ | ||
863 | if (this->options & NAND_HWECC_SYNDROME) | ||
864 | this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes); | ||
865 | else | ||
866 | this->write_buf(mtd, oob_buf, mtd->oobsize); | ||
867 | |||
868 | /* Send command to actually program the data */ | ||
869 | this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1); | ||
870 | |||
871 | if (!cached) { | ||
872 | /* call wait ready function */ | ||
873 | status = this->waitfunc (mtd, this, FL_WRITING); | ||
874 | /* See if device thinks it succeeded */ | ||
875 | if (status & 0x01) { | ||
876 | DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page); | ||
877 | return -EIO; | ||
878 | } | ||
879 | } else { | ||
880 | /* FIXME: Implement cached programming ! */ | ||
881 | /* wait until cache is ready*/ | ||
882 | // status = this->waitfunc (mtd, this, FL_CACHEDRPG); | ||
883 | } | ||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE | ||
888 | /** | ||
889 | * nand_verify_pages - [GENERIC] verify the chip contents after a write | ||
890 | * @mtd: MTD device structure | ||
891 | * @this: NAND chip structure | ||
892 | * @page: startpage inside the chip, must be called with (page & this->pagemask) | ||
893 | * @numpages: number of pages to verify | ||
894 | * @oob_buf: out of band data buffer | ||
895 | * @oobsel: out of band selecttion structre | ||
896 | * @chipnr: number of the current chip | ||
897 | * @oobmode: 1 = full buffer verify, 0 = ecc only | ||
898 | * | ||
899 | * The NAND device assumes that it is always writing to a cleanly erased page. | ||
900 | * Hence, it performs its internal write verification only on bits that | ||
901 | * transitioned from 1 to 0. The device does NOT verify the whole page on a | ||
902 | * byte by byte basis. It is possible that the page was not completely erased | ||
903 | * or the page is becoming unusable due to wear. The read with ECC would catch | ||
904 | * the error later when the ECC page check fails, but we would rather catch | ||
905 | * it early in the page write stage. Better to write no data than invalid data. | ||
906 | */ | ||
907 | static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages, | ||
908 | u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode) | ||
909 | { | ||
910 | int i, j, datidx = 0, oobofs = 0, res = -EIO; | ||
911 | int eccsteps = this->eccsteps; | ||
912 | int hweccbytes; | ||
913 | u_char oobdata[64]; | ||
914 | |||
915 | hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; | ||
916 | |||
917 | /* Send command to read back the first page */ | ||
918 | this->cmdfunc (mtd, NAND_CMD_READ0, 0, page); | ||
919 | |||
920 | for(;;) { | ||
921 | for (j = 0; j < eccsteps; j++) { | ||
922 | /* Loop through and verify the data */ | ||
923 | if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) { | ||
924 | DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); | ||
925 | goto out; | ||
926 | } | ||
927 | datidx += mtd->eccsize; | ||
928 | /* Have we a hw generator layout ? */ | ||
929 | if (!hweccbytes) | ||
930 | continue; | ||
931 | if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) { | ||
932 | DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); | ||
933 | goto out; | ||
934 | } | ||
935 | oobofs += hweccbytes; | ||
936 | } | ||
937 | |||
938 | /* check, if we must compare all data or if we just have to | ||
939 | * compare the ecc bytes | ||
940 | */ | ||
941 | if (oobmode) { | ||
942 | if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) { | ||
943 | DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page); | ||
944 | goto out; | ||
945 | } | ||
946 | } else { | ||
947 | /* Read always, else autoincrement fails */ | ||
948 | this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps); | ||
949 | |||
950 | if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) { | ||
951 | int ecccnt = oobsel->eccbytes; | ||
952 | |||
953 | for (i = 0; i < ecccnt; i++) { | ||
954 | int idx = oobsel->eccpos[i]; | ||
955 | if (oobdata[idx] != oob_buf[oobofs + idx] ) { | ||
956 | DEBUG (MTD_DEBUG_LEVEL0, | ||
957 | "%s: Failed ECC write " | ||
958 | "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i); | ||
959 | goto out; | ||
960 | } | ||
961 | } | ||
962 | } | ||
963 | } | ||
964 | oobofs += mtd->oobsize - hweccbytes * eccsteps; | ||
965 | page++; | ||
966 | numpages--; | ||
967 | |||
968 | /* Apply delay or wait for ready/busy pin | ||
969 | * Do this before the AUTOINCR check, so no problems | ||
970 | * arise if a chip which does auto increment | ||
971 | * is marked as NOAUTOINCR by the board driver. | ||
972 | * Do this also before returning, so the chip is | ||
973 | * ready for the next command. | ||
974 | */ | ||
975 | if (!this->dev_ready) | ||
976 | udelay (this->chip_delay); | ||
977 | else | ||
978 | while (!this->dev_ready(mtd)); | ||
979 | |||
980 | /* All done, return happy */ | ||
981 | if (!numpages) | ||
982 | return 0; | ||
983 | |||
984 | |||
985 | /* Check, if the chip supports auto page increment */ | ||
986 | if (!NAND_CANAUTOINCR(this)) | ||
987 | this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); | ||
988 | } | ||
989 | /* | ||
990 | * Terminate the read command. We come here in case of an error | ||
991 | * So we must issue a reset command. | ||
992 | */ | ||
993 | out: | ||
994 | this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1); | ||
995 | return res; | ||
996 | } | ||
997 | #endif | ||
998 | |||
999 | /** | ||
1000 | * nand_read - [MTD Interface] MTD compability function for nand_read_ecc | ||
1001 | * @mtd: MTD device structure | ||
1002 | * @from: offset to read from | ||
1003 | * @len: number of bytes to read | ||
1004 | * @retlen: pointer to variable to store the number of read bytes | ||
1005 | * @buf: the databuffer to put data | ||
1006 | * | ||
1007 | * This function simply calls nand_read_ecc with oob buffer and oobsel = NULL | ||
1008 | */ | ||
1009 | static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) | ||
1010 | { | ||
1011 | return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL); | ||
1012 | } | ||
1013 | |||
1014 | |||
1015 | /** | ||
1016 | * nand_read_ecc - [MTD Interface] Read data with ECC | ||
1017 | * @mtd: MTD device structure | ||
1018 | * @from: offset to read from | ||
1019 | * @len: number of bytes to read | ||
1020 | * @retlen: pointer to variable to store the number of read bytes | ||
1021 | * @buf: the databuffer to put data | ||
1022 | * @oob_buf: filesystem supplied oob data buffer | ||
1023 | * @oobsel: oob selection structure | ||
1024 | * | ||
1025 | * NAND read with ECC | ||
1026 | */ | ||
1027 | static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, | ||
1028 | size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel) | ||
1029 | { | ||
1030 | int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1; | ||
1031 | int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0; | ||
1032 | struct nand_chip *this = mtd->priv; | ||
1033 | u_char *data_poi, *oob_data = oob_buf; | ||
1034 | u_char ecc_calc[32]; | ||
1035 | u_char ecc_code[32]; | ||
1036 | int eccmode, eccsteps; | ||
1037 | int *oob_config, datidx; | ||
1038 | int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; | ||
1039 | int eccbytes; | ||
1040 | int compareecc = 1; | ||
1041 | int oobreadlen; | ||
1042 | |||
1043 | |||
1044 | DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); | ||
1045 | |||
1046 | /* Do not allow reads past end of device */ | ||
1047 | if ((from + len) > mtd->size) { | ||
1048 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n"); | ||
1049 | *retlen = 0; | ||
1050 | return -EINVAL; | ||
1051 | } | ||
1052 | |||
1053 | /* Grab the lock and see if the device is available */ | ||
1054 | nand_get_device (this, mtd ,FL_READING); | ||
1055 | |||
1056 | /* use userspace supplied oobinfo, if zero */ | ||
1057 | if (oobsel == NULL) | ||
1058 | oobsel = &mtd->oobinfo; | ||
1059 | |||
1060 | /* Autoplace of oob data ? Use the default placement scheme */ | ||
1061 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) | ||
1062 | oobsel = this->autooob; | ||
1063 | |||
1064 | eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; | ||
1065 | oob_config = oobsel->eccpos; | ||
1066 | |||
1067 | /* Select the NAND device */ | ||
1068 | chipnr = (int)(from >> this->chip_shift); | ||
1069 | this->select_chip(mtd, chipnr); | ||
1070 | |||
1071 | /* First we calculate the starting page */ | ||
1072 | realpage = (int) (from >> this->page_shift); | ||
1073 | page = realpage & this->pagemask; | ||
1074 | |||
1075 | /* Get raw starting column */ | ||
1076 | col = from & (mtd->oobblock - 1); | ||
1077 | |||
1078 | end = mtd->oobblock; | ||
1079 | ecc = this->eccsize; | ||
1080 | eccbytes = this->eccbytes; | ||
1081 | |||
1082 | if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) | ||
1083 | compareecc = 0; | ||
1084 | |||
1085 | oobreadlen = mtd->oobsize; | ||
1086 | if (this->options & NAND_HWECC_SYNDROME) | ||
1087 | oobreadlen -= oobsel->eccbytes; | ||
1088 | |||
1089 | /* Loop until all data read */ | ||
1090 | while (read < len) { | ||
1091 | |||
1092 | int aligned = (!col && (len - read) >= end); | ||
1093 | /* | ||
1094 | * If the read is not page aligned, we have to read into data buffer | ||
1095 | * due to ecc, else we read into return buffer direct | ||
1096 | */ | ||
1097 | if (aligned) | ||
1098 | data_poi = &buf[read]; | ||
1099 | else | ||
1100 | data_poi = this->data_buf; | ||
1101 | |||
1102 | /* Check, if we have this page in the buffer | ||
1103 | * | ||
1104 | * FIXME: Make it work when we must provide oob data too, | ||
1105 | * check the usage of data_buf oob field | ||
1106 | */ | ||
1107 | if (realpage == this->pagebuf && !oob_buf) { | ||
1108 | /* aligned read ? */ | ||
1109 | if (aligned) | ||
1110 | memcpy (data_poi, this->data_buf, end); | ||
1111 | goto readdata; | ||
1112 | } | ||
1113 | |||
1114 | /* Check, if we must send the read command */ | ||
1115 | if (sndcmd) { | ||
1116 | this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page); | ||
1117 | sndcmd = 0; | ||
1118 | } | ||
1119 | |||
1120 | /* get oob area, if we have no oob buffer from fs-driver */ | ||
1121 | if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE) | ||
1122 | oob_data = &this->data_buf[end]; | ||
1123 | |||
1124 | eccsteps = this->eccsteps; | ||
1125 | |||
1126 | switch (eccmode) { | ||
1127 | case NAND_ECC_NONE: { /* No ECC, Read in a page */ | ||
1128 | static unsigned long lastwhinge = 0; | ||
1129 | if ((lastwhinge / HZ) != (jiffies / HZ)) { | ||
1130 | printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n"); | ||
1131 | lastwhinge = jiffies; | ||
1132 | } | ||
1133 | this->read_buf(mtd, data_poi, end); | ||
1134 | break; | ||
1135 | } | ||
1136 | |||
1137 | case NAND_ECC_SOFT: /* Software ECC 3/256: Read in a page + oob data */ | ||
1138 | this->read_buf(mtd, data_poi, end); | ||
1139 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc) | ||
1140 | this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); | ||
1141 | break; | ||
1142 | |||
1143 | default: | ||
1144 | for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) { | ||
1145 | this->enable_hwecc(mtd, NAND_ECC_READ); | ||
1146 | this->read_buf(mtd, &data_poi[datidx], ecc); | ||
1147 | |||
1148 | /* HW ecc with syndrome calculation must read the | ||
1149 | * syndrome from flash immidiately after the data */ | ||
1150 | if (!compareecc) { | ||
1151 | /* Some hw ecc generators need to know when the | ||
1152 | * syndrome is read from flash */ | ||
1153 | this->enable_hwecc(mtd, NAND_ECC_READSYN); | ||
1154 | this->read_buf(mtd, &oob_data[i], eccbytes); | ||
1155 | /* We calc error correction directly, it checks the hw | ||
1156 | * generator for an error, reads back the syndrome and | ||
1157 | * does the error correction on the fly */ | ||
1158 | if (this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]) == -1) { | ||
1159 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " | ||
1160 | "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr); | ||
1161 | ecc_failed++; | ||
1162 | } | ||
1163 | } else { | ||
1164 | this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); | ||
1165 | } | ||
1166 | } | ||
1167 | break; | ||
1168 | } | ||
1169 | |||
1170 | /* read oobdata */ | ||
1171 | this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen); | ||
1172 | |||
1173 | /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */ | ||
1174 | if (!compareecc) | ||
1175 | goto readoob; | ||
1176 | |||
1177 | /* Pick the ECC bytes out of the oob data */ | ||
1178 | for (j = 0; j < oobsel->eccbytes; j++) | ||
1179 | ecc_code[j] = oob_data[oob_config[j]]; | ||
1180 | |||
1181 | /* correct data, if neccecary */ | ||
1182 | for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) { | ||
1183 | ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); | ||
1184 | |||
1185 | /* Get next chunk of ecc bytes */ | ||
1186 | j += eccbytes; | ||
1187 | |||
1188 | /* Check, if we have a fs supplied oob-buffer, | ||
1189 | * This is the legacy mode. Used by YAFFS1 | ||
1190 | * Should go away some day | ||
1191 | */ | ||
1192 | if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) { | ||
1193 | int *p = (int *)(&oob_data[mtd->oobsize]); | ||
1194 | p[i] = ecc_status; | ||
1195 | } | ||
1196 | |||
1197 | if (ecc_status == -1) { | ||
1198 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); | ||
1199 | ecc_failed++; | ||
1200 | } | ||
1201 | } | ||
1202 | |||
1203 | readoob: | ||
1204 | /* check, if we have a fs supplied oob-buffer */ | ||
1205 | if (oob_buf) { | ||
1206 | /* without autoplace. Legacy mode used by YAFFS1 */ | ||
1207 | switch(oobsel->useecc) { | ||
1208 | case MTD_NANDECC_AUTOPLACE: | ||
1209 | /* Walk through the autoplace chunks */ | ||
1210 | for (i = 0, j = 0; j < mtd->oobavail; i++) { | ||
1211 | int from = oobsel->oobfree[i][0]; | ||
1212 | int num = oobsel->oobfree[i][1]; | ||
1213 | memcpy(&oob_buf[oob], &oob_data[from], num); | ||
1214 | j+= num; | ||
1215 | } | ||
1216 | oob += mtd->oobavail; | ||
1217 | break; | ||
1218 | case MTD_NANDECC_PLACE: | ||
1219 | /* YAFFS1 legacy mode */ | ||
1220 | oob_data += this->eccsteps * sizeof (int); | ||
1221 | default: | ||
1222 | oob_data += mtd->oobsize; | ||
1223 | } | ||
1224 | } | ||
1225 | readdata: | ||
1226 | /* Partial page read, transfer data into fs buffer */ | ||
1227 | if (!aligned) { | ||
1228 | for (j = col; j < end && read < len; j++) | ||
1229 | buf[read++] = data_poi[j]; | ||
1230 | this->pagebuf = realpage; | ||
1231 | } else | ||
1232 | read += mtd->oobblock; | ||
1233 | |||
1234 | /* Apply delay or wait for ready/busy pin | ||
1235 | * Do this before the AUTOINCR check, so no problems | ||
1236 | * arise if a chip which does auto increment | ||
1237 | * is marked as NOAUTOINCR by the board driver. | ||
1238 | */ | ||
1239 | if (!this->dev_ready) | ||
1240 | udelay (this->chip_delay); | ||
1241 | else | ||
1242 | while (!this->dev_ready(mtd)); | ||
1243 | |||
1244 | if (read == len) | ||
1245 | break; | ||
1246 | |||
1247 | /* For subsequent reads align to page boundary. */ | ||
1248 | col = 0; | ||
1249 | /* Increment page address */ | ||
1250 | realpage++; | ||
1251 | |||
1252 | page = realpage & this->pagemask; | ||
1253 | /* Check, if we cross a chip boundary */ | ||
1254 | if (!page) { | ||
1255 | chipnr++; | ||
1256 | this->select_chip(mtd, -1); | ||
1257 | this->select_chip(mtd, chipnr); | ||
1258 | } | ||
1259 | /* Check, if the chip supports auto page increment | ||
1260 | * or if we have hit a block boundary. | ||
1261 | */ | ||
1262 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) | ||
1263 | sndcmd = 1; | ||
1264 | } | ||
1265 | |||
1266 | /* Deselect and wake up anyone waiting on the device */ | ||
1267 | nand_release_device(mtd); | ||
1268 | |||
1269 | /* | ||
1270 | * Return success, if no ECC failures, else -EBADMSG | ||
1271 | * fs driver will take care of that, because | ||
1272 | * retlen == desired len and result == -EBADMSG | ||
1273 | */ | ||
1274 | *retlen = read; | ||
1275 | return ecc_failed ? -EBADMSG : 0; | ||
1276 | } | ||
1277 | |||
1278 | /** | ||
1279 | * nand_read_oob - [MTD Interface] NAND read out-of-band | ||
1280 | * @mtd: MTD device structure | ||
1281 | * @from: offset to read from | ||
1282 | * @len: number of bytes to read | ||
1283 | * @retlen: pointer to variable to store the number of read bytes | ||
1284 | * @buf: the databuffer to put data | ||
1285 | * | ||
1286 | * NAND read out-of-band data from the spare area | ||
1287 | */ | ||
1288 | static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf) | ||
1289 | { | ||
1290 | int i, col, page, chipnr; | ||
1291 | struct nand_chip *this = mtd->priv; | ||
1292 | int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; | ||
1293 | |||
1294 | DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); | ||
1295 | |||
1296 | /* Shift to get page */ | ||
1297 | page = (int)(from >> this->page_shift); | ||
1298 | chipnr = (int)(from >> this->chip_shift); | ||
1299 | |||
1300 | /* Mask to get column */ | ||
1301 | col = from & (mtd->oobsize - 1); | ||
1302 | |||
1303 | /* Initialize return length value */ | ||
1304 | *retlen = 0; | ||
1305 | |||
1306 | /* Do not allow reads past end of device */ | ||
1307 | if ((from + len) > mtd->size) { | ||
1308 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n"); | ||
1309 | *retlen = 0; | ||
1310 | return -EINVAL; | ||
1311 | } | ||
1312 | |||
1313 | /* Grab the lock and see if the device is available */ | ||
1314 | nand_get_device (this, mtd , FL_READING); | ||
1315 | |||
1316 | /* Select the NAND device */ | ||
1317 | this->select_chip(mtd, chipnr); | ||
1318 | |||
1319 | /* Send the read command */ | ||
1320 | this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask); | ||
1321 | /* | ||
1322 | * Read the data, if we read more than one page | ||
1323 | * oob data, let the device transfer the data ! | ||
1324 | */ | ||
1325 | i = 0; | ||
1326 | while (i < len) { | ||
1327 | int thislen = mtd->oobsize - col; | ||
1328 | thislen = min_t(int, thislen, len); | ||
1329 | this->read_buf(mtd, &buf[i], thislen); | ||
1330 | i += thislen; | ||
1331 | |||
1332 | /* Apply delay or wait for ready/busy pin | ||
1333 | * Do this before the AUTOINCR check, so no problems | ||
1334 | * arise if a chip which does auto increment | ||
1335 | * is marked as NOAUTOINCR by the board driver. | ||
1336 | */ | ||
1337 | if (!this->dev_ready) | ||
1338 | udelay (this->chip_delay); | ||
1339 | else | ||
1340 | while (!this->dev_ready(mtd)); | ||
1341 | |||
1342 | /* Read more ? */ | ||
1343 | if (i < len) { | ||
1344 | page++; | ||
1345 | col = 0; | ||
1346 | |||
1347 | /* Check, if we cross a chip boundary */ | ||
1348 | if (!(page & this->pagemask)) { | ||
1349 | chipnr++; | ||
1350 | this->select_chip(mtd, -1); | ||
1351 | this->select_chip(mtd, chipnr); | ||
1352 | } | ||
1353 | |||
1354 | /* Check, if the chip supports auto page increment | ||
1355 | * or if we have hit a block boundary. | ||
1356 | */ | ||
1357 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) { | ||
1358 | /* For subsequent page reads set offset to 0 */ | ||
1359 | this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask); | ||
1360 | } | ||
1361 | } | ||
1362 | } | ||
1363 | |||
1364 | /* Deselect and wake up anyone waiting on the device */ | ||
1365 | nand_release_device(mtd); | ||
1366 | |||
1367 | /* Return happy */ | ||
1368 | *retlen = len; | ||
1369 | return 0; | ||
1370 | } | ||
1371 | |||
1372 | /** | ||
1373 | * nand_read_raw - [GENERIC] Read raw data including oob into buffer | ||
1374 | * @mtd: MTD device structure | ||
1375 | * @buf: temporary buffer | ||
1376 | * @from: offset to read from | ||
1377 | * @len: number of bytes to read | ||
1378 | * @ooblen: number of oob data bytes to read | ||
1379 | * | ||
1380 | * Read raw data including oob into buffer | ||
1381 | */ | ||
1382 | int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen) | ||
1383 | { | ||
1384 | struct nand_chip *this = mtd->priv; | ||
1385 | int page = (int) (from >> this->page_shift); | ||
1386 | int chip = (int) (from >> this->chip_shift); | ||
1387 | int sndcmd = 1; | ||
1388 | int cnt = 0; | ||
1389 | int pagesize = mtd->oobblock + mtd->oobsize; | ||
1390 | int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; | ||
1391 | |||
1392 | /* Do not allow reads past end of device */ | ||
1393 | if ((from + len) > mtd->size) { | ||
1394 | DEBUG (MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n"); | ||
1395 | return -EINVAL; | ||
1396 | } | ||
1397 | |||
1398 | /* Grab the lock and see if the device is available */ | ||
1399 | nand_get_device (this, mtd , FL_READING); | ||
1400 | |||
1401 | this->select_chip (mtd, chip); | ||
1402 | |||
1403 | /* Add requested oob length */ | ||
1404 | len += ooblen; | ||
1405 | |||
1406 | while (len) { | ||
1407 | if (sndcmd) | ||
1408 | this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask); | ||
1409 | sndcmd = 0; | ||
1410 | |||
1411 | this->read_buf (mtd, &buf[cnt], pagesize); | ||
1412 | |||
1413 | len -= pagesize; | ||
1414 | cnt += pagesize; | ||
1415 | page++; | ||
1416 | |||
1417 | if (!this->dev_ready) | ||
1418 | udelay (this->chip_delay); | ||
1419 | else | ||
1420 | while (!this->dev_ready(mtd)); | ||
1421 | |||
1422 | /* Check, if the chip supports auto page increment */ | ||
1423 | if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) | ||
1424 | sndcmd = 1; | ||
1425 | } | ||
1426 | |||
1427 | /* Deselect and wake up anyone waiting on the device */ | ||
1428 | nand_release_device(mtd); | ||
1429 | return 0; | ||
1430 | } | ||
1431 | |||
1432 | |||
1433 | /** | ||
1434 | * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer | ||
1435 | * @mtd: MTD device structure | ||
1436 | * @fsbuf: buffer given by fs driver | ||
1437 | * @oobsel: out of band selection structre | ||
1438 | * @autoplace: 1 = place given buffer into the oob bytes | ||
1439 | * @numpages: number of pages to prepare | ||
1440 | * | ||
1441 | * Return: | ||
1442 | * 1. Filesystem buffer available and autoplacement is off, | ||
1443 | * return filesystem buffer | ||
1444 | * 2. No filesystem buffer or autoplace is off, return internal | ||
1445 | * buffer | ||
1446 | * 3. Filesystem buffer is given and autoplace selected | ||
1447 | * put data from fs buffer into internal buffer and | ||
1448 | * retrun internal buffer | ||
1449 | * | ||
1450 | * Note: The internal buffer is filled with 0xff. This must | ||
1451 | * be done only once, when no autoplacement happens | ||
1452 | * Autoplacement sets the buffer dirty flag, which | ||
1453 | * forces the 0xff fill before using the buffer again. | ||
1454 | * | ||
1455 | */ | ||
1456 | static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct nand_oobinfo *oobsel, | ||
1457 | int autoplace, int numpages) | ||
1458 | { | ||
1459 | struct nand_chip *this = mtd->priv; | ||
1460 | int i, len, ofs; | ||
1461 | |||
1462 | /* Zero copy fs supplied buffer */ | ||
1463 | if (fsbuf && !autoplace) | ||
1464 | return fsbuf; | ||
1465 | |||
1466 | /* Check, if the buffer must be filled with ff again */ | ||
1467 | if (this->oobdirty) { | ||
1468 | memset (this->oob_buf, 0xff, | ||
1469 | mtd->oobsize << (this->phys_erase_shift - this->page_shift)); | ||
1470 | this->oobdirty = 0; | ||
1471 | } | ||
1472 | |||
1473 | /* If we have no autoplacement or no fs buffer use the internal one */ | ||
1474 | if (!autoplace || !fsbuf) | ||
1475 | return this->oob_buf; | ||
1476 | |||
1477 | /* Walk through the pages and place the data */ | ||
1478 | this->oobdirty = 1; | ||
1479 | ofs = 0; | ||
1480 | while (numpages--) { | ||
1481 | for (i = 0, len = 0; len < mtd->oobavail; i++) { | ||
1482 | int to = ofs + oobsel->oobfree[i][0]; | ||
1483 | int num = oobsel->oobfree[i][1]; | ||
1484 | memcpy (&this->oob_buf[to], fsbuf, num); | ||
1485 | len += num; | ||
1486 | fsbuf += num; | ||
1487 | } | ||
1488 | ofs += mtd->oobavail; | ||
1489 | } | ||
1490 | return this->oob_buf; | ||
1491 | } | ||
1492 | |||
1493 | #define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0 | ||
1494 | |||
1495 | /** | ||
1496 | * nand_write - [MTD Interface] compability function for nand_write_ecc | ||
1497 | * @mtd: MTD device structure | ||
1498 | * @to: offset to write to | ||
1499 | * @len: number of bytes to write | ||
1500 | * @retlen: pointer to variable to store the number of written bytes | ||
1501 | * @buf: the data to write | ||
1502 | * | ||
1503 | * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL | ||
1504 | * | ||
1505 | */ | ||
1506 | static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) | ||
1507 | { | ||
1508 | return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL)); | ||
1509 | } | ||
1510 | |||
1511 | /** | ||
1512 | * nand_write_ecc - [MTD Interface] NAND write with ECC | ||
1513 | * @mtd: MTD device structure | ||
1514 | * @to: offset to write to | ||
1515 | * @len: number of bytes to write | ||
1516 | * @retlen: pointer to variable to store the number of written bytes | ||
1517 | * @buf: the data to write | ||
1518 | * @eccbuf: filesystem supplied oob data buffer | ||
1519 | * @oobsel: oob selection structure | ||
1520 | * | ||
1521 | * NAND write with ECC | ||
1522 | */ | ||
1523 | static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, | ||
1524 | size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel) | ||
1525 | { | ||
1526 | int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr; | ||
1527 | int autoplace = 0, numpages, totalpages; | ||
1528 | struct nand_chip *this = mtd->priv; | ||
1529 | u_char *oobbuf, *bufstart; | ||
1530 | int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); | ||
1531 | |||
1532 | DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); | ||
1533 | |||
1534 | /* Initialize retlen, in case of early exit */ | ||
1535 | *retlen = 0; | ||
1536 | |||
1537 | /* Do not allow write past end of device */ | ||
1538 | if ((to + len) > mtd->size) { | ||
1539 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n"); | ||
1540 | return -EINVAL; | ||
1541 | } | ||
1542 | |||
1543 | /* reject writes, which are not page aligned */ | ||
1544 | if (NOTALIGNED (to) || NOTALIGNED(len)) { | ||
1545 | printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); | ||
1546 | return -EINVAL; | ||
1547 | } | ||
1548 | |||
1549 | /* Grab the lock and see if the device is available */ | ||
1550 | nand_get_device (this, mtd, FL_WRITING); | ||
1551 | |||
1552 | /* Calculate chipnr */ | ||
1553 | chipnr = (int)(to >> this->chip_shift); | ||
1554 | /* Select the NAND device */ | ||
1555 | this->select_chip(mtd, chipnr); | ||
1556 | |||
1557 | /* Check, if it is write protected */ | ||
1558 | if (nand_check_wp(mtd)) | ||
1559 | goto out; | ||
1560 | |||
1561 | /* if oobsel is NULL, use chip defaults */ | ||
1562 | if (oobsel == NULL) | ||
1563 | oobsel = &mtd->oobinfo; | ||
1564 | |||
1565 | /* Autoplace of oob data ? Use the default placement scheme */ | ||
1566 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { | ||
1567 | oobsel = this->autooob; | ||
1568 | autoplace = 1; | ||
1569 | } | ||
1570 | |||
1571 | /* Setup variables and oob buffer */ | ||
1572 | totalpages = len >> this->page_shift; | ||
1573 | page = (int) (to >> this->page_shift); | ||
1574 | /* Invalidate the page cache, if we write to the cached page */ | ||
1575 | if (page <= this->pagebuf && this->pagebuf < (page + totalpages)) | ||
1576 | this->pagebuf = -1; | ||
1577 | |||
1578 | /* Set it relative to chip */ | ||
1579 | page &= this->pagemask; | ||
1580 | startpage = page; | ||
1581 | /* Calc number of pages we can write in one go */ | ||
1582 | numpages = min (ppblock - (startpage & (ppblock - 1)), totalpages); | ||
1583 | oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages); | ||
1584 | bufstart = (u_char *)buf; | ||
1585 | |||
1586 | /* Loop until all data is written */ | ||
1587 | while (written < len) { | ||
1588 | |||
1589 | this->data_poi = (u_char*) &buf[written]; | ||
1590 | /* Write one page. If this is the last page to write | ||
1591 | * or the last page in this block, then use the | ||
1592 | * real pageprogram command, else select cached programming | ||
1593 | * if supported by the chip. | ||
1594 | */ | ||
1595 | ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0)); | ||
1596 | if (ret) { | ||
1597 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret); | ||
1598 | goto out; | ||
1599 | } | ||
1600 | /* Next oob page */ | ||
1601 | oob += mtd->oobsize; | ||
1602 | /* Update written bytes count */ | ||
1603 | written += mtd->oobblock; | ||
1604 | if (written == len) | ||
1605 | goto cmp; | ||
1606 | |||
1607 | /* Increment page address */ | ||
1608 | page++; | ||
1609 | |||
1610 | /* Have we hit a block boundary ? Then we have to verify and | ||
1611 | * if verify is ok, we have to setup the oob buffer for | ||
1612 | * the next pages. | ||
1613 | */ | ||
1614 | if (!(page & (ppblock - 1))){ | ||
1615 | int ofs; | ||
1616 | this->data_poi = bufstart; | ||
1617 | ret = nand_verify_pages (mtd, this, startpage, | ||
1618 | page - startpage, | ||
1619 | oobbuf, oobsel, chipnr, (eccbuf != NULL)); | ||
1620 | if (ret) { | ||
1621 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); | ||
1622 | goto out; | ||
1623 | } | ||
1624 | *retlen = written; | ||
1625 | |||
1626 | ofs = autoplace ? mtd->oobavail : mtd->oobsize; | ||
1627 | if (eccbuf) | ||
1628 | eccbuf += (page - startpage) * ofs; | ||
1629 | totalpages -= page - startpage; | ||
1630 | numpages = min (totalpages, ppblock); | ||
1631 | page &= this->pagemask; | ||
1632 | startpage = page; | ||
1633 | oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, | ||
1634 | autoplace, numpages); | ||
1635 | /* Check, if we cross a chip boundary */ | ||
1636 | if (!page) { | ||
1637 | chipnr++; | ||
1638 | this->select_chip(mtd, -1); | ||
1639 | this->select_chip(mtd, chipnr); | ||
1640 | } | ||
1641 | } | ||
1642 | } | ||
1643 | /* Verify the remaining pages */ | ||
1644 | cmp: | ||
1645 | this->data_poi = bufstart; | ||
1646 | ret = nand_verify_pages (mtd, this, startpage, totalpages, | ||
1647 | oobbuf, oobsel, chipnr, (eccbuf != NULL)); | ||
1648 | if (!ret) | ||
1649 | *retlen = written; | ||
1650 | else | ||
1651 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret); | ||
1652 | |||
1653 | out: | ||
1654 | /* Deselect and wake up anyone waiting on the device */ | ||
1655 | nand_release_device(mtd); | ||
1656 | |||
1657 | return ret; | ||
1658 | } | ||
1659 | |||
1660 | |||
1661 | /** | ||
1662 | * nand_write_oob - [MTD Interface] NAND write out-of-band | ||
1663 | * @mtd: MTD device structure | ||
1664 | * @to: offset to write to | ||
1665 | * @len: number of bytes to write | ||
1666 | * @retlen: pointer to variable to store the number of written bytes | ||
1667 | * @buf: the data to write | ||
1668 | * | ||
1669 | * NAND write out-of-band | ||
1670 | */ | ||
1671 | static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf) | ||
1672 | { | ||
1673 | int column, page, status, ret = -EIO, chipnr; | ||
1674 | struct nand_chip *this = mtd->priv; | ||
1675 | |||
1676 | DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); | ||
1677 | |||
1678 | /* Shift to get page */ | ||
1679 | page = (int) (to >> this->page_shift); | ||
1680 | chipnr = (int) (to >> this->chip_shift); | ||
1681 | |||
1682 | /* Mask to get column */ | ||
1683 | column = to & (mtd->oobsize - 1); | ||
1684 | |||
1685 | /* Initialize return length value */ | ||
1686 | *retlen = 0; | ||
1687 | |||
1688 | /* Do not allow write past end of page */ | ||
1689 | if ((column + len) > mtd->oobsize) { | ||
1690 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n"); | ||
1691 | return -EINVAL; | ||
1692 | } | ||
1693 | |||
1694 | /* Grab the lock and see if the device is available */ | ||
1695 | nand_get_device (this, mtd, FL_WRITING); | ||
1696 | |||
1697 | /* Select the NAND device */ | ||
1698 | this->select_chip(mtd, chipnr); | ||
1699 | |||
1700 | /* Reset the chip. Some chips (like the Toshiba TC5832DC found | ||
1701 | in one of my DiskOnChip 2000 test units) will clear the whole | ||
1702 | data page too if we don't do this. I have no clue why, but | ||
1703 | I seem to have 'fixed' it in the doc2000 driver in | ||
1704 | August 1999. dwmw2. */ | ||
1705 | this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | ||
1706 | |||
1707 | /* Check, if it is write protected */ | ||
1708 | if (nand_check_wp(mtd)) | ||
1709 | goto out; | ||
1710 | |||
1711 | /* Invalidate the page cache, if we write to the cached page */ | ||
1712 | if (page == this->pagebuf) | ||
1713 | this->pagebuf = -1; | ||
1714 | |||
1715 | if (NAND_MUST_PAD(this)) { | ||
1716 | /* Write out desired data */ | ||
1717 | this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask); | ||
1718 | /* prepad 0xff for partial programming */ | ||
1719 | this->write_buf(mtd, ffchars, column); | ||
1720 | /* write data */ | ||
1721 | this->write_buf(mtd, buf, len); | ||
1722 | /* postpad 0xff for partial programming */ | ||
1723 | this->write_buf(mtd, ffchars, mtd->oobsize - (len+column)); | ||
1724 | } else { | ||
1725 | /* Write out desired data */ | ||
1726 | this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock + column, page & this->pagemask); | ||
1727 | /* write data */ | ||
1728 | this->write_buf(mtd, buf, len); | ||
1729 | } | ||
1730 | /* Send command to program the OOB data */ | ||
1731 | this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1); | ||
1732 | |||
1733 | status = this->waitfunc (mtd, this, FL_WRITING); | ||
1734 | |||
1735 | /* See if device thinks it succeeded */ | ||
1736 | if (status & 0x01) { | ||
1737 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page); | ||
1738 | ret = -EIO; | ||
1739 | goto out; | ||
1740 | } | ||
1741 | /* Return happy */ | ||
1742 | *retlen = len; | ||
1743 | |||
1744 | #ifdef CONFIG_MTD_NAND_VERIFY_WRITE | ||
1745 | /* Send command to read back the data */ | ||
1746 | this->cmdfunc (mtd, NAND_CMD_READOOB, column, page & this->pagemask); | ||
1747 | |||
1748 | if (this->verify_buf(mtd, buf, len)) { | ||
1749 | DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page); | ||
1750 | ret = -EIO; | ||
1751 | goto out; | ||
1752 | } | ||
1753 | #endif | ||
1754 | ret = 0; | ||
1755 | out: | ||
1756 | /* Deselect and wake up anyone waiting on the device */ | ||
1757 | nand_release_device(mtd); | ||
1758 | |||
1759 | return ret; | ||
1760 | } | ||
1761 | |||
1762 | |||
1763 | /** | ||
1764 | * nand_writev - [MTD Interface] compabilty function for nand_writev_ecc | ||
1765 | * @mtd: MTD device structure | ||
1766 | * @vecs: the iovectors to write | ||
1767 | * @count: number of vectors | ||
1768 | * @to: offset to write to | ||
1769 | * @retlen: pointer to variable to store the number of written bytes | ||
1770 | * | ||
1771 | * NAND write with kvec. This just calls the ecc function | ||
1772 | */ | ||
1773 | static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, | ||
1774 | loff_t to, size_t * retlen) | ||
1775 | { | ||
1776 | return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL)); | ||
1777 | } | ||
1778 | |||
1779 | /** | ||
1780 | * nand_writev_ecc - [MTD Interface] write with iovec with ecc | ||
1781 | * @mtd: MTD device structure | ||
1782 | * @vecs: the iovectors to write | ||
1783 | * @count: number of vectors | ||
1784 | * @to: offset to write to | ||
1785 | * @retlen: pointer to variable to store the number of written bytes | ||
1786 | * @eccbuf: filesystem supplied oob data buffer | ||
1787 | * @oobsel: oob selection structure | ||
1788 | * | ||
1789 | * NAND write with iovec with ecc | ||
1790 | */ | ||
1791 | static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, | ||
1792 | loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel) | ||
1793 | { | ||
1794 | int i, page, len, total_len, ret = -EIO, written = 0, chipnr; | ||
1795 | int oob, numpages, autoplace = 0, startpage; | ||
1796 | struct nand_chip *this = mtd->priv; | ||
1797 | int ppblock = (1 << (this->phys_erase_shift - this->page_shift)); | ||
1798 | u_char *oobbuf, *bufstart; | ||
1799 | |||
1800 | /* Preset written len for early exit */ | ||
1801 | *retlen = 0; | ||
1802 | |||
1803 | /* Calculate total length of data */ | ||
1804 | total_len = 0; | ||
1805 | for (i = 0; i < count; i++) | ||
1806 | total_len += (int) vecs[i].iov_len; | ||
1807 | |||
1808 | DEBUG (MTD_DEBUG_LEVEL3, | ||
1809 | "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count); | ||
1810 | |||
1811 | /* Do not allow write past end of page */ | ||
1812 | if ((to + total_len) > mtd->size) { | ||
1813 | DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n"); | ||
1814 | return -EINVAL; | ||
1815 | } | ||
1816 | |||
1817 | /* reject writes, which are not page aligned */ | ||
1818 | if (NOTALIGNED (to) || NOTALIGNED(total_len)) { | ||
1819 | printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n"); | ||
1820 | return -EINVAL; | ||
1821 | } | ||
1822 | |||
1823 | /* Grab the lock and see if the device is available */ | ||
1824 | nand_get_device (this, mtd, FL_WRITING); | ||
1825 | |||
1826 | /* Get the current chip-nr */ | ||
1827 | chipnr = (int) (to >> this->chip_shift); | ||
1828 | /* Select the NAND device */ | ||
1829 | this->select_chip(mtd, chipnr); | ||
1830 | |||
1831 | /* Check, if it is write protected */ | ||
1832 | if (nand_check_wp(mtd)) | ||
1833 | goto out; | ||
1834 | |||
1835 | /* if oobsel is NULL, use chip defaults */ | ||
1836 | if (oobsel == NULL) | ||
1837 | oobsel = &mtd->oobinfo; | ||
1838 | |||
1839 | /* Autoplace of oob data ? Use the default placement scheme */ | ||
1840 | if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) { | ||
1841 | oobsel = this->autooob; | ||
1842 | autoplace = 1; | ||
1843 | } | ||
1844 | |||
1845 | /* Setup start page */ | ||
1846 | page = (int) (to >> this->page_shift); | ||
1847 | /* Invalidate the page cache, if we write to the cached page */ | ||
1848 | if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift)) | ||
1849 | this->pagebuf = -1; | ||
1850 | |||
1851 | startpage = page & this->pagemask; | ||
1852 | |||
1853 | /* Loop until all kvec' data has been written */ | ||
1854 | len = 0; | ||
1855 | while (count) { | ||
1856 | /* If the given tuple is >= pagesize then | ||
1857 | * write it out from the iov | ||
1858 | */ | ||
1859 | if ((vecs->iov_len - len) >= mtd->oobblock) { | ||
1860 | /* Calc number of pages we can write | ||
1861 | * out of this iov in one go */ | ||
1862 | numpages = (vecs->iov_len - len) >> this->page_shift; | ||
1863 | /* Do not cross block boundaries */ | ||
1864 | numpages = min (ppblock - (startpage & (ppblock - 1)), numpages); | ||
1865 | oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages); | ||
1866 | bufstart = (u_char *)vecs->iov_base; | ||
1867 | bufstart += len; | ||
1868 | this->data_poi = bufstart; | ||
1869 | oob = 0; | ||
1870 | for (i = 1; i <= numpages; i++) { | ||
1871 | /* Write one page. If this is the last page to write | ||
1872 | * then use the real pageprogram command, else select | ||
1873 | * cached programming if supported by the chip. | ||
1874 | */ | ||
1875 | ret = nand_write_page (mtd, this, page & this->pagemask, | ||
1876 | &oobbuf[oob], oobsel, i != numpages); | ||
1877 | if (ret) | ||
1878 | goto out; | ||
1879 | this->data_poi += mtd->oobblock; | ||
1880 | len += mtd->oobblock; | ||
1881 | oob += mtd->oobsize; | ||
1882 | page++; | ||
1883 | } | ||
1884 | /* Check, if we have to switch to the next tuple */ | ||
1885 | if (len >= (int) vecs->iov_len) { | ||
1886 | vecs++; | ||
1887 | len = 0; | ||
1888 | count--; | ||
1889 | } | ||
1890 | } else { | ||
1891 | /* We must use the internal buffer, read data out of each | ||
1892 | * tuple until we have a full page to write | ||
1893 | */ | ||
1894 | int cnt = 0; | ||
1895 | while (cnt < mtd->oobblock) { | ||
1896 | if (vecs->iov_base != NULL && vecs->iov_len) | ||
1897 | this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++]; | ||
1898 | /* Check, if we have to switch to the next tuple */ | ||
1899 | if (len >= (int) vecs->iov_len) { | ||
1900 | vecs++; | ||
1901 | len = 0; | ||
1902 | count--; | ||
1903 | } | ||
1904 | } | ||
1905 | this->pagebuf = page; | ||
1906 | this->data_poi = this->data_buf; | ||
1907 | bufstart = this->data_poi; | ||
1908 | numpages = 1; | ||
1909 | oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages); | ||
1910 | ret = nand_write_page (mtd, this, page & this->pagemask, | ||
1911 | oobbuf, oobsel, 0); | ||
1912 | if (ret) | ||
1913 | goto out; | ||
1914 | page++; | ||
1915 | } | ||
1916 | |||
1917 | this->data_poi = bufstart; | ||
1918 | ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0); | ||
1919 | if (ret) | ||
1920 | goto out; | ||
1921 | |||
1922 | written += mtd->oobblock * numpages; | ||
1923 | /* All done ? */ | ||
1924 | if (!count) | ||
1925 | break; | ||
1926 | |||
1927 | startpage = page & this->pagemask; | ||
1928 | /* Check, if we cross a chip boundary */ | ||
1929 | if (!startpage) { | ||
1930 | chipnr++; | ||
1931 | this->select_chip(mtd, -1); | ||
1932 | this->select_chip(mtd, chipnr); | ||
1933 | } | ||
1934 | } | ||
1935 | ret = 0; | ||
1936 | out: | ||
1937 | /* Deselect and wake up anyone waiting on the device */ | ||
1938 | nand_release_device(mtd); | ||
1939 | |||
1940 | *retlen = written; | ||
1941 | return ret; | ||
1942 | } | ||
1943 | |||
1944 | /** | ||
1945 | * single_erease_cmd - [GENERIC] NAND standard block erase command function | ||
1946 | * @mtd: MTD device structure | ||
1947 | * @page: the page address of the block which will be erased | ||
1948 | * | ||
1949 | * Standard erase command for NAND chips | ||
1950 | */ | ||
1951 | static void single_erase_cmd (struct mtd_info *mtd, int page) | ||
1952 | { | ||
1953 | struct nand_chip *this = mtd->priv; | ||
1954 | /* Send commands to erase a block */ | ||
1955 | this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page); | ||
1956 | this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1); | ||
1957 | } | ||
1958 | |||
1959 | /** | ||
1960 | * multi_erease_cmd - [GENERIC] AND specific block erase command function | ||
1961 | * @mtd: MTD device structure | ||
1962 | * @page: the page address of the block which will be erased | ||
1963 | * | ||
1964 | * AND multi block erase command function | ||
1965 | * Erase 4 consecutive blocks | ||
1966 | */ | ||
1967 | static void multi_erase_cmd (struct mtd_info *mtd, int page) | ||
1968 | { | ||
1969 | struct nand_chip *this = mtd->priv; | ||
1970 | /* Send commands to erase a block */ | ||
1971 | this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++); | ||
1972 | this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++); | ||
1973 | this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++); | ||
1974 | this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page); | ||
1975 | this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1); | ||
1976 | } | ||
1977 | |||
1978 | /** | ||
1979 | * nand_erase - [MTD Interface] erase block(s) | ||
1980 | * @mtd: MTD device structure | ||
1981 | * @instr: erase instruction | ||
1982 | * | ||
1983 | * Erase one ore more blocks | ||
1984 | */ | ||
1985 | static int nand_erase (struct mtd_info *mtd, struct erase_info *instr) | ||
1986 | { | ||
1987 | return nand_erase_nand (mtd, instr, 0); | ||
1988 | } | ||
1989 | |||
1990 | /** | ||
1991 | * nand_erase_intern - [NAND Interface] erase block(s) | ||
1992 | * @mtd: MTD device structure | ||
1993 | * @instr: erase instruction | ||
1994 | * @allowbbt: allow erasing the bbt area | ||
1995 | * | ||
1996 | * Erase one ore more blocks | ||
1997 | */ | ||
1998 | int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt) | ||
1999 | { | ||
2000 | int page, len, status, pages_per_block, ret, chipnr; | ||
2001 | struct nand_chip *this = mtd->priv; | ||
2002 | |||
2003 | DEBUG (MTD_DEBUG_LEVEL3, | ||
2004 | "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); | ||
2005 | |||
2006 | /* Start address must align on block boundary */ | ||
2007 | if (instr->addr & ((1 << this->phys_erase_shift) - 1)) { | ||
2008 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n"); | ||
2009 | return -EINVAL; | ||
2010 | } | ||
2011 | |||
2012 | /* Length must align on block boundary */ | ||
2013 | if (instr->len & ((1 << this->phys_erase_shift) - 1)) { | ||
2014 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n"); | ||
2015 | return -EINVAL; | ||
2016 | } | ||
2017 | |||
2018 | /* Do not allow erase past end of device */ | ||
2019 | if ((instr->len + instr->addr) > mtd->size) { | ||
2020 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n"); | ||
2021 | return -EINVAL; | ||
2022 | } | ||
2023 | |||
2024 | instr->fail_addr = 0xffffffff; | ||
2025 | |||
2026 | /* Grab the lock and see if the device is available */ | ||
2027 | nand_get_device (this, mtd, FL_ERASING); | ||
2028 | |||
2029 | /* Shift to get first page */ | ||
2030 | page = (int) (instr->addr >> this->page_shift); | ||
2031 | chipnr = (int) (instr->addr >> this->chip_shift); | ||
2032 | |||
2033 | /* Calculate pages in each block */ | ||
2034 | pages_per_block = 1 << (this->phys_erase_shift - this->page_shift); | ||
2035 | |||
2036 | /* Select the NAND device */ | ||
2037 | this->select_chip(mtd, chipnr); | ||
2038 | |||
2039 | /* Check the WP bit */ | ||
2040 | /* Check, if it is write protected */ | ||
2041 | if (nand_check_wp(mtd)) { | ||
2042 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n"); | ||
2043 | instr->state = MTD_ERASE_FAILED; | ||
2044 | goto erase_exit; | ||
2045 | } | ||
2046 | |||
2047 | /* Loop through the pages */ | ||
2048 | len = instr->len; | ||
2049 | |||
2050 | instr->state = MTD_ERASING; | ||
2051 | |||
2052 | while (len) { | ||
2053 | /* Check if we have a bad block, we do not erase bad blocks ! */ | ||
2054 | if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) { | ||
2055 | printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page); | ||
2056 | instr->state = MTD_ERASE_FAILED; | ||
2057 | goto erase_exit; | ||
2058 | } | ||
2059 | |||
2060 | /* Invalidate the page cache, if we erase the block which contains | ||
2061 | the current cached page */ | ||
2062 | if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block)) | ||
2063 | this->pagebuf = -1; | ||
2064 | |||
2065 | this->erase_cmd (mtd, page & this->pagemask); | ||
2066 | |||
2067 | status = this->waitfunc (mtd, this, FL_ERASING); | ||
2068 | |||
2069 | /* See if block erase succeeded */ | ||
2070 | if (status & 0x01) { | ||
2071 | DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page); | ||
2072 | instr->state = MTD_ERASE_FAILED; | ||
2073 | instr->fail_addr = (page << this->page_shift); | ||
2074 | goto erase_exit; | ||
2075 | } | ||
2076 | |||
2077 | /* Increment page address and decrement length */ | ||
2078 | len -= (1 << this->phys_erase_shift); | ||
2079 | page += pages_per_block; | ||
2080 | |||
2081 | /* Check, if we cross a chip boundary */ | ||
2082 | if (len && !(page & this->pagemask)) { | ||
2083 | chipnr++; | ||
2084 | this->select_chip(mtd, -1); | ||
2085 | this->select_chip(mtd, chipnr); | ||
2086 | } | ||
2087 | } | ||
2088 | instr->state = MTD_ERASE_DONE; | ||
2089 | |||
2090 | erase_exit: | ||
2091 | |||
2092 | ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; | ||
2093 | /* Do call back function */ | ||
2094 | if (!ret) | ||
2095 | mtd_erase_callback(instr); | ||
2096 | |||
2097 | /* Deselect and wake up anyone waiting on the device */ | ||
2098 | nand_release_device(mtd); | ||
2099 | |||
2100 | /* Return more or less happy */ | ||
2101 | return ret; | ||
2102 | } | ||
2103 | |||
2104 | /** | ||
2105 | * nand_sync - [MTD Interface] sync | ||
2106 | * @mtd: MTD device structure | ||
2107 | * | ||
2108 | * Sync is actually a wait for chip ready function | ||
2109 | */ | ||
2110 | static void nand_sync (struct mtd_info *mtd) | ||
2111 | { | ||
2112 | struct nand_chip *this = mtd->priv; | ||
2113 | |||
2114 | DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n"); | ||
2115 | |||
2116 | /* Grab the lock and see if the device is available */ | ||
2117 | nand_get_device (this, mtd, FL_SYNCING); | ||
2118 | /* Release it and go back */ | ||
2119 | nand_release_device (mtd); | ||
2120 | } | ||
2121 | |||
2122 | |||
2123 | /** | ||
2124 | * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad | ||
2125 | * @mtd: MTD device structure | ||
2126 | * @ofs: offset relative to mtd start | ||
2127 | */ | ||
2128 | static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs) | ||
2129 | { | ||
2130 | /* Check for invalid offset */ | ||
2131 | if (ofs > mtd->size) | ||
2132 | return -EINVAL; | ||
2133 | |||
2134 | return nand_block_checkbad (mtd, ofs, 1, 0); | ||
2135 | } | ||
2136 | |||
2137 | /** | ||
2138 | * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad | ||
2139 | * @mtd: MTD device structure | ||
2140 | * @ofs: offset relative to mtd start | ||
2141 | */ | ||
2142 | static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs) | ||
2143 | { | ||
2144 | struct nand_chip *this = mtd->priv; | ||
2145 | int ret; | ||
2146 | |||
2147 | if ((ret = nand_block_isbad(mtd, ofs))) { | ||
2148 | /* If it was bad already, return success and do nothing. */ | ||
2149 | if (ret > 0) | ||
2150 | return 0; | ||
2151 | return ret; | ||
2152 | } | ||
2153 | |||
2154 | return this->block_markbad(mtd, ofs); | ||
2155 | } | ||
2156 | |||
2157 | /** | ||
2158 | * nand_scan - [NAND Interface] Scan for the NAND device | ||
2159 | * @mtd: MTD device structure | ||
2160 | * @maxchips: Number of chips to scan for | ||
2161 | * | ||
2162 | * This fills out all the not initialized function pointers | ||
2163 | * with the defaults. | ||
2164 | * The flash ID is read and the mtd/chip structures are | ||
2165 | * filled with the appropriate values. Buffers are allocated if | ||
2166 | * they are not provided by the board driver | ||
2167 | * | ||
2168 | */ | ||
2169 | int nand_scan (struct mtd_info *mtd, int maxchips) | ||
2170 | { | ||
2171 | int i, j, nand_maf_id, nand_dev_id, busw; | ||
2172 | struct nand_chip *this = mtd->priv; | ||
2173 | |||
2174 | /* Get buswidth to select the correct functions*/ | ||
2175 | busw = this->options & NAND_BUSWIDTH_16; | ||
2176 | |||
2177 | /* check for proper chip_delay setup, set 20us if not */ | ||
2178 | if (!this->chip_delay) | ||
2179 | this->chip_delay = 20; | ||
2180 | |||
2181 | /* check, if a user supplied command function given */ | ||
2182 | if (this->cmdfunc == NULL) | ||
2183 | this->cmdfunc = nand_command; | ||
2184 | |||
2185 | /* check, if a user supplied wait function given */ | ||
2186 | if (this->waitfunc == NULL) | ||
2187 | this->waitfunc = nand_wait; | ||
2188 | |||
2189 | if (!this->select_chip) | ||
2190 | this->select_chip = nand_select_chip; | ||
2191 | if (!this->write_byte) | ||
2192 | this->write_byte = busw ? nand_write_byte16 : nand_write_byte; | ||
2193 | if (!this->read_byte) | ||
2194 | this->read_byte = busw ? nand_read_byte16 : nand_read_byte; | ||
2195 | if (!this->write_word) | ||
2196 | this->write_word = nand_write_word; | ||
2197 | if (!this->read_word) | ||
2198 | this->read_word = nand_read_word; | ||
2199 | if (!this->block_bad) | ||
2200 | this->block_bad = nand_block_bad; | ||
2201 | if (!this->block_markbad) | ||
2202 | this->block_markbad = nand_default_block_markbad; | ||
2203 | if (!this->write_buf) | ||
2204 | this->write_buf = busw ? nand_write_buf16 : nand_write_buf; | ||
2205 | if (!this->read_buf) | ||
2206 | this->read_buf = busw ? nand_read_buf16 : nand_read_buf; | ||
2207 | if (!this->verify_buf) | ||
2208 | this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf; | ||
2209 | if (!this->scan_bbt) | ||
2210 | this->scan_bbt = nand_default_bbt; | ||
2211 | |||
2212 | /* Select the device */ | ||
2213 | this->select_chip(mtd, 0); | ||
2214 | |||
2215 | /* Send the command for reading device ID */ | ||
2216 | this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); | ||
2217 | |||
2218 | /* Read manufacturer and device IDs */ | ||
2219 | nand_maf_id = this->read_byte(mtd); | ||
2220 | nand_dev_id = this->read_byte(mtd); | ||
2221 | |||
2222 | /* Print and store flash device information */ | ||
2223 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | ||
2224 | |||
2225 | if (nand_dev_id != nand_flash_ids[i].id) | ||
2226 | continue; | ||
2227 | |||
2228 | if (!mtd->name) mtd->name = nand_flash_ids[i].name; | ||
2229 | this->chipsize = nand_flash_ids[i].chipsize << 20; | ||
2230 | |||
2231 | /* New devices have all the information in additional id bytes */ | ||
2232 | if (!nand_flash_ids[i].pagesize) { | ||
2233 | int extid; | ||
2234 | /* The 3rd id byte contains non relevant data ATM */ | ||
2235 | extid = this->read_byte(mtd); | ||
2236 | /* The 4th id byte is the important one */ | ||
2237 | extid = this->read_byte(mtd); | ||
2238 | /* Calc pagesize */ | ||
2239 | mtd->oobblock = 1024 << (extid & 0x3); | ||
2240 | extid >>= 2; | ||
2241 | /* Calc oobsize */ | ||
2242 | mtd->oobsize = (8 << (extid & 0x03)) * (mtd->oobblock / 512); | ||
2243 | extid >>= 2; | ||
2244 | /* Calc blocksize. Blocksize is multiples of 64KiB */ | ||
2245 | mtd->erasesize = (64 * 1024) << (extid & 0x03); | ||
2246 | extid >>= 2; | ||
2247 | /* Get buswidth information */ | ||
2248 | busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; | ||
2249 | |||
2250 | } else { | ||
2251 | /* Old devices have this data hardcoded in the | ||
2252 | * device id table */ | ||
2253 | mtd->erasesize = nand_flash_ids[i].erasesize; | ||
2254 | mtd->oobblock = nand_flash_ids[i].pagesize; | ||
2255 | mtd->oobsize = mtd->oobblock / 32; | ||
2256 | busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16; | ||
2257 | } | ||
2258 | |||
2259 | /* Check, if buswidth is correct. Hardware drivers should set | ||
2260 | * this correct ! */ | ||
2261 | if (busw != (this->options & NAND_BUSWIDTH_16)) { | ||
2262 | printk (KERN_INFO "NAND device: Manufacturer ID:" | ||
2263 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, | ||
2264 | nand_manuf_ids[i].name , mtd->name); | ||
2265 | printk (KERN_WARNING | ||
2266 | "NAND bus width %d instead %d bit\n", | ||
2267 | (this->options & NAND_BUSWIDTH_16) ? 16 : 8, | ||
2268 | busw ? 16 : 8); | ||
2269 | this->select_chip(mtd, -1); | ||
2270 | return 1; | ||
2271 | } | ||
2272 | |||
2273 | /* Calculate the address shift from the page size */ | ||
2274 | this->page_shift = ffs(mtd->oobblock) - 1; | ||
2275 | this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1; | ||
2276 | this->chip_shift = ffs(this->chipsize) - 1; | ||
2277 | |||
2278 | /* Set the bad block position */ | ||
2279 | this->badblockpos = mtd->oobblock > 512 ? | ||
2280 | NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; | ||
2281 | |||
2282 | /* Get chip options, preserve non chip based options */ | ||
2283 | this->options &= ~NAND_CHIPOPTIONS_MSK; | ||
2284 | this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK; | ||
2285 | /* Set this as a default. Board drivers can override it, if neccecary */ | ||
2286 | this->options |= NAND_NO_AUTOINCR; | ||
2287 | /* Check if this is a not a samsung device. Do not clear the options | ||
2288 | * for chips which are not having an extended id. | ||
2289 | */ | ||
2290 | if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize) | ||
2291 | this->options &= ~NAND_SAMSUNG_LP_OPTIONS; | ||
2292 | |||
2293 | /* Check for AND chips with 4 page planes */ | ||
2294 | if (this->options & NAND_4PAGE_ARRAY) | ||
2295 | this->erase_cmd = multi_erase_cmd; | ||
2296 | else | ||
2297 | this->erase_cmd = single_erase_cmd; | ||
2298 | |||
2299 | /* Do not replace user supplied command function ! */ | ||
2300 | if (mtd->oobblock > 512 && this->cmdfunc == nand_command) | ||
2301 | this->cmdfunc = nand_command_lp; | ||
2302 | |||
2303 | /* Try to identify manufacturer */ | ||
2304 | for (j = 0; nand_manuf_ids[j].id != 0x0; j++) { | ||
2305 | if (nand_manuf_ids[j].id == nand_maf_id) | ||
2306 | break; | ||
2307 | } | ||
2308 | printk (KERN_INFO "NAND device: Manufacturer ID:" | ||
2309 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id, | ||
2310 | nand_manuf_ids[j].name , nand_flash_ids[i].name); | ||
2311 | break; | ||
2312 | } | ||
2313 | |||
2314 | if (!nand_flash_ids[i].name) { | ||
2315 | printk (KERN_WARNING "No NAND device found!!!\n"); | ||
2316 | this->select_chip(mtd, -1); | ||
2317 | return 1; | ||
2318 | } | ||
2319 | |||
2320 | for (i=1; i < maxchips; i++) { | ||
2321 | this->select_chip(mtd, i); | ||
2322 | |||
2323 | /* Send the command for reading device ID */ | ||
2324 | this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1); | ||
2325 | |||
2326 | /* Read manufacturer and device IDs */ | ||
2327 | if (nand_maf_id != this->read_byte(mtd) || | ||
2328 | nand_dev_id != this->read_byte(mtd)) | ||
2329 | break; | ||
2330 | } | ||
2331 | if (i > 1) | ||
2332 | printk(KERN_INFO "%d NAND chips detected\n", i); | ||
2333 | |||
2334 | /* Allocate buffers, if neccecary */ | ||
2335 | if (!this->oob_buf) { | ||
2336 | size_t len; | ||
2337 | len = mtd->oobsize << (this->phys_erase_shift - this->page_shift); | ||
2338 | this->oob_buf = kmalloc (len, GFP_KERNEL); | ||
2339 | if (!this->oob_buf) { | ||
2340 | printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n"); | ||
2341 | return -ENOMEM; | ||
2342 | } | ||
2343 | this->options |= NAND_OOBBUF_ALLOC; | ||
2344 | } | ||
2345 | |||
2346 | if (!this->data_buf) { | ||
2347 | size_t len; | ||
2348 | len = mtd->oobblock + mtd->oobsize; | ||
2349 | this->data_buf = kmalloc (len, GFP_KERNEL); | ||
2350 | if (!this->data_buf) { | ||
2351 | if (this->options & NAND_OOBBUF_ALLOC) | ||
2352 | kfree (this->oob_buf); | ||
2353 | printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n"); | ||
2354 | return -ENOMEM; | ||
2355 | } | ||
2356 | this->options |= NAND_DATABUF_ALLOC; | ||
2357 | } | ||
2358 | |||
2359 | /* Store the number of chips and calc total size for mtd */ | ||
2360 | this->numchips = i; | ||
2361 | mtd->size = i * this->chipsize; | ||
2362 | /* Convert chipsize to number of pages per chip -1. */ | ||
2363 | this->pagemask = (this->chipsize >> this->page_shift) - 1; | ||
2364 | /* Preset the internal oob buffer */ | ||
2365 | memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift)); | ||
2366 | |||
2367 | /* If no default placement scheme is given, select an | ||
2368 | * appropriate one */ | ||
2369 | if (!this->autooob) { | ||
2370 | /* Select the appropriate default oob placement scheme for | ||
2371 | * placement agnostic filesystems */ | ||
2372 | switch (mtd->oobsize) { | ||
2373 | case 8: | ||
2374 | this->autooob = &nand_oob_8; | ||
2375 | break; | ||
2376 | case 16: | ||
2377 | this->autooob = &nand_oob_16; | ||
2378 | break; | ||
2379 | case 64: | ||
2380 | this->autooob = &nand_oob_64; | ||
2381 | break; | ||
2382 | default: | ||
2383 | printk (KERN_WARNING "No oob scheme defined for oobsize %d\n", | ||
2384 | mtd->oobsize); | ||
2385 | BUG(); | ||
2386 | } | ||
2387 | } | ||
2388 | |||
2389 | /* The number of bytes available for the filesystem to place fs dependend | ||
2390 | * oob data */ | ||
2391 | if (this->options & NAND_BUSWIDTH_16) { | ||
2392 | mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 2); | ||
2393 | if (this->autooob->eccbytes & 0x01) | ||
2394 | mtd->oobavail--; | ||
2395 | } else | ||
2396 | mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1); | ||
2397 | |||
2398 | /* | ||
2399 | * check ECC mode, default to software | ||
2400 | * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize | ||
2401 | * fallback to software ECC | ||
2402 | */ | ||
2403 | this->eccsize = 256; /* set default eccsize */ | ||
2404 | this->eccbytes = 3; | ||
2405 | |||
2406 | switch (this->eccmode) { | ||
2407 | case NAND_ECC_HW12_2048: | ||
2408 | if (mtd->oobblock < 2048) { | ||
2409 | printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n", | ||
2410 | mtd->oobblock); | ||
2411 | this->eccmode = NAND_ECC_SOFT; | ||
2412 | this->calculate_ecc = nand_calculate_ecc; | ||
2413 | this->correct_data = nand_correct_data; | ||
2414 | } else | ||
2415 | this->eccsize = 2048; | ||
2416 | break; | ||
2417 | |||
2418 | case NAND_ECC_HW3_512: | ||
2419 | case NAND_ECC_HW6_512: | ||
2420 | case NAND_ECC_HW8_512: | ||
2421 | if (mtd->oobblock == 256) { | ||
2422 | printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n"); | ||
2423 | this->eccmode = NAND_ECC_SOFT; | ||
2424 | this->calculate_ecc = nand_calculate_ecc; | ||
2425 | this->correct_data = nand_correct_data; | ||
2426 | } else | ||
2427 | this->eccsize = 512; /* set eccsize to 512 */ | ||
2428 | break; | ||
2429 | |||
2430 | case NAND_ECC_HW3_256: | ||
2431 | break; | ||
2432 | |||
2433 | case NAND_ECC_NONE: | ||
2434 | printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); | ||
2435 | this->eccmode = NAND_ECC_NONE; | ||
2436 | break; | ||
2437 | |||
2438 | case NAND_ECC_SOFT: | ||
2439 | this->calculate_ecc = nand_calculate_ecc; | ||
2440 | this->correct_data = nand_correct_data; | ||
2441 | break; | ||
2442 | |||
2443 | default: | ||
2444 | printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); | ||
2445 | BUG(); | ||
2446 | } | ||
2447 | |||
2448 | /* Check hardware ecc function availability and adjust number of ecc bytes per | ||
2449 | * calculation step | ||
2450 | */ | ||
2451 | switch (this->eccmode) { | ||
2452 | case NAND_ECC_HW12_2048: | ||
2453 | this->eccbytes += 4; | ||
2454 | case NAND_ECC_HW8_512: | ||
2455 | this->eccbytes += 2; | ||
2456 | case NAND_ECC_HW6_512: | ||
2457 | this->eccbytes += 3; | ||
2458 | case NAND_ECC_HW3_512: | ||
2459 | case NAND_ECC_HW3_256: | ||
2460 | if (this->calculate_ecc && this->correct_data && this->enable_hwecc) | ||
2461 | break; | ||
2462 | printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n"); | ||
2463 | BUG(); | ||
2464 | } | ||
2465 | |||
2466 | mtd->eccsize = this->eccsize; | ||
2467 | |||
2468 | /* Set the number of read / write steps for one page to ensure ECC generation */ | ||
2469 | switch (this->eccmode) { | ||
2470 | case NAND_ECC_HW12_2048: | ||
2471 | this->eccsteps = mtd->oobblock / 2048; | ||
2472 | break; | ||
2473 | case NAND_ECC_HW3_512: | ||
2474 | case NAND_ECC_HW6_512: | ||
2475 | case NAND_ECC_HW8_512: | ||
2476 | this->eccsteps = mtd->oobblock / 512; | ||
2477 | break; | ||
2478 | case NAND_ECC_HW3_256: | ||
2479 | case NAND_ECC_SOFT: | ||
2480 | this->eccsteps = mtd->oobblock / 256; | ||
2481 | break; | ||
2482 | |||
2483 | case NAND_ECC_NONE: | ||
2484 | this->eccsteps = 1; | ||
2485 | break; | ||
2486 | } | ||
2487 | |||
2488 | /* Initialize state, waitqueue and spinlock */ | ||
2489 | this->state = FL_READY; | ||
2490 | init_waitqueue_head (&this->wq); | ||
2491 | spin_lock_init (&this->chip_lock); | ||
2492 | |||
2493 | /* De-select the device */ | ||
2494 | this->select_chip(mtd, -1); | ||
2495 | |||
2496 | /* Invalidate the pagebuffer reference */ | ||
2497 | this->pagebuf = -1; | ||
2498 | |||
2499 | /* Fill in remaining MTD driver data */ | ||
2500 | mtd->type = MTD_NANDFLASH; | ||
2501 | mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; | ||
2502 | mtd->ecctype = MTD_ECC_SW; | ||
2503 | mtd->erase = nand_erase; | ||
2504 | mtd->point = NULL; | ||
2505 | mtd->unpoint = NULL; | ||
2506 | mtd->read = nand_read; | ||
2507 | mtd->write = nand_write; | ||
2508 | mtd->read_ecc = nand_read_ecc; | ||
2509 | mtd->write_ecc = nand_write_ecc; | ||
2510 | mtd->read_oob = nand_read_oob; | ||
2511 | mtd->write_oob = nand_write_oob; | ||
2512 | mtd->readv = NULL; | ||
2513 | mtd->writev = nand_writev; | ||
2514 | mtd->writev_ecc = nand_writev_ecc; | ||
2515 | mtd->sync = nand_sync; | ||
2516 | mtd->lock = NULL; | ||
2517 | mtd->unlock = NULL; | ||
2518 | mtd->suspend = NULL; | ||
2519 | mtd->resume = NULL; | ||
2520 | mtd->block_isbad = nand_block_isbad; | ||
2521 | mtd->block_markbad = nand_block_markbad; | ||
2522 | |||
2523 | /* and make the autooob the default one */ | ||
2524 | memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); | ||
2525 | |||
2526 | mtd->owner = THIS_MODULE; | ||
2527 | |||
2528 | /* Build bad block table */ | ||
2529 | return this->scan_bbt (mtd); | ||
2530 | } | ||
2531 | |||
2532 | /** | ||
2533 | * nand_release - [NAND Interface] Free resources held by the NAND device | ||
2534 | * @mtd: MTD device structure | ||
2535 | */ | ||
2536 | void nand_release (struct mtd_info *mtd) | ||
2537 | { | ||
2538 | struct nand_chip *this = mtd->priv; | ||
2539 | |||
2540 | #ifdef CONFIG_MTD_PARTITIONS | ||
2541 | /* Deregister partitions */ | ||
2542 | del_mtd_partitions (mtd); | ||
2543 | #endif | ||
2544 | /* Deregister the device */ | ||
2545 | del_mtd_device (mtd); | ||
2546 | |||
2547 | /* Free bad block table memory, if allocated */ | ||
2548 | if (this->bbt) | ||
2549 | kfree (this->bbt); | ||
2550 | /* Buffer allocated by nand_scan ? */ | ||
2551 | if (this->options & NAND_OOBBUF_ALLOC) | ||
2552 | kfree (this->oob_buf); | ||
2553 | /* Buffer allocated by nand_scan ? */ | ||
2554 | if (this->options & NAND_DATABUF_ALLOC) | ||
2555 | kfree (this->data_buf); | ||
2556 | } | ||
2557 | |||
2558 | EXPORT_SYMBOL (nand_scan); | ||
2559 | EXPORT_SYMBOL (nand_release); | ||
2560 | |||
2561 | MODULE_LICENSE ("GPL"); | ||
2562 | MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); | ||
2563 | MODULE_DESCRIPTION ("Generic NAND flash driver code"); | ||
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c new file mode 100644 index 000000000000..9a1949751c1f --- /dev/null +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -0,0 +1,1056 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand_bbt.c | ||
3 | * | ||
4 | * Overview: | ||
5 | * Bad block table support for the NAND driver | ||
6 | * | ||
7 | * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) | ||
8 | * | ||
9 | * $Id: nand_bbt.c,v 1.28 2004/11/13 10:19:09 gleixner Exp $ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * Description: | ||
16 | * | ||
17 | * When nand_scan_bbt is called, then it tries to find the bad block table | ||
18 | * depending on the options in the bbt descriptor(s). If a bbt is found | ||
19 | * then the contents are read and the memory based bbt is created. If a | ||
20 | * mirrored bbt is selected then the mirror is searched too and the | ||
21 | * versions are compared. If the mirror has a greater version number | ||
22 | * than the mirror bbt is used to build the memory based bbt. | ||
23 | * If the tables are not versioned, then we "or" the bad block information. | ||
24 | * If one of the bbt's is out of date or does not exist it is (re)created. | ||
25 | * If no bbt exists at all then the device is scanned for factory marked | ||
26 | * good / bad blocks and the bad block tables are created. | ||
27 | * | ||
28 | * For manufacturer created bbts like the one found on M-SYS DOC devices | ||
29 | * the bbt is searched and read but never created | ||
30 | * | ||
31 | * The autogenerated bad block table is located in the last good blocks | ||
32 | * of the device. The table is mirrored, so it can be updated eventually. | ||
33 | * The table is marked in the oob area with an ident pattern and a version | ||
34 | * number which indicates which of both tables is more up to date. | ||
35 | * | ||
36 | * The table uses 2 bits per block | ||
37 | * 11b: block is good | ||
38 | * 00b: block is factory marked bad | ||
39 | * 01b, 10b: block is marked bad due to wear | ||
40 | * | ||
41 | * The memory bad block table uses the following scheme: | ||
42 | * 00b: block is good | ||
43 | * 01b: block is marked bad due to wear | ||
44 | * 10b: block is reserved (to protect the bbt area) | ||
45 | * 11b: block is factory marked bad | ||
46 | * | ||
47 | * Multichip devices like DOC store the bad block info per floor. | ||
48 | * | ||
49 | * Following assumptions are made: | ||
50 | * - bbts start at a page boundary, if autolocated on a block boundary | ||
51 | * - the space neccecary for a bbt in FLASH does not exceed a block boundary | ||
52 | * | ||
53 | */ | ||
54 | |||
55 | #include <linux/slab.h> | ||
56 | #include <linux/types.h> | ||
57 | #include <linux/mtd/mtd.h> | ||
58 | #include <linux/mtd/nand.h> | ||
59 | #include <linux/mtd/nand_ecc.h> | ||
60 | #include <linux/mtd/compatmac.h> | ||
61 | #include <linux/bitops.h> | ||
62 | #include <linux/delay.h> | ||
63 | |||
64 | |||
65 | /** | ||
66 | * check_pattern - [GENERIC] check if a pattern is in the buffer | ||
67 | * @buf: the buffer to search | ||
68 | * @len: the length of buffer to search | ||
69 | * @paglen: the pagelength | ||
70 | * @td: search pattern descriptor | ||
71 | * | ||
72 | * Check for a pattern at the given place. Used to search bad block | ||
73 | * tables and good / bad block identifiers. | ||
74 | * If the SCAN_EMPTY option is set then check, if all bytes except the | ||
75 | * pattern area contain 0xff | ||
76 | * | ||
77 | */ | ||
78 | static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) | ||
79 | { | ||
80 | int i, end; | ||
81 | uint8_t *p = buf; | ||
82 | |||
83 | end = paglen + td->offs; | ||
84 | if (td->options & NAND_BBT_SCANEMPTY) { | ||
85 | for (i = 0; i < end; i++) { | ||
86 | if (p[i] != 0xff) | ||
87 | return -1; | ||
88 | } | ||
89 | } | ||
90 | p += end; | ||
91 | |||
92 | /* Compare the pattern */ | ||
93 | for (i = 0; i < td->len; i++) { | ||
94 | if (p[i] != td->pattern[i]) | ||
95 | return -1; | ||
96 | } | ||
97 | |||
98 | p += td->len; | ||
99 | end += td->len; | ||
100 | if (td->options & NAND_BBT_SCANEMPTY) { | ||
101 | for (i = end; i < len; i++) { | ||
102 | if (*p++ != 0xff) | ||
103 | return -1; | ||
104 | } | ||
105 | } | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * read_bbt - [GENERIC] Read the bad block table starting from page | ||
111 | * @mtd: MTD device structure | ||
112 | * @buf: temporary buffer | ||
113 | * @page: the starting page | ||
114 | * @num: the number of bbt descriptors to read | ||
115 | * @bits: number of bits per block | ||
116 | * @offs: offset in the memory table | ||
117 | * @reserved_block_code: Pattern to identify reserved blocks | ||
118 | * | ||
119 | * Read the bad block table starting from page. | ||
120 | * | ||
121 | */ | ||
122 | static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, | ||
123 | int bits, int offs, int reserved_block_code) | ||
124 | { | ||
125 | int res, i, j, act = 0; | ||
126 | struct nand_chip *this = mtd->priv; | ||
127 | size_t retlen, len, totlen; | ||
128 | loff_t from; | ||
129 | uint8_t msk = (uint8_t) ((1 << bits) - 1); | ||
130 | |||
131 | totlen = (num * bits) >> 3; | ||
132 | from = ((loff_t)page) << this->page_shift; | ||
133 | |||
134 | while (totlen) { | ||
135 | len = min (totlen, (size_t) (1 << this->bbt_erase_shift)); | ||
136 | res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob); | ||
137 | if (res < 0) { | ||
138 | if (retlen != len) { | ||
139 | printk (KERN_INFO "nand_bbt: Error reading bad block table\n"); | ||
140 | return res; | ||
141 | } | ||
142 | printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); | ||
143 | } | ||
144 | |||
145 | /* Analyse data */ | ||
146 | for (i = 0; i < len; i++) { | ||
147 | uint8_t dat = buf[i]; | ||
148 | for (j = 0; j < 8; j += bits, act += 2) { | ||
149 | uint8_t tmp = (dat >> j) & msk; | ||
150 | if (tmp == msk) | ||
151 | continue; | ||
152 | if (reserved_block_code && | ||
153 | (tmp == reserved_block_code)) { | ||
154 | printk (KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n", | ||
155 | ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); | ||
156 | this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06); | ||
157 | continue; | ||
158 | } | ||
159 | /* Leave it for now, if its matured we can move this | ||
160 | * message to MTD_DEBUG_LEVEL0 */ | ||
161 | printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", | ||
162 | ((offs << 2) + (act >> 1)) << this->bbt_erase_shift); | ||
163 | /* Factory marked bad or worn out ? */ | ||
164 | if (tmp == 0) | ||
165 | this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); | ||
166 | else | ||
167 | this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); | ||
168 | } | ||
169 | } | ||
170 | totlen -= len; | ||
171 | from += len; | ||
172 | } | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page | ||
178 | * @mtd: MTD device structure | ||
179 | * @buf: temporary buffer | ||
180 | * @td: descriptor for the bad block table | ||
181 | * @chip: read the table for a specific chip, -1 read all chips. | ||
182 | * Applies only if NAND_BBT_PERCHIP option is set | ||
183 | * | ||
184 | * Read the bad block table for all chips starting at a given page | ||
185 | * We assume that the bbt bits are in consecutive order. | ||
186 | */ | ||
187 | static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip) | ||
188 | { | ||
189 | struct nand_chip *this = mtd->priv; | ||
190 | int res = 0, i; | ||
191 | int bits; | ||
192 | |||
193 | bits = td->options & NAND_BBT_NRBITS_MSK; | ||
194 | if (td->options & NAND_BBT_PERCHIP) { | ||
195 | int offs = 0; | ||
196 | for (i = 0; i < this->numchips; i++) { | ||
197 | if (chip == -1 || chip == i) | ||
198 | res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code); | ||
199 | if (res) | ||
200 | return res; | ||
201 | offs += this->chipsize >> (this->bbt_erase_shift + 2); | ||
202 | } | ||
203 | } else { | ||
204 | res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code); | ||
205 | if (res) | ||
206 | return res; | ||
207 | } | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | /** | ||
212 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page | ||
213 | * @mtd: MTD device structure | ||
214 | * @buf: temporary buffer | ||
215 | * @td: descriptor for the bad block table | ||
216 | * @md: descriptor for the bad block table mirror | ||
217 | * | ||
218 | * Read the bad block table(s) for all chips starting at a given page | ||
219 | * We assume that the bbt bits are in consecutive order. | ||
220 | * | ||
221 | */ | ||
222 | static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, | ||
223 | struct nand_bbt_descr *md) | ||
224 | { | ||
225 | struct nand_chip *this = mtd->priv; | ||
226 | |||
227 | /* Read the primary version, if available */ | ||
228 | if (td->options & NAND_BBT_VERSION) { | ||
229 | nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); | ||
230 | td->version[0] = buf[mtd->oobblock + td->veroffs]; | ||
231 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]); | ||
232 | } | ||
233 | |||
234 | /* Read the mirror version, if available */ | ||
235 | if (md && (md->options & NAND_BBT_VERSION)) { | ||
236 | nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize); | ||
237 | md->version[0] = buf[mtd->oobblock + md->veroffs]; | ||
238 | printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); | ||
239 | } | ||
240 | |||
241 | return 1; | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * create_bbt - [GENERIC] Create a bad block table by scanning the device | ||
246 | * @mtd: MTD device structure | ||
247 | * @buf: temporary buffer | ||
248 | * @bd: descriptor for the good/bad block search pattern | ||
249 | * @chip: create the table for a specific chip, -1 read all chips. | ||
250 | * Applies only if NAND_BBT_PERCHIP option is set | ||
251 | * | ||
252 | * Create a bad block table by scanning the device | ||
253 | * for the given good/bad block identify pattern | ||
254 | */ | ||
255 | static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) | ||
256 | { | ||
257 | struct nand_chip *this = mtd->priv; | ||
258 | int i, j, numblocks, len, scanlen; | ||
259 | int startblock; | ||
260 | loff_t from; | ||
261 | size_t readlen, ooblen; | ||
262 | |||
263 | printk (KERN_INFO "Scanning device for bad blocks\n"); | ||
264 | |||
265 | if (bd->options & NAND_BBT_SCANALLPAGES) | ||
266 | len = 1 << (this->bbt_erase_shift - this->page_shift); | ||
267 | else { | ||
268 | if (bd->options & NAND_BBT_SCAN2NDPAGE) | ||
269 | len = 2; | ||
270 | else | ||
271 | len = 1; | ||
272 | } | ||
273 | scanlen = mtd->oobblock + mtd->oobsize; | ||
274 | readlen = len * mtd->oobblock; | ||
275 | ooblen = len * mtd->oobsize; | ||
276 | |||
277 | if (chip == -1) { | ||
278 | /* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it | ||
279 | * makes shifting and masking less painful */ | ||
280 | numblocks = mtd->size >> (this->bbt_erase_shift - 1); | ||
281 | startblock = 0; | ||
282 | from = 0; | ||
283 | } else { | ||
284 | if (chip >= this->numchips) { | ||
285 | printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", | ||
286 | chip + 1, this->numchips); | ||
287 | return; | ||
288 | } | ||
289 | numblocks = this->chipsize >> (this->bbt_erase_shift - 1); | ||
290 | startblock = chip * numblocks; | ||
291 | numblocks += startblock; | ||
292 | from = startblock << (this->bbt_erase_shift - 1); | ||
293 | } | ||
294 | |||
295 | for (i = startblock; i < numblocks;) { | ||
296 | nand_read_raw (mtd, buf, from, readlen, ooblen); | ||
297 | for (j = 0; j < len; j++) { | ||
298 | if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { | ||
299 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); | ||
300 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", | ||
301 | i >> 1, (unsigned int) from); | ||
302 | break; | ||
303 | } | ||
304 | } | ||
305 | i += 2; | ||
306 | from += (1 << this->bbt_erase_shift); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * search_bbt - [GENERIC] scan the device for a specific bad block table | ||
312 | * @mtd: MTD device structure | ||
313 | * @buf: temporary buffer | ||
314 | * @td: descriptor for the bad block table | ||
315 | * | ||
316 | * Read the bad block table by searching for a given ident pattern. | ||
317 | * Search is preformed either from the beginning up or from the end of | ||
318 | * the device downwards. The search starts always at the start of a | ||
319 | * block. | ||
320 | * If the option NAND_BBT_PERCHIP is given, each chip is searched | ||
321 | * for a bbt, which contains the bad block information of this chip. | ||
322 | * This is neccecary to provide support for certain DOC devices. | ||
323 | * | ||
324 | * The bbt ident pattern resides in the oob area of the first page | ||
325 | * in a block. | ||
326 | */ | ||
327 | static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td) | ||
328 | { | ||
329 | struct nand_chip *this = mtd->priv; | ||
330 | int i, chips; | ||
331 | int bits, startblock, block, dir; | ||
332 | int scanlen = mtd->oobblock + mtd->oobsize; | ||
333 | int bbtblocks; | ||
334 | |||
335 | /* Search direction top -> down ? */ | ||
336 | if (td->options & NAND_BBT_LASTBLOCK) { | ||
337 | startblock = (mtd->size >> this->bbt_erase_shift) -1; | ||
338 | dir = -1; | ||
339 | } else { | ||
340 | startblock = 0; | ||
341 | dir = 1; | ||
342 | } | ||
343 | |||
344 | /* Do we have a bbt per chip ? */ | ||
345 | if (td->options & NAND_BBT_PERCHIP) { | ||
346 | chips = this->numchips; | ||
347 | bbtblocks = this->chipsize >> this->bbt_erase_shift; | ||
348 | startblock &= bbtblocks - 1; | ||
349 | } else { | ||
350 | chips = 1; | ||
351 | bbtblocks = mtd->size >> this->bbt_erase_shift; | ||
352 | } | ||
353 | |||
354 | /* Number of bits for each erase block in the bbt */ | ||
355 | bits = td->options & NAND_BBT_NRBITS_MSK; | ||
356 | |||
357 | for (i = 0; i < chips; i++) { | ||
358 | /* Reset version information */ | ||
359 | td->version[i] = 0; | ||
360 | td->pages[i] = -1; | ||
361 | /* Scan the maximum number of blocks */ | ||
362 | for (block = 0; block < td->maxblocks; block++) { | ||
363 | int actblock = startblock + dir * block; | ||
364 | /* Read first page */ | ||
365 | nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize); | ||
366 | if (!check_pattern(buf, scanlen, mtd->oobblock, td)) { | ||
367 | td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift); | ||
368 | if (td->options & NAND_BBT_VERSION) { | ||
369 | td->version[i] = buf[mtd->oobblock + td->veroffs]; | ||
370 | } | ||
371 | break; | ||
372 | } | ||
373 | } | ||
374 | startblock += this->chipsize >> this->bbt_erase_shift; | ||
375 | } | ||
376 | /* Check, if we found a bbt for each requested chip */ | ||
377 | for (i = 0; i < chips; i++) { | ||
378 | if (td->pages[i] == -1) | ||
379 | printk (KERN_WARNING "Bad block table not found for chip %d\n", i); | ||
380 | else | ||
381 | printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]); | ||
382 | } | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | /** | ||
387 | * search_read_bbts - [GENERIC] scan the device for bad block table(s) | ||
388 | * @mtd: MTD device structure | ||
389 | * @buf: temporary buffer | ||
390 | * @td: descriptor for the bad block table | ||
391 | * @md: descriptor for the bad block table mirror | ||
392 | * | ||
393 | * Search and read the bad block table(s) | ||
394 | */ | ||
395 | static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, | ||
396 | struct nand_bbt_descr *td, struct nand_bbt_descr *md) | ||
397 | { | ||
398 | /* Search the primary table */ | ||
399 | search_bbt (mtd, buf, td); | ||
400 | |||
401 | /* Search the mirror table */ | ||
402 | if (md) | ||
403 | search_bbt (mtd, buf, md); | ||
404 | |||
405 | /* Force result check */ | ||
406 | return 1; | ||
407 | } | ||
408 | |||
409 | |||
410 | /** | ||
411 | * write_bbt - [GENERIC] (Re)write the bad block table | ||
412 | * | ||
413 | * @mtd: MTD device structure | ||
414 | * @buf: temporary buffer | ||
415 | * @td: descriptor for the bad block table | ||
416 | * @md: descriptor for the bad block table mirror | ||
417 | * @chipsel: selector for a specific chip, -1 for all | ||
418 | * | ||
419 | * (Re)write the bad block table | ||
420 | * | ||
421 | */ | ||
422 | static int write_bbt (struct mtd_info *mtd, uint8_t *buf, | ||
423 | struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel) | ||
424 | { | ||
425 | struct nand_chip *this = mtd->priv; | ||
426 | struct nand_oobinfo oobinfo; | ||
427 | struct erase_info einfo; | ||
428 | int i, j, res, chip = 0; | ||
429 | int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; | ||
430 | int nrchips, bbtoffs, pageoffs; | ||
431 | uint8_t msk[4]; | ||
432 | uint8_t rcode = td->reserved_block_code; | ||
433 | size_t retlen, len = 0; | ||
434 | loff_t to; | ||
435 | |||
436 | if (!rcode) | ||
437 | rcode = 0xff; | ||
438 | /* Write bad block table per chip rather than per device ? */ | ||
439 | if (td->options & NAND_BBT_PERCHIP) { | ||
440 | numblocks = (int) (this->chipsize >> this->bbt_erase_shift); | ||
441 | /* Full device write or specific chip ? */ | ||
442 | if (chipsel == -1) { | ||
443 | nrchips = this->numchips; | ||
444 | } else { | ||
445 | nrchips = chipsel + 1; | ||
446 | chip = chipsel; | ||
447 | } | ||
448 | } else { | ||
449 | numblocks = (int) (mtd->size >> this->bbt_erase_shift); | ||
450 | nrchips = 1; | ||
451 | } | ||
452 | |||
453 | /* Loop through the chips */ | ||
454 | for (; chip < nrchips; chip++) { | ||
455 | |||
456 | /* There was already a version of the table, reuse the page | ||
457 | * This applies for absolute placement too, as we have the | ||
458 | * page nr. in td->pages. | ||
459 | */ | ||
460 | if (td->pages[chip] != -1) { | ||
461 | page = td->pages[chip]; | ||
462 | goto write; | ||
463 | } | ||
464 | |||
465 | /* Automatic placement of the bad block table */ | ||
466 | /* Search direction top -> down ? */ | ||
467 | if (td->options & NAND_BBT_LASTBLOCK) { | ||
468 | startblock = numblocks * (chip + 1) - 1; | ||
469 | dir = -1; | ||
470 | } else { | ||
471 | startblock = chip * numblocks; | ||
472 | dir = 1; | ||
473 | } | ||
474 | |||
475 | for (i = 0; i < td->maxblocks; i++) { | ||
476 | int block = startblock + dir * i; | ||
477 | /* Check, if the block is bad */ | ||
478 | switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) { | ||
479 | case 0x01: | ||
480 | case 0x03: | ||
481 | continue; | ||
482 | } | ||
483 | page = block << (this->bbt_erase_shift - this->page_shift); | ||
484 | /* Check, if the block is used by the mirror table */ | ||
485 | if (!md || md->pages[chip] != page) | ||
486 | goto write; | ||
487 | } | ||
488 | printk (KERN_ERR "No space left to write bad block table\n"); | ||
489 | return -ENOSPC; | ||
490 | write: | ||
491 | |||
492 | /* Set up shift count and masks for the flash table */ | ||
493 | bits = td->options & NAND_BBT_NRBITS_MSK; | ||
494 | switch (bits) { | ||
495 | case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break; | ||
496 | case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break; | ||
497 | case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break; | ||
498 | case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break; | ||
499 | default: return -EINVAL; | ||
500 | } | ||
501 | |||
502 | bbtoffs = chip * (numblocks >> 2); | ||
503 | |||
504 | to = ((loff_t) page) << this->page_shift; | ||
505 | |||
506 | memcpy (&oobinfo, this->autooob, sizeof(oobinfo)); | ||
507 | oobinfo.useecc = MTD_NANDECC_PLACEONLY; | ||
508 | |||
509 | /* Must we save the block contents ? */ | ||
510 | if (td->options & NAND_BBT_SAVECONTENT) { | ||
511 | /* Make it block aligned */ | ||
512 | to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); | ||
513 | len = 1 << this->bbt_erase_shift; | ||
514 | res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); | ||
515 | if (res < 0) { | ||
516 | if (retlen != len) { | ||
517 | printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n"); | ||
518 | return res; | ||
519 | } | ||
520 | printk (KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n"); | ||
521 | } | ||
522 | /* Calc the byte offset in the buffer */ | ||
523 | pageoffs = page - (int)(to >> this->page_shift); | ||
524 | offs = pageoffs << this->page_shift; | ||
525 | /* Preset the bbt area with 0xff */ | ||
526 | memset (&buf[offs], 0xff, (size_t)(numblocks >> sft)); | ||
527 | /* Preset the bbt's oob area with 0xff */ | ||
528 | memset (&buf[len + pageoffs * mtd->oobsize], 0xff, | ||
529 | ((len >> this->page_shift) - pageoffs) * mtd->oobsize); | ||
530 | if (td->options & NAND_BBT_VERSION) { | ||
531 | buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip]; | ||
532 | } | ||
533 | } else { | ||
534 | /* Calc length */ | ||
535 | len = (size_t) (numblocks >> sft); | ||
536 | /* Make it page aligned ! */ | ||
537 | len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1); | ||
538 | /* Preset the buffer with 0xff */ | ||
539 | memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize); | ||
540 | offs = 0; | ||
541 | /* Pattern is located in oob area of first page */ | ||
542 | memcpy (&buf[len + td->offs], td->pattern, td->len); | ||
543 | if (td->options & NAND_BBT_VERSION) { | ||
544 | buf[len + td->veroffs] = td->version[chip]; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | /* walk through the memory table */ | ||
549 | for (i = 0; i < numblocks; ) { | ||
550 | uint8_t dat; | ||
551 | dat = this->bbt[bbtoffs + (i >> 2)]; | ||
552 | for (j = 0; j < 4; j++ , i++) { | ||
553 | int sftcnt = (i << (3 - sft)) & sftmsk; | ||
554 | /* Do not store the reserved bbt blocks ! */ | ||
555 | buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt); | ||
556 | dat >>= 2; | ||
557 | } | ||
558 | } | ||
559 | |||
560 | memset (&einfo, 0, sizeof (einfo)); | ||
561 | einfo.mtd = mtd; | ||
562 | einfo.addr = (unsigned long) to; | ||
563 | einfo.len = 1 << this->bbt_erase_shift; | ||
564 | res = nand_erase_nand (mtd, &einfo, 1); | ||
565 | if (res < 0) { | ||
566 | printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res); | ||
567 | return res; | ||
568 | } | ||
569 | |||
570 | res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo); | ||
571 | if (res < 0) { | ||
572 | printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res); | ||
573 | return res; | ||
574 | } | ||
575 | printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", | ||
576 | (unsigned int) to, td->version[chip]); | ||
577 | |||
578 | /* Mark it as used */ | ||
579 | td->pages[chip] = page; | ||
580 | } | ||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * nand_memory_bbt - [GENERIC] create a memory based bad block table | ||
586 | * @mtd: MTD device structure | ||
587 | * @bd: descriptor for the good/bad block search pattern | ||
588 | * | ||
589 | * The function creates a memory based bbt by scanning the device | ||
590 | * for manufacturer / software marked good / bad blocks | ||
591 | */ | ||
592 | static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) | ||
593 | { | ||
594 | struct nand_chip *this = mtd->priv; | ||
595 | |||
596 | /* Ensure that we only scan for the pattern and nothing else */ | ||
597 | bd->options = 0; | ||
598 | create_bbt (mtd, this->data_buf, bd, -1); | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | /** | ||
603 | * check_create - [GENERIC] create and write bbt(s) if neccecary | ||
604 | * @mtd: MTD device structure | ||
605 | * @buf: temporary buffer | ||
606 | * @bd: descriptor for the good/bad block search pattern | ||
607 | * | ||
608 | * The function checks the results of the previous call to read_bbt | ||
609 | * and creates / updates the bbt(s) if neccecary | ||
610 | * Creation is neccecary if no bbt was found for the chip/device | ||
611 | * Update is neccecary if one of the tables is missing or the | ||
612 | * version nr. of one table is less than the other | ||
613 | */ | ||
614 | static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd) | ||
615 | { | ||
616 | int i, chips, writeops, chipsel, res; | ||
617 | struct nand_chip *this = mtd->priv; | ||
618 | struct nand_bbt_descr *td = this->bbt_td; | ||
619 | struct nand_bbt_descr *md = this->bbt_md; | ||
620 | struct nand_bbt_descr *rd, *rd2; | ||
621 | |||
622 | /* Do we have a bbt per chip ? */ | ||
623 | if (td->options & NAND_BBT_PERCHIP) | ||
624 | chips = this->numchips; | ||
625 | else | ||
626 | chips = 1; | ||
627 | |||
628 | for (i = 0; i < chips; i++) { | ||
629 | writeops = 0; | ||
630 | rd = NULL; | ||
631 | rd2 = NULL; | ||
632 | /* Per chip or per device ? */ | ||
633 | chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1; | ||
634 | /* Mirrored table avilable ? */ | ||
635 | if (md) { | ||
636 | if (td->pages[i] == -1 && md->pages[i] == -1) { | ||
637 | writeops = 0x03; | ||
638 | goto create; | ||
639 | } | ||
640 | |||
641 | if (td->pages[i] == -1) { | ||
642 | rd = md; | ||
643 | td->version[i] = md->version[i]; | ||
644 | writeops = 1; | ||
645 | goto writecheck; | ||
646 | } | ||
647 | |||
648 | if (md->pages[i] == -1) { | ||
649 | rd = td; | ||
650 | md->version[i] = td->version[i]; | ||
651 | writeops = 2; | ||
652 | goto writecheck; | ||
653 | } | ||
654 | |||
655 | if (td->version[i] == md->version[i]) { | ||
656 | rd = td; | ||
657 | if (!(td->options & NAND_BBT_VERSION)) | ||
658 | rd2 = md; | ||
659 | goto writecheck; | ||
660 | } | ||
661 | |||
662 | if (((int8_t) (td->version[i] - md->version[i])) > 0) { | ||
663 | rd = td; | ||
664 | md->version[i] = td->version[i]; | ||
665 | writeops = 2; | ||
666 | } else { | ||
667 | rd = md; | ||
668 | td->version[i] = md->version[i]; | ||
669 | writeops = 1; | ||
670 | } | ||
671 | |||
672 | goto writecheck; | ||
673 | |||
674 | } else { | ||
675 | if (td->pages[i] == -1) { | ||
676 | writeops = 0x01; | ||
677 | goto create; | ||
678 | } | ||
679 | rd = td; | ||
680 | goto writecheck; | ||
681 | } | ||
682 | create: | ||
683 | /* Create the bad block table by scanning the device ? */ | ||
684 | if (!(td->options & NAND_BBT_CREATE)) | ||
685 | continue; | ||
686 | |||
687 | /* Create the table in memory by scanning the chip(s) */ | ||
688 | create_bbt (mtd, buf, bd, chipsel); | ||
689 | |||
690 | td->version[i] = 1; | ||
691 | if (md) | ||
692 | md->version[i] = 1; | ||
693 | writecheck: | ||
694 | /* read back first ? */ | ||
695 | if (rd) | ||
696 | read_abs_bbt (mtd, buf, rd, chipsel); | ||
697 | /* If they weren't versioned, read both. */ | ||
698 | if (rd2) | ||
699 | read_abs_bbt (mtd, buf, rd2, chipsel); | ||
700 | |||
701 | /* Write the bad block table to the device ? */ | ||
702 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { | ||
703 | res = write_bbt (mtd, buf, td, md, chipsel); | ||
704 | if (res < 0) | ||
705 | return res; | ||
706 | } | ||
707 | |||
708 | /* Write the mirror bad block table to the device ? */ | ||
709 | if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { | ||
710 | res = write_bbt (mtd, buf, md, td, chipsel); | ||
711 | if (res < 0) | ||
712 | return res; | ||
713 | } | ||
714 | } | ||
715 | return 0; | ||
716 | } | ||
717 | |||
718 | /** | ||
719 | * mark_bbt_regions - [GENERIC] mark the bad block table regions | ||
720 | * @mtd: MTD device structure | ||
721 | * @td: bad block table descriptor | ||
722 | * | ||
723 | * The bad block table regions are marked as "bad" to prevent | ||
724 | * accidental erasures / writes. The regions are identified by | ||
725 | * the mark 0x02. | ||
726 | */ | ||
727 | static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td) | ||
728 | { | ||
729 | struct nand_chip *this = mtd->priv; | ||
730 | int i, j, chips, block, nrblocks, update; | ||
731 | uint8_t oldval, newval; | ||
732 | |||
733 | /* Do we have a bbt per chip ? */ | ||
734 | if (td->options & NAND_BBT_PERCHIP) { | ||
735 | chips = this->numchips; | ||
736 | nrblocks = (int)(this->chipsize >> this->bbt_erase_shift); | ||
737 | } else { | ||
738 | chips = 1; | ||
739 | nrblocks = (int)(mtd->size >> this->bbt_erase_shift); | ||
740 | } | ||
741 | |||
742 | for (i = 0; i < chips; i++) { | ||
743 | if ((td->options & NAND_BBT_ABSPAGE) || | ||
744 | !(td->options & NAND_BBT_WRITE)) { | ||
745 | if (td->pages[i] == -1) continue; | ||
746 | block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); | ||
747 | block <<= 1; | ||
748 | oldval = this->bbt[(block >> 3)]; | ||
749 | newval = oldval | (0x2 << (block & 0x06)); | ||
750 | this->bbt[(block >> 3)] = newval; | ||
751 | if ((oldval != newval) && td->reserved_block_code) | ||
752 | nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1)); | ||
753 | continue; | ||
754 | } | ||
755 | update = 0; | ||
756 | if (td->options & NAND_BBT_LASTBLOCK) | ||
757 | block = ((i + 1) * nrblocks) - td->maxblocks; | ||
758 | else | ||
759 | block = i * nrblocks; | ||
760 | block <<= 1; | ||
761 | for (j = 0; j < td->maxblocks; j++) { | ||
762 | oldval = this->bbt[(block >> 3)]; | ||
763 | newval = oldval | (0x2 << (block & 0x06)); | ||
764 | this->bbt[(block >> 3)] = newval; | ||
765 | if (oldval != newval) update = 1; | ||
766 | block += 2; | ||
767 | } | ||
768 | /* If we want reserved blocks to be recorded to flash, and some | ||
769 | new ones have been marked, then we need to update the stored | ||
770 | bbts. This should only happen once. */ | ||
771 | if (update && td->reserved_block_code) | ||
772 | nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1)); | ||
773 | } | ||
774 | } | ||
775 | |||
776 | /** | ||
777 | * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) | ||
778 | * @mtd: MTD device structure | ||
779 | * @bd: descriptor for the good/bad block search pattern | ||
780 | * | ||
781 | * The function checks, if a bad block table(s) is/are already | ||
782 | * available. If not it scans the device for manufacturer | ||
783 | * marked good / bad blocks and writes the bad block table(s) to | ||
784 | * the selected place. | ||
785 | * | ||
786 | * The bad block table memory is allocated here. It must be freed | ||
787 | * by calling the nand_free_bbt function. | ||
788 | * | ||
789 | */ | ||
790 | int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) | ||
791 | { | ||
792 | struct nand_chip *this = mtd->priv; | ||
793 | int len, res = 0; | ||
794 | uint8_t *buf; | ||
795 | struct nand_bbt_descr *td = this->bbt_td; | ||
796 | struct nand_bbt_descr *md = this->bbt_md; | ||
797 | |||
798 | len = mtd->size >> (this->bbt_erase_shift + 2); | ||
799 | /* Allocate memory (2bit per block) */ | ||
800 | this->bbt = kmalloc (len, GFP_KERNEL); | ||
801 | if (!this->bbt) { | ||
802 | printk (KERN_ERR "nand_scan_bbt: Out of memory\n"); | ||
803 | return -ENOMEM; | ||
804 | } | ||
805 | /* Clear the memory bad block table */ | ||
806 | memset (this->bbt, 0x00, len); | ||
807 | |||
808 | /* If no primary table decriptor is given, scan the device | ||
809 | * to build a memory based bad block table | ||
810 | */ | ||
811 | if (!td) | ||
812 | return nand_memory_bbt(mtd, bd); | ||
813 | |||
814 | /* Allocate a temporary buffer for one eraseblock incl. oob */ | ||
815 | len = (1 << this->bbt_erase_shift); | ||
816 | len += (len >> this->page_shift) * mtd->oobsize; | ||
817 | buf = kmalloc (len, GFP_KERNEL); | ||
818 | if (!buf) { | ||
819 | printk (KERN_ERR "nand_bbt: Out of memory\n"); | ||
820 | kfree (this->bbt); | ||
821 | this->bbt = NULL; | ||
822 | return -ENOMEM; | ||
823 | } | ||
824 | |||
825 | /* Is the bbt at a given page ? */ | ||
826 | if (td->options & NAND_BBT_ABSPAGE) { | ||
827 | res = read_abs_bbts (mtd, buf, td, md); | ||
828 | } else { | ||
829 | /* Search the bad block table using a pattern in oob */ | ||
830 | res = search_read_bbts (mtd, buf, td, md); | ||
831 | } | ||
832 | |||
833 | if (res) | ||
834 | res = check_create (mtd, buf, bd); | ||
835 | |||
836 | /* Prevent the bbt regions from erasing / writing */ | ||
837 | mark_bbt_region (mtd, td); | ||
838 | if (md) | ||
839 | mark_bbt_region (mtd, md); | ||
840 | |||
841 | kfree (buf); | ||
842 | return res; | ||
843 | } | ||
844 | |||
845 | |||
846 | /** | ||
847 | * nand_update_bbt - [NAND Interface] update bad block table(s) | ||
848 | * @mtd: MTD device structure | ||
849 | * @offs: the offset of the newly marked block | ||
850 | * | ||
851 | * The function updates the bad block table(s) | ||
852 | */ | ||
853 | int nand_update_bbt (struct mtd_info *mtd, loff_t offs) | ||
854 | { | ||
855 | struct nand_chip *this = mtd->priv; | ||
856 | int len, res = 0, writeops = 0; | ||
857 | int chip, chipsel; | ||
858 | uint8_t *buf; | ||
859 | struct nand_bbt_descr *td = this->bbt_td; | ||
860 | struct nand_bbt_descr *md = this->bbt_md; | ||
861 | |||
862 | if (!this->bbt || !td) | ||
863 | return -EINVAL; | ||
864 | |||
865 | len = mtd->size >> (this->bbt_erase_shift + 2); | ||
866 | /* Allocate a temporary buffer for one eraseblock incl. oob */ | ||
867 | len = (1 << this->bbt_erase_shift); | ||
868 | len += (len >> this->page_shift) * mtd->oobsize; | ||
869 | buf = kmalloc (len, GFP_KERNEL); | ||
870 | if (!buf) { | ||
871 | printk (KERN_ERR "nand_update_bbt: Out of memory\n"); | ||
872 | return -ENOMEM; | ||
873 | } | ||
874 | |||
875 | writeops = md != NULL ? 0x03 : 0x01; | ||
876 | |||
877 | /* Do we have a bbt per chip ? */ | ||
878 | if (td->options & NAND_BBT_PERCHIP) { | ||
879 | chip = (int) (offs >> this->chip_shift); | ||
880 | chipsel = chip; | ||
881 | } else { | ||
882 | chip = 0; | ||
883 | chipsel = -1; | ||
884 | } | ||
885 | |||
886 | td->version[chip]++; | ||
887 | if (md) | ||
888 | md->version[chip]++; | ||
889 | |||
890 | /* Write the bad block table to the device ? */ | ||
891 | if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { | ||
892 | res = write_bbt (mtd, buf, td, md, chipsel); | ||
893 | if (res < 0) | ||
894 | goto out; | ||
895 | } | ||
896 | /* Write the mirror bad block table to the device ? */ | ||
897 | if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { | ||
898 | res = write_bbt (mtd, buf, md, td, chipsel); | ||
899 | } | ||
900 | |||
901 | out: | ||
902 | kfree (buf); | ||
903 | return res; | ||
904 | } | ||
905 | |||
906 | /* Define some generic bad / good block scan pattern which are used | ||
907 | * while scanning a device for factory marked good / bad blocks | ||
908 | * | ||
909 | * The memory based patterns just | ||
910 | */ | ||
911 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | ||
912 | |||
913 | static struct nand_bbt_descr smallpage_memorybased = { | ||
914 | .options = 0, | ||
915 | .offs = 5, | ||
916 | .len = 1, | ||
917 | .pattern = scan_ff_pattern | ||
918 | }; | ||
919 | |||
920 | static struct nand_bbt_descr largepage_memorybased = { | ||
921 | .options = 0, | ||
922 | .offs = 0, | ||
923 | .len = 2, | ||
924 | .pattern = scan_ff_pattern | ||
925 | }; | ||
926 | |||
927 | static struct nand_bbt_descr smallpage_flashbased = { | ||
928 | .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, | ||
929 | .offs = 5, | ||
930 | .len = 1, | ||
931 | .pattern = scan_ff_pattern | ||
932 | }; | ||
933 | |||
934 | static struct nand_bbt_descr largepage_flashbased = { | ||
935 | .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, | ||
936 | .offs = 0, | ||
937 | .len = 2, | ||
938 | .pattern = scan_ff_pattern | ||
939 | }; | ||
940 | |||
941 | static uint8_t scan_agand_pattern[] = { 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7 }; | ||
942 | |||
943 | static struct nand_bbt_descr agand_flashbased = { | ||
944 | .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, | ||
945 | .offs = 0x20, | ||
946 | .len = 6, | ||
947 | .pattern = scan_agand_pattern | ||
948 | }; | ||
949 | |||
950 | /* Generic flash bbt decriptors | ||
951 | */ | ||
952 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; | ||
953 | static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; | ||
954 | |||
955 | static struct nand_bbt_descr bbt_main_descr = { | ||
956 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
957 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | ||
958 | .offs = 8, | ||
959 | .len = 4, | ||
960 | .veroffs = 12, | ||
961 | .maxblocks = 4, | ||
962 | .pattern = bbt_pattern | ||
963 | }; | ||
964 | |||
965 | static struct nand_bbt_descr bbt_mirror_descr = { | ||
966 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
967 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | ||
968 | .offs = 8, | ||
969 | .len = 4, | ||
970 | .veroffs = 12, | ||
971 | .maxblocks = 4, | ||
972 | .pattern = mirror_pattern | ||
973 | }; | ||
974 | |||
975 | /** | ||
976 | * nand_default_bbt - [NAND Interface] Select a default bad block table for the device | ||
977 | * @mtd: MTD device structure | ||
978 | * | ||
979 | * This function selects the default bad block table | ||
980 | * support for the device and calls the nand_scan_bbt function | ||
981 | * | ||
982 | */ | ||
983 | int nand_default_bbt (struct mtd_info *mtd) | ||
984 | { | ||
985 | struct nand_chip *this = mtd->priv; | ||
986 | |||
987 | /* Default for AG-AND. We must use a flash based | ||
988 | * bad block table as the devices have factory marked | ||
989 | * _good_ blocks. Erasing those blocks leads to loss | ||
990 | * of the good / bad information, so we _must_ store | ||
991 | * this information in a good / bad table during | ||
992 | * startup | ||
993 | */ | ||
994 | if (this->options & NAND_IS_AND) { | ||
995 | /* Use the default pattern descriptors */ | ||
996 | if (!this->bbt_td) { | ||
997 | this->bbt_td = &bbt_main_descr; | ||
998 | this->bbt_md = &bbt_mirror_descr; | ||
999 | } | ||
1000 | this->options |= NAND_USE_FLASH_BBT; | ||
1001 | return nand_scan_bbt (mtd, &agand_flashbased); | ||
1002 | } | ||
1003 | |||
1004 | |||
1005 | /* Is a flash based bad block table requested ? */ | ||
1006 | if (this->options & NAND_USE_FLASH_BBT) { | ||
1007 | /* Use the default pattern descriptors */ | ||
1008 | if (!this->bbt_td) { | ||
1009 | this->bbt_td = &bbt_main_descr; | ||
1010 | this->bbt_md = &bbt_mirror_descr; | ||
1011 | } | ||
1012 | if (!this->badblock_pattern) { | ||
1013 | this->badblock_pattern = (mtd->oobblock > 512) ? | ||
1014 | &largepage_flashbased : &smallpage_flashbased; | ||
1015 | } | ||
1016 | } else { | ||
1017 | this->bbt_td = NULL; | ||
1018 | this->bbt_md = NULL; | ||
1019 | if (!this->badblock_pattern) { | ||
1020 | this->badblock_pattern = (mtd->oobblock > 512) ? | ||
1021 | &largepage_memorybased : &smallpage_memorybased; | ||
1022 | } | ||
1023 | } | ||
1024 | return nand_scan_bbt (mtd, this->badblock_pattern); | ||
1025 | } | ||
1026 | |||
1027 | /** | ||
1028 | * nand_isbad_bbt - [NAND Interface] Check if a block is bad | ||
1029 | * @mtd: MTD device structure | ||
1030 | * @offs: offset in the device | ||
1031 | * @allowbbt: allow access to bad block table region | ||
1032 | * | ||
1033 | */ | ||
1034 | int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt) | ||
1035 | { | ||
1036 | struct nand_chip *this = mtd->priv; | ||
1037 | int block; | ||
1038 | uint8_t res; | ||
1039 | |||
1040 | /* Get block number * 2 */ | ||
1041 | block = (int) (offs >> (this->bbt_erase_shift - 1)); | ||
1042 | res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; | ||
1043 | |||
1044 | DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", | ||
1045 | (unsigned int)offs, res, block >> 1); | ||
1046 | |||
1047 | switch ((int)res) { | ||
1048 | case 0x00: return 0; | ||
1049 | case 0x01: return 1; | ||
1050 | case 0x02: return allowbbt ? 0 : 1; | ||
1051 | } | ||
1052 | return 1; | ||
1053 | } | ||
1054 | |||
1055 | EXPORT_SYMBOL (nand_scan_bbt); | ||
1056 | EXPORT_SYMBOL (nand_default_bbt); | ||
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c new file mode 100644 index 000000000000..2e341b75437a --- /dev/null +++ b/drivers/mtd/nand/nand_ecc.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * This file contains an ECC algorithm from Toshiba that detects and | ||
3 | * corrects 1 bit errors in a 256 byte block of data. | ||
4 | * | ||
5 | * drivers/mtd/nand/nand_ecc.c | ||
6 | * | ||
7 | * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com) | ||
8 | * Toshiba America Electronics Components, Inc. | ||
9 | * | ||
10 | * $Id: nand_ecc.c,v 1.14 2004/06/16 15:34:37 gleixner Exp $ | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 or (at your option) any | ||
15 | * later version. | ||
16 | * | ||
17 | * This file is distributed in the hope that it will be useful, but WITHOUT | ||
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
20 | * for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this file; if not, write to the Free Software Foundation, Inc., | ||
24 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
25 | * | ||
26 | * As a special exception, if other files instantiate templates or use | ||
27 | * macros or inline functions from these files, or you compile these | ||
28 | * files and link them with other works to produce a work based on these | ||
29 | * files, these files do not by themselves cause the resulting work to be | ||
30 | * covered by the GNU General Public License. However the source code for | ||
31 | * these files must still be made available in accordance with section (3) | ||
32 | * of the GNU General Public License. | ||
33 | * | ||
34 | * This exception does not invalidate any other reasons why a work based on | ||
35 | * this file might be covered by the GNU General Public License. | ||
36 | */ | ||
37 | |||
38 | #include <linux/types.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/module.h> | ||
41 | #include <linux/mtd/nand_ecc.h> | ||
42 | |||
43 | /* | ||
44 | * Pre-calculated 256-way 1 byte column parity | ||
45 | */ | ||
46 | static const u_char nand_ecc_precalc_table[] = { | ||
47 | 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, | ||
48 | 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, | ||
49 | 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, | ||
50 | 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, | ||
51 | 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, | ||
52 | 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, | ||
53 | 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, | ||
54 | 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, | ||
55 | 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, | ||
56 | 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, | ||
57 | 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, | ||
58 | 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, | ||
59 | 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, | ||
60 | 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, | ||
61 | 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, | ||
62 | 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 | ||
63 | }; | ||
64 | |||
65 | |||
66 | /** | ||
67 | * nand_trans_result - [GENERIC] create non-inverted ECC | ||
68 | * @reg2: line parity reg 2 | ||
69 | * @reg3: line parity reg 3 | ||
70 | * @ecc_code: ecc | ||
71 | * | ||
72 | * Creates non-inverted ECC code from line parity | ||
73 | */ | ||
74 | static void nand_trans_result(u_char reg2, u_char reg3, | ||
75 | u_char *ecc_code) | ||
76 | { | ||
77 | u_char a, b, i, tmp1, tmp2; | ||
78 | |||
79 | /* Initialize variables */ | ||
80 | a = b = 0x80; | ||
81 | tmp1 = tmp2 = 0; | ||
82 | |||
83 | /* Calculate first ECC byte */ | ||
84 | for (i = 0; i < 4; i++) { | ||
85 | if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ | ||
86 | tmp1 |= b; | ||
87 | b >>= 1; | ||
88 | if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ | ||
89 | tmp1 |= b; | ||
90 | b >>= 1; | ||
91 | a >>= 1; | ||
92 | } | ||
93 | |||
94 | /* Calculate second ECC byte */ | ||
95 | b = 0x80; | ||
96 | for (i = 0; i < 4; i++) { | ||
97 | if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ | ||
98 | tmp2 |= b; | ||
99 | b >>= 1; | ||
100 | if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ | ||
101 | tmp2 |= b; | ||
102 | b >>= 1; | ||
103 | a >>= 1; | ||
104 | } | ||
105 | |||
106 | /* Store two of the ECC bytes */ | ||
107 | ecc_code[0] = tmp1; | ||
108 | ecc_code[1] = tmp2; | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block | ||
113 | * @mtd: MTD block structure | ||
114 | * @dat: raw data | ||
115 | * @ecc_code: buffer for ECC | ||
116 | */ | ||
117 | int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) | ||
118 | { | ||
119 | u_char idx, reg1, reg2, reg3; | ||
120 | int j; | ||
121 | |||
122 | /* Initialize variables */ | ||
123 | reg1 = reg2 = reg3 = 0; | ||
124 | ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; | ||
125 | |||
126 | /* Build up column parity */ | ||
127 | for(j = 0; j < 256; j++) { | ||
128 | |||
129 | /* Get CP0 - CP5 from table */ | ||
130 | idx = nand_ecc_precalc_table[dat[j]]; | ||
131 | reg1 ^= (idx & 0x3f); | ||
132 | |||
133 | /* All bit XOR = 1 ? */ | ||
134 | if (idx & 0x40) { | ||
135 | reg3 ^= (u_char) j; | ||
136 | reg2 ^= ~((u_char) j); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | /* Create non-inverted ECC code from line parity */ | ||
141 | nand_trans_result(reg2, reg3, ecc_code); | ||
142 | |||
143 | /* Calculate final ECC code */ | ||
144 | ecc_code[0] = ~ecc_code[0]; | ||
145 | ecc_code[1] = ~ecc_code[1]; | ||
146 | ecc_code[2] = ((~reg1) << 2) | 0x03; | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * nand_correct_data - [NAND Interface] Detect and correct bit error(s) | ||
152 | * @mtd: MTD block structure | ||
153 | * @dat: raw data read from the chip | ||
154 | * @read_ecc: ECC from the chip | ||
155 | * @calc_ecc: the ECC calculated from raw data | ||
156 | * | ||
157 | * Detect and correct a 1 bit error for 256 byte block | ||
158 | */ | ||
159 | int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) | ||
160 | { | ||
161 | u_char a, b, c, d1, d2, d3, add, bit, i; | ||
162 | |||
163 | /* Do error detection */ | ||
164 | d1 = calc_ecc[0] ^ read_ecc[0]; | ||
165 | d2 = calc_ecc[1] ^ read_ecc[1]; | ||
166 | d3 = calc_ecc[2] ^ read_ecc[2]; | ||
167 | |||
168 | if ((d1 | d2 | d3) == 0) { | ||
169 | /* No errors */ | ||
170 | return 0; | ||
171 | } | ||
172 | else { | ||
173 | a = (d1 ^ (d1 >> 1)) & 0x55; | ||
174 | b = (d2 ^ (d2 >> 1)) & 0x55; | ||
175 | c = (d3 ^ (d3 >> 1)) & 0x54; | ||
176 | |||
177 | /* Found and will correct single bit error in the data */ | ||
178 | if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { | ||
179 | c = 0x80; | ||
180 | add = 0; | ||
181 | a = 0x80; | ||
182 | for (i=0; i<4; i++) { | ||
183 | if (d1 & c) | ||
184 | add |= a; | ||
185 | c >>= 2; | ||
186 | a >>= 1; | ||
187 | } | ||
188 | c = 0x80; | ||
189 | for (i=0; i<4; i++) { | ||
190 | if (d2 & c) | ||
191 | add |= a; | ||
192 | c >>= 2; | ||
193 | a >>= 1; | ||
194 | } | ||
195 | bit = 0; | ||
196 | b = 0x04; | ||
197 | c = 0x80; | ||
198 | for (i=0; i<3; i++) { | ||
199 | if (d3 & c) | ||
200 | bit |= b; | ||
201 | c >>= 2; | ||
202 | b >>= 1; | ||
203 | } | ||
204 | b = 0x01; | ||
205 | a = dat[add]; | ||
206 | a ^= (b << bit); | ||
207 | dat[add] = a; | ||
208 | return 1; | ||
209 | } | ||
210 | else { | ||
211 | i = 0; | ||
212 | while (d1) { | ||
213 | if (d1 & 0x01) | ||
214 | ++i; | ||
215 | d1 >>= 1; | ||
216 | } | ||
217 | while (d2) { | ||
218 | if (d2 & 0x01) | ||
219 | ++i; | ||
220 | d2 >>= 1; | ||
221 | } | ||
222 | while (d3) { | ||
223 | if (d3 & 0x01) | ||
224 | ++i; | ||
225 | d3 >>= 1; | ||
226 | } | ||
227 | if (i == 1) { | ||
228 | /* ECC Code Error Correction */ | ||
229 | read_ecc[0] = calc_ecc[0]; | ||
230 | read_ecc[1] = calc_ecc[1]; | ||
231 | read_ecc[2] = calc_ecc[2]; | ||
232 | return 2; | ||
233 | } | ||
234 | else { | ||
235 | /* Uncorrectable Error */ | ||
236 | return -1; | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /* Should never happen */ | ||
242 | return -1; | ||
243 | } | ||
244 | |||
245 | EXPORT_SYMBOL(nand_calculate_ecc); | ||
246 | EXPORT_SYMBOL(nand_correct_data); | ||
247 | |||
248 | MODULE_LICENSE("GPL"); | ||
249 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>"); | ||
250 | MODULE_DESCRIPTION("Generic NAND ECC support"); | ||
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c new file mode 100644 index 000000000000..2d8c4321275b --- /dev/null +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nandids.c | ||
3 | * | ||
4 | * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) | ||
5 | * | ||
6 | * $Id: nand_ids.c,v 1.10 2004/05/26 13:40:12 gleixner Exp $ | ||
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 | */ | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/mtd/nand.h> | ||
15 | /* | ||
16 | * Chip ID list | ||
17 | * | ||
18 | * Name. ID code, pagesize, chipsize in MegaByte, eraseblock size, | ||
19 | * options | ||
20 | * | ||
21 | * Pagesize; 0, 256, 512 | ||
22 | * 0 get this information from the extended chip ID | ||
23 | + 256 256 Byte page size | ||
24 | * 512 512 Byte page size | ||
25 | */ | ||
26 | struct nand_flash_dev nand_flash_ids[] = { | ||
27 | {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, | ||
28 | {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, | ||
29 | {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, | ||
30 | {"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0}, | ||
31 | {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0}, | ||
32 | {"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0}, | ||
33 | {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0}, | ||
34 | {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0}, | ||
35 | {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0}, | ||
36 | {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0}, | ||
37 | |||
38 | {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0}, | ||
39 | {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, | ||
40 | {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, | ||
41 | {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, | ||
42 | |||
43 | {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, | ||
44 | {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, | ||
45 | {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16}, | ||
46 | {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16}, | ||
47 | |||
48 | {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0}, | ||
49 | {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0}, | ||
50 | {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16}, | ||
51 | {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16}, | ||
52 | |||
53 | {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0}, | ||
54 | {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0}, | ||
55 | {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16}, | ||
56 | {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16}, | ||
57 | |||
58 | {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0}, | ||
59 | {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0}, | ||
60 | {"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16}, | ||
61 | {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16}, | ||
62 | |||
63 | {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0}, | ||
64 | |||
65 | {"NAND 512MiB 3,3V 8-bit", 0xDC, 512, 512, 0x4000, 0}, | ||
66 | |||
67 | /* These are the new chips with large page size. The pagesize | ||
68 | * and the erasesize is determined from the extended id bytes | ||
69 | */ | ||
70 | /* 1 Gigabit */ | ||
71 | {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
72 | {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
73 | {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
74 | {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
75 | |||
76 | /* 2 Gigabit */ | ||
77 | {"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
78 | {"NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
79 | {"NAND 256MiB 1,8V 16-bit", 0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
80 | {"NAND 256MiB 3,3V 16-bit", 0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
81 | |||
82 | /* 4 Gigabit */ | ||
83 | {"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
84 | {"NAND 512MiB 3,3V 8-bit", 0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
85 | {"NAND 512MiB 1,8V 16-bit", 0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
86 | {"NAND 512MiB 3,3V 16-bit", 0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
87 | |||
88 | /* 8 Gigabit */ | ||
89 | {"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
90 | {"NAND 1GiB 3,3V 8-bit", 0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
91 | {"NAND 1GiB 1,8V 16-bit", 0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
92 | {"NAND 1GiB 3,3V 16-bit", 0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
93 | |||
94 | /* 16 Gigabit */ | ||
95 | {"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
96 | {"NAND 2GiB 3,3V 8-bit", 0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR}, | ||
97 | {"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
98 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR}, | ||
99 | |||
100 | /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout ! | ||
101 | * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes | ||
102 | * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 | ||
103 | * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go | ||
104 | * There are more speed improvements for reads and writes possible, but not implemented now | ||
105 | */ | ||
106 | {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY}, | ||
107 | |||
108 | {NULL,} | ||
109 | }; | ||
110 | |||
111 | /* | ||
112 | * Manufacturer ID list | ||
113 | */ | ||
114 | struct nand_manufacturers nand_manuf_ids[] = { | ||
115 | {NAND_MFR_TOSHIBA, "Toshiba"}, | ||
116 | {NAND_MFR_SAMSUNG, "Samsung"}, | ||
117 | {NAND_MFR_FUJITSU, "Fujitsu"}, | ||
118 | {NAND_MFR_NATIONAL, "National"}, | ||
119 | {NAND_MFR_RENESAS, "Renesas"}, | ||
120 | {NAND_MFR_STMICRO, "ST Micro"}, | ||
121 | {0x0, "Unknown"} | ||
122 | }; | ||
123 | |||
124 | EXPORT_SYMBOL (nand_manuf_ids); | ||
125 | EXPORT_SYMBOL (nand_flash_ids); | ||
126 | |||
127 | MODULE_LICENSE ("GPL"); | ||
128 | MODULE_AUTHOR ("Thomas Gleixner <tglx@linutronix.de>"); | ||
129 | MODULE_DESCRIPTION ("Nand device & manufacturer ID's"); | ||
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c new file mode 100644 index 000000000000..13feefd7d8ca --- /dev/null +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -0,0 +1,1613 @@ | |||
1 | /* | ||
2 | * NAND flash simulator. | ||
3 | * | ||
4 | * Author: Artem B. Bityuckiy <dedekind@oktetlabs.ru>, <dedekind@infradead.org> | ||
5 | * | ||
6 | * Copyright (C) 2004 Nokia Corporation | ||
7 | * | ||
8 | * Note: NS means "NAND Simulator". | ||
9 | * Note: Input means input TO flash chip, output means output FROM chip. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2, or (at your option) any later | ||
14 | * version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, but | ||
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | ||
19 | * Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA | ||
24 | * | ||
25 | * $Id: nandsim.c,v 1.7 2004/12/06 11:53:06 dedekind Exp $ | ||
26 | */ | ||
27 | |||
28 | #include <linux/config.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/moduleparam.h> | ||
33 | #include <linux/vmalloc.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/string.h> | ||
37 | #include <linux/mtd/mtd.h> | ||
38 | #include <linux/mtd/nand.h> | ||
39 | #include <linux/mtd/partitions.h> | ||
40 | #include <linux/delay.h> | ||
41 | #ifdef CONFIG_NS_ABS_POS | ||
42 | #include <asm/io.h> | ||
43 | #endif | ||
44 | |||
45 | |||
46 | /* Default simulator parameters values */ | ||
47 | #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \ | ||
48 | !defined(CONFIG_NANDSIM_SECOND_ID_BYTE) || \ | ||
49 | !defined(CONFIG_NANDSIM_THIRD_ID_BYTE) || \ | ||
50 | !defined(CONFIG_NANDSIM_FOURTH_ID_BYTE) | ||
51 | #define CONFIG_NANDSIM_FIRST_ID_BYTE 0x98 | ||
52 | #define CONFIG_NANDSIM_SECOND_ID_BYTE 0x39 | ||
53 | #define CONFIG_NANDSIM_THIRD_ID_BYTE 0xFF /* No byte */ | ||
54 | #define CONFIG_NANDSIM_FOURTH_ID_BYTE 0xFF /* No byte */ | ||
55 | #endif | ||
56 | |||
57 | #ifndef CONFIG_NANDSIM_ACCESS_DELAY | ||
58 | #define CONFIG_NANDSIM_ACCESS_DELAY 25 | ||
59 | #endif | ||
60 | #ifndef CONFIG_NANDSIM_PROGRAMM_DELAY | ||
61 | #define CONFIG_NANDSIM_PROGRAMM_DELAY 200 | ||
62 | #endif | ||
63 | #ifndef CONFIG_NANDSIM_ERASE_DELAY | ||
64 | #define CONFIG_NANDSIM_ERASE_DELAY 2 | ||
65 | #endif | ||
66 | #ifndef CONFIG_NANDSIM_OUTPUT_CYCLE | ||
67 | #define CONFIG_NANDSIM_OUTPUT_CYCLE 40 | ||
68 | #endif | ||
69 | #ifndef CONFIG_NANDSIM_INPUT_CYCLE | ||
70 | #define CONFIG_NANDSIM_INPUT_CYCLE 50 | ||
71 | #endif | ||
72 | #ifndef CONFIG_NANDSIM_BUS_WIDTH | ||
73 | #define CONFIG_NANDSIM_BUS_WIDTH 8 | ||
74 | #endif | ||
75 | #ifndef CONFIG_NANDSIM_DO_DELAYS | ||
76 | #define CONFIG_NANDSIM_DO_DELAYS 0 | ||
77 | #endif | ||
78 | #ifndef CONFIG_NANDSIM_LOG | ||
79 | #define CONFIG_NANDSIM_LOG 0 | ||
80 | #endif | ||
81 | #ifndef CONFIG_NANDSIM_DBG | ||
82 | #define CONFIG_NANDSIM_DBG 0 | ||
83 | #endif | ||
84 | |||
85 | static uint first_id_byte = CONFIG_NANDSIM_FIRST_ID_BYTE; | ||
86 | static uint second_id_byte = CONFIG_NANDSIM_SECOND_ID_BYTE; | ||
87 | static uint third_id_byte = CONFIG_NANDSIM_THIRD_ID_BYTE; | ||
88 | static uint fourth_id_byte = CONFIG_NANDSIM_FOURTH_ID_BYTE; | ||
89 | static uint access_delay = CONFIG_NANDSIM_ACCESS_DELAY; | ||
90 | static uint programm_delay = CONFIG_NANDSIM_PROGRAMM_DELAY; | ||
91 | static uint erase_delay = CONFIG_NANDSIM_ERASE_DELAY; | ||
92 | static uint output_cycle = CONFIG_NANDSIM_OUTPUT_CYCLE; | ||
93 | static uint input_cycle = CONFIG_NANDSIM_INPUT_CYCLE; | ||
94 | static uint bus_width = CONFIG_NANDSIM_BUS_WIDTH; | ||
95 | static uint do_delays = CONFIG_NANDSIM_DO_DELAYS; | ||
96 | static uint log = CONFIG_NANDSIM_LOG; | ||
97 | static uint dbg = CONFIG_NANDSIM_DBG; | ||
98 | |||
99 | module_param(first_id_byte, uint, 0400); | ||
100 | module_param(second_id_byte, uint, 0400); | ||
101 | module_param(third_id_byte, uint, 0400); | ||
102 | module_param(fourth_id_byte, uint, 0400); | ||
103 | module_param(access_delay, uint, 0400); | ||
104 | module_param(programm_delay, uint, 0400); | ||
105 | module_param(erase_delay, uint, 0400); | ||
106 | module_param(output_cycle, uint, 0400); | ||
107 | module_param(input_cycle, uint, 0400); | ||
108 | module_param(bus_width, uint, 0400); | ||
109 | module_param(do_delays, uint, 0400); | ||
110 | module_param(log, uint, 0400); | ||
111 | module_param(dbg, uint, 0400); | ||
112 | |||
113 | MODULE_PARM_DESC(first_id_byte, "The fist byte returned by NAND Flash 'read ID' command (manufaturer ID)"); | ||
114 | MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); | ||
115 | MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command"); | ||
116 | MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command"); | ||
117 | MODULE_PARM_DESC(access_delay, "Initial page access delay (microiseconds)"); | ||
118 | MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds"); | ||
119 | MODULE_PARM_DESC(erase_delay, "Sector erase delay (milliseconds)"); | ||
120 | MODULE_PARM_DESC(output_cycle, "Word output (from flash) time (nanodeconds)"); | ||
121 | MODULE_PARM_DESC(input_cycle, "Word input (to flash) time (nanodeconds)"); | ||
122 | MODULE_PARM_DESC(bus_width, "Chip's bus width (8- or 16-bit)"); | ||
123 | MODULE_PARM_DESC(do_delays, "Simulate NAND delays using busy-waits if not zero"); | ||
124 | MODULE_PARM_DESC(log, "Perform logging if not zero"); | ||
125 | MODULE_PARM_DESC(dbg, "Output debug information if not zero"); | ||
126 | |||
127 | /* The largest possible page size */ | ||
128 | #define NS_LARGEST_PAGE_SIZE 2048 | ||
129 | |||
130 | /* The prefix for simulator output */ | ||
131 | #define NS_OUTPUT_PREFIX "[nandsim]" | ||
132 | |||
133 | /* Simulator's output macros (logging, debugging, warning, error) */ | ||
134 | #define NS_LOG(args...) \ | ||
135 | do { if (log) printk(KERN_DEBUG NS_OUTPUT_PREFIX " log: " args); } while(0) | ||
136 | #define NS_DBG(args...) \ | ||
137 | do { if (dbg) printk(KERN_DEBUG NS_OUTPUT_PREFIX " debug: " args); } while(0) | ||
138 | #define NS_WARN(args...) \ | ||
139 | do { printk(KERN_WARNING NS_OUTPUT_PREFIX " warnig: " args); } while(0) | ||
140 | #define NS_ERR(args...) \ | ||
141 | do { printk(KERN_ERR NS_OUTPUT_PREFIX " errorr: " args); } while(0) | ||
142 | |||
143 | /* Busy-wait delay macros (microseconds, milliseconds) */ | ||
144 | #define NS_UDELAY(us) \ | ||
145 | do { if (do_delays) udelay(us); } while(0) | ||
146 | #define NS_MDELAY(us) \ | ||
147 | do { if (do_delays) mdelay(us); } while(0) | ||
148 | |||
149 | /* Is the nandsim structure initialized ? */ | ||
150 | #define NS_IS_INITIALIZED(ns) ((ns)->geom.totsz != 0) | ||
151 | |||
152 | /* Good operation completion status */ | ||
153 | #define NS_STATUS_OK(ns) (NAND_STATUS_READY | (NAND_STATUS_WP * ((ns)->lines.wp == 0))) | ||
154 | |||
155 | /* Operation failed completion status */ | ||
156 | #define NS_STATUS_FAILED(ns) (NAND_STATUS_FAIL | NS_STATUS_OK(ns)) | ||
157 | |||
158 | /* Calculate the page offset in flash RAM image by (row, column) address */ | ||
159 | #define NS_RAW_OFFSET(ns) \ | ||
160 | (((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column) | ||
161 | |||
162 | /* Calculate the OOB offset in flash RAM image by (row, column) address */ | ||
163 | #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) | ||
164 | |||
165 | /* After a command is input, the simulator goes to one of the following states */ | ||
166 | #define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */ | ||
167 | #define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */ | ||
168 | #define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */ | ||
169 | #define STATE_CMD_PAGEPROG 0x00000004 /* start page programm */ | ||
170 | #define STATE_CMD_READOOB 0x00000005 /* read OOB area */ | ||
171 | #define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */ | ||
172 | #define STATE_CMD_STATUS 0x00000007 /* read status */ | ||
173 | #define STATE_CMD_STATUS_M 0x00000008 /* read multi-plane status (isn't implemented) */ | ||
174 | #define STATE_CMD_SEQIN 0x00000009 /* sequential data imput */ | ||
175 | #define STATE_CMD_READID 0x0000000A /* read ID */ | ||
176 | #define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */ | ||
177 | #define STATE_CMD_RESET 0x0000000C /* reset */ | ||
178 | #define STATE_CMD_MASK 0x0000000F /* command states mask */ | ||
179 | |||
180 | /* After an addres is input, the simulator goes to one of these states */ | ||
181 | #define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */ | ||
182 | #define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */ | ||
183 | #define STATE_ADDR_ZERO 0x00000030 /* one byte zero address was accepted */ | ||
184 | #define STATE_ADDR_MASK 0x00000030 /* address states mask */ | ||
185 | |||
186 | /* Durind data input/output the simulator is in these states */ | ||
187 | #define STATE_DATAIN 0x00000100 /* waiting for data input */ | ||
188 | #define STATE_DATAIN_MASK 0x00000100 /* data input states mask */ | ||
189 | |||
190 | #define STATE_DATAOUT 0x00001000 /* waiting for page data output */ | ||
191 | #define STATE_DATAOUT_ID 0x00002000 /* waiting for ID bytes output */ | ||
192 | #define STATE_DATAOUT_STATUS 0x00003000 /* waiting for status output */ | ||
193 | #define STATE_DATAOUT_STATUS_M 0x00004000 /* waiting for multi-plane status output */ | ||
194 | #define STATE_DATAOUT_MASK 0x00007000 /* data output states mask */ | ||
195 | |||
196 | /* Previous operation is done, ready to accept new requests */ | ||
197 | #define STATE_READY 0x00000000 | ||
198 | |||
199 | /* This state is used to mark that the next state isn't known yet */ | ||
200 | #define STATE_UNKNOWN 0x10000000 | ||
201 | |||
202 | /* Simulator's actions bit masks */ | ||
203 | #define ACTION_CPY 0x00100000 /* copy page/OOB to the internal buffer */ | ||
204 | #define ACTION_PRGPAGE 0x00200000 /* programm the internal buffer to flash */ | ||
205 | #define ACTION_SECERASE 0x00300000 /* erase sector */ | ||
206 | #define ACTION_ZEROOFF 0x00400000 /* don't add any offset to address */ | ||
207 | #define ACTION_HALFOFF 0x00500000 /* add to address half of page */ | ||
208 | #define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */ | ||
209 | #define ACTION_MASK 0x00700000 /* action mask */ | ||
210 | |||
211 | #define NS_OPER_NUM 12 /* Number of operations supported by the simulator */ | ||
212 | #define NS_OPER_STATES 6 /* Maximum number of states in operation */ | ||
213 | |||
214 | #define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */ | ||
215 | #define OPT_PAGE256 0x00000001 /* 256-byte page chips */ | ||
216 | #define OPT_PAGE512 0x00000002 /* 512-byte page chips */ | ||
217 | #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */ | ||
218 | #define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */ | ||
219 | #define OPT_AUTOINCR 0x00000020 /* page number auto inctimentation is possible */ | ||
220 | #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */ | ||
221 | #define OPT_LARGEPAGE (OPT_PAGE2048) /* 2048-byte page chips */ | ||
222 | #define OPT_SMALLPAGE (OPT_PAGE256 | OPT_PAGE512) /* 256 and 512-byte page chips */ | ||
223 | |||
224 | /* Remove action bits ftom state */ | ||
225 | #define NS_STATE(x) ((x) & ~ACTION_MASK) | ||
226 | |||
227 | /* | ||
228 | * Maximum previous states which need to be saved. Currently saving is | ||
229 | * only needed for page programm operation with preceeded read command | ||
230 | * (which is only valid for 512-byte pages). | ||
231 | */ | ||
232 | #define NS_MAX_PREVSTATES 1 | ||
233 | |||
234 | /* | ||
235 | * The structure which describes all the internal simulator data. | ||
236 | */ | ||
237 | struct nandsim { | ||
238 | struct mtd_partition part; | ||
239 | |||
240 | uint busw; /* flash chip bus width (8 or 16) */ | ||
241 | u_char ids[4]; /* chip's ID bytes */ | ||
242 | uint32_t options; /* chip's characteristic bits */ | ||
243 | uint32_t state; /* current chip state */ | ||
244 | uint32_t nxstate; /* next expected state */ | ||
245 | |||
246 | uint32_t *op; /* current operation, NULL operations isn't known yet */ | ||
247 | uint32_t pstates[NS_MAX_PREVSTATES]; /* previous states */ | ||
248 | uint16_t npstates; /* number of previous states saved */ | ||
249 | uint16_t stateidx; /* current state index */ | ||
250 | |||
251 | /* The simulated NAND flash image */ | ||
252 | union flash_media { | ||
253 | u_char *byte; | ||
254 | uint16_t *word; | ||
255 | } mem; | ||
256 | |||
257 | /* Internal buffer of page + OOB size bytes */ | ||
258 | union internal_buffer { | ||
259 | u_char *byte; /* for byte access */ | ||
260 | uint16_t *word; /* for 16-bit word access */ | ||
261 | } buf; | ||
262 | |||
263 | /* NAND flash "geometry" */ | ||
264 | struct nandsin_geometry { | ||
265 | uint32_t totsz; /* total flash size, bytes */ | ||
266 | uint32_t secsz; /* flash sector (erase block) size, bytes */ | ||
267 | uint pgsz; /* NAND flash page size, bytes */ | ||
268 | uint oobsz; /* page OOB area size, bytes */ | ||
269 | uint32_t totszoob; /* total flash size including OOB, bytes */ | ||
270 | uint pgszoob; /* page size including OOB , bytes*/ | ||
271 | uint secszoob; /* sector size including OOB, bytes */ | ||
272 | uint pgnum; /* total number of pages */ | ||
273 | uint pgsec; /* number of pages per sector */ | ||
274 | uint secshift; /* bits number in sector size */ | ||
275 | uint pgshift; /* bits number in page size */ | ||
276 | uint oobshift; /* bits number in OOB size */ | ||
277 | uint pgaddrbytes; /* bytes per page address */ | ||
278 | uint secaddrbytes; /* bytes per sector address */ | ||
279 | uint idbytes; /* the number ID bytes that this chip outputs */ | ||
280 | } geom; | ||
281 | |||
282 | /* NAND flash internal registers */ | ||
283 | struct nandsim_regs { | ||
284 | unsigned command; /* the command register */ | ||
285 | u_char status; /* the status register */ | ||
286 | uint row; /* the page number */ | ||
287 | uint column; /* the offset within page */ | ||
288 | uint count; /* internal counter */ | ||
289 | uint num; /* number of bytes which must be processed */ | ||
290 | uint off; /* fixed page offset */ | ||
291 | } regs; | ||
292 | |||
293 | /* NAND flash lines state */ | ||
294 | struct ns_lines_status { | ||
295 | int ce; /* chip Enable */ | ||
296 | int cle; /* command Latch Enable */ | ||
297 | int ale; /* address Latch Enable */ | ||
298 | int wp; /* write Protect */ | ||
299 | } lines; | ||
300 | }; | ||
301 | |||
302 | /* | ||
303 | * Operations array. To perform any operation the simulator must pass | ||
304 | * through the correspondent states chain. | ||
305 | */ | ||
306 | static struct nandsim_operations { | ||
307 | uint32_t reqopts; /* options which are required to perform the operation */ | ||
308 | uint32_t states[NS_OPER_STATES]; /* operation's states */ | ||
309 | } ops[NS_OPER_NUM] = { | ||
310 | /* Read page + OOB from the beginning */ | ||
311 | {OPT_SMALLPAGE, {STATE_CMD_READ0 | ACTION_ZEROOFF, STATE_ADDR_PAGE | ACTION_CPY, | ||
312 | STATE_DATAOUT, STATE_READY}}, | ||
313 | /* Read page + OOB from the second half */ | ||
314 | {OPT_PAGE512_8BIT, {STATE_CMD_READ1 | ACTION_HALFOFF, STATE_ADDR_PAGE | ACTION_CPY, | ||
315 | STATE_DATAOUT, STATE_READY}}, | ||
316 | /* Read OOB */ | ||
317 | {OPT_SMALLPAGE, {STATE_CMD_READOOB | ACTION_OOBOFF, STATE_ADDR_PAGE | ACTION_CPY, | ||
318 | STATE_DATAOUT, STATE_READY}}, | ||
319 | /* Programm page starting from the beginning */ | ||
320 | {OPT_ANY, {STATE_CMD_SEQIN, STATE_ADDR_PAGE, STATE_DATAIN, | ||
321 | STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}}, | ||
322 | /* Programm page starting from the beginning */ | ||
323 | {OPT_SMALLPAGE, {STATE_CMD_READ0, STATE_CMD_SEQIN | ACTION_ZEROOFF, STATE_ADDR_PAGE, | ||
324 | STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}}, | ||
325 | /* Programm page starting from the second half */ | ||
326 | {OPT_PAGE512, {STATE_CMD_READ1, STATE_CMD_SEQIN | ACTION_HALFOFF, STATE_ADDR_PAGE, | ||
327 | STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}}, | ||
328 | /* Programm OOB */ | ||
329 | {OPT_SMALLPAGE, {STATE_CMD_READOOB, STATE_CMD_SEQIN | ACTION_OOBOFF, STATE_ADDR_PAGE, | ||
330 | STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}}, | ||
331 | /* Erase sector */ | ||
332 | {OPT_ANY, {STATE_CMD_ERASE1, STATE_ADDR_SEC, STATE_CMD_ERASE2 | ACTION_SECERASE, STATE_READY}}, | ||
333 | /* Read status */ | ||
334 | {OPT_ANY, {STATE_CMD_STATUS, STATE_DATAOUT_STATUS, STATE_READY}}, | ||
335 | /* Read multi-plane status */ | ||
336 | {OPT_SMARTMEDIA, {STATE_CMD_STATUS_M, STATE_DATAOUT_STATUS_M, STATE_READY}}, | ||
337 | /* Read ID */ | ||
338 | {OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}}, | ||
339 | /* Large page devices read page */ | ||
340 | {OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY, | ||
341 | STATE_DATAOUT, STATE_READY}} | ||
342 | }; | ||
343 | |||
344 | /* MTD structure for NAND controller */ | ||
345 | static struct mtd_info *nsmtd; | ||
346 | |||
347 | static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE]; | ||
348 | |||
349 | /* | ||
350 | * Initialize the nandsim structure. | ||
351 | * | ||
352 | * RETURNS: 0 if success, -ERRNO if failure. | ||
353 | */ | ||
354 | static int | ||
355 | init_nandsim(struct mtd_info *mtd) | ||
356 | { | ||
357 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | ||
358 | struct nandsim *ns = (struct nandsim *)(chip->priv); | ||
359 | int i; | ||
360 | |||
361 | if (NS_IS_INITIALIZED(ns)) { | ||
362 | NS_ERR("init_nandsim: nandsim is already initialized\n"); | ||
363 | return -EIO; | ||
364 | } | ||
365 | |||
366 | /* Force mtd to not do delays */ | ||
367 | chip->chip_delay = 0; | ||
368 | |||
369 | /* Initialize the NAND flash parameters */ | ||
370 | ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8; | ||
371 | ns->geom.totsz = mtd->size; | ||
372 | ns->geom.pgsz = mtd->oobblock; | ||
373 | ns->geom.oobsz = mtd->oobsize; | ||
374 | ns->geom.secsz = mtd->erasesize; | ||
375 | ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; | ||
376 | ns->geom.pgnum = ns->geom.totsz / ns->geom.pgsz; | ||
377 | ns->geom.totszoob = ns->geom.totsz + ns->geom.pgnum * ns->geom.oobsz; | ||
378 | ns->geom.secshift = ffs(ns->geom.secsz) - 1; | ||
379 | ns->geom.pgshift = chip->page_shift; | ||
380 | ns->geom.oobshift = ffs(ns->geom.oobsz) - 1; | ||
381 | ns->geom.pgsec = ns->geom.secsz / ns->geom.pgsz; | ||
382 | ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec; | ||
383 | ns->options = 0; | ||
384 | |||
385 | if (ns->geom.pgsz == 256) { | ||
386 | ns->options |= OPT_PAGE256; | ||
387 | } | ||
388 | else if (ns->geom.pgsz == 512) { | ||
389 | ns->options |= (OPT_PAGE512 | OPT_AUTOINCR); | ||
390 | if (ns->busw == 8) | ||
391 | ns->options |= OPT_PAGE512_8BIT; | ||
392 | } else if (ns->geom.pgsz == 2048) { | ||
393 | ns->options |= OPT_PAGE2048; | ||
394 | } else { | ||
395 | NS_ERR("init_nandsim: unknown page size %u\n", ns->geom.pgsz); | ||
396 | return -EIO; | ||
397 | } | ||
398 | |||
399 | if (ns->options & OPT_SMALLPAGE) { | ||
400 | if (ns->geom.totsz < (64 << 20)) { | ||
401 | ns->geom.pgaddrbytes = 3; | ||
402 | ns->geom.secaddrbytes = 2; | ||
403 | } else { | ||
404 | ns->geom.pgaddrbytes = 4; | ||
405 | ns->geom.secaddrbytes = 3; | ||
406 | } | ||
407 | } else { | ||
408 | if (ns->geom.totsz <= (128 << 20)) { | ||
409 | ns->geom.pgaddrbytes = 5; | ||
410 | ns->geom.secaddrbytes = 2; | ||
411 | } else { | ||
412 | ns->geom.pgaddrbytes = 5; | ||
413 | ns->geom.secaddrbytes = 3; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | /* Detect how many ID bytes the NAND chip outputs */ | ||
418 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | ||
419 | if (second_id_byte != nand_flash_ids[i].id) | ||
420 | continue; | ||
421 | if (!(nand_flash_ids[i].options & NAND_NO_AUTOINCR)) | ||
422 | ns->options |= OPT_AUTOINCR; | ||
423 | } | ||
424 | |||
425 | if (ns->busw == 16) | ||
426 | NS_WARN("16-bit flashes support wasn't tested\n"); | ||
427 | |||
428 | printk("flash size: %u MiB\n", ns->geom.totsz >> 20); | ||
429 | printk("page size: %u bytes\n", ns->geom.pgsz); | ||
430 | printk("OOB area size: %u bytes\n", ns->geom.oobsz); | ||
431 | printk("sector size: %u KiB\n", ns->geom.secsz >> 10); | ||
432 | printk("pages number: %u\n", ns->geom.pgnum); | ||
433 | printk("pages per sector: %u\n", ns->geom.pgsec); | ||
434 | printk("bus width: %u\n", ns->busw); | ||
435 | printk("bits in sector size: %u\n", ns->geom.secshift); | ||
436 | printk("bits in page size: %u\n", ns->geom.pgshift); | ||
437 | printk("bits in OOB size: %u\n", ns->geom.oobshift); | ||
438 | printk("flash size with OOB: %u KiB\n", ns->geom.totszoob >> 10); | ||
439 | printk("page address bytes: %u\n", ns->geom.pgaddrbytes); | ||
440 | printk("sector address bytes: %u\n", ns->geom.secaddrbytes); | ||
441 | printk("options: %#x\n", ns->options); | ||
442 | |||
443 | /* Map / allocate and initialize the flash image */ | ||
444 | #ifdef CONFIG_NS_ABS_POS | ||
445 | ns->mem.byte = ioremap(CONFIG_NS_ABS_POS, ns->geom.totszoob); | ||
446 | if (!ns->mem.byte) { | ||
447 | NS_ERR("init_nandsim: failed to map the NAND flash image at address %p\n", | ||
448 | (void *)CONFIG_NS_ABS_POS); | ||
449 | return -ENOMEM; | ||
450 | } | ||
451 | #else | ||
452 | ns->mem.byte = vmalloc(ns->geom.totszoob); | ||
453 | if (!ns->mem.byte) { | ||
454 | NS_ERR("init_nandsim: unable to allocate %u bytes for flash image\n", | ||
455 | ns->geom.totszoob); | ||
456 | return -ENOMEM; | ||
457 | } | ||
458 | memset(ns->mem.byte, 0xFF, ns->geom.totszoob); | ||
459 | #endif | ||
460 | |||
461 | /* Allocate / initialize the internal buffer */ | ||
462 | ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); | ||
463 | if (!ns->buf.byte) { | ||
464 | NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n", | ||
465 | ns->geom.pgszoob); | ||
466 | goto error; | ||
467 | } | ||
468 | memset(ns->buf.byte, 0xFF, ns->geom.pgszoob); | ||
469 | |||
470 | /* Fill the partition_info structure */ | ||
471 | ns->part.name = "NAND simulator partition"; | ||
472 | ns->part.offset = 0; | ||
473 | ns->part.size = ns->geom.totsz; | ||
474 | |||
475 | return 0; | ||
476 | |||
477 | error: | ||
478 | #ifdef CONFIG_NS_ABS_POS | ||
479 | iounmap(ns->mem.byte); | ||
480 | #else | ||
481 | vfree(ns->mem.byte); | ||
482 | #endif | ||
483 | |||
484 | return -ENOMEM; | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | * Free the nandsim structure. | ||
489 | */ | ||
490 | static void | ||
491 | free_nandsim(struct nandsim *ns) | ||
492 | { | ||
493 | kfree(ns->buf.byte); | ||
494 | |||
495 | #ifdef CONFIG_NS_ABS_POS | ||
496 | iounmap(ns->mem.byte); | ||
497 | #else | ||
498 | vfree(ns->mem.byte); | ||
499 | #endif | ||
500 | |||
501 | return; | ||
502 | } | ||
503 | |||
504 | /* | ||
505 | * Returns the string representation of 'state' state. | ||
506 | */ | ||
507 | static char * | ||
508 | get_state_name(uint32_t state) | ||
509 | { | ||
510 | switch (NS_STATE(state)) { | ||
511 | case STATE_CMD_READ0: | ||
512 | return "STATE_CMD_READ0"; | ||
513 | case STATE_CMD_READ1: | ||
514 | return "STATE_CMD_READ1"; | ||
515 | case STATE_CMD_PAGEPROG: | ||
516 | return "STATE_CMD_PAGEPROG"; | ||
517 | case STATE_CMD_READOOB: | ||
518 | return "STATE_CMD_READOOB"; | ||
519 | case STATE_CMD_READSTART: | ||
520 | return "STATE_CMD_READSTART"; | ||
521 | case STATE_CMD_ERASE1: | ||
522 | return "STATE_CMD_ERASE1"; | ||
523 | case STATE_CMD_STATUS: | ||
524 | return "STATE_CMD_STATUS"; | ||
525 | case STATE_CMD_STATUS_M: | ||
526 | return "STATE_CMD_STATUS_M"; | ||
527 | case STATE_CMD_SEQIN: | ||
528 | return "STATE_CMD_SEQIN"; | ||
529 | case STATE_CMD_READID: | ||
530 | return "STATE_CMD_READID"; | ||
531 | case STATE_CMD_ERASE2: | ||
532 | return "STATE_CMD_ERASE2"; | ||
533 | case STATE_CMD_RESET: | ||
534 | return "STATE_CMD_RESET"; | ||
535 | case STATE_ADDR_PAGE: | ||
536 | return "STATE_ADDR_PAGE"; | ||
537 | case STATE_ADDR_SEC: | ||
538 | return "STATE_ADDR_SEC"; | ||
539 | case STATE_ADDR_ZERO: | ||
540 | return "STATE_ADDR_ZERO"; | ||
541 | case STATE_DATAIN: | ||
542 | return "STATE_DATAIN"; | ||
543 | case STATE_DATAOUT: | ||
544 | return "STATE_DATAOUT"; | ||
545 | case STATE_DATAOUT_ID: | ||
546 | return "STATE_DATAOUT_ID"; | ||
547 | case STATE_DATAOUT_STATUS: | ||
548 | return "STATE_DATAOUT_STATUS"; | ||
549 | case STATE_DATAOUT_STATUS_M: | ||
550 | return "STATE_DATAOUT_STATUS_M"; | ||
551 | case STATE_READY: | ||
552 | return "STATE_READY"; | ||
553 | case STATE_UNKNOWN: | ||
554 | return "STATE_UNKNOWN"; | ||
555 | } | ||
556 | |||
557 | NS_ERR("get_state_name: unknown state, BUG\n"); | ||
558 | return NULL; | ||
559 | } | ||
560 | |||
561 | /* | ||
562 | * Check if command is valid. | ||
563 | * | ||
564 | * RETURNS: 1 if wrong command, 0 if right. | ||
565 | */ | ||
566 | static int | ||
567 | check_command(int cmd) | ||
568 | { | ||
569 | switch (cmd) { | ||
570 | |||
571 | case NAND_CMD_READ0: | ||
572 | case NAND_CMD_READSTART: | ||
573 | case NAND_CMD_PAGEPROG: | ||
574 | case NAND_CMD_READOOB: | ||
575 | case NAND_CMD_ERASE1: | ||
576 | case NAND_CMD_STATUS: | ||
577 | case NAND_CMD_SEQIN: | ||
578 | case NAND_CMD_READID: | ||
579 | case NAND_CMD_ERASE2: | ||
580 | case NAND_CMD_RESET: | ||
581 | case NAND_CMD_READ1: | ||
582 | return 0; | ||
583 | |||
584 | case NAND_CMD_STATUS_MULTI: | ||
585 | default: | ||
586 | return 1; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /* | ||
591 | * Returns state after command is accepted by command number. | ||
592 | */ | ||
593 | static uint32_t | ||
594 | get_state_by_command(unsigned command) | ||
595 | { | ||
596 | switch (command) { | ||
597 | case NAND_CMD_READ0: | ||
598 | return STATE_CMD_READ0; | ||
599 | case NAND_CMD_READ1: | ||
600 | return STATE_CMD_READ1; | ||
601 | case NAND_CMD_PAGEPROG: | ||
602 | return STATE_CMD_PAGEPROG; | ||
603 | case NAND_CMD_READSTART: | ||
604 | return STATE_CMD_READSTART; | ||
605 | case NAND_CMD_READOOB: | ||
606 | return STATE_CMD_READOOB; | ||
607 | case NAND_CMD_ERASE1: | ||
608 | return STATE_CMD_ERASE1; | ||
609 | case NAND_CMD_STATUS: | ||
610 | return STATE_CMD_STATUS; | ||
611 | case NAND_CMD_STATUS_MULTI: | ||
612 | return STATE_CMD_STATUS_M; | ||
613 | case NAND_CMD_SEQIN: | ||
614 | return STATE_CMD_SEQIN; | ||
615 | case NAND_CMD_READID: | ||
616 | return STATE_CMD_READID; | ||
617 | case NAND_CMD_ERASE2: | ||
618 | return STATE_CMD_ERASE2; | ||
619 | case NAND_CMD_RESET: | ||
620 | return STATE_CMD_RESET; | ||
621 | } | ||
622 | |||
623 | NS_ERR("get_state_by_command: unknown command, BUG\n"); | ||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | /* | ||
628 | * Move an address byte to the correspondent internal register. | ||
629 | */ | ||
630 | static inline void | ||
631 | accept_addr_byte(struct nandsim *ns, u_char bt) | ||
632 | { | ||
633 | uint byte = (uint)bt; | ||
634 | |||
635 | if (ns->regs.count < (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ||
636 | ns->regs.column |= (byte << 8 * ns->regs.count); | ||
637 | else { | ||
638 | ns->regs.row |= (byte << 8 * (ns->regs.count - | ||
639 | ns->geom.pgaddrbytes + | ||
640 | ns->geom.secaddrbytes)); | ||
641 | } | ||
642 | |||
643 | return; | ||
644 | } | ||
645 | |||
646 | /* | ||
647 | * Switch to STATE_READY state. | ||
648 | */ | ||
649 | static inline void | ||
650 | switch_to_ready_state(struct nandsim *ns, u_char status) | ||
651 | { | ||
652 | NS_DBG("switch_to_ready_state: switch to %s state\n", get_state_name(STATE_READY)); | ||
653 | |||
654 | ns->state = STATE_READY; | ||
655 | ns->nxstate = STATE_UNKNOWN; | ||
656 | ns->op = NULL; | ||
657 | ns->npstates = 0; | ||
658 | ns->stateidx = 0; | ||
659 | ns->regs.num = 0; | ||
660 | ns->regs.count = 0; | ||
661 | ns->regs.off = 0; | ||
662 | ns->regs.row = 0; | ||
663 | ns->regs.column = 0; | ||
664 | ns->regs.status = status; | ||
665 | } | ||
666 | |||
667 | /* | ||
668 | * If the operation isn't known yet, try to find it in the global array | ||
669 | * of supported operations. | ||
670 | * | ||
671 | * Operation can be unknown because of the following. | ||
672 | * 1. New command was accepted and this is the firs call to find the | ||
673 | * correspondent states chain. In this case ns->npstates = 0; | ||
674 | * 2. There is several operations which begin with the same command(s) | ||
675 | * (for example program from the second half and read from the | ||
676 | * second half operations both begin with the READ1 command). In this | ||
677 | * case the ns->pstates[] array contains previous states. | ||
678 | * | ||
679 | * Thus, the function tries to find operation containing the following | ||
680 | * states (if the 'flag' parameter is 0): | ||
681 | * ns->pstates[0], ... ns->pstates[ns->npstates], ns->state | ||
682 | * | ||
683 | * If (one and only one) matching operation is found, it is accepted ( | ||
684 | * ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is | ||
685 | * zeroed). | ||
686 | * | ||
687 | * If there are several maches, the current state is pushed to the | ||
688 | * ns->pstates. | ||
689 | * | ||
690 | * The operation can be unknown only while commands are input to the chip. | ||
691 | * As soon as address command is accepted, the operation must be known. | ||
692 | * In such situation the function is called with 'flag' != 0, and the | ||
693 | * operation is searched using the following pattern: | ||
694 | * ns->pstates[0], ... ns->pstates[ns->npstates], <address input> | ||
695 | * | ||
696 | * It is supposed that this pattern must either match one operation on | ||
697 | * none. There can't be ambiguity in that case. | ||
698 | * | ||
699 | * If no matches found, the functions does the following: | ||
700 | * 1. if there are saved states present, try to ignore them and search | ||
701 | * again only using the last command. If nothing was found, switch | ||
702 | * to the STATE_READY state. | ||
703 | * 2. if there are no saved states, switch to the STATE_READY state. | ||
704 | * | ||
705 | * RETURNS: -2 - no matched operations found. | ||
706 | * -1 - several matches. | ||
707 | * 0 - operation is found. | ||
708 | */ | ||
709 | static int | ||
710 | find_operation(struct nandsim *ns, uint32_t flag) | ||
711 | { | ||
712 | int opsfound = 0; | ||
713 | int i, j, idx = 0; | ||
714 | |||
715 | for (i = 0; i < NS_OPER_NUM; i++) { | ||
716 | |||
717 | int found = 1; | ||
718 | |||
719 | if (!(ns->options & ops[i].reqopts)) | ||
720 | /* Ignore operations we can't perform */ | ||
721 | continue; | ||
722 | |||
723 | if (flag) { | ||
724 | if (!(ops[i].states[ns->npstates] & STATE_ADDR_MASK)) | ||
725 | continue; | ||
726 | } else { | ||
727 | if (NS_STATE(ns->state) != NS_STATE(ops[i].states[ns->npstates])) | ||
728 | continue; | ||
729 | } | ||
730 | |||
731 | for (j = 0; j < ns->npstates; j++) | ||
732 | if (NS_STATE(ops[i].states[j]) != NS_STATE(ns->pstates[j]) | ||
733 | && (ns->options & ops[idx].reqopts)) { | ||
734 | found = 0; | ||
735 | break; | ||
736 | } | ||
737 | |||
738 | if (found) { | ||
739 | idx = i; | ||
740 | opsfound += 1; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | if (opsfound == 1) { | ||
745 | /* Exact match */ | ||
746 | ns->op = &ops[idx].states[0]; | ||
747 | if (flag) { | ||
748 | /* | ||
749 | * In this case the find_operation function was | ||
750 | * called when address has just began input. But it isn't | ||
751 | * yet fully input and the current state must | ||
752 | * not be one of STATE_ADDR_*, but the STATE_ADDR_* | ||
753 | * state must be the next state (ns->nxstate). | ||
754 | */ | ||
755 | ns->stateidx = ns->npstates - 1; | ||
756 | } else { | ||
757 | ns->stateidx = ns->npstates; | ||
758 | } | ||
759 | ns->npstates = 0; | ||
760 | ns->state = ns->op[ns->stateidx]; | ||
761 | ns->nxstate = ns->op[ns->stateidx + 1]; | ||
762 | NS_DBG("find_operation: operation found, index: %d, state: %s, nxstate %s\n", | ||
763 | idx, get_state_name(ns->state), get_state_name(ns->nxstate)); | ||
764 | return 0; | ||
765 | } | ||
766 | |||
767 | if (opsfound == 0) { | ||
768 | /* Nothing was found. Try to ignore previous commands (if any) and search again */ | ||
769 | if (ns->npstates != 0) { | ||
770 | NS_DBG("find_operation: no operation found, try again with state %s\n", | ||
771 | get_state_name(ns->state)); | ||
772 | ns->npstates = 0; | ||
773 | return find_operation(ns, 0); | ||
774 | |||
775 | } | ||
776 | NS_DBG("find_operation: no operations found\n"); | ||
777 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
778 | return -2; | ||
779 | } | ||
780 | |||
781 | if (flag) { | ||
782 | /* This shouldn't happen */ | ||
783 | NS_DBG("find_operation: BUG, operation must be known if address is input\n"); | ||
784 | return -2; | ||
785 | } | ||
786 | |||
787 | NS_DBG("find_operation: there is still ambiguity\n"); | ||
788 | |||
789 | ns->pstates[ns->npstates++] = ns->state; | ||
790 | |||
791 | return -1; | ||
792 | } | ||
793 | |||
794 | /* | ||
795 | * If state has any action bit, perform this action. | ||
796 | * | ||
797 | * RETURNS: 0 if success, -1 if error. | ||
798 | */ | ||
799 | static int | ||
800 | do_state_action(struct nandsim *ns, uint32_t action) | ||
801 | { | ||
802 | int i, num; | ||
803 | int busdiv = ns->busw == 8 ? 1 : 2; | ||
804 | |||
805 | action &= ACTION_MASK; | ||
806 | |||
807 | /* Check that page address input is correct */ | ||
808 | if (action != ACTION_SECERASE && ns->regs.row >= ns->geom.pgnum) { | ||
809 | NS_WARN("do_state_action: wrong page number (%#x)\n", ns->regs.row); | ||
810 | return -1; | ||
811 | } | ||
812 | |||
813 | switch (action) { | ||
814 | |||
815 | case ACTION_CPY: | ||
816 | /* | ||
817 | * Copy page data to the internal buffer. | ||
818 | */ | ||
819 | |||
820 | /* Column shouldn't be very large */ | ||
821 | if (ns->regs.column >= (ns->geom.pgszoob - ns->regs.off)) { | ||
822 | NS_ERR("do_state_action: column number is too large\n"); | ||
823 | break; | ||
824 | } | ||
825 | num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; | ||
826 | memcpy(ns->buf.byte, ns->mem.byte + NS_RAW_OFFSET(ns) + ns->regs.off, num); | ||
827 | |||
828 | NS_DBG("do_state_action: (ACTION_CPY:) copy %d bytes to int buf, raw offset %d\n", | ||
829 | num, NS_RAW_OFFSET(ns) + ns->regs.off); | ||
830 | |||
831 | if (ns->regs.off == 0) | ||
832 | NS_LOG("read page %d\n", ns->regs.row); | ||
833 | else if (ns->regs.off < ns->geom.pgsz) | ||
834 | NS_LOG("read page %d (second half)\n", ns->regs.row); | ||
835 | else | ||
836 | NS_LOG("read OOB of page %d\n", ns->regs.row); | ||
837 | |||
838 | NS_UDELAY(access_delay); | ||
839 | NS_UDELAY(input_cycle * ns->geom.pgsz / 1000 / busdiv); | ||
840 | |||
841 | break; | ||
842 | |||
843 | case ACTION_SECERASE: | ||
844 | /* | ||
845 | * Erase sector. | ||
846 | */ | ||
847 | |||
848 | if (ns->lines.wp) { | ||
849 | NS_ERR("do_state_action: device is write-protected, ignore sector erase\n"); | ||
850 | return -1; | ||
851 | } | ||
852 | |||
853 | if (ns->regs.row >= ns->geom.pgnum - ns->geom.pgsec | ||
854 | || (ns->regs.row & ~(ns->geom.secsz - 1))) { | ||
855 | NS_ERR("do_state_action: wrong sector address (%#x)\n", ns->regs.row); | ||
856 | return -1; | ||
857 | } | ||
858 | |||
859 | ns->regs.row = (ns->regs.row << | ||
860 | 8 * (ns->geom.pgaddrbytes - ns->geom.secaddrbytes)) | ns->regs.column; | ||
861 | ns->regs.column = 0; | ||
862 | |||
863 | NS_DBG("do_state_action: erase sector at address %#x, off = %d\n", | ||
864 | ns->regs.row, NS_RAW_OFFSET(ns)); | ||
865 | NS_LOG("erase sector %d\n", ns->regs.row >> (ns->geom.secshift - ns->geom.pgshift)); | ||
866 | |||
867 | memset(ns->mem.byte + NS_RAW_OFFSET(ns), 0xFF, ns->geom.secszoob); | ||
868 | |||
869 | NS_MDELAY(erase_delay); | ||
870 | |||
871 | break; | ||
872 | |||
873 | case ACTION_PRGPAGE: | ||
874 | /* | ||
875 | * Programm page - move internal buffer data to the page. | ||
876 | */ | ||
877 | |||
878 | if (ns->lines.wp) { | ||
879 | NS_WARN("do_state_action: device is write-protected, programm\n"); | ||
880 | return -1; | ||
881 | } | ||
882 | |||
883 | num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; | ||
884 | if (num != ns->regs.count) { | ||
885 | NS_ERR("do_state_action: too few bytes were input (%d instead of %d)\n", | ||
886 | ns->regs.count, num); | ||
887 | return -1; | ||
888 | } | ||
889 | |||
890 | for (i = 0; i < num; i++) | ||
891 | ns->mem.byte[NS_RAW_OFFSET(ns) + ns->regs.off + i] &= ns->buf.byte[i]; | ||
892 | |||
893 | NS_DBG("do_state_action: copy %d bytes from int buf to (%#x, %#x), raw off = %d\n", | ||
894 | num, ns->regs.row, ns->regs.column, NS_RAW_OFFSET(ns) + ns->regs.off); | ||
895 | NS_LOG("programm page %d\n", ns->regs.row); | ||
896 | |||
897 | NS_UDELAY(programm_delay); | ||
898 | NS_UDELAY(output_cycle * ns->geom.pgsz / 1000 / busdiv); | ||
899 | |||
900 | break; | ||
901 | |||
902 | case ACTION_ZEROOFF: | ||
903 | NS_DBG("do_state_action: set internal offset to 0\n"); | ||
904 | ns->regs.off = 0; | ||
905 | break; | ||
906 | |||
907 | case ACTION_HALFOFF: | ||
908 | if (!(ns->options & OPT_PAGE512_8BIT)) { | ||
909 | NS_ERR("do_state_action: BUG! can't skip half of page for non-512" | ||
910 | "byte page size 8x chips\n"); | ||
911 | return -1; | ||
912 | } | ||
913 | NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz/2); | ||
914 | ns->regs.off = ns->geom.pgsz/2; | ||
915 | break; | ||
916 | |||
917 | case ACTION_OOBOFF: | ||
918 | NS_DBG("do_state_action: set internal offset to %d\n", ns->geom.pgsz); | ||
919 | ns->regs.off = ns->geom.pgsz; | ||
920 | break; | ||
921 | |||
922 | default: | ||
923 | NS_DBG("do_state_action: BUG! unknown action\n"); | ||
924 | } | ||
925 | |||
926 | return 0; | ||
927 | } | ||
928 | |||
929 | /* | ||
930 | * Switch simulator's state. | ||
931 | */ | ||
932 | static void | ||
933 | switch_state(struct nandsim *ns) | ||
934 | { | ||
935 | if (ns->op) { | ||
936 | /* | ||
937 | * The current operation have already been identified. | ||
938 | * Just follow the states chain. | ||
939 | */ | ||
940 | |||
941 | ns->stateidx += 1; | ||
942 | ns->state = ns->nxstate; | ||
943 | ns->nxstate = ns->op[ns->stateidx + 1]; | ||
944 | |||
945 | NS_DBG("switch_state: operation is known, switch to the next state, " | ||
946 | "state: %s, nxstate: %s\n", | ||
947 | get_state_name(ns->state), get_state_name(ns->nxstate)); | ||
948 | |||
949 | /* See, whether we need to do some action */ | ||
950 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { | ||
951 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
952 | return; | ||
953 | } | ||
954 | |||
955 | } else { | ||
956 | /* | ||
957 | * We don't yet know which operation we perform. | ||
958 | * Try to identify it. | ||
959 | */ | ||
960 | |||
961 | /* | ||
962 | * The only event causing the switch_state function to | ||
963 | * be called with yet unknown operation is new command. | ||
964 | */ | ||
965 | ns->state = get_state_by_command(ns->regs.command); | ||
966 | |||
967 | NS_DBG("switch_state: operation is unknown, try to find it\n"); | ||
968 | |||
969 | if (find_operation(ns, 0) != 0) | ||
970 | return; | ||
971 | |||
972 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { | ||
973 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
974 | return; | ||
975 | } | ||
976 | } | ||
977 | |||
978 | /* For 16x devices column means the page offset in words */ | ||
979 | if ((ns->nxstate & STATE_ADDR_MASK) && ns->busw == 16) { | ||
980 | NS_DBG("switch_state: double the column number for 16x device\n"); | ||
981 | ns->regs.column <<= 1; | ||
982 | } | ||
983 | |||
984 | if (NS_STATE(ns->nxstate) == STATE_READY) { | ||
985 | /* | ||
986 | * The current state is the last. Return to STATE_READY | ||
987 | */ | ||
988 | |||
989 | u_char status = NS_STATUS_OK(ns); | ||
990 | |||
991 | /* In case of data states, see if all bytes were input/output */ | ||
992 | if ((ns->state & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) | ||
993 | && ns->regs.count != ns->regs.num) { | ||
994 | NS_WARN("switch_state: not all bytes were processed, %d left\n", | ||
995 | ns->regs.num - ns->regs.count); | ||
996 | status = NS_STATUS_FAILED(ns); | ||
997 | } | ||
998 | |||
999 | NS_DBG("switch_state: operation complete, switch to STATE_READY state\n"); | ||
1000 | |||
1001 | switch_to_ready_state(ns, status); | ||
1002 | |||
1003 | return; | ||
1004 | } else if (ns->nxstate & (STATE_DATAIN_MASK | STATE_DATAOUT_MASK)) { | ||
1005 | /* | ||
1006 | * If the next state is data input/output, switch to it now | ||
1007 | */ | ||
1008 | |||
1009 | ns->state = ns->nxstate; | ||
1010 | ns->nxstate = ns->op[++ns->stateidx + 1]; | ||
1011 | ns->regs.num = ns->regs.count = 0; | ||
1012 | |||
1013 | NS_DBG("switch_state: the next state is data I/O, switch, " | ||
1014 | "state: %s, nxstate: %s\n", | ||
1015 | get_state_name(ns->state), get_state_name(ns->nxstate)); | ||
1016 | |||
1017 | /* | ||
1018 | * Set the internal register to the count of bytes which | ||
1019 | * are expected to be input or output | ||
1020 | */ | ||
1021 | switch (NS_STATE(ns->state)) { | ||
1022 | case STATE_DATAIN: | ||
1023 | case STATE_DATAOUT: | ||
1024 | ns->regs.num = ns->geom.pgszoob - ns->regs.off - ns->regs.column; | ||
1025 | break; | ||
1026 | |||
1027 | case STATE_DATAOUT_ID: | ||
1028 | ns->regs.num = ns->geom.idbytes; | ||
1029 | break; | ||
1030 | |||
1031 | case STATE_DATAOUT_STATUS: | ||
1032 | case STATE_DATAOUT_STATUS_M: | ||
1033 | ns->regs.count = ns->regs.num = 0; | ||
1034 | break; | ||
1035 | |||
1036 | default: | ||
1037 | NS_ERR("switch_state: BUG! unknown data state\n"); | ||
1038 | } | ||
1039 | |||
1040 | } else if (ns->nxstate & STATE_ADDR_MASK) { | ||
1041 | /* | ||
1042 | * If the next state is address input, set the internal | ||
1043 | * register to the number of expected address bytes | ||
1044 | */ | ||
1045 | |||
1046 | ns->regs.count = 0; | ||
1047 | |||
1048 | switch (NS_STATE(ns->nxstate)) { | ||
1049 | case STATE_ADDR_PAGE: | ||
1050 | ns->regs.num = ns->geom.pgaddrbytes; | ||
1051 | |||
1052 | break; | ||
1053 | case STATE_ADDR_SEC: | ||
1054 | ns->regs.num = ns->geom.secaddrbytes; | ||
1055 | break; | ||
1056 | |||
1057 | case STATE_ADDR_ZERO: | ||
1058 | ns->regs.num = 1; | ||
1059 | break; | ||
1060 | |||
1061 | default: | ||
1062 | NS_ERR("switch_state: BUG! unknown address state\n"); | ||
1063 | } | ||
1064 | } else { | ||
1065 | /* | ||
1066 | * Just reset internal counters. | ||
1067 | */ | ||
1068 | |||
1069 | ns->regs.num = 0; | ||
1070 | ns->regs.count = 0; | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | static void | ||
1075 | ns_hwcontrol(struct mtd_info *mtd, int cmd) | ||
1076 | { | ||
1077 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1078 | |||
1079 | switch (cmd) { | ||
1080 | |||
1081 | /* set CLE line high */ | ||
1082 | case NAND_CTL_SETCLE: | ||
1083 | NS_DBG("ns_hwcontrol: start command latch cycles\n"); | ||
1084 | ns->lines.cle = 1; | ||
1085 | break; | ||
1086 | |||
1087 | /* set CLE line low */ | ||
1088 | case NAND_CTL_CLRCLE: | ||
1089 | NS_DBG("ns_hwcontrol: stop command latch cycles\n"); | ||
1090 | ns->lines.cle = 0; | ||
1091 | break; | ||
1092 | |||
1093 | /* set ALE line high */ | ||
1094 | case NAND_CTL_SETALE: | ||
1095 | NS_DBG("ns_hwcontrol: start address latch cycles\n"); | ||
1096 | ns->lines.ale = 1; | ||
1097 | break; | ||
1098 | |||
1099 | /* set ALE line low */ | ||
1100 | case NAND_CTL_CLRALE: | ||
1101 | NS_DBG("ns_hwcontrol: stop address latch cycles\n"); | ||
1102 | ns->lines.ale = 0; | ||
1103 | break; | ||
1104 | |||
1105 | /* set WP line high */ | ||
1106 | case NAND_CTL_SETWP: | ||
1107 | NS_DBG("ns_hwcontrol: enable write protection\n"); | ||
1108 | ns->lines.wp = 1; | ||
1109 | break; | ||
1110 | |||
1111 | /* set WP line low */ | ||
1112 | case NAND_CTL_CLRWP: | ||
1113 | NS_DBG("ns_hwcontrol: disable write protection\n"); | ||
1114 | ns->lines.wp = 0; | ||
1115 | break; | ||
1116 | |||
1117 | /* set CE line low */ | ||
1118 | case NAND_CTL_SETNCE: | ||
1119 | NS_DBG("ns_hwcontrol: enable chip\n"); | ||
1120 | ns->lines.ce = 1; | ||
1121 | break; | ||
1122 | |||
1123 | /* set CE line high */ | ||
1124 | case NAND_CTL_CLRNCE: | ||
1125 | NS_DBG("ns_hwcontrol: disable chip\n"); | ||
1126 | ns->lines.ce = 0; | ||
1127 | break; | ||
1128 | |||
1129 | default: | ||
1130 | NS_ERR("hwcontrol: unknown command\n"); | ||
1131 | } | ||
1132 | |||
1133 | return; | ||
1134 | } | ||
1135 | |||
1136 | static u_char | ||
1137 | ns_nand_read_byte(struct mtd_info *mtd) | ||
1138 | { | ||
1139 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1140 | u_char outb = 0x00; | ||
1141 | |||
1142 | /* Sanity and correctness checks */ | ||
1143 | if (!ns->lines.ce) { | ||
1144 | NS_ERR("read_byte: chip is disabled, return %#x\n", (uint)outb); | ||
1145 | return outb; | ||
1146 | } | ||
1147 | if (ns->lines.ale || ns->lines.cle) { | ||
1148 | NS_ERR("read_byte: ALE or CLE pin is high, return %#x\n", (uint)outb); | ||
1149 | return outb; | ||
1150 | } | ||
1151 | if (!(ns->state & STATE_DATAOUT_MASK)) { | ||
1152 | NS_WARN("read_byte: unexpected data output cycle, state is %s " | ||
1153 | "return %#x\n", get_state_name(ns->state), (uint)outb); | ||
1154 | return outb; | ||
1155 | } | ||
1156 | |||
1157 | /* Status register may be read as many times as it is wanted */ | ||
1158 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS) { | ||
1159 | NS_DBG("read_byte: return %#x status\n", ns->regs.status); | ||
1160 | return ns->regs.status; | ||
1161 | } | ||
1162 | |||
1163 | /* Check if there is any data in the internal buffer which may be read */ | ||
1164 | if (ns->regs.count == ns->regs.num) { | ||
1165 | NS_WARN("read_byte: no more data to output, return %#x\n", (uint)outb); | ||
1166 | return outb; | ||
1167 | } | ||
1168 | |||
1169 | switch (NS_STATE(ns->state)) { | ||
1170 | case STATE_DATAOUT: | ||
1171 | if (ns->busw == 8) { | ||
1172 | outb = ns->buf.byte[ns->regs.count]; | ||
1173 | ns->regs.count += 1; | ||
1174 | } else { | ||
1175 | outb = (u_char)cpu_to_le16(ns->buf.word[ns->regs.count >> 1]); | ||
1176 | ns->regs.count += 2; | ||
1177 | } | ||
1178 | break; | ||
1179 | case STATE_DATAOUT_ID: | ||
1180 | NS_DBG("read_byte: read ID byte %d, total = %d\n", ns->regs.count, ns->regs.num); | ||
1181 | outb = ns->ids[ns->regs.count]; | ||
1182 | ns->regs.count += 1; | ||
1183 | break; | ||
1184 | default: | ||
1185 | BUG(); | ||
1186 | } | ||
1187 | |||
1188 | if (ns->regs.count == ns->regs.num) { | ||
1189 | NS_DBG("read_byte: all bytes were read\n"); | ||
1190 | |||
1191 | /* | ||
1192 | * The OPT_AUTOINCR allows to read next conseqitive pages without | ||
1193 | * new read operation cycle. | ||
1194 | */ | ||
1195 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { | ||
1196 | ns->regs.count = 0; | ||
1197 | if (ns->regs.row + 1 < ns->geom.pgnum) | ||
1198 | ns->regs.row += 1; | ||
1199 | NS_DBG("read_byte: switch to the next page (%#x)\n", ns->regs.row); | ||
1200 | do_state_action(ns, ACTION_CPY); | ||
1201 | } | ||
1202 | else if (NS_STATE(ns->nxstate) == STATE_READY) | ||
1203 | switch_state(ns); | ||
1204 | |||
1205 | } | ||
1206 | |||
1207 | return outb; | ||
1208 | } | ||
1209 | |||
1210 | static void | ||
1211 | ns_nand_write_byte(struct mtd_info *mtd, u_char byte) | ||
1212 | { | ||
1213 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1214 | |||
1215 | /* Sanity and correctness checks */ | ||
1216 | if (!ns->lines.ce) { | ||
1217 | NS_ERR("write_byte: chip is disabled, ignore write\n"); | ||
1218 | return; | ||
1219 | } | ||
1220 | if (ns->lines.ale && ns->lines.cle) { | ||
1221 | NS_ERR("write_byte: ALE and CLE pins are high simultaneously, ignore write\n"); | ||
1222 | return; | ||
1223 | } | ||
1224 | |||
1225 | if (ns->lines.cle == 1) { | ||
1226 | /* | ||
1227 | * The byte written is a command. | ||
1228 | */ | ||
1229 | |||
1230 | if (byte == NAND_CMD_RESET) { | ||
1231 | NS_LOG("reset chip\n"); | ||
1232 | switch_to_ready_state(ns, NS_STATUS_OK(ns)); | ||
1233 | return; | ||
1234 | } | ||
1235 | |||
1236 | /* | ||
1237 | * Chip might still be in STATE_DATAOUT | ||
1238 | * (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or | ||
1239 | * STATE_DATAOUT_STATUS_M state. If so, switch state. | ||
1240 | */ | ||
1241 | if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS | ||
1242 | || NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M | ||
1243 | || ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT)) | ||
1244 | switch_state(ns); | ||
1245 | |||
1246 | /* Check if chip is expecting command */ | ||
1247 | if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) { | ||
1248 | /* | ||
1249 | * We are in situation when something else (not command) | ||
1250 | * was expected but command was input. In this case ignore | ||
1251 | * previous command(s)/state(s) and accept the last one. | ||
1252 | */ | ||
1253 | NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, " | ||
1254 | "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate)); | ||
1255 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1256 | } | ||
1257 | |||
1258 | /* Check that the command byte is correct */ | ||
1259 | if (check_command(byte)) { | ||
1260 | NS_ERR("write_byte: unknown command %#x\n", (uint)byte); | ||
1261 | return; | ||
1262 | } | ||
1263 | |||
1264 | NS_DBG("command byte corresponding to %s state accepted\n", | ||
1265 | get_state_name(get_state_by_command(byte))); | ||
1266 | ns->regs.command = byte; | ||
1267 | switch_state(ns); | ||
1268 | |||
1269 | } else if (ns->lines.ale == 1) { | ||
1270 | /* | ||
1271 | * The byte written is an address. | ||
1272 | */ | ||
1273 | |||
1274 | if (NS_STATE(ns->nxstate) == STATE_UNKNOWN) { | ||
1275 | |||
1276 | NS_DBG("write_byte: operation isn't known yet, identify it\n"); | ||
1277 | |||
1278 | if (find_operation(ns, 1) < 0) | ||
1279 | return; | ||
1280 | |||
1281 | if ((ns->state & ACTION_MASK) && do_state_action(ns, ns->state) < 0) { | ||
1282 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1283 | return; | ||
1284 | } | ||
1285 | |||
1286 | ns->regs.count = 0; | ||
1287 | switch (NS_STATE(ns->nxstate)) { | ||
1288 | case STATE_ADDR_PAGE: | ||
1289 | ns->regs.num = ns->geom.pgaddrbytes; | ||
1290 | break; | ||
1291 | case STATE_ADDR_SEC: | ||
1292 | ns->regs.num = ns->geom.secaddrbytes; | ||
1293 | break; | ||
1294 | case STATE_ADDR_ZERO: | ||
1295 | ns->regs.num = 1; | ||
1296 | break; | ||
1297 | default: | ||
1298 | BUG(); | ||
1299 | } | ||
1300 | } | ||
1301 | |||
1302 | /* Check that chip is expecting address */ | ||
1303 | if (!(ns->nxstate & STATE_ADDR_MASK)) { | ||
1304 | NS_ERR("write_byte: address (%#x) isn't expected, expected state is %s, " | ||
1305 | "switch to STATE_READY\n", (uint)byte, get_state_name(ns->nxstate)); | ||
1306 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1307 | return; | ||
1308 | } | ||
1309 | |||
1310 | /* Check if this is expected byte */ | ||
1311 | if (ns->regs.count == ns->regs.num) { | ||
1312 | NS_ERR("write_byte: no more address bytes expected\n"); | ||
1313 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1314 | return; | ||
1315 | } | ||
1316 | |||
1317 | accept_addr_byte(ns, byte); | ||
1318 | |||
1319 | ns->regs.count += 1; | ||
1320 | |||
1321 | NS_DBG("write_byte: address byte %#x was accepted (%d bytes input, %d expected)\n", | ||
1322 | (uint)byte, ns->regs.count, ns->regs.num); | ||
1323 | |||
1324 | if (ns->regs.count == ns->regs.num) { | ||
1325 | NS_DBG("address (%#x, %#x) is accepted\n", ns->regs.row, ns->regs.column); | ||
1326 | switch_state(ns); | ||
1327 | } | ||
1328 | |||
1329 | } else { | ||
1330 | /* | ||
1331 | * The byte written is an input data. | ||
1332 | */ | ||
1333 | |||
1334 | /* Check that chip is expecting data input */ | ||
1335 | if (!(ns->state & STATE_DATAIN_MASK)) { | ||
1336 | NS_ERR("write_byte: data input (%#x) isn't expected, state is %s, " | ||
1337 | "switch to %s\n", (uint)byte, | ||
1338 | get_state_name(ns->state), get_state_name(STATE_READY)); | ||
1339 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1340 | return; | ||
1341 | } | ||
1342 | |||
1343 | /* Check if this is expected byte */ | ||
1344 | if (ns->regs.count == ns->regs.num) { | ||
1345 | NS_WARN("write_byte: %u input bytes has already been accepted, ignore write\n", | ||
1346 | ns->regs.num); | ||
1347 | return; | ||
1348 | } | ||
1349 | |||
1350 | if (ns->busw == 8) { | ||
1351 | ns->buf.byte[ns->regs.count] = byte; | ||
1352 | ns->regs.count += 1; | ||
1353 | } else { | ||
1354 | ns->buf.word[ns->regs.count >> 1] = cpu_to_le16((uint16_t)byte); | ||
1355 | ns->regs.count += 2; | ||
1356 | } | ||
1357 | } | ||
1358 | |||
1359 | return; | ||
1360 | } | ||
1361 | |||
1362 | static int | ||
1363 | ns_device_ready(struct mtd_info *mtd) | ||
1364 | { | ||
1365 | NS_DBG("device_ready\n"); | ||
1366 | return 1; | ||
1367 | } | ||
1368 | |||
1369 | static uint16_t | ||
1370 | ns_nand_read_word(struct mtd_info *mtd) | ||
1371 | { | ||
1372 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | ||
1373 | |||
1374 | NS_DBG("read_word\n"); | ||
1375 | |||
1376 | return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8); | ||
1377 | } | ||
1378 | |||
1379 | static void | ||
1380 | ns_nand_write_word(struct mtd_info *mtd, uint16_t word) | ||
1381 | { | ||
1382 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | ||
1383 | |||
1384 | NS_DBG("write_word\n"); | ||
1385 | |||
1386 | chip->write_byte(mtd, word & 0xFF); | ||
1387 | chip->write_byte(mtd, word >> 8); | ||
1388 | } | ||
1389 | |||
1390 | static void | ||
1391 | ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
1392 | { | ||
1393 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1394 | |||
1395 | /* Check that chip is expecting data input */ | ||
1396 | if (!(ns->state & STATE_DATAIN_MASK)) { | ||
1397 | NS_ERR("write_buf: data input isn't expected, state is %s, " | ||
1398 | "switch to STATE_READY\n", get_state_name(ns->state)); | ||
1399 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1400 | return; | ||
1401 | } | ||
1402 | |||
1403 | /* Check if these are expected bytes */ | ||
1404 | if (ns->regs.count + len > ns->regs.num) { | ||
1405 | NS_ERR("write_buf: too many input bytes\n"); | ||
1406 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1407 | return; | ||
1408 | } | ||
1409 | |||
1410 | memcpy(ns->buf.byte + ns->regs.count, buf, len); | ||
1411 | ns->regs.count += len; | ||
1412 | |||
1413 | if (ns->regs.count == ns->regs.num) { | ||
1414 | NS_DBG("write_buf: %d bytes were written\n", ns->regs.count); | ||
1415 | } | ||
1416 | } | ||
1417 | |||
1418 | static void | ||
1419 | ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | ||
1420 | { | ||
1421 | struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv; | ||
1422 | |||
1423 | /* Sanity and correctness checks */ | ||
1424 | if (!ns->lines.ce) { | ||
1425 | NS_ERR("read_buf: chip is disabled\n"); | ||
1426 | return; | ||
1427 | } | ||
1428 | if (ns->lines.ale || ns->lines.cle) { | ||
1429 | NS_ERR("read_buf: ALE or CLE pin is high\n"); | ||
1430 | return; | ||
1431 | } | ||
1432 | if (!(ns->state & STATE_DATAOUT_MASK)) { | ||
1433 | NS_WARN("read_buf: unexpected data output cycle, current state is %s\n", | ||
1434 | get_state_name(ns->state)); | ||
1435 | return; | ||
1436 | } | ||
1437 | |||
1438 | if (NS_STATE(ns->state) != STATE_DATAOUT) { | ||
1439 | int i; | ||
1440 | |||
1441 | for (i = 0; i < len; i++) | ||
1442 | buf[i] = ((struct nand_chip *)mtd->priv)->read_byte(mtd); | ||
1443 | |||
1444 | return; | ||
1445 | } | ||
1446 | |||
1447 | /* Check if these are expected bytes */ | ||
1448 | if (ns->regs.count + len > ns->regs.num) { | ||
1449 | NS_ERR("read_buf: too many bytes to read\n"); | ||
1450 | switch_to_ready_state(ns, NS_STATUS_FAILED(ns)); | ||
1451 | return; | ||
1452 | } | ||
1453 | |||
1454 | memcpy(buf, ns->buf.byte + ns->regs.count, len); | ||
1455 | ns->regs.count += len; | ||
1456 | |||
1457 | if (ns->regs.count == ns->regs.num) { | ||
1458 | if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { | ||
1459 | ns->regs.count = 0; | ||
1460 | if (ns->regs.row + 1 < ns->geom.pgnum) | ||
1461 | ns->regs.row += 1; | ||
1462 | NS_DBG("read_buf: switch to the next page (%#x)\n", ns->regs.row); | ||
1463 | do_state_action(ns, ACTION_CPY); | ||
1464 | } | ||
1465 | else if (NS_STATE(ns->nxstate) == STATE_READY) | ||
1466 | switch_state(ns); | ||
1467 | } | ||
1468 | |||
1469 | return; | ||
1470 | } | ||
1471 | |||
1472 | static int | ||
1473 | ns_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
1474 | { | ||
1475 | ns_nand_read_buf(mtd, (u_char *)&ns_verify_buf[0], len); | ||
1476 | |||
1477 | if (!memcmp(buf, &ns_verify_buf[0], len)) { | ||
1478 | NS_DBG("verify_buf: the buffer is OK\n"); | ||
1479 | return 0; | ||
1480 | } else { | ||
1481 | NS_DBG("verify_buf: the buffer is wrong\n"); | ||
1482 | return -EFAULT; | ||
1483 | } | ||
1484 | } | ||
1485 | |||
1486 | /* | ||
1487 | * Having only NAND chip IDs we call nand_scan which detects NAND flash | ||
1488 | * parameters and then calls scan_bbt in order to scan/find/build the | ||
1489 | * NAND flash bad block table. But since at that moment the NAND flash | ||
1490 | * image isn't allocated in the simulator, errors arise. To avoid this | ||
1491 | * we redefine the scan_bbt callback and initialize the nandsim structure | ||
1492 | * before the flash media scanning. | ||
1493 | */ | ||
1494 | int ns_scan_bbt(struct mtd_info *mtd) | ||
1495 | { | ||
1496 | struct nand_chip *chip = (struct nand_chip *)mtd->priv; | ||
1497 | struct nandsim *ns = (struct nandsim *)(chip->priv); | ||
1498 | int retval; | ||
1499 | |||
1500 | if (!NS_IS_INITIALIZED(ns)) | ||
1501 | if ((retval = init_nandsim(mtd)) != 0) { | ||
1502 | NS_ERR("scan_bbt: can't initialize the nandsim structure\n"); | ||
1503 | return retval; | ||
1504 | } | ||
1505 | if ((retval = nand_default_bbt(mtd)) != 0) { | ||
1506 | free_nandsim(ns); | ||
1507 | return retval; | ||
1508 | } | ||
1509 | |||
1510 | return 0; | ||
1511 | } | ||
1512 | |||
1513 | /* | ||
1514 | * Module initialization function | ||
1515 | */ | ||
1516 | int __init ns_init_module(void) | ||
1517 | { | ||
1518 | struct nand_chip *chip; | ||
1519 | struct nandsim *nand; | ||
1520 | int retval = -ENOMEM; | ||
1521 | |||
1522 | if (bus_width != 8 && bus_width != 16) { | ||
1523 | NS_ERR("wrong bus width (%d), use only 8 or 16\n", bus_width); | ||
1524 | return -EINVAL; | ||
1525 | } | ||
1526 | |||
1527 | /* Allocate and initialize mtd_info, nand_chip and nandsim structures */ | ||
1528 | nsmtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip) | ||
1529 | + sizeof(struct nandsim), GFP_KERNEL); | ||
1530 | if (!nsmtd) { | ||
1531 | NS_ERR("unable to allocate core structures.\n"); | ||
1532 | return -ENOMEM; | ||
1533 | } | ||
1534 | memset(nsmtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip) + | ||
1535 | sizeof(struct nandsim)); | ||
1536 | chip = (struct nand_chip *)(nsmtd + 1); | ||
1537 | nsmtd->priv = (void *)chip; | ||
1538 | nand = (struct nandsim *)(chip + 1); | ||
1539 | chip->priv = (void *)nand; | ||
1540 | |||
1541 | /* | ||
1542 | * Register simulator's callbacks. | ||
1543 | */ | ||
1544 | chip->hwcontrol = ns_hwcontrol; | ||
1545 | chip->read_byte = ns_nand_read_byte; | ||
1546 | chip->dev_ready = ns_device_ready; | ||
1547 | chip->scan_bbt = ns_scan_bbt; | ||
1548 | chip->write_byte = ns_nand_write_byte; | ||
1549 | chip->write_buf = ns_nand_write_buf; | ||
1550 | chip->read_buf = ns_nand_read_buf; | ||
1551 | chip->verify_buf = ns_nand_verify_buf; | ||
1552 | chip->write_word = ns_nand_write_word; | ||
1553 | chip->read_word = ns_nand_read_word; | ||
1554 | chip->eccmode = NAND_ECC_SOFT; | ||
1555 | |||
1556 | /* | ||
1557 | * Perform minimum nandsim structure initialization to handle | ||
1558 | * the initial ID read command correctly | ||
1559 | */ | ||
1560 | if (third_id_byte != 0xFF || fourth_id_byte != 0xFF) | ||
1561 | nand->geom.idbytes = 4; | ||
1562 | else | ||
1563 | nand->geom.idbytes = 2; | ||
1564 | nand->regs.status = NS_STATUS_OK(nand); | ||
1565 | nand->nxstate = STATE_UNKNOWN; | ||
1566 | nand->options |= OPT_PAGE256; /* temporary value */ | ||
1567 | nand->ids[0] = first_id_byte; | ||
1568 | nand->ids[1] = second_id_byte; | ||
1569 | nand->ids[2] = third_id_byte; | ||
1570 | nand->ids[3] = fourth_id_byte; | ||
1571 | if (bus_width == 16) { | ||
1572 | nand->busw = 16; | ||
1573 | chip->options |= NAND_BUSWIDTH_16; | ||
1574 | } | ||
1575 | |||
1576 | if ((retval = nand_scan(nsmtd, 1)) != 0) { | ||
1577 | NS_ERR("can't register NAND Simulator\n"); | ||
1578 | if (retval > 0) | ||
1579 | retval = -ENXIO; | ||
1580 | goto error; | ||
1581 | } | ||
1582 | |||
1583 | /* Register NAND as one big partition */ | ||
1584 | add_mtd_partitions(nsmtd, &nand->part, 1); | ||
1585 | |||
1586 | return 0; | ||
1587 | |||
1588 | error: | ||
1589 | kfree(nsmtd); | ||
1590 | |||
1591 | return retval; | ||
1592 | } | ||
1593 | |||
1594 | module_init(ns_init_module); | ||
1595 | |||
1596 | /* | ||
1597 | * Module clean-up function | ||
1598 | */ | ||
1599 | static void __exit ns_cleanup_module(void) | ||
1600 | { | ||
1601 | struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv); | ||
1602 | |||
1603 | free_nandsim(ns); /* Free nandsim private resources */ | ||
1604 | nand_release(nsmtd); /* Unregisterd drived */ | ||
1605 | kfree(nsmtd); /* Free other structures */ | ||
1606 | } | ||
1607 | |||
1608 | module_exit(ns_cleanup_module); | ||
1609 | |||
1610 | MODULE_LICENSE ("GPL"); | ||
1611 | MODULE_AUTHOR ("Artem B. Bityuckiy"); | ||
1612 | MODULE_DESCRIPTION ("The NAND flash simulator"); | ||
1613 | |||
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c new file mode 100644 index 000000000000..e510a83d7bdb --- /dev/null +++ b/drivers/mtd/nand/ppchameleonevb.c | |||
@@ -0,0 +1,420 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/ppchameleonevb.c | ||
3 | * | ||
4 | * Copyright (C) 2003 DAVE Srl (info@wawnet.biz) | ||
5 | * | ||
6 | * Derived from drivers/mtd/nand/edb7312.c | ||
7 | * | ||
8 | * | ||
9 | * $Id: ppchameleonevb.c,v 1.6 2004/11/05 16:07:16 kalev Exp $ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * Overview: | ||
16 | * This is a device driver for the NAND flash devices found on the | ||
17 | * PPChameleon/PPChameleonEVB system. | ||
18 | * PPChameleon options (autodetected): | ||
19 | * - BA model: no NAND | ||
20 | * - ME model: 32MB (Samsung K9F5608U0B) | ||
21 | * - HI model: 128MB (Samsung K9F1G08UOM) | ||
22 | * PPChameleonEVB options: | ||
23 | * - 32MB (Samsung K9F5608U0B) | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/mtd/mtd.h> | ||
30 | #include <linux/mtd/nand.h> | ||
31 | #include <linux/mtd/partitions.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <platforms/PPChameleonEVB.h> | ||
34 | |||
35 | #undef USE_READY_BUSY_PIN | ||
36 | #define USE_READY_BUSY_PIN | ||
37 | /* see datasheets (tR) */ | ||
38 | #define NAND_BIG_DELAY_US 25 | ||
39 | #define NAND_SMALL_DELAY_US 10 | ||
40 | |||
41 | /* handy sizes */ | ||
42 | #define SZ_4M 0x00400000 | ||
43 | #define NAND_SMALL_SIZE 0x02000000 | ||
44 | #define NAND_MTD_NAME "ppchameleon-nand" | ||
45 | #define NAND_EVB_MTD_NAME "ppchameleonevb-nand" | ||
46 | |||
47 | /* GPIO pins used to drive NAND chip mounted on processor module */ | ||
48 | #define NAND_nCE_GPIO_PIN (0x80000000 >> 1) | ||
49 | #define NAND_CLE_GPIO_PIN (0x80000000 >> 2) | ||
50 | #define NAND_ALE_GPIO_PIN (0x80000000 >> 3) | ||
51 | #define NAND_RB_GPIO_PIN (0x80000000 >> 4) | ||
52 | /* GPIO pins used to drive NAND chip mounted on EVB */ | ||
53 | #define NAND_EVB_nCE_GPIO_PIN (0x80000000 >> 14) | ||
54 | #define NAND_EVB_CLE_GPIO_PIN (0x80000000 >> 15) | ||
55 | #define NAND_EVB_ALE_GPIO_PIN (0x80000000 >> 16) | ||
56 | #define NAND_EVB_RB_GPIO_PIN (0x80000000 >> 31) | ||
57 | |||
58 | /* | ||
59 | * MTD structure for PPChameleonEVB board | ||
60 | */ | ||
61 | static struct mtd_info *ppchameleon_mtd = NULL; | ||
62 | static struct mtd_info *ppchameleonevb_mtd = NULL; | ||
63 | |||
64 | /* | ||
65 | * Module stuff | ||
66 | */ | ||
67 | static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR; | ||
68 | static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR; | ||
69 | |||
70 | #ifdef MODULE | ||
71 | module_param(ppchameleon_fio_pbase, ulong, 0); | ||
72 | module_param(ppchameleonevb_fio_pbase, ulong, 0); | ||
73 | #else | ||
74 | __setup("ppchameleon_fio_pbase=",ppchameleon_fio_pbase); | ||
75 | __setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase); | ||
76 | #endif | ||
77 | |||
78 | #ifdef CONFIG_MTD_PARTITIONS | ||
79 | /* | ||
80 | * Define static partitions for flash devices | ||
81 | */ | ||
82 | static struct mtd_partition partition_info_hi[] = { | ||
83 | { name: "PPChameleon HI Nand Flash", | ||
84 | offset: 0, | ||
85 | size: 128*1024*1024 } | ||
86 | }; | ||
87 | |||
88 | static struct mtd_partition partition_info_me[] = { | ||
89 | { name: "PPChameleon ME Nand Flash", | ||
90 | offset: 0, | ||
91 | size: 32*1024*1024 } | ||
92 | }; | ||
93 | |||
94 | static struct mtd_partition partition_info_evb[] = { | ||
95 | { name: "PPChameleonEVB Nand Flash", | ||
96 | offset: 0, | ||
97 | size: 32*1024*1024 } | ||
98 | }; | ||
99 | |||
100 | #define NUM_PARTITIONS 1 | ||
101 | |||
102 | extern int parse_cmdline_partitions(struct mtd_info *master, | ||
103 | struct mtd_partition **pparts, | ||
104 | const char *mtd_id); | ||
105 | #endif | ||
106 | |||
107 | |||
108 | /* | ||
109 | * hardware specific access to control-lines | ||
110 | */ | ||
111 | static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd) | ||
112 | { | ||
113 | switch(cmd) { | ||
114 | |||
115 | case NAND_CTL_SETCLE: | ||
116 | MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR); | ||
117 | break; | ||
118 | case NAND_CTL_CLRCLE: | ||
119 | MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR); | ||
120 | break; | ||
121 | case NAND_CTL_SETALE: | ||
122 | MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR); | ||
123 | break; | ||
124 | case NAND_CTL_CLRALE: | ||
125 | MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR); | ||
126 | break; | ||
127 | case NAND_CTL_SETNCE: | ||
128 | MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR); | ||
129 | break; | ||
130 | case NAND_CTL_CLRNCE: | ||
131 | MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR); | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd) | ||
137 | { | ||
138 | switch(cmd) { | ||
139 | |||
140 | case NAND_CTL_SETCLE: | ||
141 | MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR); | ||
142 | break; | ||
143 | case NAND_CTL_CLRCLE: | ||
144 | MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR); | ||
145 | break; | ||
146 | case NAND_CTL_SETALE: | ||
147 | MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR); | ||
148 | break; | ||
149 | case NAND_CTL_CLRALE: | ||
150 | MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR); | ||
151 | break; | ||
152 | case NAND_CTL_SETNCE: | ||
153 | MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR); | ||
154 | break; | ||
155 | case NAND_CTL_CLRNCE: | ||
156 | MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR); | ||
157 | break; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | #ifdef USE_READY_BUSY_PIN | ||
162 | /* | ||
163 | * read device ready pin | ||
164 | */ | ||
165 | static int ppchameleon_device_ready(struct mtd_info *minfo) | ||
166 | { | ||
167 | if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_RB_GPIO_PIN) | ||
168 | return 1; | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int ppchameleonevb_device_ready(struct mtd_info *minfo) | ||
173 | { | ||
174 | if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN) | ||
175 | return 1; | ||
176 | return 0; | ||
177 | } | ||
178 | #endif | ||
179 | |||
180 | #ifdef CONFIG_MTD_PARTITIONS | ||
181 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
182 | const char *part_probes_evb[] = { "cmdlinepart", NULL }; | ||
183 | #endif | ||
184 | |||
185 | /* | ||
186 | * Main initialization routine | ||
187 | */ | ||
188 | static int __init ppchameleonevb_init (void) | ||
189 | { | ||
190 | struct nand_chip *this; | ||
191 | const char *part_type = 0; | ||
192 | int mtd_parts_nb = 0; | ||
193 | struct mtd_partition *mtd_parts = 0; | ||
194 | void __iomem *ppchameleon_fio_base; | ||
195 | void __iomem *ppchameleonevb_fio_base; | ||
196 | |||
197 | |||
198 | /********************************* | ||
199 | * Processor module NAND (if any) * | ||
200 | *********************************/ | ||
201 | /* Allocate memory for MTD device structure and private data */ | ||
202 | ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + | ||
203 | sizeof(struct nand_chip), GFP_KERNEL); | ||
204 | if (!ppchameleon_mtd) { | ||
205 | printk("Unable to allocate PPChameleon NAND MTD device structure.\n"); | ||
206 | return -ENOMEM; | ||
207 | } | ||
208 | |||
209 | /* map physical address */ | ||
210 | ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M); | ||
211 | if(!ppchameleon_fio_base) { | ||
212 | printk("ioremap PPChameleon NAND flash failed\n"); | ||
213 | kfree(ppchameleon_mtd); | ||
214 | return -EIO; | ||
215 | } | ||
216 | |||
217 | /* Get pointer to private data */ | ||
218 | this = (struct nand_chip *) (&ppchameleon_mtd[1]); | ||
219 | |||
220 | /* Initialize structures */ | ||
221 | memset((char *) ppchameleon_mtd, 0, sizeof(struct mtd_info)); | ||
222 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
223 | |||
224 | /* Link the private data with the MTD structure */ | ||
225 | ppchameleon_mtd->priv = this; | ||
226 | |||
227 | /* Initialize GPIOs */ | ||
228 | /* Pin mapping for NAND chip */ | ||
229 | /* | ||
230 | CE GPIO_01 | ||
231 | CLE GPIO_02 | ||
232 | ALE GPIO_03 | ||
233 | R/B GPIO_04 | ||
234 | */ | ||
235 | /* output select */ | ||
236 | out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xC0FFFFFF); | ||
237 | /* three-state select */ | ||
238 | out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xC0FFFFFF); | ||
239 | /* enable output driver */ | ||
240 | out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN); | ||
241 | #ifdef USE_READY_BUSY_PIN | ||
242 | /* three-state select */ | ||
243 | out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFF3FFFFF); | ||
244 | /* high-impedecence */ | ||
245 | out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_RB_GPIO_PIN)); | ||
246 | /* input select */ | ||
247 | out_be32((volatile unsigned*)GPIO0_ISR1H, (in_be32((volatile unsigned*)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000); | ||
248 | #endif | ||
249 | |||
250 | /* insert callbacks */ | ||
251 | this->IO_ADDR_R = ppchameleon_fio_base; | ||
252 | this->IO_ADDR_W = ppchameleon_fio_base; | ||
253 | this->hwcontrol = ppchameleon_hwcontrol; | ||
254 | #ifdef USE_READY_BUSY_PIN | ||
255 | this->dev_ready = ppchameleon_device_ready; | ||
256 | #endif | ||
257 | this->chip_delay = NAND_BIG_DELAY_US; | ||
258 | /* ECC mode */ | ||
259 | this->eccmode = NAND_ECC_SOFT; | ||
260 | |||
261 | /* Scan to find existence of the device (it could not be mounted) */ | ||
262 | if (nand_scan (ppchameleon_mtd, 1)) { | ||
263 | iounmap((void *)ppchameleon_fio_base); | ||
264 | kfree (ppchameleon_mtd); | ||
265 | goto nand_evb_init; | ||
266 | } | ||
267 | |||
268 | #ifndef USE_READY_BUSY_PIN | ||
269 | /* Adjust delay if necessary */ | ||
270 | if (ppchameleon_mtd->size == NAND_SMALL_SIZE) | ||
271 | this->chip_delay = NAND_SMALL_DELAY_US; | ||
272 | #endif | ||
273 | |||
274 | #ifdef CONFIG_MTD_PARTITIONS | ||
275 | ppchameleon_mtd->name = "ppchameleon-nand"; | ||
276 | mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0); | ||
277 | if (mtd_parts_nb > 0) | ||
278 | part_type = "command line"; | ||
279 | else | ||
280 | mtd_parts_nb = 0; | ||
281 | #endif | ||
282 | if (mtd_parts_nb == 0) | ||
283 | { | ||
284 | if (ppchameleon_mtd->size == NAND_SMALL_SIZE) | ||
285 | mtd_parts = partition_info_me; | ||
286 | else | ||
287 | mtd_parts = partition_info_hi; | ||
288 | mtd_parts_nb = NUM_PARTITIONS; | ||
289 | part_type = "static"; | ||
290 | } | ||
291 | |||
292 | /* Register the partitions */ | ||
293 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | ||
294 | add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb); | ||
295 | |||
296 | nand_evb_init: | ||
297 | /**************************** | ||
298 | * EVB NAND (always present) * | ||
299 | ****************************/ | ||
300 | /* Allocate memory for MTD device structure and private data */ | ||
301 | ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + | ||
302 | sizeof(struct nand_chip), GFP_KERNEL); | ||
303 | if (!ppchameleonevb_mtd) { | ||
304 | printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n"); | ||
305 | return -ENOMEM; | ||
306 | } | ||
307 | |||
308 | /* map physical address */ | ||
309 | ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M); | ||
310 | if(!ppchameleonevb_fio_base) { | ||
311 | printk("ioremap PPChameleonEVB NAND flash failed\n"); | ||
312 | kfree(ppchameleonevb_mtd); | ||
313 | return -EIO; | ||
314 | } | ||
315 | |||
316 | /* Get pointer to private data */ | ||
317 | this = (struct nand_chip *) (&ppchameleonevb_mtd[1]); | ||
318 | |||
319 | /* Initialize structures */ | ||
320 | memset((char *) ppchameleonevb_mtd, 0, sizeof(struct mtd_info)); | ||
321 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
322 | |||
323 | /* Link the private data with the MTD structure */ | ||
324 | ppchameleonevb_mtd->priv = this; | ||
325 | |||
326 | /* Initialize GPIOs */ | ||
327 | /* Pin mapping for NAND chip */ | ||
328 | /* | ||
329 | CE GPIO_14 | ||
330 | CLE GPIO_15 | ||
331 | ALE GPIO_16 | ||
332 | R/B GPIO_31 | ||
333 | */ | ||
334 | /* output select */ | ||
335 | out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xFFFFFFF0); | ||
336 | out_be32((volatile unsigned*)GPIO0_OSRL, in_be32((volatile unsigned*)GPIO0_OSRL) & 0x3FFFFFFF); | ||
337 | /* three-state select */ | ||
338 | out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0); | ||
339 | out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF); | ||
340 | /* enable output driver */ | ||
341 | out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN | | ||
342 | NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN); | ||
343 | #ifdef USE_READY_BUSY_PIN | ||
344 | /* three-state select */ | ||
345 | out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC); | ||
346 | /* high-impedecence */ | ||
347 | out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN)); | ||
348 | /* input select */ | ||
349 | out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001); | ||
350 | #endif | ||
351 | |||
352 | /* insert callbacks */ | ||
353 | this->IO_ADDR_R = ppchameleonevb_fio_base; | ||
354 | this->IO_ADDR_W = ppchameleonevb_fio_base; | ||
355 | this->hwcontrol = ppchameleonevb_hwcontrol; | ||
356 | #ifdef USE_READY_BUSY_PIN | ||
357 | this->dev_ready = ppchameleonevb_device_ready; | ||
358 | #endif | ||
359 | this->chip_delay = NAND_SMALL_DELAY_US; | ||
360 | |||
361 | /* ECC mode */ | ||
362 | this->eccmode = NAND_ECC_SOFT; | ||
363 | |||
364 | /* Scan to find existence of the device */ | ||
365 | if (nand_scan (ppchameleonevb_mtd, 1)) { | ||
366 | iounmap((void *)ppchameleonevb_fio_base); | ||
367 | kfree (ppchameleonevb_mtd); | ||
368 | return -ENXIO; | ||
369 | } | ||
370 | |||
371 | #ifdef CONFIG_MTD_PARTITIONS | ||
372 | ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME; | ||
373 | mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0); | ||
374 | if (mtd_parts_nb > 0) | ||
375 | part_type = "command line"; | ||
376 | else | ||
377 | mtd_parts_nb = 0; | ||
378 | #endif | ||
379 | if (mtd_parts_nb == 0) | ||
380 | { | ||
381 | mtd_parts = partition_info_evb; | ||
382 | mtd_parts_nb = NUM_PARTITIONS; | ||
383 | part_type = "static"; | ||
384 | } | ||
385 | |||
386 | /* Register the partitions */ | ||
387 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | ||
388 | add_mtd_partitions(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb); | ||
389 | |||
390 | /* Return happy */ | ||
391 | return 0; | ||
392 | } | ||
393 | module_init(ppchameleonevb_init); | ||
394 | |||
395 | /* | ||
396 | * Clean up routine | ||
397 | */ | ||
398 | static void __exit ppchameleonevb_cleanup (void) | ||
399 | { | ||
400 | struct nand_chip *this; | ||
401 | |||
402 | /* Release resources, unregister device(s) */ | ||
403 | nand_release (ppchameleon_mtd); | ||
404 | nand_release (ppchameleonevb_mtd); | ||
405 | |||
406 | /* Release iomaps */ | ||
407 | this = (struct nand_chip *) &ppchameleon_mtd[1]; | ||
408 | iounmap((void *) this->IO_ADDR_R; | ||
409 | this = (struct nand_chip *) &ppchameleonevb_mtd[1]; | ||
410 | iounmap((void *) this->IO_ADDR_R; | ||
411 | |||
412 | /* Free the MTD device structure */ | ||
413 | kfree (ppchameleon_mtd); | ||
414 | kfree (ppchameleonevb_mtd); | ||
415 | } | ||
416 | module_exit(ppchameleonevb_cleanup); | ||
417 | |||
418 | MODULE_LICENSE("GPL"); | ||
419 | MODULE_AUTHOR("DAVE Srl <support-ppchameleon@dave-tech.it>"); | ||
420 | MODULE_DESCRIPTION("MTD map driver for DAVE Srl PPChameleonEVB board"); | ||
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c new file mode 100644 index 000000000000..02305a2adca7 --- /dev/null +++ b/drivers/mtd/nand/rtc_from4.c | |||
@@ -0,0 +1,559 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/rtc_from4.c | ||
3 | * | ||
4 | * Copyright (C) 2004 Red Hat, Inc. | ||
5 | * | ||
6 | * Derived from drivers/mtd/nand/spia.c | ||
7 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | ||
8 | * | ||
9 | * $Id: rtc_from4.c,v 1.7 2004/11/04 12:53:10 gleixner Exp $ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * Overview: | ||
16 | * This is a device driver for the AG-AND flash device found on the | ||
17 | * Renesas Technology Corp. Flash ROM 4-slot interface board (FROM_BOARD4), | ||
18 | * which utilizes the Renesas HN29V1G91T-30 part. | ||
19 | * This chip is a 1 GBibit (128MiB x 8 bits) AG-AND flash device. | ||
20 | */ | ||
21 | |||
22 | #include <linux/delay.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/rslib.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/mtd/compatmac.h> | ||
29 | #include <linux/mtd/mtd.h> | ||
30 | #include <linux/mtd/nand.h> | ||
31 | #include <linux/mtd/partitions.h> | ||
32 | #include <asm/io.h> | ||
33 | |||
34 | /* | ||
35 | * MTD structure for Renesas board | ||
36 | */ | ||
37 | static struct mtd_info *rtc_from4_mtd = NULL; | ||
38 | |||
39 | #define RTC_FROM4_MAX_CHIPS 2 | ||
40 | |||
41 | /* HS77x9 processor register defines */ | ||
42 | #define SH77X9_BCR1 ((volatile unsigned short *)(0xFFFFFF60)) | ||
43 | #define SH77X9_BCR2 ((volatile unsigned short *)(0xFFFFFF62)) | ||
44 | #define SH77X9_WCR1 ((volatile unsigned short *)(0xFFFFFF64)) | ||
45 | #define SH77X9_WCR2 ((volatile unsigned short *)(0xFFFFFF66)) | ||
46 | #define SH77X9_MCR ((volatile unsigned short *)(0xFFFFFF68)) | ||
47 | #define SH77X9_PCR ((volatile unsigned short *)(0xFFFFFF6C)) | ||
48 | #define SH77X9_FRQCR ((volatile unsigned short *)(0xFFFFFF80)) | ||
49 | |||
50 | /* | ||
51 | * Values specific to the Renesas Technology Corp. FROM_BOARD4 (used with HS77x9 processor) | ||
52 | */ | ||
53 | /* Address where flash is mapped */ | ||
54 | #define RTC_FROM4_FIO_BASE 0x14000000 | ||
55 | |||
56 | /* CLE and ALE are tied to address lines 5 & 4, respectively */ | ||
57 | #define RTC_FROM4_CLE (1 << 5) | ||
58 | #define RTC_FROM4_ALE (1 << 4) | ||
59 | |||
60 | /* address lines A24-A22 used for chip selection */ | ||
61 | #define RTC_FROM4_NAND_ADDR_SLOT3 (0x00800000) | ||
62 | #define RTC_FROM4_NAND_ADDR_SLOT4 (0x00C00000) | ||
63 | #define RTC_FROM4_NAND_ADDR_FPGA (0x01000000) | ||
64 | /* mask address lines A24-A22 used for chip selection */ | ||
65 | #define RTC_FROM4_NAND_ADDR_MASK (RTC_FROM4_NAND_ADDR_SLOT3 | RTC_FROM4_NAND_ADDR_SLOT4 | RTC_FROM4_NAND_ADDR_FPGA) | ||
66 | |||
67 | /* FPGA status register for checking device ready (bit zero) */ | ||
68 | #define RTC_FROM4_FPGA_SR (RTC_FROM4_NAND_ADDR_FPGA | 0x00000002) | ||
69 | #define RTC_FROM4_DEVICE_READY 0x0001 | ||
70 | |||
71 | /* FPGA Reed-Solomon ECC Control register */ | ||
72 | |||
73 | #define RTC_FROM4_RS_ECC_CTL (RTC_FROM4_NAND_ADDR_FPGA | 0x00000050) | ||
74 | #define RTC_FROM4_RS_ECC_CTL_CLR (1 << 7) | ||
75 | #define RTC_FROM4_RS_ECC_CTL_GEN (1 << 6) | ||
76 | #define RTC_FROM4_RS_ECC_CTL_FD_E (1 << 5) | ||
77 | |||
78 | /* FPGA Reed-Solomon ECC code base */ | ||
79 | #define RTC_FROM4_RS_ECC (RTC_FROM4_NAND_ADDR_FPGA | 0x00000060) | ||
80 | #define RTC_FROM4_RS_ECCN (RTC_FROM4_NAND_ADDR_FPGA | 0x00000080) | ||
81 | |||
82 | /* FPGA Reed-Solomon ECC check register */ | ||
83 | #define RTC_FROM4_RS_ECC_CHK (RTC_FROM4_NAND_ADDR_FPGA | 0x00000070) | ||
84 | #define RTC_FROM4_RS_ECC_CHK_ERROR (1 << 7) | ||
85 | |||
86 | /* Undefine for software ECC */ | ||
87 | #define RTC_FROM4_HWECC 1 | ||
88 | |||
89 | /* | ||
90 | * Module stuff | ||
91 | */ | ||
92 | static void __iomem *rtc_from4_fio_base = P2SEGADDR(RTC_FROM4_FIO_BASE); | ||
93 | |||
94 | const static struct mtd_partition partition_info[] = { | ||
95 | { | ||
96 | .name = "Renesas flash partition 1", | ||
97 | .offset = 0, | ||
98 | .size = MTDPART_SIZ_FULL | ||
99 | }, | ||
100 | }; | ||
101 | #define NUM_PARTITIONS 1 | ||
102 | |||
103 | /* | ||
104 | * hardware specific flash bbt decriptors | ||
105 | * Note: this is to allow debugging by disabling | ||
106 | * NAND_BBT_CREATE and/or NAND_BBT_WRITE | ||
107 | * | ||
108 | */ | ||
109 | static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; | ||
110 | static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; | ||
111 | |||
112 | static struct nand_bbt_descr rtc_from4_bbt_main_descr = { | ||
113 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
114 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | ||
115 | .offs = 40, | ||
116 | .len = 4, | ||
117 | .veroffs = 44, | ||
118 | .maxblocks = 4, | ||
119 | .pattern = bbt_pattern | ||
120 | }; | ||
121 | |||
122 | static struct nand_bbt_descr rtc_from4_bbt_mirror_descr = { | ||
123 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
124 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, | ||
125 | .offs = 40, | ||
126 | .len = 4, | ||
127 | .veroffs = 44, | ||
128 | .maxblocks = 4, | ||
129 | .pattern = mirror_pattern | ||
130 | }; | ||
131 | |||
132 | |||
133 | |||
134 | #ifdef RTC_FROM4_HWECC | ||
135 | |||
136 | /* the Reed Solomon control structure */ | ||
137 | static struct rs_control *rs_decoder; | ||
138 | |||
139 | /* | ||
140 | * hardware specific Out Of Band information | ||
141 | */ | ||
142 | static struct nand_oobinfo rtc_from4_nand_oobinfo = { | ||
143 | .useecc = MTD_NANDECC_AUTOPLACE, | ||
144 | .eccbytes = 32, | ||
145 | .eccpos = { | ||
146 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
147 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
148 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
149 | 24, 25, 26, 27, 28, 29, 30, 31}, | ||
150 | .oobfree = { {32, 32} } | ||
151 | }; | ||
152 | |||
153 | /* Aargh. I missed the reversed bit order, when I | ||
154 | * was talking to Renesas about the FPGA. | ||
155 | * | ||
156 | * The table is used for bit reordering and inversion | ||
157 | * of the ecc byte which we get from the FPGA | ||
158 | */ | ||
159 | static uint8_t revbits[256] = { | ||
160 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, | ||
161 | 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, | ||
162 | 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, | ||
163 | 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, | ||
164 | 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, | ||
165 | 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, | ||
166 | 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, | ||
167 | 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, | ||
168 | 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, | ||
169 | 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, | ||
170 | 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, | ||
171 | 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, | ||
172 | 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, | ||
173 | 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, | ||
174 | 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, | ||
175 | 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, | ||
176 | 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, | ||
177 | 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, | ||
178 | 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, | ||
179 | 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, | ||
180 | 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, | ||
181 | 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, | ||
182 | 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, | ||
183 | 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, | ||
184 | 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, | ||
185 | 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, | ||
186 | 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, | ||
187 | 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, | ||
188 | 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, | ||
189 | 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, | ||
190 | 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, | ||
191 | 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, | ||
192 | }; | ||
193 | |||
194 | #endif | ||
195 | |||
196 | |||
197 | |||
198 | /* | ||
199 | * rtc_from4_hwcontrol - hardware specific access to control-lines | ||
200 | * @mtd: MTD device structure | ||
201 | * @cmd: hardware control command | ||
202 | * | ||
203 | * Address lines (A5 and A4) are used to control Command and Address Latch | ||
204 | * Enable on this board, so set the read/write address appropriately. | ||
205 | * | ||
206 | * Chip Enable is also controlled by the Chip Select (CS5) and | ||
207 | * Address lines (A24-A22), so no action is required here. | ||
208 | * | ||
209 | */ | ||
210 | static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd) | ||
211 | { | ||
212 | struct nand_chip* this = (struct nand_chip *) (mtd->priv); | ||
213 | |||
214 | switch(cmd) { | ||
215 | |||
216 | case NAND_CTL_SETCLE: | ||
217 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE); | ||
218 | break; | ||
219 | case NAND_CTL_CLRCLE: | ||
220 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE); | ||
221 | break; | ||
222 | |||
223 | case NAND_CTL_SETALE: | ||
224 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE); | ||
225 | break; | ||
226 | case NAND_CTL_CLRALE: | ||
227 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE); | ||
228 | break; | ||
229 | |||
230 | case NAND_CTL_SETNCE: | ||
231 | break; | ||
232 | case NAND_CTL_CLRNCE: | ||
233 | break; | ||
234 | |||
235 | } | ||
236 | } | ||
237 | |||
238 | |||
239 | /* | ||
240 | * rtc_from4_nand_select_chip - hardware specific chip select | ||
241 | * @mtd: MTD device structure | ||
242 | * @chip: Chip to select (0 == slot 3, 1 == slot 4) | ||
243 | * | ||
244 | * The chip select is based on address lines A24-A22. | ||
245 | * This driver uses flash slots 3 and 4 (A23-A22). | ||
246 | * | ||
247 | */ | ||
248 | static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip) | ||
249 | { | ||
250 | struct nand_chip *this = mtd->priv; | ||
251 | |||
252 | this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R & ~RTC_FROM4_NAND_ADDR_MASK); | ||
253 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_NAND_ADDR_MASK); | ||
254 | |||
255 | switch(chip) { | ||
256 | |||
257 | case 0: /* select slot 3 chip */ | ||
258 | this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT3); | ||
259 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT3); | ||
260 | break; | ||
261 | case 1: /* select slot 4 chip */ | ||
262 | this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT4); | ||
263 | this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT4); | ||
264 | break; | ||
265 | |||
266 | } | ||
267 | } | ||
268 | |||
269 | |||
270 | |||
271 | /* | ||
272 | * rtc_from4_nand_device_ready - hardware specific ready/busy check | ||
273 | * @mtd: MTD device structure | ||
274 | * | ||
275 | * This board provides the Ready/Busy state in the status register | ||
276 | * of the FPGA. Bit zero indicates the RDY(1)/BSY(0) signal. | ||
277 | * | ||
278 | */ | ||
279 | static int rtc_from4_nand_device_ready(struct mtd_info *mtd) | ||
280 | { | ||
281 | unsigned short status; | ||
282 | |||
283 | status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_FPGA_SR)); | ||
284 | |||
285 | return (status & RTC_FROM4_DEVICE_READY); | ||
286 | |||
287 | } | ||
288 | |||
289 | #ifdef RTC_FROM4_HWECC | ||
290 | /* | ||
291 | * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function | ||
292 | * @mtd: MTD device structure | ||
293 | * @mode: I/O mode; read or write | ||
294 | * | ||
295 | * enable hardware ECC for data read or write | ||
296 | * | ||
297 | */ | ||
298 | static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode) | ||
299 | { | ||
300 | volatile unsigned short * rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL); | ||
301 | unsigned short status; | ||
302 | |||
303 | switch (mode) { | ||
304 | case NAND_ECC_READ : | ||
305 | status = RTC_FROM4_RS_ECC_CTL_CLR | ||
306 | | RTC_FROM4_RS_ECC_CTL_FD_E; | ||
307 | |||
308 | *rs_ecc_ctl = status; | ||
309 | break; | ||
310 | |||
311 | case NAND_ECC_READSYN : | ||
312 | status = 0x00; | ||
313 | |||
314 | *rs_ecc_ctl = status; | ||
315 | break; | ||
316 | |||
317 | case NAND_ECC_WRITE : | ||
318 | status = RTC_FROM4_RS_ECC_CTL_CLR | ||
319 | | RTC_FROM4_RS_ECC_CTL_GEN | ||
320 | | RTC_FROM4_RS_ECC_CTL_FD_E; | ||
321 | |||
322 | *rs_ecc_ctl = status; | ||
323 | break; | ||
324 | |||
325 | default: | ||
326 | BUG(); | ||
327 | break; | ||
328 | } | ||
329 | |||
330 | } | ||
331 | |||
332 | /* | ||
333 | * rtc_from4_calculate_ecc - hardware specific code to read ECC code | ||
334 | * @mtd: MTD device structure | ||
335 | * @dat: buffer containing the data to generate ECC codes | ||
336 | * @ecc_code ECC codes calculated | ||
337 | * | ||
338 | * The ECC code is calculated by the FPGA. All we have to do is read the values | ||
339 | * from the FPGA registers. | ||
340 | * | ||
341 | * Note: We read from the inverted registers, since data is inverted before | ||
342 | * the code is calculated. So all 0xff data (blank page) results in all 0xff rs code | ||
343 | * | ||
344 | */ | ||
345 | static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) | ||
346 | { | ||
347 | volatile unsigned short * rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN); | ||
348 | unsigned short value; | ||
349 | int i; | ||
350 | |||
351 | for (i = 0; i < 8; i++) { | ||
352 | value = *rs_eccn; | ||
353 | ecc_code[i] = (unsigned char)value; | ||
354 | rs_eccn++; | ||
355 | } | ||
356 | ecc_code[7] |= 0x0f; /* set the last four bits (not used) */ | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * rtc_from4_correct_data - hardware specific code to correct data using ECC code | ||
361 | * @mtd: MTD device structure | ||
362 | * @buf: buffer containing the data to generate ECC codes | ||
363 | * @ecc1 ECC codes read | ||
364 | * @ecc2 ECC codes calculated | ||
365 | * | ||
366 | * The FPGA tells us fast, if there's an error or not. If no, we go back happy | ||
367 | * else we read the ecc results from the fpga and call the rs library to decode | ||
368 | * and hopefully correct the error | ||
369 | * | ||
370 | * For now I use the code, which we read from the FLASH to use the RS lib, | ||
371 | * as the syndrom conversion has a unresolved issue. | ||
372 | */ | ||
373 | static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_char *ecc1, u_char *ecc2) | ||
374 | { | ||
375 | int i, j, res; | ||
376 | unsigned short status; | ||
377 | uint16_t par[6], syn[6], tmp; | ||
378 | uint8_t ecc[8]; | ||
379 | volatile unsigned short *rs_ecc; | ||
380 | |||
381 | status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CHK)); | ||
382 | |||
383 | if (!(status & RTC_FROM4_RS_ECC_CHK_ERROR)) { | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | /* Read the syndrom pattern from the FPGA and correct the bitorder */ | ||
388 | rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC); | ||
389 | for (i = 0; i < 8; i++) { | ||
390 | ecc[i] = revbits[(*rs_ecc) & 0xFF]; | ||
391 | rs_ecc++; | ||
392 | } | ||
393 | |||
394 | /* convert into 6 10bit syndrome fields */ | ||
395 | par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) | | ||
396 | (((uint16_t)ecc[1] << 8) & 0x300)]; | ||
397 | par[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) | | ||
398 | (((uint16_t)ecc[2] << 6) & 0x3c0)]; | ||
399 | par[3] = rs_decoder->index_of[(((uint16_t)ecc[2] >> 4) & 0x00f) | | ||
400 | (((uint16_t)ecc[3] << 4) & 0x3f0)]; | ||
401 | par[2] = rs_decoder->index_of[(((uint16_t)ecc[3] >> 6) & 0x003) | | ||
402 | (((uint16_t)ecc[4] << 2) & 0x3fc)]; | ||
403 | par[1] = rs_decoder->index_of[(((uint16_t)ecc[5] >> 0) & 0x0ff) | | ||
404 | (((uint16_t)ecc[6] << 8) & 0x300)]; | ||
405 | par[0] = (((uint16_t)ecc[6] >> 2) & 0x03f) | (((uint16_t)ecc[7] << 6) & 0x3c0); | ||
406 | |||
407 | /* Convert to computable syndrome */ | ||
408 | for (i = 0; i < 6; i++) { | ||
409 | syn[i] = par[0]; | ||
410 | for (j = 1; j < 6; j++) | ||
411 | if (par[j] != rs_decoder->nn) | ||
412 | syn[i] ^= rs_decoder->alpha_to[rs_modnn(rs_decoder, par[j] + i * j)]; | ||
413 | |||
414 | /* Convert to index form */ | ||
415 | syn[i] = rs_decoder->index_of[syn[i]]; | ||
416 | } | ||
417 | |||
418 | /* Let the library code do its magic.*/ | ||
419 | res = decode_rs8(rs_decoder, buf, par, 512, syn, 0, NULL, 0xff, NULL); | ||
420 | if (res > 0) { | ||
421 | DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " | ||
422 | "ECC corrected %d errors on read\n", res); | ||
423 | } | ||
424 | return res; | ||
425 | } | ||
426 | #endif | ||
427 | |||
428 | /* | ||
429 | * Main initialization routine | ||
430 | */ | ||
431 | int __init rtc_from4_init (void) | ||
432 | { | ||
433 | struct nand_chip *this; | ||
434 | unsigned short bcr1, bcr2, wcr2; | ||
435 | |||
436 | /* Allocate memory for MTD device structure and private data */ | ||
437 | rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), | ||
438 | GFP_KERNEL); | ||
439 | if (!rtc_from4_mtd) { | ||
440 | printk ("Unable to allocate Renesas NAND MTD device structure.\n"); | ||
441 | return -ENOMEM; | ||
442 | } | ||
443 | |||
444 | /* Get pointer to private data */ | ||
445 | this = (struct nand_chip *) (&rtc_from4_mtd[1]); | ||
446 | |||
447 | /* Initialize structures */ | ||
448 | memset((char *) rtc_from4_mtd, 0, sizeof(struct mtd_info)); | ||
449 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
450 | |||
451 | /* Link the private data with the MTD structure */ | ||
452 | rtc_from4_mtd->priv = this; | ||
453 | |||
454 | /* set area 5 as PCMCIA mode to clear the spec of tDH(Data hold time;9ns min) */ | ||
455 | bcr1 = *SH77X9_BCR1 & ~0x0002; | ||
456 | bcr1 |= 0x0002; | ||
457 | *SH77X9_BCR1 = bcr1; | ||
458 | |||
459 | /* set */ | ||
460 | bcr2 = *SH77X9_BCR2 & ~0x0c00; | ||
461 | bcr2 |= 0x0800; | ||
462 | *SH77X9_BCR2 = bcr2; | ||
463 | |||
464 | /* set area 5 wait states */ | ||
465 | wcr2 = *SH77X9_WCR2 & ~0x1c00; | ||
466 | wcr2 |= 0x1c00; | ||
467 | *SH77X9_WCR2 = wcr2; | ||
468 | |||
469 | /* Set address of NAND IO lines */ | ||
470 | this->IO_ADDR_R = rtc_from4_fio_base; | ||
471 | this->IO_ADDR_W = rtc_from4_fio_base; | ||
472 | /* Set address of hardware control function */ | ||
473 | this->hwcontrol = rtc_from4_hwcontrol; | ||
474 | /* Set address of chip select function */ | ||
475 | this->select_chip = rtc_from4_nand_select_chip; | ||
476 | /* command delay time (in us) */ | ||
477 | this->chip_delay = 100; | ||
478 | /* return the status of the Ready/Busy line */ | ||
479 | this->dev_ready = rtc_from4_nand_device_ready; | ||
480 | |||
481 | #ifdef RTC_FROM4_HWECC | ||
482 | printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n"); | ||
483 | |||
484 | this->eccmode = NAND_ECC_HW8_512; | ||
485 | this->options |= NAND_HWECC_SYNDROME; | ||
486 | /* set the nand_oobinfo to support FPGA H/W error detection */ | ||
487 | this->autooob = &rtc_from4_nand_oobinfo; | ||
488 | this->enable_hwecc = rtc_from4_enable_hwecc; | ||
489 | this->calculate_ecc = rtc_from4_calculate_ecc; | ||
490 | this->correct_data = rtc_from4_correct_data; | ||
491 | #else | ||
492 | printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n"); | ||
493 | |||
494 | this->eccmode = NAND_ECC_SOFT; | ||
495 | #endif | ||
496 | |||
497 | /* set the bad block tables to support debugging */ | ||
498 | this->bbt_td = &rtc_from4_bbt_main_descr; | ||
499 | this->bbt_md = &rtc_from4_bbt_mirror_descr; | ||
500 | |||
501 | /* Scan to find existence of the device */ | ||
502 | if (nand_scan(rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) { | ||
503 | kfree(rtc_from4_mtd); | ||
504 | return -ENXIO; | ||
505 | } | ||
506 | |||
507 | /* Register the partitions */ | ||
508 | add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS); | ||
509 | |||
510 | #ifdef RTC_FROM4_HWECC | ||
511 | /* We could create the decoder on demand, if memory is a concern. | ||
512 | * This way we have it handy, if an error happens | ||
513 | * | ||
514 | * Symbolsize is 10 (bits) | ||
515 | * Primitve polynomial is x^10+x^3+1 | ||
516 | * first consecutive root is 0 | ||
517 | * primitve element to generate roots = 1 | ||
518 | * generator polinomial degree = 6 | ||
519 | */ | ||
520 | rs_decoder = init_rs(10, 0x409, 0, 1, 6); | ||
521 | if (!rs_decoder) { | ||
522 | printk (KERN_ERR "Could not create a RS decoder\n"); | ||
523 | nand_release(rtc_from4_mtd); | ||
524 | kfree(rtc_from4_mtd); | ||
525 | return -ENOMEM; | ||
526 | } | ||
527 | #endif | ||
528 | /* Return happy */ | ||
529 | return 0; | ||
530 | } | ||
531 | module_init(rtc_from4_init); | ||
532 | |||
533 | |||
534 | /* | ||
535 | * Clean up routine | ||
536 | */ | ||
537 | #ifdef MODULE | ||
538 | static void __exit rtc_from4_cleanup (void) | ||
539 | { | ||
540 | /* Release resource, unregister partitions */ | ||
541 | nand_release(rtc_from4_mtd); | ||
542 | |||
543 | /* Free the MTD device structure */ | ||
544 | kfree (rtc_from4_mtd); | ||
545 | |||
546 | #ifdef RTC_FROM4_HWECC | ||
547 | /* Free the reed solomon resources */ | ||
548 | if (rs_decoder) { | ||
549 | free_rs(rs_decoder); | ||
550 | } | ||
551 | #endif | ||
552 | } | ||
553 | module_exit(rtc_from4_cleanup); | ||
554 | #endif | ||
555 | |||
556 | MODULE_LICENSE("GPL"); | ||
557 | MODULE_AUTHOR("d.marlin <dmarlin@redhat.com"); | ||
558 | MODULE_DESCRIPTION("Board-specific glue layer for AG-AND flash on Renesas FROM_BOARD4"); | ||
559 | |||
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c new file mode 100644 index 000000000000..d05e9b97947d --- /dev/null +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -0,0 +1,704 @@ | |||
1 | /* linux/drivers/mtd/nand/s3c2410.c | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Samsung S3C2410 NAND driver | ||
7 | * | ||
8 | * Changelog: | ||
9 | * 21-Sep-2004 BJD Initial version | ||
10 | * 23-Sep-2004 BJD Mulitple device support | ||
11 | * 28-Sep-2004 BJD Fixed ECC placement for Hardware mode | ||
12 | * 12-Oct-2004 BJD Fixed errors in use of platform data | ||
13 | * | ||
14 | * $Id: s3c2410.c,v 1.7 2005/01/05 18:05:14 dwmw2 Exp $ | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
29 | */ | ||
30 | |||
31 | #include <config/mtd/nand/s3c2410/hwecc.h> | ||
32 | #include <config/mtd/nand/s3c2410/debug.h> | ||
33 | |||
34 | #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG | ||
35 | #define DEBUG | ||
36 | #endif | ||
37 | |||
38 | #include <linux/module.h> | ||
39 | #include <linux/types.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/kernel.h> | ||
42 | #include <linux/string.h> | ||
43 | #include <linux/ioport.h> | ||
44 | #include <linux/device.h> | ||
45 | #include <linux/delay.h> | ||
46 | #include <linux/err.h> | ||
47 | |||
48 | #include <linux/mtd/mtd.h> | ||
49 | #include <linux/mtd/nand.h> | ||
50 | #include <linux/mtd/nand_ecc.h> | ||
51 | #include <linux/mtd/partitions.h> | ||
52 | |||
53 | #include <asm/io.h> | ||
54 | #include <asm/mach-types.h> | ||
55 | #include <asm/hardware/clock.h> | ||
56 | |||
57 | #include <asm/arch/regs-nand.h> | ||
58 | #include <asm/arch/nand.h> | ||
59 | |||
60 | #define PFX "s3c2410-nand: " | ||
61 | |||
62 | #ifdef CONFIG_MTD_NAND_S3C2410_HWECC | ||
63 | static int hardware_ecc = 1; | ||
64 | #else | ||
65 | static int hardware_ecc = 0; | ||
66 | #endif | ||
67 | |||
68 | /* new oob placement block for use with hardware ecc generation | ||
69 | */ | ||
70 | |||
71 | static struct nand_oobinfo nand_hw_eccoob = { | ||
72 | .useecc = MTD_NANDECC_AUTOPLACE, | ||
73 | .eccbytes = 3, | ||
74 | .eccpos = {0, 1, 2 }, | ||
75 | .oobfree = { {8, 8} } | ||
76 | }; | ||
77 | |||
78 | /* controller and mtd information */ | ||
79 | |||
80 | struct s3c2410_nand_info; | ||
81 | |||
82 | struct s3c2410_nand_mtd { | ||
83 | struct mtd_info mtd; | ||
84 | struct nand_chip chip; | ||
85 | struct s3c2410_nand_set *set; | ||
86 | struct s3c2410_nand_info *info; | ||
87 | int scan_res; | ||
88 | }; | ||
89 | |||
90 | /* overview of the s3c2410 nand state */ | ||
91 | |||
92 | struct s3c2410_nand_info { | ||
93 | /* mtd info */ | ||
94 | struct nand_hw_control controller; | ||
95 | struct s3c2410_nand_mtd *mtds; | ||
96 | struct s3c2410_platform_nand *platform; | ||
97 | |||
98 | /* device info */ | ||
99 | struct device *device; | ||
100 | struct resource *area; | ||
101 | struct clk *clk; | ||
102 | void *regs; | ||
103 | int mtd_count; | ||
104 | }; | ||
105 | |||
106 | /* conversion functions */ | ||
107 | |||
108 | static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd) | ||
109 | { | ||
110 | return container_of(mtd, struct s3c2410_nand_mtd, mtd); | ||
111 | } | ||
112 | |||
113 | static struct s3c2410_nand_info *s3c2410_nand_mtd_toinfo(struct mtd_info *mtd) | ||
114 | { | ||
115 | return s3c2410_nand_mtd_toours(mtd)->info; | ||
116 | } | ||
117 | |||
118 | static struct s3c2410_nand_info *to_nand_info(struct device *dev) | ||
119 | { | ||
120 | return dev_get_drvdata(dev); | ||
121 | } | ||
122 | |||
123 | static struct s3c2410_platform_nand *to_nand_plat(struct device *dev) | ||
124 | { | ||
125 | return dev->platform_data; | ||
126 | } | ||
127 | |||
128 | /* timing calculations */ | ||
129 | |||
130 | #define NS_IN_KHZ 10000000 | ||
131 | |||
132 | static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max) | ||
133 | { | ||
134 | int result; | ||
135 | |||
136 | result = (wanted * NS_IN_KHZ) / clk; | ||
137 | result++; | ||
138 | |||
139 | pr_debug("result %d from %ld, %d\n", result, clk, wanted); | ||
140 | |||
141 | if (result > max) { | ||
142 | printk("%d ns is too big for current clock rate %ld\n", | ||
143 | wanted, clk); | ||
144 | return -1; | ||
145 | } | ||
146 | |||
147 | if (result < 1) | ||
148 | result = 1; | ||
149 | |||
150 | return result; | ||
151 | } | ||
152 | |||
153 | #define to_ns(ticks,clk) (((clk) * (ticks)) / NS_IN_KHZ) | ||
154 | |||
155 | /* controller setup */ | ||
156 | |||
157 | static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, | ||
158 | struct device *dev) | ||
159 | { | ||
160 | struct s3c2410_platform_nand *plat = to_nand_plat(dev); | ||
161 | unsigned int tacls, twrph0, twrph1; | ||
162 | unsigned long clkrate = clk_get_rate(info->clk); | ||
163 | unsigned long cfg; | ||
164 | |||
165 | /* calculate the timing information for the controller */ | ||
166 | |||
167 | if (plat != NULL) { | ||
168 | tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 8); | ||
169 | twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8); | ||
170 | twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8); | ||
171 | } else { | ||
172 | /* default timings */ | ||
173 | tacls = 8; | ||
174 | twrph0 = 8; | ||
175 | twrph1 = 8; | ||
176 | } | ||
177 | |||
178 | if (tacls < 0 || twrph0 < 0 || twrph1 < 0) { | ||
179 | printk(KERN_ERR PFX "cannot get timings suitable for board\n"); | ||
180 | return -EINVAL; | ||
181 | } | ||
182 | |||
183 | printk(KERN_INFO PFX "timing: Tacls %ldns, Twrph0 %ldns, Twrph1 %ldns\n", | ||
184 | to_ns(tacls, clkrate), | ||
185 | to_ns(twrph0, clkrate), | ||
186 | to_ns(twrph1, clkrate)); | ||
187 | |||
188 | cfg = S3C2410_NFCONF_EN; | ||
189 | cfg |= S3C2410_NFCONF_TACLS(tacls-1); | ||
190 | cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1); | ||
191 | cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1); | ||
192 | |||
193 | pr_debug(PFX "NF_CONF is 0x%lx\n", cfg); | ||
194 | |||
195 | writel(cfg, info->regs + S3C2410_NFCONF); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | /* select chip */ | ||
200 | |||
201 | static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip) | ||
202 | { | ||
203 | struct s3c2410_nand_info *info; | ||
204 | struct s3c2410_nand_mtd *nmtd; | ||
205 | struct nand_chip *this = mtd->priv; | ||
206 | unsigned long cur; | ||
207 | |||
208 | nmtd = this->priv; | ||
209 | info = nmtd->info; | ||
210 | |||
211 | cur = readl(info->regs + S3C2410_NFCONF); | ||
212 | |||
213 | if (chip == -1) { | ||
214 | cur |= S3C2410_NFCONF_nFCE; | ||
215 | } else { | ||
216 | if (chip > nmtd->set->nr_chips) { | ||
217 | printk(KERN_ERR PFX "chip %d out of range\n", chip); | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | if (info->platform != NULL) { | ||
222 | if (info->platform->select_chip != NULL) | ||
223 | (info->platform->select_chip)(nmtd->set, chip); | ||
224 | } | ||
225 | |||
226 | cur &= ~S3C2410_NFCONF_nFCE; | ||
227 | } | ||
228 | |||
229 | writel(cur, info->regs + S3C2410_NFCONF); | ||
230 | } | ||
231 | |||
232 | /* command and control functions */ | ||
233 | |||
234 | static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd) | ||
235 | { | ||
236 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | ||
237 | unsigned long cur; | ||
238 | |||
239 | switch (cmd) { | ||
240 | case NAND_CTL_SETNCE: | ||
241 | cur = readl(info->regs + S3C2410_NFCONF); | ||
242 | cur &= ~S3C2410_NFCONF_nFCE; | ||
243 | writel(cur, info->regs + S3C2410_NFCONF); | ||
244 | break; | ||
245 | |||
246 | case NAND_CTL_CLRNCE: | ||
247 | cur = readl(info->regs + S3C2410_NFCONF); | ||
248 | cur |= S3C2410_NFCONF_nFCE; | ||
249 | writel(cur, info->regs + S3C2410_NFCONF); | ||
250 | break; | ||
251 | |||
252 | /* we don't need to implement these */ | ||
253 | case NAND_CTL_SETCLE: | ||
254 | case NAND_CTL_CLRCLE: | ||
255 | case NAND_CTL_SETALE: | ||
256 | case NAND_CTL_CLRALE: | ||
257 | pr_debug(PFX "s3c2410_nand_hwcontrol(%d) unusedn", cmd); | ||
258 | break; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /* s3c2410_nand_command | ||
263 | * | ||
264 | * This function implements sending commands and the relevant address | ||
265 | * information to the chip, via the hardware controller. Since the | ||
266 | * S3C2410 generates the correct ALE/CLE signaling automatically, we | ||
267 | * do not need to use hwcontrol. | ||
268 | */ | ||
269 | |||
270 | static void s3c2410_nand_command (struct mtd_info *mtd, unsigned command, | ||
271 | int column, int page_addr) | ||
272 | { | ||
273 | register struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | ||
274 | register struct nand_chip *this = mtd->priv; | ||
275 | |||
276 | /* | ||
277 | * Write out the command to the device. | ||
278 | */ | ||
279 | if (command == NAND_CMD_SEQIN) { | ||
280 | int readcmd; | ||
281 | |||
282 | if (column >= mtd->oobblock) { | ||
283 | /* OOB area */ | ||
284 | column -= mtd->oobblock; | ||
285 | readcmd = NAND_CMD_READOOB; | ||
286 | } else if (column < 256) { | ||
287 | /* First 256 bytes --> READ0 */ | ||
288 | readcmd = NAND_CMD_READ0; | ||
289 | } else { | ||
290 | column -= 256; | ||
291 | readcmd = NAND_CMD_READ1; | ||
292 | } | ||
293 | |||
294 | writeb(readcmd, info->regs + S3C2410_NFCMD); | ||
295 | } | ||
296 | writeb(command, info->regs + S3C2410_NFCMD); | ||
297 | |||
298 | /* Set ALE and clear CLE to start address cycle */ | ||
299 | |||
300 | if (column != -1 || page_addr != -1) { | ||
301 | |||
302 | /* Serially input address */ | ||
303 | if (column != -1) { | ||
304 | /* Adjust columns for 16 bit buswidth */ | ||
305 | if (this->options & NAND_BUSWIDTH_16) | ||
306 | column >>= 1; | ||
307 | writeb(column, info->regs + S3C2410_NFADDR); | ||
308 | } | ||
309 | if (page_addr != -1) { | ||
310 | writeb((unsigned char) (page_addr), info->regs + S3C2410_NFADDR); | ||
311 | writeb((unsigned char) (page_addr >> 8), info->regs + S3C2410_NFADDR); | ||
312 | /* One more address cycle for higher density devices */ | ||
313 | if (this->chipsize & 0x0c000000) | ||
314 | writeb((unsigned char) ((page_addr >> 16) & 0x0f), | ||
315 | info->regs + S3C2410_NFADDR); | ||
316 | } | ||
317 | /* Latch in address */ | ||
318 | } | ||
319 | |||
320 | /* | ||
321 | * program and erase have their own busy handlers | ||
322 | * status and sequential in needs no delay | ||
323 | */ | ||
324 | switch (command) { | ||
325 | |||
326 | case NAND_CMD_PAGEPROG: | ||
327 | case NAND_CMD_ERASE1: | ||
328 | case NAND_CMD_ERASE2: | ||
329 | case NAND_CMD_SEQIN: | ||
330 | case NAND_CMD_STATUS: | ||
331 | return; | ||
332 | |||
333 | case NAND_CMD_RESET: | ||
334 | if (this->dev_ready) | ||
335 | break; | ||
336 | |||
337 | udelay(this->chip_delay); | ||
338 | writeb(NAND_CMD_STATUS, info->regs + S3C2410_NFCMD); | ||
339 | |||
340 | while ( !(this->read_byte(mtd) & 0x40)); | ||
341 | return; | ||
342 | |||
343 | /* This applies to read commands */ | ||
344 | default: | ||
345 | /* | ||
346 | * If we don't have access to the busy pin, we apply the given | ||
347 | * command delay | ||
348 | */ | ||
349 | if (!this->dev_ready) { | ||
350 | udelay (this->chip_delay); | ||
351 | return; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | /* Apply this short delay always to ensure that we do wait tWB in | ||
356 | * any case on any machine. */ | ||
357 | ndelay (100); | ||
358 | /* wait until command is processed */ | ||
359 | while (!this->dev_ready(mtd)); | ||
360 | } | ||
361 | |||
362 | |||
363 | /* s3c2410_nand_devready() | ||
364 | * | ||
365 | * returns 0 if the nand is busy, 1 if it is ready | ||
366 | */ | ||
367 | |||
368 | static int s3c2410_nand_devready(struct mtd_info *mtd) | ||
369 | { | ||
370 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | ||
371 | |||
372 | return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY; | ||
373 | } | ||
374 | |||
375 | /* ECC handling functions */ | ||
376 | |||
377 | static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, | ||
378 | u_char *read_ecc, u_char *calc_ecc) | ||
379 | { | ||
380 | pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", | ||
381 | mtd, dat, read_ecc, calc_ecc); | ||
382 | |||
383 | pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n", | ||
384 | read_ecc[0], read_ecc[1], read_ecc[2], | ||
385 | calc_ecc[0], calc_ecc[1], calc_ecc[2]); | ||
386 | |||
387 | if (read_ecc[0] == calc_ecc[0] && | ||
388 | read_ecc[1] == calc_ecc[1] && | ||
389 | read_ecc[2] == calc_ecc[2]) | ||
390 | return 0; | ||
391 | |||
392 | /* we curently have no method for correcting the error */ | ||
393 | |||
394 | return -1; | ||
395 | } | ||
396 | |||
397 | static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode) | ||
398 | { | ||
399 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | ||
400 | unsigned long ctrl; | ||
401 | |||
402 | ctrl = readl(info->regs + S3C2410_NFCONF); | ||
403 | ctrl |= S3C2410_NFCONF_INITECC; | ||
404 | writel(ctrl, info->regs + S3C2410_NFCONF); | ||
405 | } | ||
406 | |||
407 | static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, | ||
408 | const u_char *dat, u_char *ecc_code) | ||
409 | { | ||
410 | struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); | ||
411 | |||
412 | ecc_code[0] = readb(info->regs + S3C2410_NFECC + 0); | ||
413 | ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1); | ||
414 | ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2); | ||
415 | |||
416 | pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", | ||
417 | ecc_code[0], ecc_code[1], ecc_code[2]); | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | |||
423 | /* over-ride the standard functions for a little more speed? */ | ||
424 | |||
425 | static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | ||
426 | { | ||
427 | struct nand_chip *this = mtd->priv; | ||
428 | readsb(this->IO_ADDR_R, buf, len); | ||
429 | } | ||
430 | |||
431 | static void s3c2410_nand_write_buf(struct mtd_info *mtd, | ||
432 | const u_char *buf, int len) | ||
433 | { | ||
434 | struct nand_chip *this = mtd->priv; | ||
435 | writesb(this->IO_ADDR_W, buf, len); | ||
436 | } | ||
437 | |||
438 | /* device management functions */ | ||
439 | |||
440 | static int s3c2410_nand_remove(struct device *dev) | ||
441 | { | ||
442 | struct s3c2410_nand_info *info = to_nand_info(dev); | ||
443 | |||
444 | dev_set_drvdata(dev, NULL); | ||
445 | |||
446 | if (info == NULL) | ||
447 | return 0; | ||
448 | |||
449 | /* first thing we need to do is release all our mtds | ||
450 | * and their partitions, then go through freeing the | ||
451 | * resources used | ||
452 | */ | ||
453 | |||
454 | if (info->mtds != NULL) { | ||
455 | struct s3c2410_nand_mtd *ptr = info->mtds; | ||
456 | int mtdno; | ||
457 | |||
458 | for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) { | ||
459 | pr_debug("releasing mtd %d (%p)\n", mtdno, ptr); | ||
460 | nand_release(&ptr->mtd); | ||
461 | } | ||
462 | |||
463 | kfree(info->mtds); | ||
464 | } | ||
465 | |||
466 | /* free the common resources */ | ||
467 | |||
468 | if (info->clk != NULL && !IS_ERR(info->clk)) { | ||
469 | clk_disable(info->clk); | ||
470 | clk_unuse(info->clk); | ||
471 | clk_put(info->clk); | ||
472 | } | ||
473 | |||
474 | if (info->regs != NULL) { | ||
475 | iounmap(info->regs); | ||
476 | info->regs = NULL; | ||
477 | } | ||
478 | |||
479 | if (info->area != NULL) { | ||
480 | release_resource(info->area); | ||
481 | kfree(info->area); | ||
482 | info->area = NULL; | ||
483 | } | ||
484 | |||
485 | kfree(info); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | #ifdef CONFIG_MTD_PARTITIONS | ||
491 | static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | ||
492 | struct s3c2410_nand_mtd *mtd, | ||
493 | struct s3c2410_nand_set *set) | ||
494 | { | ||
495 | if (set == NULL) | ||
496 | return add_mtd_device(&mtd->mtd); | ||
497 | |||
498 | if (set->nr_partitions > 0 && set->partitions != NULL) { | ||
499 | return add_mtd_partitions(&mtd->mtd, | ||
500 | set->partitions, | ||
501 | set->nr_partitions); | ||
502 | } | ||
503 | |||
504 | return add_mtd_device(&mtd->mtd); | ||
505 | } | ||
506 | #else | ||
507 | static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info, | ||
508 | struct s3c2410_nand_mtd *mtd, | ||
509 | struct s3c2410_nand_set *set) | ||
510 | { | ||
511 | return add_mtd_device(&mtd->mtd); | ||
512 | } | ||
513 | #endif | ||
514 | |||
515 | /* s3c2410_nand_init_chip | ||
516 | * | ||
517 | * init a single instance of an chip | ||
518 | */ | ||
519 | |||
520 | static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | ||
521 | struct s3c2410_nand_mtd *nmtd, | ||
522 | struct s3c2410_nand_set *set) | ||
523 | { | ||
524 | struct nand_chip *chip = &nmtd->chip; | ||
525 | |||
526 | chip->IO_ADDR_R = (char *)info->regs + S3C2410_NFDATA; | ||
527 | chip->IO_ADDR_W = (char *)info->regs + S3C2410_NFDATA; | ||
528 | chip->hwcontrol = s3c2410_nand_hwcontrol; | ||
529 | chip->dev_ready = s3c2410_nand_devready; | ||
530 | chip->cmdfunc = s3c2410_nand_command; | ||
531 | chip->write_buf = s3c2410_nand_write_buf; | ||
532 | chip->read_buf = s3c2410_nand_read_buf; | ||
533 | chip->select_chip = s3c2410_nand_select_chip; | ||
534 | chip->chip_delay = 50; | ||
535 | chip->priv = nmtd; | ||
536 | chip->options = 0; | ||
537 | chip->controller = &info->controller; | ||
538 | |||
539 | nmtd->info = info; | ||
540 | nmtd->mtd.priv = chip; | ||
541 | nmtd->set = set; | ||
542 | |||
543 | if (hardware_ecc) { | ||
544 | chip->correct_data = s3c2410_nand_correct_data; | ||
545 | chip->enable_hwecc = s3c2410_nand_enable_hwecc; | ||
546 | chip->calculate_ecc = s3c2410_nand_calculate_ecc; | ||
547 | chip->eccmode = NAND_ECC_HW3_512; | ||
548 | chip->autooob = &nand_hw_eccoob; | ||
549 | } else { | ||
550 | chip->eccmode = NAND_ECC_SOFT; | ||
551 | } | ||
552 | } | ||
553 | |||
554 | /* s3c2410_nand_probe | ||
555 | * | ||
556 | * called by device layer when it finds a device matching | ||
557 | * one our driver can handled. This code checks to see if | ||
558 | * it can allocate all necessary resources then calls the | ||
559 | * nand layer to look for devices | ||
560 | */ | ||
561 | |||
562 | static int s3c2410_nand_probe(struct device *dev) | ||
563 | { | ||
564 | struct platform_device *pdev = to_platform_device(dev); | ||
565 | struct s3c2410_platform_nand *plat = to_nand_plat(dev); | ||
566 | struct s3c2410_nand_info *info; | ||
567 | struct s3c2410_nand_mtd *nmtd; | ||
568 | struct s3c2410_nand_set *sets; | ||
569 | struct resource *res; | ||
570 | int err = 0; | ||
571 | int size; | ||
572 | int nr_sets; | ||
573 | int setno; | ||
574 | |||
575 | pr_debug("s3c2410_nand_probe(%p)\n", dev); | ||
576 | |||
577 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
578 | if (info == NULL) { | ||
579 | printk(KERN_ERR PFX "no memory for flash info\n"); | ||
580 | err = -ENOMEM; | ||
581 | goto exit_error; | ||
582 | } | ||
583 | |||
584 | memzero(info, sizeof(*info)); | ||
585 | dev_set_drvdata(dev, info); | ||
586 | |||
587 | spin_lock_init(&info->controller.lock); | ||
588 | |||
589 | /* get the clock source and enable it */ | ||
590 | |||
591 | info->clk = clk_get(dev, "nand"); | ||
592 | if (IS_ERR(info->clk)) { | ||
593 | printk(KERN_ERR PFX "failed to get clock"); | ||
594 | err = -ENOENT; | ||
595 | goto exit_error; | ||
596 | } | ||
597 | |||
598 | clk_use(info->clk); | ||
599 | clk_enable(info->clk); | ||
600 | |||
601 | /* allocate and map the resource */ | ||
602 | |||
603 | res = pdev->resource; /* assume that the flash has one resource */ | ||
604 | size = res->end - res->start + 1; | ||
605 | |||
606 | info->area = request_mem_region(res->start, size, pdev->name); | ||
607 | |||
608 | if (info->area == NULL) { | ||
609 | printk(KERN_ERR PFX "cannot reserve register region\n"); | ||
610 | err = -ENOENT; | ||
611 | goto exit_error; | ||
612 | } | ||
613 | |||
614 | info->device = dev; | ||
615 | info->platform = plat; | ||
616 | info->regs = ioremap(res->start, size); | ||
617 | |||
618 | if (info->regs == NULL) { | ||
619 | printk(KERN_ERR PFX "cannot reserve register region\n"); | ||
620 | err = -EIO; | ||
621 | goto exit_error; | ||
622 | } | ||
623 | |||
624 | printk(KERN_INFO PFX "mapped registers at %p\n", info->regs); | ||
625 | |||
626 | /* initialise the hardware */ | ||
627 | |||
628 | err = s3c2410_nand_inithw(info, dev); | ||
629 | if (err != 0) | ||
630 | goto exit_error; | ||
631 | |||
632 | sets = (plat != NULL) ? plat->sets : NULL; | ||
633 | nr_sets = (plat != NULL) ? plat->nr_sets : 1; | ||
634 | |||
635 | info->mtd_count = nr_sets; | ||
636 | |||
637 | /* allocate our information */ | ||
638 | |||
639 | size = nr_sets * sizeof(*info->mtds); | ||
640 | info->mtds = kmalloc(size, GFP_KERNEL); | ||
641 | if (info->mtds == NULL) { | ||
642 | printk(KERN_ERR PFX "failed to allocate mtd storage\n"); | ||
643 | err = -ENOMEM; | ||
644 | goto exit_error; | ||
645 | } | ||
646 | |||
647 | memzero(info->mtds, size); | ||
648 | |||
649 | /* initialise all possible chips */ | ||
650 | |||
651 | nmtd = info->mtds; | ||
652 | |||
653 | for (setno = 0; setno < nr_sets; setno++, nmtd++) { | ||
654 | pr_debug("initialising set %d (%p, info %p)\n", | ||
655 | setno, nmtd, info); | ||
656 | |||
657 | s3c2410_nand_init_chip(info, nmtd, sets); | ||
658 | |||
659 | nmtd->scan_res = nand_scan(&nmtd->mtd, | ||
660 | (sets) ? sets->nr_chips : 1); | ||
661 | |||
662 | if (nmtd->scan_res == 0) { | ||
663 | s3c2410_nand_add_partition(info, nmtd, sets); | ||
664 | } | ||
665 | |||
666 | if (sets != NULL) | ||
667 | sets++; | ||
668 | } | ||
669 | |||
670 | pr_debug("initialised ok\n"); | ||
671 | return 0; | ||
672 | |||
673 | exit_error: | ||
674 | s3c2410_nand_remove(dev); | ||
675 | |||
676 | if (err == 0) | ||
677 | err = -EINVAL; | ||
678 | return err; | ||
679 | } | ||
680 | |||
681 | static struct device_driver s3c2410_nand_driver = { | ||
682 | .name = "s3c2410-nand", | ||
683 | .bus = &platform_bus_type, | ||
684 | .probe = s3c2410_nand_probe, | ||
685 | .remove = s3c2410_nand_remove, | ||
686 | }; | ||
687 | |||
688 | static int __init s3c2410_nand_init(void) | ||
689 | { | ||
690 | printk("S3C2410 NAND Driver, (c) 2004 Simtec Electronics\n"); | ||
691 | return driver_register(&s3c2410_nand_driver); | ||
692 | } | ||
693 | |||
694 | static void __exit s3c2410_nand_exit(void) | ||
695 | { | ||
696 | driver_unregister(&s3c2410_nand_driver); | ||
697 | } | ||
698 | |||
699 | module_init(s3c2410_nand_init); | ||
700 | module_exit(s3c2410_nand_exit); | ||
701 | |||
702 | MODULE_LICENSE("GPL"); | ||
703 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
704 | MODULE_DESCRIPTION("S3C2410 MTD NAND driver"); | ||
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c new file mode 100755 index 000000000000..29572793334c --- /dev/null +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -0,0 +1,260 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/sharpsl.c | ||
3 | * | ||
4 | * Copyright (C) 2004 Richard Purdie | ||
5 | * | ||
6 | * $Id: sharpsl.c,v 1.3 2005/01/03 14:53:50 rpurdie Exp $ | ||
7 | * | ||
8 | * Based on Sharp's NAND driver sharp_sl.c | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/genhd.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/mtd/mtd.h> | ||
21 | #include <linux/mtd/nand.h> | ||
22 | #include <linux/mtd/nand_ecc.h> | ||
23 | #include <linux/mtd/partitions.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <asm/io.h> | ||
26 | #include <asm/hardware.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | |||
29 | static void __iomem *sharpsl_io_base; | ||
30 | static int sharpsl_phys_base = 0x0C000000; | ||
31 | |||
32 | /* register offset */ | ||
33 | #define ECCLPLB sharpsl_io_base+0x00 /* line parity 7 - 0 bit */ | ||
34 | #define ECCLPUB sharpsl_io_base+0x04 /* line parity 15 - 8 bit */ | ||
35 | #define ECCCP sharpsl_io_base+0x08 /* column parity 5 - 0 bit */ | ||
36 | #define ECCCNTR sharpsl_io_base+0x0C /* ECC byte counter */ | ||
37 | #define ECCCLRR sharpsl_io_base+0x10 /* cleare ECC */ | ||
38 | #define FLASHIO sharpsl_io_base+0x14 /* Flash I/O */ | ||
39 | #define FLASHCTL sharpsl_io_base+0x18 /* Flash Control */ | ||
40 | |||
41 | /* Flash control bit */ | ||
42 | #define FLRYBY (1 << 5) | ||
43 | #define FLCE1 (1 << 4) | ||
44 | #define FLWP (1 << 3) | ||
45 | #define FLALE (1 << 2) | ||
46 | #define FLCLE (1 << 1) | ||
47 | #define FLCE0 (1 << 0) | ||
48 | |||
49 | |||
50 | /* | ||
51 | * MTD structure for SharpSL | ||
52 | */ | ||
53 | static struct mtd_info *sharpsl_mtd = NULL; | ||
54 | |||
55 | /* | ||
56 | * Define partitions for flash device | ||
57 | */ | ||
58 | #define DEFAULT_NUM_PARTITIONS 3 | ||
59 | |||
60 | static int nr_partitions; | ||
61 | static struct mtd_partition sharpsl_nand_default_partition_info[] = { | ||
62 | { | ||
63 | .name = "System Area", | ||
64 | .offset = 0, | ||
65 | .size = 7 * 1024 * 1024, | ||
66 | }, | ||
67 | { | ||
68 | .name = "Root Filesystem", | ||
69 | .offset = 7 * 1024 * 1024, | ||
70 | .size = 30 * 1024 * 1024, | ||
71 | }, | ||
72 | { | ||
73 | .name = "Home Filesystem", | ||
74 | .offset = MTDPART_OFS_APPEND , | ||
75 | .size = MTDPART_SIZ_FULL , | ||
76 | }, | ||
77 | }; | ||
78 | |||
79 | /* | ||
80 | * hardware specific access to control-lines | ||
81 | */ | ||
82 | static void | ||
83 | sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd) | ||
84 | { | ||
85 | switch (cmd) { | ||
86 | case NAND_CTL_SETCLE: | ||
87 | writeb(readb(FLASHCTL) | FLCLE, FLASHCTL); | ||
88 | break; | ||
89 | case NAND_CTL_CLRCLE: | ||
90 | writeb(readb(FLASHCTL) & ~FLCLE, FLASHCTL); | ||
91 | break; | ||
92 | |||
93 | case NAND_CTL_SETALE: | ||
94 | writeb(readb(FLASHCTL) | FLALE, FLASHCTL); | ||
95 | break; | ||
96 | case NAND_CTL_CLRALE: | ||
97 | writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL); | ||
98 | break; | ||
99 | |||
100 | case NAND_CTL_SETNCE: | ||
101 | writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL); | ||
102 | break; | ||
103 | case NAND_CTL_CLRNCE: | ||
104 | writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL); | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | ||
110 | |||
111 | static struct nand_bbt_descr sharpsl_bbt = { | ||
112 | .options = 0, | ||
113 | .offs = 4, | ||
114 | .len = 2, | ||
115 | .pattern = scan_ff_pattern | ||
116 | }; | ||
117 | |||
118 | static int | ||
119 | sharpsl_nand_dev_ready(struct mtd_info* mtd) | ||
120 | { | ||
121 | return !((readb(FLASHCTL) & FLRYBY) == 0); | ||
122 | } | ||
123 | |||
124 | static void | ||
125 | sharpsl_nand_enable_hwecc(struct mtd_info* mtd, int mode) | ||
126 | { | ||
127 | writeb(0 ,ECCCLRR); | ||
128 | } | ||
129 | |||
130 | static int | ||
131 | sharpsl_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat, | ||
132 | u_char* ecc_code) | ||
133 | { | ||
134 | ecc_code[0] = ~readb(ECCLPUB); | ||
135 | ecc_code[1] = ~readb(ECCLPLB); | ||
136 | ecc_code[2] = (~readb(ECCCP) << 2) | 0x03; | ||
137 | return readb(ECCCNTR) != 0; | ||
138 | } | ||
139 | |||
140 | |||
141 | #ifdef CONFIG_MTD_PARTITIONS | ||
142 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
143 | #endif | ||
144 | |||
145 | |||
146 | /* | ||
147 | * Main initialization routine | ||
148 | */ | ||
149 | int __init | ||
150 | sharpsl_nand_init(void) | ||
151 | { | ||
152 | struct nand_chip *this; | ||
153 | struct mtd_partition* sharpsl_partition_info; | ||
154 | int err = 0; | ||
155 | |||
156 | /* Allocate memory for MTD device structure and private data */ | ||
157 | sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), | ||
158 | GFP_KERNEL); | ||
159 | if (!sharpsl_mtd) { | ||
160 | printk ("Unable to allocate SharpSL NAND MTD device structure.\n"); | ||
161 | return -ENOMEM; | ||
162 | } | ||
163 | |||
164 | /* map physical adress */ | ||
165 | sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000); | ||
166 | if(!sharpsl_io_base){ | ||
167 | printk("ioremap to access Sharp SL NAND chip failed\n"); | ||
168 | kfree(sharpsl_mtd); | ||
169 | return -EIO; | ||
170 | } | ||
171 | |||
172 | /* Get pointer to private data */ | ||
173 | this = (struct nand_chip *) (&sharpsl_mtd[1]); | ||
174 | |||
175 | /* Initialize structures */ | ||
176 | memset((char *) sharpsl_mtd, 0, sizeof(struct mtd_info)); | ||
177 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
178 | |||
179 | /* Link the private data with the MTD structure */ | ||
180 | sharpsl_mtd->priv = this; | ||
181 | |||
182 | /* | ||
183 | * PXA initialize | ||
184 | */ | ||
185 | writeb(readb(FLASHCTL) | FLWP, FLASHCTL); | ||
186 | |||
187 | /* Set address of NAND IO lines */ | ||
188 | this->IO_ADDR_R = FLASHIO; | ||
189 | this->IO_ADDR_W = FLASHIO; | ||
190 | /* Set address of hardware control function */ | ||
191 | this->hwcontrol = sharpsl_nand_hwcontrol; | ||
192 | this->dev_ready = sharpsl_nand_dev_ready; | ||
193 | /* 15 us command delay time */ | ||
194 | this->chip_delay = 15; | ||
195 | /* set eccmode using hardware ECC */ | ||
196 | this->eccmode = NAND_ECC_HW3_256; | ||
197 | this->enable_hwecc = sharpsl_nand_enable_hwecc; | ||
198 | this->calculate_ecc = sharpsl_nand_calculate_ecc; | ||
199 | this->correct_data = nand_correct_data; | ||
200 | this->badblock_pattern = &sharpsl_bbt; | ||
201 | |||
202 | /* Scan to find existence of the device */ | ||
203 | err=nand_scan(sharpsl_mtd,1); | ||
204 | if (err) { | ||
205 | iounmap(sharpsl_io_base); | ||
206 | kfree(sharpsl_mtd); | ||
207 | return err; | ||
208 | } | ||
209 | |||
210 | /* Register the partitions */ | ||
211 | sharpsl_mtd->name = "sharpsl-nand"; | ||
212 | nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, | ||
213 | &sharpsl_partition_info, 0); | ||
214 | |||
215 | if (nr_partitions <= 0) { | ||
216 | nr_partitions = DEFAULT_NUM_PARTITIONS; | ||
217 | sharpsl_partition_info = sharpsl_nand_default_partition_info; | ||
218 | if (machine_is_poodle()) { | ||
219 | sharpsl_partition_info[1].size=22 * 1024 * 1024; | ||
220 | } else if (machine_is_corgi() || machine_is_shepherd()) { | ||
221 | sharpsl_partition_info[1].size=25 * 1024 * 1024; | ||
222 | } else if (machine_is_husky()) { | ||
223 | sharpsl_partition_info[1].size=53 * 1024 * 1024; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | if (machine_is_husky()) { | ||
228 | /* Need to use small eraseblock size for backward compatibility */ | ||
229 | sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; | ||
230 | } | ||
231 | |||
232 | add_mtd_partitions(sharpsl_mtd, sharpsl_partition_info, nr_partitions); | ||
233 | |||
234 | /* Return happy */ | ||
235 | return 0; | ||
236 | } | ||
237 | module_init(sharpsl_nand_init); | ||
238 | |||
239 | /* | ||
240 | * Clean up routine | ||
241 | */ | ||
242 | #ifdef MODULE | ||
243 | static void __exit sharpsl_nand_cleanup(void) | ||
244 | { | ||
245 | struct nand_chip *this = (struct nand_chip *) &sharpsl_mtd[1]; | ||
246 | |||
247 | /* Release resources, unregister device */ | ||
248 | nand_release(sharpsl_mtd); | ||
249 | |||
250 | iounmap(sharpsl_io_base); | ||
251 | |||
252 | /* Free the MTD device structure */ | ||
253 | kfree(sharpsl_mtd); | ||
254 | } | ||
255 | module_exit(sharpsl_nand_cleanup); | ||
256 | #endif | ||
257 | |||
258 | MODULE_LICENSE("GPL"); | ||
259 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
260 | MODULE_DESCRIPTION("Device specific logic for NAND flash on Sharp SL-C7xx Series"); | ||
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c new file mode 100644 index 000000000000..b777c412b758 --- /dev/null +++ b/drivers/mtd/nand/spia.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/spia.c | ||
3 | * | ||
4 | * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) | ||
5 | * | ||
6 | * | ||
7 | * 10-29-2001 TG change to support hardwarespecific access | ||
8 | * to controllines (due to change in nand.c) | ||
9 | * page_cache added | ||
10 | * | ||
11 | * $Id: spia.c,v 1.24 2004/11/04 12:53:10 gleixner Exp $ | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | * | ||
17 | * Overview: | ||
18 | * This is a device driver for the NAND flash device found on the | ||
19 | * SPIA board which utilizes the Toshiba TC58V64AFT part. This is | ||
20 | * a 64Mibit (8MiB x 8 bits) NAND flash device. | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/mtd/mtd.h> | ||
28 | #include <linux/mtd/nand.h> | ||
29 | #include <linux/mtd/partitions.h> | ||
30 | #include <asm/io.h> | ||
31 | |||
32 | /* | ||
33 | * MTD structure for SPIA board | ||
34 | */ | ||
35 | static struct mtd_info *spia_mtd = NULL; | ||
36 | |||
37 | /* | ||
38 | * Values specific to the SPIA board (used with EP7212 processor) | ||
39 | */ | ||
40 | #define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */ | ||
41 | #define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */ | ||
42 | #define SPIA_PEDR 0x0080 /* | ||
43 | * IO offset to Port E data register | ||
44 | * where the CLE, ALE and NCE pins | ||
45 | * are wired to. | ||
46 | */ | ||
47 | #define SPIA_PEDDR 0x00c0 /* | ||
48 | * IO offset to Port E data direction | ||
49 | * register so we can control the IO | ||
50 | * lines. | ||
51 | */ | ||
52 | |||
53 | /* | ||
54 | * Module stuff | ||
55 | */ | ||
56 | |||
57 | static int spia_io_base = SPIA_IO_BASE; | ||
58 | static int spia_fio_base = SPIA_FIO_BASE; | ||
59 | static int spia_pedr = SPIA_PEDR; | ||
60 | static int spia_peddr = SPIA_PEDDR; | ||
61 | |||
62 | module_param(spia_io_base, int, 0); | ||
63 | module_param(spia_fio_base, int, 0); | ||
64 | module_param(spia_pedr, int, 0); | ||
65 | module_param(spia_peddr, int, 0); | ||
66 | |||
67 | /* | ||
68 | * Define partitions for flash device | ||
69 | */ | ||
70 | const static struct mtd_partition partition_info[] = { | ||
71 | { | ||
72 | .name = "SPIA flash partition 1", | ||
73 | .offset = 0, | ||
74 | .size = 2*1024*1024 | ||
75 | }, | ||
76 | { | ||
77 | .name = "SPIA flash partition 2", | ||
78 | .offset = 2*1024*1024, | ||
79 | .size = 6*1024*1024 | ||
80 | } | ||
81 | }; | ||
82 | #define NUM_PARTITIONS 2 | ||
83 | |||
84 | |||
85 | /* | ||
86 | * hardware specific access to control-lines | ||
87 | */ | ||
88 | static void spia_hwcontrol(struct mtd_info *mtd, int cmd){ | ||
89 | |||
90 | switch(cmd){ | ||
91 | |||
92 | case NAND_CTL_SETCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x01; break; | ||
93 | case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x01; break; | ||
94 | |||
95 | case NAND_CTL_SETALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x02; break; | ||
96 | case NAND_CTL_CLRALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x02; break; | ||
97 | |||
98 | case NAND_CTL_SETNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x04; break; | ||
99 | case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x04; break; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Main initialization routine | ||
105 | */ | ||
106 | int __init spia_init (void) | ||
107 | { | ||
108 | struct nand_chip *this; | ||
109 | |||
110 | /* Allocate memory for MTD device structure and private data */ | ||
111 | spia_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), | ||
112 | GFP_KERNEL); | ||
113 | if (!spia_mtd) { | ||
114 | printk ("Unable to allocate SPIA NAND MTD device structure.\n"); | ||
115 | return -ENOMEM; | ||
116 | } | ||
117 | |||
118 | /* Get pointer to private data */ | ||
119 | this = (struct nand_chip *) (&spia_mtd[1]); | ||
120 | |||
121 | /* Initialize structures */ | ||
122 | memset((char *) spia_mtd, 0, sizeof(struct mtd_info)); | ||
123 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
124 | |||
125 | /* Link the private data with the MTD structure */ | ||
126 | spia_mtd->priv = this; | ||
127 | |||
128 | /* | ||
129 | * Set GPIO Port E control register so that the pins are configured | ||
130 | * to be outputs for controlling the NAND flash. | ||
131 | */ | ||
132 | (*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07; | ||
133 | |||
134 | /* Set address of NAND IO lines */ | ||
135 | this->IO_ADDR_R = (void __iomem *) spia_fio_base; | ||
136 | this->IO_ADDR_W = (void __iomem *) spia_fio_base; | ||
137 | /* Set address of hardware control function */ | ||
138 | this->hwcontrol = spia_hwcontrol; | ||
139 | /* 15 us command delay time */ | ||
140 | this->chip_delay = 15; | ||
141 | |||
142 | /* Scan to find existence of the device */ | ||
143 | if (nand_scan (spia_mtd, 1)) { | ||
144 | kfree (spia_mtd); | ||
145 | return -ENXIO; | ||
146 | } | ||
147 | |||
148 | /* Register the partitions */ | ||
149 | add_mtd_partitions(spia_mtd, partition_info, NUM_PARTITIONS); | ||
150 | |||
151 | /* Return happy */ | ||
152 | return 0; | ||
153 | } | ||
154 | module_init(spia_init); | ||
155 | |||
156 | /* | ||
157 | * Clean up routine | ||
158 | */ | ||
159 | #ifdef MODULE | ||
160 | static void __exit spia_cleanup (void) | ||
161 | { | ||
162 | /* Release resources, unregister device */ | ||
163 | nand_release (spia_mtd); | ||
164 | |||
165 | /* Free the MTD device structure */ | ||
166 | kfree (spia_mtd); | ||
167 | } | ||
168 | module_exit(spia_cleanup); | ||
169 | #endif | ||
170 | |||
171 | MODULE_LICENSE("GPL"); | ||
172 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com"); | ||
173 | MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on SPIA board"); | ||
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c new file mode 100644 index 000000000000..52c808fb5fa9 --- /dev/null +++ b/drivers/mtd/nand/toto.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/toto.c | ||
3 | * | ||
4 | * Copyright (c) 2003 Texas Instruments | ||
5 | * | ||
6 | * Derived from drivers/mtd/autcpu12.c | ||
7 | * | ||
8 | * Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * Overview: | ||
15 | * This is a device driver for the NAND flash device found on the | ||
16 | * TI fido board. It supports 32MiB and 64MiB cards | ||
17 | * | ||
18 | * $Id: toto.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ | ||
19 | */ | ||
20 | |||
21 | #include <linux/slab.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/mtd/mtd.h> | ||
26 | #include <linux/mtd/nand.h> | ||
27 | #include <linux/mtd/partitions.h> | ||
28 | #include <asm/io.h> | ||
29 | #include <asm/arch/hardware.h> | ||
30 | #include <asm/sizes.h> | ||
31 | #include <asm/arch/toto.h> | ||
32 | #include <asm/arch-omap1510/hardware.h> | ||
33 | #include <asm/arch/gpio.h> | ||
34 | |||
35 | /* | ||
36 | * MTD structure for TOTO board | ||
37 | */ | ||
38 | static struct mtd_info *toto_mtd = NULL; | ||
39 | |||
40 | static unsigned long toto_io_base = OMAP_FLASH_1_BASE; | ||
41 | |||
42 | #define CONFIG_NAND_WORKAROUND 1 | ||
43 | |||
44 | #define NAND_NCE 0x4000 | ||
45 | #define NAND_CLE 0x1000 | ||
46 | #define NAND_ALE 0x0002 | ||
47 | #define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE) | ||
48 | |||
49 | #define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0) | ||
50 | #define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE) | ||
51 | #ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */ | ||
52 | #define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2) | ||
53 | #define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0) | ||
54 | #else | ||
55 | #define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0) | ||
56 | #define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE) | ||
57 | #endif | ||
58 | #define T_NAND_CTL_SETNCE(iob) gpiosetout(NAND_NCE, 0) | ||
59 | #define T_NAND_CTL_CLRNCE(iob) gpiosetout(NAND_NCE, NAND_NCE) | ||
60 | |||
61 | /* | ||
62 | * Define partitions for flash devices | ||
63 | */ | ||
64 | |||
65 | static struct mtd_partition partition_info64M[] = { | ||
66 | { .name = "toto kernel partition 1", | ||
67 | .offset = 0, | ||
68 | .size = 2 * SZ_1M }, | ||
69 | { .name = "toto file sys partition 2", | ||
70 | .offset = 2 * SZ_1M, | ||
71 | .size = 14 * SZ_1M }, | ||
72 | { .name = "toto user partition 3", | ||
73 | .offset = 16 * SZ_1M, | ||
74 | .size = 16 * SZ_1M }, | ||
75 | { .name = "toto devboard extra partition 4", | ||
76 | .offset = 32 * SZ_1M, | ||
77 | .size = 32 * SZ_1M }, | ||
78 | }; | ||
79 | |||
80 | static struct mtd_partition partition_info32M[] = { | ||
81 | { .name = "toto kernel partition 1", | ||
82 | .offset = 0, | ||
83 | .size = 2 * SZ_1M }, | ||
84 | { .name = "toto file sys partition 2", | ||
85 | .offset = 2 * SZ_1M, | ||
86 | .size = 14 * SZ_1M }, | ||
87 | { .name = "toto user partition 3", | ||
88 | .offset = 16 * SZ_1M, | ||
89 | .size = 16 * SZ_1M }, | ||
90 | }; | ||
91 | |||
92 | #define NUM_PARTITIONS32M 3 | ||
93 | #define NUM_PARTITIONS64M 4 | ||
94 | /* | ||
95 | * hardware specific access to control-lines | ||
96 | */ | ||
97 | |||
98 | static void toto_hwcontrol(struct mtd_info *mtd, int cmd) | ||
99 | { | ||
100 | |||
101 | udelay(1); /* hopefully enough time for tc make proceding write to clear */ | ||
102 | switch(cmd){ | ||
103 | |||
104 | case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break; | ||
105 | case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break; | ||
106 | |||
107 | case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break; | ||
108 | case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break; | ||
109 | |||
110 | case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break; | ||
111 | case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break; | ||
112 | } | ||
113 | udelay(1); /* allow time to ensure gpio state to over take memory write */ | ||
114 | } | ||
115 | |||
116 | /* | ||
117 | * Main initialization routine | ||
118 | */ | ||
119 | int __init toto_init (void) | ||
120 | { | ||
121 | struct nand_chip *this; | ||
122 | int err = 0; | ||
123 | |||
124 | /* Allocate memory for MTD device structure and private data */ | ||
125 | toto_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), | ||
126 | GFP_KERNEL); | ||
127 | if (!toto_mtd) { | ||
128 | printk (KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n"); | ||
129 | err = -ENOMEM; | ||
130 | goto out; | ||
131 | } | ||
132 | |||
133 | /* Get pointer to private data */ | ||
134 | this = (struct nand_chip *) (&toto_mtd[1]); | ||
135 | |||
136 | /* Initialize structures */ | ||
137 | memset((char *) toto_mtd, 0, sizeof(struct mtd_info)); | ||
138 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
139 | |||
140 | /* Link the private data with the MTD structure */ | ||
141 | toto_mtd->priv = this; | ||
142 | |||
143 | /* Set address of NAND IO lines */ | ||
144 | this->IO_ADDR_R = toto_io_base; | ||
145 | this->IO_ADDR_W = toto_io_base; | ||
146 | this->hwcontrol = toto_hwcontrol; | ||
147 | this->dev_ready = NULL; | ||
148 | /* 25 us command delay time */ | ||
149 | this->chip_delay = 30; | ||
150 | this->eccmode = NAND_ECC_SOFT; | ||
151 | |||
152 | /* Scan to find existance of the device */ | ||
153 | if (nand_scan (toto_mtd, 1)) { | ||
154 | err = -ENXIO; | ||
155 | goto out_mtd; | ||
156 | } | ||
157 | |||
158 | /* Register the partitions */ | ||
159 | switch(toto_mtd->size){ | ||
160 | case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; | ||
161 | case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break; | ||
162 | default: { | ||
163 | printk (KERN_WARNING "Unsupported Nand device\n"); | ||
164 | err = -ENXIO; | ||
165 | goto out_buf; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | gpioreserve(NAND_MASK); /* claim our gpios */ | ||
170 | archflashwp(0,0); /* open up flash for writing */ | ||
171 | |||
172 | goto out; | ||
173 | |||
174 | out_buf: | ||
175 | kfree (this->data_buf); | ||
176 | out_mtd: | ||
177 | kfree (toto_mtd); | ||
178 | out: | ||
179 | return err; | ||
180 | } | ||
181 | |||
182 | module_init(toto_init); | ||
183 | |||
184 | /* | ||
185 | * Clean up routine | ||
186 | */ | ||
187 | static void __exit toto_cleanup (void) | ||
188 | { | ||
189 | /* Release resources, unregister device */ | ||
190 | nand_release (toto_mtd); | ||
191 | |||
192 | /* Free the MTD device structure */ | ||
193 | kfree (toto_mtd); | ||
194 | |||
195 | /* stop flash writes */ | ||
196 | archflashwp(0,1); | ||
197 | |||
198 | /* release gpios to system */ | ||
199 | gpiorelease(NAND_MASK); | ||
200 | } | ||
201 | module_exit(toto_cleanup); | ||
202 | |||
203 | MODULE_LICENSE("GPL"); | ||
204 | MODULE_AUTHOR("Richard Woodruff <r-woodruff2@ti.com>"); | ||
205 | MODULE_DESCRIPTION("Glue layer for NAND flash on toto board"); | ||
diff --git a/drivers/mtd/nand/tx4925ndfmc.c b/drivers/mtd/nand/tx4925ndfmc.c new file mode 100644 index 000000000000..bba688830c9b --- /dev/null +++ b/drivers/mtd/nand/tx4925ndfmc.c | |||
@@ -0,0 +1,416 @@ | |||
1 | /* | ||
2 | * drivers/mtd/tx4925ndfmc.c | ||
3 | * | ||
4 | * Overview: | ||
5 | * This is a device driver for the NAND flash device found on the | ||
6 | * Toshiba RBTX4925 reference board, which is a SmartMediaCard. It supports | ||
7 | * 16MiB, 32MiB and 64MiB cards. | ||
8 | * | ||
9 | * Author: MontaVista Software, Inc. source@mvista.com | ||
10 | * | ||
11 | * Derived from drivers/mtd/autcpu12.c | ||
12 | * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) | ||
13 | * | ||
14 | * $Id: tx4925ndfmc.c,v 1.5 2004/10/05 13:50:20 gleixner Exp $ | ||
15 | * | ||
16 | * Copyright (C) 2001 Toshiba Corporation | ||
17 | * | ||
18 | * 2003 (c) MontaVista Software, Inc. This file is licensed under | ||
19 | * the terms of the GNU General Public License version 2. This program | ||
20 | * is licensed "as is" without any warranty of any kind, whether express | ||
21 | * or implied. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/slab.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/mtd/mtd.h> | ||
29 | #include <linux/mtd/nand.h> | ||
30 | #include <linux/mtd/partitions.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <asm/tx4925/tx4925_nand.h> | ||
34 | |||
35 | extern struct nand_oobinfo jffs2_oobinfo; | ||
36 | |||
37 | /* | ||
38 | * MTD structure for RBTX4925 board | ||
39 | */ | ||
40 | static struct mtd_info *tx4925ndfmc_mtd = NULL; | ||
41 | |||
42 | /* | ||
43 | * Define partitions for flash devices | ||
44 | */ | ||
45 | |||
46 | static struct mtd_partition partition_info16k[] = { | ||
47 | { .name = "RBTX4925 flash partition 1", | ||
48 | .offset = 0, | ||
49 | .size = 8 * 0x00100000 }, | ||
50 | { .name = "RBTX4925 flash partition 2", | ||
51 | .offset = 8 * 0x00100000, | ||
52 | .size = 8 * 0x00100000 }, | ||
53 | }; | ||
54 | |||
55 | static struct mtd_partition partition_info32k[] = { | ||
56 | { .name = "RBTX4925 flash partition 1", | ||
57 | .offset = 0, | ||
58 | .size = 8 * 0x00100000 }, | ||
59 | { .name = "RBTX4925 flash partition 2", | ||
60 | .offset = 8 * 0x00100000, | ||
61 | .size = 24 * 0x00100000 }, | ||
62 | }; | ||
63 | |||
64 | static struct mtd_partition partition_info64k[] = { | ||
65 | { .name = "User FS", | ||
66 | .offset = 0, | ||
67 | .size = 16 * 0x00100000 }, | ||
68 | { .name = "RBTX4925 flash partition 2", | ||
69 | .offset = 16 * 0x00100000, | ||
70 | .size = 48 * 0x00100000}, | ||
71 | }; | ||
72 | |||
73 | static struct mtd_partition partition_info128k[] = { | ||
74 | { .name = "Skip bad section", | ||
75 | .offset = 0, | ||
76 | .size = 16 * 0x00100000 }, | ||
77 | { .name = "User FS", | ||
78 | .offset = 16 * 0x00100000, | ||
79 | .size = 112 * 0x00100000 }, | ||
80 | }; | ||
81 | #define NUM_PARTITIONS16K 2 | ||
82 | #define NUM_PARTITIONS32K 2 | ||
83 | #define NUM_PARTITIONS64K 2 | ||
84 | #define NUM_PARTITIONS128K 2 | ||
85 | |||
86 | /* | ||
87 | * hardware specific access to control-lines | ||
88 | */ | ||
89 | static void tx4925ndfmc_hwcontrol(struct mtd_info *mtd, int cmd) | ||
90 | { | ||
91 | |||
92 | switch(cmd){ | ||
93 | |||
94 | case NAND_CTL_SETCLE: | ||
95 | tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CLE; | ||
96 | break; | ||
97 | case NAND_CTL_CLRCLE: | ||
98 | tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CLE; | ||
99 | break; | ||
100 | case NAND_CTL_SETALE: | ||
101 | tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ALE; | ||
102 | break; | ||
103 | case NAND_CTL_CLRALE: | ||
104 | tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ALE; | ||
105 | break; | ||
106 | case NAND_CTL_SETNCE: | ||
107 | tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_CE; | ||
108 | break; | ||
109 | case NAND_CTL_CLRNCE: | ||
110 | tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_CE; | ||
111 | break; | ||
112 | case NAND_CTL_SETWP: | ||
113 | tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_WE; | ||
114 | break; | ||
115 | case NAND_CTL_CLRWP: | ||
116 | tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_WE; | ||
117 | break; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * read device ready pin | ||
123 | */ | ||
124 | static int tx4925ndfmc_device_ready(struct mtd_info *mtd) | ||
125 | { | ||
126 | int ready; | ||
127 | ready = (tx4925_ndfmcptr->sr & TX4925_NDSFR_BUSY) ? 0 : 1; | ||
128 | return ready; | ||
129 | } | ||
130 | void tx4925ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) | ||
131 | { | ||
132 | /* reset first */ | ||
133 | tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_MASK; | ||
134 | tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK; | ||
135 | tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_ENAB; | ||
136 | } | ||
137 | static void tx4925ndfmc_disable_ecc(void) | ||
138 | { | ||
139 | tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK; | ||
140 | } | ||
141 | static void tx4925ndfmc_enable_read_ecc(void) | ||
142 | { | ||
143 | tx4925_ndfmcptr->mcr &= ~TX4925_NDFMCR_ECC_CNTL_MASK; | ||
144 | tx4925_ndfmcptr->mcr |= TX4925_NDFMCR_ECC_CNTL_READ; | ||
145 | } | ||
146 | void tx4925ndfmc_readecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code){ | ||
147 | int i; | ||
148 | u_char *ecc = ecc_code; | ||
149 | tx4925ndfmc_enable_read_ecc(); | ||
150 | for (i = 0;i < 6;i++,ecc++) | ||
151 | *ecc = tx4925_read_nfmc(&(tx4925_ndfmcptr->dtr)); | ||
152 | tx4925ndfmc_disable_ecc(); | ||
153 | } | ||
154 | void tx4925ndfmc_device_setup(void) | ||
155 | { | ||
156 | |||
157 | *(unsigned char *)0xbb005000 &= ~0x08; | ||
158 | |||
159 | /* reset NDFMC */ | ||
160 | tx4925_ndfmcptr->rstr |= TX4925_NDFRSTR_RST; | ||
161 | while (tx4925_ndfmcptr->rstr & TX4925_NDFRSTR_RST); | ||
162 | |||
163 | /* setup BusSeparete, Hold Time, Strobe Pulse Width */ | ||
164 | tx4925_ndfmcptr->mcr = TX4925_BSPRT ? TX4925_NDFMCR_BSPRT : 0; | ||
165 | tx4925_ndfmcptr->spr = TX4925_HOLD << 4 | TX4925_SPW; | ||
166 | } | ||
167 | static u_char tx4925ndfmc_nand_read_byte(struct mtd_info *mtd) | ||
168 | { | ||
169 | struct nand_chip *this = mtd->priv; | ||
170 | return tx4925_read_nfmc(this->IO_ADDR_R); | ||
171 | } | ||
172 | |||
173 | static void tx4925ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte) | ||
174 | { | ||
175 | struct nand_chip *this = mtd->priv; | ||
176 | tx4925_write_nfmc(byte, this->IO_ADDR_W); | ||
177 | } | ||
178 | |||
179 | static void tx4925ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
180 | { | ||
181 | int i; | ||
182 | struct nand_chip *this = mtd->priv; | ||
183 | |||
184 | for (i=0; i<len; i++) | ||
185 | tx4925_write_nfmc(buf[i], this->IO_ADDR_W); | ||
186 | } | ||
187 | |||
188 | static void tx4925ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | ||
189 | { | ||
190 | int i; | ||
191 | struct nand_chip *this = mtd->priv; | ||
192 | |||
193 | for (i=0; i<len; i++) | ||
194 | buf[i] = tx4925_read_nfmc(this->IO_ADDR_R); | ||
195 | } | ||
196 | |||
197 | static int tx4925ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
198 | { | ||
199 | int i; | ||
200 | struct nand_chip *this = mtd->priv; | ||
201 | |||
202 | for (i=0; i<len; i++) | ||
203 | if (buf[i] != tx4925_read_nfmc(this->IO_ADDR_R)) | ||
204 | return -EFAULT; | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * Send command to NAND device | ||
211 | */ | ||
212 | static void tx4925ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) | ||
213 | { | ||
214 | register struct nand_chip *this = mtd->priv; | ||
215 | |||
216 | /* Begin command latch cycle */ | ||
217 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
218 | /* | ||
219 | * Write out the command to the device. | ||
220 | */ | ||
221 | if (command == NAND_CMD_SEQIN) { | ||
222 | int readcmd; | ||
223 | |||
224 | if (column >= mtd->oobblock) { | ||
225 | /* OOB area */ | ||
226 | column -= mtd->oobblock; | ||
227 | readcmd = NAND_CMD_READOOB; | ||
228 | } else if (column < 256) { | ||
229 | /* First 256 bytes --> READ0 */ | ||
230 | readcmd = NAND_CMD_READ0; | ||
231 | } else { | ||
232 | column -= 256; | ||
233 | readcmd = NAND_CMD_READ1; | ||
234 | } | ||
235 | this->write_byte(mtd, readcmd); | ||
236 | } | ||
237 | this->write_byte(mtd, command); | ||
238 | |||
239 | /* Set ALE and clear CLE to start address cycle */ | ||
240 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
241 | |||
242 | if (column != -1 || page_addr != -1) { | ||
243 | this->hwcontrol(mtd, NAND_CTL_SETALE); | ||
244 | |||
245 | /* Serially input address */ | ||
246 | if (column != -1) | ||
247 | this->write_byte(mtd, column); | ||
248 | if (page_addr != -1) { | ||
249 | this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); | ||
250 | this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); | ||
251 | /* One more address cycle for higher density devices */ | ||
252 | if (mtd->size & 0x0c000000) | ||
253 | this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); | ||
254 | } | ||
255 | /* Latch in address */ | ||
256 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * program and erase have their own busy handlers | ||
261 | * status and sequential in needs no delay | ||
262 | */ | ||
263 | switch (command) { | ||
264 | |||
265 | case NAND_CMD_PAGEPROG: | ||
266 | /* Turn off WE */ | ||
267 | this->hwcontrol (mtd, NAND_CTL_CLRWP); | ||
268 | return; | ||
269 | |||
270 | case NAND_CMD_SEQIN: | ||
271 | /* Turn on WE */ | ||
272 | this->hwcontrol (mtd, NAND_CTL_SETWP); | ||
273 | return; | ||
274 | |||
275 | case NAND_CMD_ERASE1: | ||
276 | case NAND_CMD_ERASE2: | ||
277 | case NAND_CMD_STATUS: | ||
278 | return; | ||
279 | |||
280 | case NAND_CMD_RESET: | ||
281 | if (this->dev_ready) | ||
282 | break; | ||
283 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
284 | this->write_byte(mtd, NAND_CMD_STATUS); | ||
285 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
286 | while ( !(this->read_byte(mtd) & 0x40)); | ||
287 | return; | ||
288 | |||
289 | /* This applies to read commands */ | ||
290 | default: | ||
291 | /* | ||
292 | * If we don't have access to the busy pin, we apply the given | ||
293 | * command delay | ||
294 | */ | ||
295 | if (!this->dev_ready) { | ||
296 | udelay (this->chip_delay); | ||
297 | return; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | /* wait until command is processed */ | ||
302 | while (!this->dev_ready(mtd)); | ||
303 | } | ||
304 | |||
305 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
306 | extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partitio | ||
307 | n **pparts, char *); | ||
308 | #endif | ||
309 | |||
310 | /* | ||
311 | * Main initialization routine | ||
312 | */ | ||
313 | extern int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); | ||
314 | int __init tx4925ndfmc_init (void) | ||
315 | { | ||
316 | struct nand_chip *this; | ||
317 | int err = 0; | ||
318 | |||
319 | /* Allocate memory for MTD device structure and private data */ | ||
320 | tx4925ndfmc_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), | ||
321 | GFP_KERNEL); | ||
322 | if (!tx4925ndfmc_mtd) { | ||
323 | printk ("Unable to allocate RBTX4925 NAND MTD device structure.\n"); | ||
324 | err = -ENOMEM; | ||
325 | goto out; | ||
326 | } | ||
327 | |||
328 | tx4925ndfmc_device_setup(); | ||
329 | |||
330 | /* io is indirect via a register so don't need to ioremap address */ | ||
331 | |||
332 | /* Get pointer to private data */ | ||
333 | this = (struct nand_chip *) (&tx4925ndfmc_mtd[1]); | ||
334 | |||
335 | /* Initialize structures */ | ||
336 | memset((char *) tx4925ndfmc_mtd, 0, sizeof(struct mtd_info)); | ||
337 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
338 | |||
339 | /* Link the private data with the MTD structure */ | ||
340 | tx4925ndfmc_mtd->priv = this; | ||
341 | |||
342 | /* Set address of NAND IO lines */ | ||
343 | this->IO_ADDR_R = (void __iomem *)&(tx4925_ndfmcptr->dtr); | ||
344 | this->IO_ADDR_W = (void __iomem *)&(tx4925_ndfmcptr->dtr); | ||
345 | this->hwcontrol = tx4925ndfmc_hwcontrol; | ||
346 | this->enable_hwecc = tx4925ndfmc_enable_hwecc; | ||
347 | this->calculate_ecc = tx4925ndfmc_readecc; | ||
348 | this->correct_data = nand_correct_data; | ||
349 | this->eccmode = NAND_ECC_HW6_512; | ||
350 | this->dev_ready = tx4925ndfmc_device_ready; | ||
351 | /* 20 us command delay time */ | ||
352 | this->chip_delay = 20; | ||
353 | this->read_byte = tx4925ndfmc_nand_read_byte; | ||
354 | this->write_byte = tx4925ndfmc_nand_write_byte; | ||
355 | this->cmdfunc = tx4925ndfmc_nand_command; | ||
356 | this->write_buf = tx4925ndfmc_nand_write_buf; | ||
357 | this->read_buf = tx4925ndfmc_nand_read_buf; | ||
358 | this->verify_buf = tx4925ndfmc_nand_verify_buf; | ||
359 | |||
360 | /* Scan to find existance of the device */ | ||
361 | if (nand_scan (tx4925ndfmc_mtd, 1)) { | ||
362 | err = -ENXIO; | ||
363 | goto out_ior; | ||
364 | } | ||
365 | |||
366 | /* Register the partitions */ | ||
367 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
368 | { | ||
369 | int mtd_parts_nb = 0; | ||
370 | struct mtd_partition *mtd_parts = 0; | ||
371 | mtd_parts_nb = parse_cmdline_partitions(tx4925ndfmc_mtd, &mtd_parts, "tx4925ndfmc"); | ||
372 | if (mtd_parts_nb > 0) | ||
373 | add_mtd_partitions(tx4925ndfmc_mtd, mtd_parts, mtd_parts_nb); | ||
374 | else | ||
375 | add_mtd_device(tx4925ndfmc_mtd); | ||
376 | } | ||
377 | #else /* ifdef CONFIG_MTD_CMDLINE_PARTS */ | ||
378 | switch(tx4925ndfmc_mtd->size){ | ||
379 | case 0x01000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info16k, NUM_PARTITIONS16K); break; | ||
380 | case 0x02000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info32k, NUM_PARTITIONS32K); break; | ||
381 | case 0x04000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info64k, NUM_PARTITIONS64K); break; | ||
382 | case 0x08000000: add_mtd_partitions(tx4925ndfmc_mtd, partition_info128k, NUM_PARTITIONS128K); break; | ||
383 | default: { | ||
384 | printk ("Unsupported SmartMedia device\n"); | ||
385 | err = -ENXIO; | ||
386 | goto out_ior; | ||
387 | } | ||
388 | } | ||
389 | #endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */ | ||
390 | goto out; | ||
391 | |||
392 | out_ior: | ||
393 | out: | ||
394 | return err; | ||
395 | } | ||
396 | |||
397 | module_init(tx4925ndfmc_init); | ||
398 | |||
399 | /* | ||
400 | * Clean up routine | ||
401 | */ | ||
402 | #ifdef MODULE | ||
403 | static void __exit tx4925ndfmc_cleanup (void) | ||
404 | { | ||
405 | /* Release resources, unregister device */ | ||
406 | nand_release (tx4925ndfmc_mtd); | ||
407 | |||
408 | /* Free the MTD device structure */ | ||
409 | kfree (tx4925ndfmc_mtd); | ||
410 | } | ||
411 | module_exit(tx4925ndfmc_cleanup); | ||
412 | #endif | ||
413 | |||
414 | MODULE_LICENSE("GPL"); | ||
415 | MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>"); | ||
416 | MODULE_DESCRIPTION("Glue layer for SmartMediaCard on Toshiba RBTX4925"); | ||
diff --git a/drivers/mtd/nand/tx4938ndfmc.c b/drivers/mtd/nand/tx4938ndfmc.c new file mode 100644 index 000000000000..df26e58820b3 --- /dev/null +++ b/drivers/mtd/nand/tx4938ndfmc.c | |||
@@ -0,0 +1,406 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/tx4938ndfmc.c | ||
3 | * | ||
4 | * Overview: | ||
5 | * This is a device driver for the NAND flash device connected to | ||
6 | * TX4938 internal NAND Memory Controller. | ||
7 | * TX4938 NDFMC is almost same as TX4925 NDFMC, but register size are 64 bit. | ||
8 | * | ||
9 | * Author: source@mvista.com | ||
10 | * | ||
11 | * Based on spia.c by Steven J. Hill | ||
12 | * | ||
13 | * $Id: tx4938ndfmc.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ | ||
14 | * | ||
15 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
16 | * | ||
17 | * 2003 (c) MontaVista Software, Inc. This file is licensed under the | ||
18 | * terms of the GNU General Public License version 2. This program is | ||
19 | * licensed "as is" without any warranty of any kind, whether express | ||
20 | * or implied. | ||
21 | */ | ||
22 | #include <linux/config.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/mtd/mtd.h> | ||
27 | #include <linux/mtd/nand.h> | ||
28 | #include <linux/mtd/nand_ecc.h> | ||
29 | #include <linux/mtd/partitions.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/bootinfo.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <asm/tx4938/rbtx4938.h> | ||
34 | |||
35 | extern struct nand_oobinfo jffs2_oobinfo; | ||
36 | |||
37 | /* | ||
38 | * MTD structure for TX4938 NDFMC | ||
39 | */ | ||
40 | static struct mtd_info *tx4938ndfmc_mtd; | ||
41 | |||
42 | /* | ||
43 | * Define partitions for flash device | ||
44 | */ | ||
45 | #define flush_wb() (void)tx4938_ndfmcptr->mcr; | ||
46 | |||
47 | #define NUM_PARTITIONS 3 | ||
48 | #define NUMBER_OF_CIS_BLOCKS 24 | ||
49 | #define SIZE_OF_BLOCK 0x00004000 | ||
50 | #define NUMBER_OF_BLOCK_PER_ZONE 1024 | ||
51 | #define SIZE_OF_ZONE (NUMBER_OF_BLOCK_PER_ZONE * SIZE_OF_BLOCK) | ||
52 | #ifndef CONFIG_MTD_CMDLINE_PARTS | ||
53 | /* | ||
54 | * You can use the following sample of MTD partitions | ||
55 | * on the NAND Flash Memory 32MB or more. | ||
56 | * | ||
57 | * The following figure shows the image of the sample partition on | ||
58 | * the 32MB NAND Flash Memory. | ||
59 | * | ||
60 | * Block No. | ||
61 | * 0 +-----------------------------+ ------ | ||
62 | * | CIS | ^ | ||
63 | * 24 +-----------------------------+ | | ||
64 | * | kernel image | | Zone 0 | ||
65 | * | | | | ||
66 | * +-----------------------------+ | | ||
67 | * 1023 | unused area | v | ||
68 | * +-----------------------------+ ------ | ||
69 | * 1024 | JFFS2 | ^ | ||
70 | * | | | | ||
71 | * | | | Zone 1 | ||
72 | * | | | | ||
73 | * | | | | ||
74 | * | | v | ||
75 | * 2047 +-----------------------------+ ------ | ||
76 | * | ||
77 | */ | ||
78 | static struct mtd_partition partition_info[NUM_PARTITIONS] = { | ||
79 | { | ||
80 | .name = "RBTX4938 CIS Area", | ||
81 | .offset = 0, | ||
82 | .size = (NUMBER_OF_CIS_BLOCKS * SIZE_OF_BLOCK), | ||
83 | .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */ | ||
84 | }, | ||
85 | { | ||
86 | .name = "RBTX4938 kernel image", | ||
87 | .offset = MTDPART_OFS_APPEND, | ||
88 | .size = 8 * 0x00100000, /* 8MB (Depends on size of kernel image) */ | ||
89 | .mask_flags = MTD_WRITEABLE /* This partition is NOT writable */ | ||
90 | }, | ||
91 | { | ||
92 | .name = "Root FS (JFFS2)", | ||
93 | .offset = (0 + SIZE_OF_ZONE), /* start address of next zone */ | ||
94 | .size = MTDPART_SIZ_FULL | ||
95 | }, | ||
96 | }; | ||
97 | #endif | ||
98 | |||
99 | static void tx4938ndfmc_hwcontrol(struct mtd_info *mtd, int cmd) | ||
100 | { | ||
101 | switch (cmd) { | ||
102 | case NAND_CTL_SETCLE: | ||
103 | tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CLE; | ||
104 | break; | ||
105 | case NAND_CTL_CLRCLE: | ||
106 | tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CLE; | ||
107 | break; | ||
108 | case NAND_CTL_SETALE: | ||
109 | tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_ALE; | ||
110 | break; | ||
111 | case NAND_CTL_CLRALE: | ||
112 | tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_ALE; | ||
113 | break; | ||
114 | /* TX4938_NDFMCR_CE bit is 0:high 1:low */ | ||
115 | case NAND_CTL_SETNCE: | ||
116 | tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CE; | ||
117 | break; | ||
118 | case NAND_CTL_CLRNCE: | ||
119 | tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CE; | ||
120 | break; | ||
121 | case NAND_CTL_SETWP: | ||
122 | tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_WE; | ||
123 | break; | ||
124 | case NAND_CTL_CLRWP: | ||
125 | tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_WE; | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | static int tx4938ndfmc_dev_ready(struct mtd_info *mtd) | ||
130 | { | ||
131 | flush_wb(); | ||
132 | return !(tx4938_ndfmcptr->sr & TX4938_NDFSR_BUSY); | ||
133 | } | ||
134 | static void tx4938ndfmc_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) | ||
135 | { | ||
136 | u32 mcr = tx4938_ndfmcptr->mcr; | ||
137 | mcr &= ~TX4938_NDFMCR_ECC_ALL; | ||
138 | tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF; | ||
139 | tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_READ; | ||
140 | ecc_code[1] = tx4938_ndfmcptr->dtr; | ||
141 | ecc_code[0] = tx4938_ndfmcptr->dtr; | ||
142 | ecc_code[2] = tx4938_ndfmcptr->dtr; | ||
143 | tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF; | ||
144 | } | ||
145 | static void tx4938ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) | ||
146 | { | ||
147 | u32 mcr = tx4938_ndfmcptr->mcr; | ||
148 | mcr &= ~TX4938_NDFMCR_ECC_ALL; | ||
149 | tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_RESET; | ||
150 | tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF; | ||
151 | tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_ON; | ||
152 | } | ||
153 | |||
154 | static u_char tx4938ndfmc_nand_read_byte(struct mtd_info *mtd) | ||
155 | { | ||
156 | struct nand_chip *this = mtd->priv; | ||
157 | return tx4938_read_nfmc(this->IO_ADDR_R); | ||
158 | } | ||
159 | |||
160 | static void tx4938ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte) | ||
161 | { | ||
162 | struct nand_chip *this = mtd->priv; | ||
163 | tx4938_write_nfmc(byte, this->IO_ADDR_W); | ||
164 | } | ||
165 | |||
166 | static void tx4938ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
167 | { | ||
168 | int i; | ||
169 | struct nand_chip *this = mtd->priv; | ||
170 | |||
171 | for (i=0; i<len; i++) | ||
172 | tx4938_write_nfmc(buf[i], this->IO_ADDR_W); | ||
173 | } | ||
174 | |||
175 | static void tx4938ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | ||
176 | { | ||
177 | int i; | ||
178 | struct nand_chip *this = mtd->priv; | ||
179 | |||
180 | for (i=0; i<len; i++) | ||
181 | buf[i] = tx4938_read_nfmc(this->IO_ADDR_R); | ||
182 | } | ||
183 | |||
184 | static int tx4938ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | ||
185 | { | ||
186 | int i; | ||
187 | struct nand_chip *this = mtd->priv; | ||
188 | |||
189 | for (i=0; i<len; i++) | ||
190 | if (buf[i] != tx4938_read_nfmc(this->IO_ADDR_R)) | ||
191 | return -EFAULT; | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * Send command to NAND device | ||
198 | */ | ||
199 | static void tx4938ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) | ||
200 | { | ||
201 | register struct nand_chip *this = mtd->priv; | ||
202 | |||
203 | /* Begin command latch cycle */ | ||
204 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
205 | /* | ||
206 | * Write out the command to the device. | ||
207 | */ | ||
208 | if (command == NAND_CMD_SEQIN) { | ||
209 | int readcmd; | ||
210 | |||
211 | if (column >= mtd->oobblock) { | ||
212 | /* OOB area */ | ||
213 | column -= mtd->oobblock; | ||
214 | readcmd = NAND_CMD_READOOB; | ||
215 | } else if (column < 256) { | ||
216 | /* First 256 bytes --> READ0 */ | ||
217 | readcmd = NAND_CMD_READ0; | ||
218 | } else { | ||
219 | column -= 256; | ||
220 | readcmd = NAND_CMD_READ1; | ||
221 | } | ||
222 | this->write_byte(mtd, readcmd); | ||
223 | } | ||
224 | this->write_byte(mtd, command); | ||
225 | |||
226 | /* Set ALE and clear CLE to start address cycle */ | ||
227 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
228 | |||
229 | if (column != -1 || page_addr != -1) { | ||
230 | this->hwcontrol(mtd, NAND_CTL_SETALE); | ||
231 | |||
232 | /* Serially input address */ | ||
233 | if (column != -1) | ||
234 | this->write_byte(mtd, column); | ||
235 | if (page_addr != -1) { | ||
236 | this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); | ||
237 | this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); | ||
238 | /* One more address cycle for higher density devices */ | ||
239 | if (mtd->size & 0x0c000000) | ||
240 | this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); | ||
241 | } | ||
242 | /* Latch in address */ | ||
243 | this->hwcontrol(mtd, NAND_CTL_CLRALE); | ||
244 | } | ||
245 | |||
246 | /* | ||
247 | * program and erase have their own busy handlers | ||
248 | * status and sequential in needs no delay | ||
249 | */ | ||
250 | switch (command) { | ||
251 | |||
252 | case NAND_CMD_PAGEPROG: | ||
253 | /* Turn off WE */ | ||
254 | this->hwcontrol (mtd, NAND_CTL_CLRWP); | ||
255 | return; | ||
256 | |||
257 | case NAND_CMD_SEQIN: | ||
258 | /* Turn on WE */ | ||
259 | this->hwcontrol (mtd, NAND_CTL_SETWP); | ||
260 | return; | ||
261 | |||
262 | case NAND_CMD_ERASE1: | ||
263 | case NAND_CMD_ERASE2: | ||
264 | case NAND_CMD_STATUS: | ||
265 | return; | ||
266 | |||
267 | case NAND_CMD_RESET: | ||
268 | if (this->dev_ready) | ||
269 | break; | ||
270 | this->hwcontrol(mtd, NAND_CTL_SETCLE); | ||
271 | this->write_byte(mtd, NAND_CMD_STATUS); | ||
272 | this->hwcontrol(mtd, NAND_CTL_CLRCLE); | ||
273 | while ( !(this->read_byte(mtd) & 0x40)); | ||
274 | return; | ||
275 | |||
276 | /* This applies to read commands */ | ||
277 | default: | ||
278 | /* | ||
279 | * If we don't have access to the busy pin, we apply the given | ||
280 | * command delay | ||
281 | */ | ||
282 | if (!this->dev_ready) { | ||
283 | udelay (this->chip_delay); | ||
284 | return; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | /* wait until command is processed */ | ||
289 | while (!this->dev_ready(mtd)); | ||
290 | } | ||
291 | |||
292 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
293 | extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *); | ||
294 | #endif | ||
295 | /* | ||
296 | * Main initialization routine | ||
297 | */ | ||
298 | int __init tx4938ndfmc_init (void) | ||
299 | { | ||
300 | struct nand_chip *this; | ||
301 | int bsprt = 0, hold = 0xf, spw = 0xf; | ||
302 | int protected = 0; | ||
303 | |||
304 | if ((*rbtx4938_piosel_ptr & 0x0c) != 0x08) { | ||
305 | printk("TX4938 NDFMC: disabled by IOC PIOSEL\n"); | ||
306 | return -ENODEV; | ||
307 | } | ||
308 | bsprt = 1; | ||
309 | hold = 2; | ||
310 | spw = 9 - 1; /* 8 GBUSCLK = 80ns (@ GBUSCLK 100MHz) */ | ||
311 | |||
312 | if ((tx4938_ccfgptr->pcfg & | ||
313 | (TX4938_PCFG_ATA_SEL|TX4938_PCFG_ISA_SEL|TX4938_PCFG_NDF_SEL)) | ||
314 | != TX4938_PCFG_NDF_SEL) { | ||
315 | printk("TX4938 NDFMC: disabled by PCFG.\n"); | ||
316 | return -ENODEV; | ||
317 | } | ||
318 | |||
319 | /* reset NDFMC */ | ||
320 | tx4938_ndfmcptr->rstr |= TX4938_NDFRSTR_RST; | ||
321 | while (tx4938_ndfmcptr->rstr & TX4938_NDFRSTR_RST) | ||
322 | ; | ||
323 | /* setup BusSeparete, Hold Time, Strobe Pulse Width */ | ||
324 | tx4938_ndfmcptr->mcr = bsprt ? TX4938_NDFMCR_BSPRT : 0; | ||
325 | tx4938_ndfmcptr->spr = hold << 4 | spw; | ||
326 | |||
327 | /* Allocate memory for MTD device structure and private data */ | ||
328 | tx4938ndfmc_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), | ||
329 | GFP_KERNEL); | ||
330 | if (!tx4938ndfmc_mtd) { | ||
331 | printk ("Unable to allocate TX4938 NDFMC MTD device structure.\n"); | ||
332 | return -ENOMEM; | ||
333 | } | ||
334 | |||
335 | /* Get pointer to private data */ | ||
336 | this = (struct nand_chip *) (&tx4938ndfmc_mtd[1]); | ||
337 | |||
338 | /* Initialize structures */ | ||
339 | memset((char *) tx4938ndfmc_mtd, 0, sizeof(struct mtd_info)); | ||
340 | memset((char *) this, 0, sizeof(struct nand_chip)); | ||
341 | |||
342 | /* Link the private data with the MTD structure */ | ||
343 | tx4938ndfmc_mtd->priv = this; | ||
344 | |||
345 | /* Set address of NAND IO lines */ | ||
346 | this->IO_ADDR_R = (unsigned long)&tx4938_ndfmcptr->dtr; | ||
347 | this->IO_ADDR_W = (unsigned long)&tx4938_ndfmcptr->dtr; | ||
348 | this->hwcontrol = tx4938ndfmc_hwcontrol; | ||
349 | this->dev_ready = tx4938ndfmc_dev_ready; | ||
350 | this->calculate_ecc = tx4938ndfmc_calculate_ecc; | ||
351 | this->correct_data = nand_correct_data; | ||
352 | this->enable_hwecc = tx4938ndfmc_enable_hwecc; | ||
353 | this->eccmode = NAND_ECC_HW3_256; | ||
354 | this->chip_delay = 100; | ||
355 | this->read_byte = tx4938ndfmc_nand_read_byte; | ||
356 | this->write_byte = tx4938ndfmc_nand_write_byte; | ||
357 | this->cmdfunc = tx4938ndfmc_nand_command; | ||
358 | this->write_buf = tx4938ndfmc_nand_write_buf; | ||
359 | this->read_buf = tx4938ndfmc_nand_read_buf; | ||
360 | this->verify_buf = tx4938ndfmc_nand_verify_buf; | ||
361 | |||
362 | /* Scan to find existance of the device */ | ||
363 | if (nand_scan (tx4938ndfmc_mtd, 1)) { | ||
364 | kfree (tx4938ndfmc_mtd); | ||
365 | return -ENXIO; | ||
366 | } | ||
367 | |||
368 | if (protected) { | ||
369 | printk(KERN_INFO "TX4938 NDFMC: write protected.\n"); | ||
370 | tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE); | ||
371 | } | ||
372 | |||
373 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
374 | { | ||
375 | int mtd_parts_nb = 0; | ||
376 | struct mtd_partition *mtd_parts = 0; | ||
377 | mtd_parts_nb = parse_cmdline_partitions(tx4938ndfmc_mtd, &mtd_parts, "tx4938ndfmc"); | ||
378 | if (mtd_parts_nb > 0) | ||
379 | add_mtd_partitions(tx4938ndfmc_mtd, mtd_parts, mtd_parts_nb); | ||
380 | else | ||
381 | add_mtd_device(tx4938ndfmc_mtd); | ||
382 | } | ||
383 | #else | ||
384 | add_mtd_partitions(tx4938ndfmc_mtd, partition_info, NUM_PARTITIONS ); | ||
385 | #endif | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | module_init(tx4938ndfmc_init); | ||
390 | |||
391 | /* | ||
392 | * Clean up routine | ||
393 | */ | ||
394 | static void __exit tx4938ndfmc_cleanup (void) | ||
395 | { | ||
396 | /* Release resources, unregister device */ | ||
397 | nand_release (tx4938ndfmc_mtd); | ||
398 | |||
399 | /* Free the MTD device structure */ | ||
400 | kfree (tx4938ndfmc_mtd); | ||
401 | } | ||
402 | module_exit(tx4938ndfmc_cleanup); | ||
403 | |||
404 | MODULE_LICENSE("GPL"); | ||
405 | MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>"); | ||
406 | MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on TX4938 NDFMC"); | ||