diff options
Diffstat (limited to 'drivers/mtd/nand/diskonchip.c')
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 530 |
1 files changed, 261 insertions, 269 deletions
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index ec5e45e4e4ef..6107f532855b 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -58,10 +58,10 @@ static unsigned long __initdata doc_locations[] = { | |||
58 | 0xe4000000, | 58 | 0xe4000000, |
59 | #elif defined(CONFIG_MOMENCO_OCELOT) | 59 | #elif defined(CONFIG_MOMENCO_OCELOT) |
60 | 0x2f000000, | 60 | 0x2f000000, |
61 | 0xff000000, | 61 | 0xff000000, |
62 | #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) | 62 | #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) |
63 | 0xff000000, | 63 | 0xff000000, |
64 | ##else | 64 | #else |
65 | #warning Unknown architecture for DiskOnChip. No default probe locations defined | 65 | #warning Unknown architecture for DiskOnChip. No default probe locations defined |
66 | #endif | 66 | #endif |
67 | 0xffffffff }; | 67 | 0xffffffff }; |
@@ -73,7 +73,7 @@ struct doc_priv { | |||
73 | unsigned long physadr; | 73 | unsigned long physadr; |
74 | u_char ChipID; | 74 | u_char ChipID; |
75 | u_char CDSNControl; | 75 | u_char CDSNControl; |
76 | int chips_per_floor; /* The number of chips detected on each floor */ | 76 | int chips_per_floor; /* The number of chips detected on each floor */ |
77 | int curfloor; | 77 | int curfloor; |
78 | int curchip; | 78 | int curchip; |
79 | int mh0_page; | 79 | int mh0_page; |
@@ -84,6 +84,7 @@ struct doc_priv { | |||
84 | /* This is the syndrome computed by the HW ecc generator upon reading an empty | 84 | /* This is the syndrome computed by the HW ecc generator upon reading an empty |
85 | page, one with all 0xff for data and stored ecc code. */ | 85 | page, one with all 0xff for data and stored ecc code. */ |
86 | static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; | 86 | static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a }; |
87 | |||
87 | /* This is the ecc value computed by the HW ecc generator upon writing an empty | 88 | /* This is the ecc value computed by the HW ecc generator upon writing an empty |
88 | page, one with all 0xff for data. */ | 89 | page, one with all 0xff for data. */ |
89 | static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; | 90 | static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; |
@@ -94,28 +95,29 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 }; | |||
94 | #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) | 95 | #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil) |
95 | #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) | 96 | #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k) |
96 | 97 | ||
97 | static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd); | 98 | static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, |
99 | unsigned int bitmask); | ||
98 | static void doc200x_select_chip(struct mtd_info *mtd, int chip); | 100 | static void doc200x_select_chip(struct mtd_info *mtd, int chip); |
99 | 101 | ||
100 | static int debug=0; | 102 | static int debug = 0; |
101 | module_param(debug, int, 0); | 103 | module_param(debug, int, 0); |
102 | 104 | ||
103 | static int try_dword=1; | 105 | static int try_dword = 1; |
104 | module_param(try_dword, int, 0); | 106 | module_param(try_dword, int, 0); |
105 | 107 | ||
106 | static int no_ecc_failures=0; | 108 | static int no_ecc_failures = 0; |
107 | module_param(no_ecc_failures, int, 0); | 109 | module_param(no_ecc_failures, int, 0); |
108 | 110 | ||
109 | static int no_autopart=0; | 111 | static int no_autopart = 0; |
110 | module_param(no_autopart, int, 0); | 112 | module_param(no_autopart, int, 0); |
111 | 113 | ||
112 | static int show_firmware_partition=0; | 114 | static int show_firmware_partition = 0; |
113 | module_param(show_firmware_partition, int, 0); | 115 | module_param(show_firmware_partition, int, 0); |
114 | 116 | ||
115 | #ifdef MTD_NAND_DISKONCHIP_BBTWRITE | 117 | #ifdef MTD_NAND_DISKONCHIP_BBTWRITE |
116 | static int inftl_bbt_write=1; | 118 | static int inftl_bbt_write = 1; |
117 | #else | 119 | #else |
118 | static int inftl_bbt_write=0; | 120 | static int inftl_bbt_write = 0; |
119 | #endif | 121 | #endif |
120 | module_param(inftl_bbt_write, int, 0); | 122 | module_param(inftl_bbt_write, int, 0); |
121 | 123 | ||
@@ -123,7 +125,6 @@ static unsigned long doc_config_location = CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDR | |||
123 | module_param(doc_config_location, ulong, 0); | 125 | module_param(doc_config_location, ulong, 0); |
124 | MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); | 126 | MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip"); |
125 | 127 | ||
126 | |||
127 | /* Sector size for HW ECC */ | 128 | /* Sector size for HW ECC */ |
128 | #define SECTOR_SIZE 512 | 129 | #define SECTOR_SIZE 512 |
129 | /* The sector bytes are packed into NB_DATA 10 bit words */ | 130 | /* The sector bytes are packed into NB_DATA 10 bit words */ |
@@ -147,7 +148,7 @@ static struct rs_control *rs_decoder; | |||
147 | * some comments, improved a minor bit and converted it to make use | 148 | * some comments, improved a minor bit and converted it to make use |
148 | * of the generic Reed-Solomon libary. tglx | 149 | * of the generic Reed-Solomon libary. tglx |
149 | */ | 150 | */ |
150 | static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | 151 | static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) |
151 | { | 152 | { |
152 | int i, j, nerr, errpos[8]; | 153 | int i, j, nerr, errpos[8]; |
153 | uint8_t parity; | 154 | uint8_t parity; |
@@ -168,18 +169,18 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
168 | * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] | 169 | * s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0] |
169 | * where x = alpha^(FCR + i) | 170 | * where x = alpha^(FCR + i) |
170 | */ | 171 | */ |
171 | for(j = 1; j < NROOTS; j++) { | 172 | for (j = 1; j < NROOTS; j++) { |
172 | if(ds[j] == 0) | 173 | if (ds[j] == 0) |
173 | continue; | 174 | continue; |
174 | tmp = rs->index_of[ds[j]]; | 175 | tmp = rs->index_of[ds[j]]; |
175 | for(i = 0; i < NROOTS; i++) | 176 | for (i = 0; i < NROOTS; i++) |
176 | s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; | 177 | s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; |
177 | } | 178 | } |
178 | 179 | ||
179 | /* Calc s[i] = s[i] / alpha^(v + i) */ | 180 | /* Calc s[i] = s[i] / alpha^(v + i) */ |
180 | for (i = 0; i < NROOTS; i++) { | 181 | for (i = 0; i < NROOTS; i++) { |
181 | if (syn[i]) | 182 | if (syn[i]) |
182 | syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); | 183 | syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); |
183 | } | 184 | } |
184 | /* Call the decoder library */ | 185 | /* Call the decoder library */ |
185 | nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval); | 186 | nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval); |
@@ -193,7 +194,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
193 | * but they are given by the design of the de/encoder circuit | 194 | * but they are given by the design of the de/encoder circuit |
194 | * in the DoC ASIC's. | 195 | * in the DoC ASIC's. |
195 | */ | 196 | */ |
196 | for(i = 0;i < nerr; i++) { | 197 | for (i = 0; i < nerr; i++) { |
197 | int index, bitpos, pos = 1015 - errpos[i]; | 198 | int index, bitpos, pos = 1015 - errpos[i]; |
198 | uint8_t val; | 199 | uint8_t val; |
199 | if (pos >= NB_DATA && pos < 1019) | 200 | if (pos >= NB_DATA && pos < 1019) |
@@ -205,8 +206,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
205 | can be modified since pos is even */ | 206 | can be modified since pos is even */ |
206 | index = (pos >> 3) ^ 1; | 207 | index = (pos >> 3) ^ 1; |
207 | bitpos = pos & 7; | 208 | bitpos = pos & 7; |
208 | if ((index >= 0 && index < SECTOR_SIZE) || | 209 | if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { |
209 | index == (SECTOR_SIZE + 1)) { | ||
210 | val = (uint8_t) (errval[i] >> (2 + bitpos)); | 210 | val = (uint8_t) (errval[i] >> (2 + bitpos)); |
211 | parity ^= val; | 211 | parity ^= val; |
212 | if (index < SECTOR_SIZE) | 212 | if (index < SECTOR_SIZE) |
@@ -216,9 +216,8 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc) | |||
216 | bitpos = (bitpos + 10) & 7; | 216 | bitpos = (bitpos + 10) & 7; |
217 | if (bitpos == 0) | 217 | if (bitpos == 0) |
218 | bitpos = 8; | 218 | bitpos = 8; |
219 | if ((index >= 0 && index < SECTOR_SIZE) || | 219 | if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) { |
220 | index == (SECTOR_SIZE + 1)) { | 220 | val = (uint8_t) (errval[i] << (8 - bitpos)); |
221 | val = (uint8_t)(errval[i] << (8 - bitpos)); | ||
222 | parity ^= val; | 221 | parity ^= val; |
223 | if (index < SECTOR_SIZE) | 222 | if (index < SECTOR_SIZE) |
224 | data[index] ^= val; | 223 | data[index] ^= val; |
@@ -250,10 +249,11 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) | |||
250 | /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ | 249 | /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ |
251 | static int _DoC_WaitReady(struct doc_priv *doc) | 250 | static int _DoC_WaitReady(struct doc_priv *doc) |
252 | { | 251 | { |
253 | void __iomem *docptr = doc->virtadr; | 252 | void __iomem *docptr = doc->virtadr; |
254 | unsigned long timeo = jiffies + (HZ * 10); | 253 | unsigned long timeo = jiffies + (HZ * 10); |
255 | 254 | ||
256 | if(debug) printk("_DoC_WaitReady...\n"); | 255 | if (debug) |
256 | printk("_DoC_WaitReady...\n"); | ||
257 | /* Out-of-line routine to wait for chip response */ | 257 | /* Out-of-line routine to wait for chip response */ |
258 | if (DoC_is_MillenniumPlus(doc)) { | 258 | if (DoC_is_MillenniumPlus(doc)) { |
259 | while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { | 259 | while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { |
@@ -280,7 +280,7 @@ static int _DoC_WaitReady(struct doc_priv *doc) | |||
280 | 280 | ||
281 | static inline int DoC_WaitReady(struct doc_priv *doc) | 281 | static inline int DoC_WaitReady(struct doc_priv *doc) |
282 | { | 282 | { |
283 | void __iomem *docptr = doc->virtadr; | 283 | void __iomem *docptr = doc->virtadr; |
284 | int ret = 0; | 284 | int ret = 0; |
285 | 285 | ||
286 | if (DoC_is_MillenniumPlus(doc)) { | 286 | if (DoC_is_MillenniumPlus(doc)) { |
@@ -298,7 +298,8 @@ static inline int DoC_WaitReady(struct doc_priv *doc) | |||
298 | DoC_Delay(doc, 2); | 298 | DoC_Delay(doc, 2); |
299 | } | 299 | } |
300 | 300 | ||
301 | if(debug) printk("DoC_WaitReady OK\n"); | 301 | if (debug) |
302 | printk("DoC_WaitReady OK\n"); | ||
302 | return ret; | 303 | return ret; |
303 | } | 304 | } |
304 | 305 | ||
@@ -306,9 +307,10 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum) | |||
306 | { | 307 | { |
307 | struct nand_chip *this = mtd->priv; | 308 | struct nand_chip *this = mtd->priv; |
308 | struct doc_priv *doc = this->priv; | 309 | struct doc_priv *doc = this->priv; |
309 | void __iomem *docptr = doc->virtadr; | 310 | void __iomem *docptr = doc->virtadr; |
310 | 311 | ||
311 | if(debug)printk("write_byte %02x\n", datum); | 312 | if (debug) |
313 | printk("write_byte %02x\n", datum); | ||
312 | WriteDOC(datum, docptr, CDSNSlowIO); | 314 | WriteDOC(datum, docptr, CDSNSlowIO); |
313 | WriteDOC(datum, docptr, 2k_CDSN_IO); | 315 | WriteDOC(datum, docptr, 2k_CDSN_IO); |
314 | } | 316 | } |
@@ -317,77 +319,78 @@ static u_char doc2000_read_byte(struct mtd_info *mtd) | |||
317 | { | 319 | { |
318 | struct nand_chip *this = mtd->priv; | 320 | struct nand_chip *this = mtd->priv; |
319 | struct doc_priv *doc = this->priv; | 321 | struct doc_priv *doc = this->priv; |
320 | void __iomem *docptr = doc->virtadr; | 322 | void __iomem *docptr = doc->virtadr; |
321 | u_char ret; | 323 | u_char ret; |
322 | 324 | ||
323 | ReadDOC(docptr, CDSNSlowIO); | 325 | ReadDOC(docptr, CDSNSlowIO); |
324 | DoC_Delay(doc, 2); | 326 | DoC_Delay(doc, 2); |
325 | ret = ReadDOC(docptr, 2k_CDSN_IO); | 327 | ret = ReadDOC(docptr, 2k_CDSN_IO); |
326 | if (debug) printk("read_byte returns %02x\n", ret); | 328 | if (debug) |
329 | printk("read_byte returns %02x\n", ret); | ||
327 | return ret; | 330 | return ret; |
328 | } | 331 | } |
329 | 332 | ||
330 | static void doc2000_writebuf(struct mtd_info *mtd, | 333 | static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len) |
331 | const u_char *buf, int len) | ||
332 | { | 334 | { |
333 | struct nand_chip *this = mtd->priv; | 335 | struct nand_chip *this = mtd->priv; |
334 | struct doc_priv *doc = this->priv; | 336 | struct doc_priv *doc = this->priv; |
335 | void __iomem *docptr = doc->virtadr; | 337 | void __iomem *docptr = doc->virtadr; |
336 | int i; | 338 | int i; |
337 | if (debug)printk("writebuf of %d bytes: ", len); | 339 | if (debug) |
338 | for (i=0; i < len; i++) { | 340 | printk("writebuf of %d bytes: ", len); |
341 | for (i = 0; i < len; i++) { | ||
339 | WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i); | 342 | WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i); |
340 | if (debug && i < 16) | 343 | if (debug && i < 16) |
341 | printk("%02x ", buf[i]); | 344 | printk("%02x ", buf[i]); |
342 | } | 345 | } |
343 | if (debug) printk("\n"); | 346 | if (debug) |
347 | printk("\n"); | ||
344 | } | 348 | } |
345 | 349 | ||
346 | static void doc2000_readbuf(struct mtd_info *mtd, | 350 | static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len) |
347 | u_char *buf, int len) | ||
348 | { | 351 | { |
349 | struct nand_chip *this = mtd->priv; | 352 | struct nand_chip *this = mtd->priv; |
350 | struct doc_priv *doc = this->priv; | 353 | struct doc_priv *doc = this->priv; |
351 | void __iomem *docptr = doc->virtadr; | 354 | void __iomem *docptr = doc->virtadr; |
352 | int i; | 355 | int i; |
353 | 356 | ||
354 | if (debug)printk("readbuf of %d bytes: ", len); | 357 | if (debug) |
358 | printk("readbuf of %d bytes: ", len); | ||
355 | 359 | ||
356 | for (i=0; i < len; i++) { | 360 | for (i = 0; i < len; i++) { |
357 | buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i); | 361 | buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i); |
358 | } | 362 | } |
359 | } | 363 | } |
360 | 364 | ||
361 | static void doc2000_readbuf_dword(struct mtd_info *mtd, | 365 | static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len) |
362 | u_char *buf, int len) | ||
363 | { | 366 | { |
364 | struct nand_chip *this = mtd->priv; | 367 | struct nand_chip *this = mtd->priv; |
365 | struct doc_priv *doc = this->priv; | 368 | struct doc_priv *doc = this->priv; |
366 | void __iomem *docptr = doc->virtadr; | 369 | void __iomem *docptr = doc->virtadr; |
367 | int i; | 370 | int i; |
368 | 371 | ||
369 | if (debug) printk("readbuf_dword of %d bytes: ", len); | 372 | if (debug) |
373 | printk("readbuf_dword of %d bytes: ", len); | ||
370 | 374 | ||
371 | if (unlikely((((unsigned long)buf)|len) & 3)) { | 375 | if (unlikely((((unsigned long)buf) | len) & 3)) { |
372 | for (i=0; i < len; i++) { | 376 | for (i = 0; i < len; i++) { |
373 | *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); | 377 | *(uint8_t *) (&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i); |
374 | } | 378 | } |
375 | } else { | 379 | } else { |
376 | for (i=0; i < len; i+=4) { | 380 | for (i = 0; i < len; i += 4) { |
377 | *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); | 381 | *(uint32_t *) (&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i); |
378 | } | 382 | } |
379 | } | 383 | } |
380 | } | 384 | } |
381 | 385 | ||
382 | static int doc2000_verifybuf(struct mtd_info *mtd, | 386 | static int doc2000_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) |
383 | const u_char *buf, int len) | ||
384 | { | 387 | { |
385 | struct nand_chip *this = mtd->priv; | 388 | struct nand_chip *this = mtd->priv; |
386 | struct doc_priv *doc = this->priv; | 389 | struct doc_priv *doc = this->priv; |
387 | void __iomem *docptr = doc->virtadr; | 390 | void __iomem *docptr = doc->virtadr; |
388 | int i; | 391 | int i; |
389 | 392 | ||
390 | for (i=0; i < len; i++) | 393 | for (i = 0; i < len; i++) |
391 | if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO)) | 394 | if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO)) |
392 | return -EFAULT; | 395 | return -EFAULT; |
393 | return 0; | 396 | return 0; |
@@ -400,12 +403,10 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) | |||
400 | uint16_t ret; | 403 | uint16_t ret; |
401 | 404 | ||
402 | doc200x_select_chip(mtd, nr); | 405 | doc200x_select_chip(mtd, nr); |
403 | doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); | 406 | doc200x_hwcontrol(mtd, NAND_CMD_READID, |
404 | this->write_byte(mtd, NAND_CMD_READID); | 407 | NAND_CTRL_CLE | NAND_CTRL_CHANGE); |
405 | doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); | 408 | doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); |
406 | doc200x_hwcontrol(mtd, NAND_CTL_SETALE); | 409 | doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); |
407 | this->write_byte(mtd, 0); | ||
408 | doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); | ||
409 | 410 | ||
410 | /* We cant' use dev_ready here, but at least we wait for the | 411 | /* We cant' use dev_ready here, but at least we wait for the |
411 | * command to complete | 412 | * command to complete |
@@ -423,12 +424,11 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr) | |||
423 | } ident; | 424 | } ident; |
424 | void __iomem *docptr = doc->virtadr; | 425 | void __iomem *docptr = doc->virtadr; |
425 | 426 | ||
426 | doc200x_hwcontrol(mtd, NAND_CTL_SETCLE); | 427 | doc200x_hwcontrol(mtd, NAND_CMD_READID, |
427 | doc2000_write_byte(mtd, NAND_CMD_READID); | 428 | NAND_CTRL_CLE | NAND_CTRL_CHANGE); |
428 | doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE); | 429 | doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); |
429 | doc200x_hwcontrol(mtd, NAND_CTL_SETALE); | 430 | doc200x_hwcontrol(mtd, NAND_CMD_NONE, |
430 | doc2000_write_byte(mtd, 0); | 431 | NAND_NCE | NAND_CTRL_CHANGE); |
431 | doc200x_hwcontrol(mtd, NAND_CTL_CLRALE); | ||
432 | 432 | ||
433 | udelay(50); | 433 | udelay(50); |
434 | 434 | ||
@@ -464,7 +464,7 @@ static void __init doc2000_count_chips(struct mtd_info *mtd) | |||
464 | printk(KERN_DEBUG "Detected %d chips per floor.\n", i); | 464 | printk(KERN_DEBUG "Detected %d chips per floor.\n", i); |
465 | } | 465 | } |
466 | 466 | ||
467 | static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state) | 467 | static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this) |
468 | { | 468 | { |
469 | struct doc_priv *doc = this->priv; | 469 | struct doc_priv *doc = this->priv; |
470 | 470 | ||
@@ -482,7 +482,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum) | |||
482 | { | 482 | { |
483 | struct nand_chip *this = mtd->priv; | 483 | struct nand_chip *this = mtd->priv; |
484 | struct doc_priv *doc = this->priv; | 484 | struct doc_priv *doc = this->priv; |
485 | void __iomem *docptr = doc->virtadr; | 485 | void __iomem *docptr = doc->virtadr; |
486 | 486 | ||
487 | WriteDOC(datum, docptr, CDSNSlowIO); | 487 | WriteDOC(datum, docptr, CDSNSlowIO); |
488 | WriteDOC(datum, docptr, Mil_CDSN_IO); | 488 | WriteDOC(datum, docptr, Mil_CDSN_IO); |
@@ -493,7 +493,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) | |||
493 | { | 493 | { |
494 | struct nand_chip *this = mtd->priv; | 494 | struct nand_chip *this = mtd->priv; |
495 | struct doc_priv *doc = this->priv; | 495 | struct doc_priv *doc = this->priv; |
496 | void __iomem *docptr = doc->virtadr; | 496 | void __iomem *docptr = doc->virtadr; |
497 | 497 | ||
498 | //ReadDOC(docptr, CDSNSlowIO); | 498 | //ReadDOC(docptr, CDSNSlowIO); |
499 | /* 11.4.5 -- delay twice to allow extended length cycle */ | 499 | /* 11.4.5 -- delay twice to allow extended length cycle */ |
@@ -503,50 +503,47 @@ static u_char doc2001_read_byte(struct mtd_info *mtd) | |||
503 | return ReadDOC(docptr, LastDataRead); | 503 | return ReadDOC(docptr, LastDataRead); |
504 | } | 504 | } |
505 | 505 | ||
506 | static void doc2001_writebuf(struct mtd_info *mtd, | 506 | static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len) |
507 | const u_char *buf, int len) | ||
508 | { | 507 | { |
509 | struct nand_chip *this = mtd->priv; | 508 | struct nand_chip *this = mtd->priv; |
510 | struct doc_priv *doc = this->priv; | 509 | struct doc_priv *doc = this->priv; |
511 | void __iomem *docptr = doc->virtadr; | 510 | void __iomem *docptr = doc->virtadr; |
512 | int i; | 511 | int i; |
513 | 512 | ||
514 | for (i=0; i < len; i++) | 513 | for (i = 0; i < len; i++) |
515 | WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); | 514 | WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); |
516 | /* Terminate write pipeline */ | 515 | /* Terminate write pipeline */ |
517 | WriteDOC(0x00, docptr, WritePipeTerm); | 516 | WriteDOC(0x00, docptr, WritePipeTerm); |
518 | } | 517 | } |
519 | 518 | ||
520 | static void doc2001_readbuf(struct mtd_info *mtd, | 519 | static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len) |
521 | u_char *buf, int len) | ||
522 | { | 520 | { |
523 | struct nand_chip *this = mtd->priv; | 521 | struct nand_chip *this = mtd->priv; |
524 | struct doc_priv *doc = this->priv; | 522 | struct doc_priv *doc = this->priv; |
525 | void __iomem *docptr = doc->virtadr; | 523 | void __iomem *docptr = doc->virtadr; |
526 | int i; | 524 | int i; |
527 | 525 | ||
528 | /* Start read pipeline */ | 526 | /* Start read pipeline */ |
529 | ReadDOC(docptr, ReadPipeInit); | 527 | ReadDOC(docptr, ReadPipeInit); |
530 | 528 | ||
531 | for (i=0; i < len-1; i++) | 529 | for (i = 0; i < len - 1; i++) |
532 | buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); | 530 | buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); |
533 | 531 | ||
534 | /* Terminate read pipeline */ | 532 | /* Terminate read pipeline */ |
535 | buf[i] = ReadDOC(docptr, LastDataRead); | 533 | buf[i] = ReadDOC(docptr, LastDataRead); |
536 | } | 534 | } |
537 | 535 | ||
538 | static int doc2001_verifybuf(struct mtd_info *mtd, | 536 | static int doc2001_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) |
539 | const u_char *buf, int len) | ||
540 | { | 537 | { |
541 | struct nand_chip *this = mtd->priv; | 538 | struct nand_chip *this = mtd->priv; |
542 | struct doc_priv *doc = this->priv; | 539 | struct doc_priv *doc = this->priv; |
543 | void __iomem *docptr = doc->virtadr; | 540 | void __iomem *docptr = doc->virtadr; |
544 | int i; | 541 | int i; |
545 | 542 | ||
546 | /* Start read pipeline */ | 543 | /* Start read pipeline */ |
547 | ReadDOC(docptr, ReadPipeInit); | 544 | ReadDOC(docptr, ReadPipeInit); |
548 | 545 | ||
549 | for (i=0; i < len-1; i++) | 546 | for (i = 0; i < len - 1; i++) |
550 | if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { | 547 | if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { |
551 | ReadDOC(docptr, LastDataRead); | 548 | ReadDOC(docptr, LastDataRead); |
552 | return i; | 549 | return i; |
@@ -560,87 +557,90 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd) | |||
560 | { | 557 | { |
561 | struct nand_chip *this = mtd->priv; | 558 | struct nand_chip *this = mtd->priv; |
562 | struct doc_priv *doc = this->priv; | 559 | struct doc_priv *doc = this->priv; |
563 | void __iomem *docptr = doc->virtadr; | 560 | void __iomem *docptr = doc->virtadr; |
564 | u_char ret; | 561 | u_char ret; |
565 | 562 | ||
566 | ReadDOC(docptr, Mplus_ReadPipeInit); | 563 | ReadDOC(docptr, Mplus_ReadPipeInit); |
567 | ReadDOC(docptr, Mplus_ReadPipeInit); | 564 | ReadDOC(docptr, Mplus_ReadPipeInit); |
568 | ret = ReadDOC(docptr, Mplus_LastDataRead); | 565 | ret = ReadDOC(docptr, Mplus_LastDataRead); |
569 | if (debug) printk("read_byte returns %02x\n", ret); | 566 | if (debug) |
567 | printk("read_byte returns %02x\n", ret); | ||
570 | return ret; | 568 | return ret; |
571 | } | 569 | } |
572 | 570 | ||
573 | static void doc2001plus_writebuf(struct mtd_info *mtd, | 571 | static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len) |
574 | const u_char *buf, int len) | ||
575 | { | 572 | { |
576 | struct nand_chip *this = mtd->priv; | 573 | struct nand_chip *this = mtd->priv; |
577 | struct doc_priv *doc = this->priv; | 574 | struct doc_priv *doc = this->priv; |
578 | void __iomem *docptr = doc->virtadr; | 575 | void __iomem *docptr = doc->virtadr; |
579 | int i; | 576 | int i; |
580 | 577 | ||
581 | if (debug)printk("writebuf of %d bytes: ", len); | 578 | if (debug) |
582 | for (i=0; i < len; i++) { | 579 | printk("writebuf of %d bytes: ", len); |
580 | for (i = 0; i < len; i++) { | ||
583 | WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); | 581 | WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i); |
584 | if (debug && i < 16) | 582 | if (debug && i < 16) |
585 | printk("%02x ", buf[i]); | 583 | printk("%02x ", buf[i]); |
586 | } | 584 | } |
587 | if (debug) printk("\n"); | 585 | if (debug) |
586 | printk("\n"); | ||
588 | } | 587 | } |
589 | 588 | ||
590 | static void doc2001plus_readbuf(struct mtd_info *mtd, | 589 | static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len) |
591 | u_char *buf, int len) | ||
592 | { | 590 | { |
593 | struct nand_chip *this = mtd->priv; | 591 | struct nand_chip *this = mtd->priv; |
594 | struct doc_priv *doc = this->priv; | 592 | struct doc_priv *doc = this->priv; |
595 | void __iomem *docptr = doc->virtadr; | 593 | void __iomem *docptr = doc->virtadr; |
596 | int i; | 594 | int i; |
597 | 595 | ||
598 | if (debug)printk("readbuf of %d bytes: ", len); | 596 | if (debug) |
597 | printk("readbuf of %d bytes: ", len); | ||
599 | 598 | ||
600 | /* Start read pipeline */ | 599 | /* Start read pipeline */ |
601 | ReadDOC(docptr, Mplus_ReadPipeInit); | 600 | ReadDOC(docptr, Mplus_ReadPipeInit); |
602 | ReadDOC(docptr, Mplus_ReadPipeInit); | 601 | ReadDOC(docptr, Mplus_ReadPipeInit); |
603 | 602 | ||
604 | for (i=0; i < len-2; i++) { | 603 | for (i = 0; i < len - 2; i++) { |
605 | buf[i] = ReadDOC(docptr, Mil_CDSN_IO); | 604 | buf[i] = ReadDOC(docptr, Mil_CDSN_IO); |
606 | if (debug && i < 16) | 605 | if (debug && i < 16) |
607 | printk("%02x ", buf[i]); | 606 | printk("%02x ", buf[i]); |
608 | } | 607 | } |
609 | 608 | ||
610 | /* Terminate read pipeline */ | 609 | /* Terminate read pipeline */ |
611 | buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead); | 610 | buf[len - 2] = ReadDOC(docptr, Mplus_LastDataRead); |
612 | if (debug && i < 16) | 611 | if (debug && i < 16) |
613 | printk("%02x ", buf[len-2]); | 612 | printk("%02x ", buf[len - 2]); |
614 | buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead); | 613 | buf[len - 1] = ReadDOC(docptr, Mplus_LastDataRead); |
615 | if (debug && i < 16) | 614 | if (debug && i < 16) |
616 | printk("%02x ", buf[len-1]); | 615 | printk("%02x ", buf[len - 1]); |
617 | if (debug) printk("\n"); | 616 | if (debug) |
617 | printk("\n"); | ||
618 | } | 618 | } |
619 | 619 | ||
620 | static int doc2001plus_verifybuf(struct mtd_info *mtd, | 620 | static int doc2001plus_verifybuf(struct mtd_info *mtd, const u_char *buf, int len) |
621 | const u_char *buf, int len) | ||
622 | { | 621 | { |
623 | struct nand_chip *this = mtd->priv; | 622 | struct nand_chip *this = mtd->priv; |
624 | struct doc_priv *doc = this->priv; | 623 | struct doc_priv *doc = this->priv; |
625 | void __iomem *docptr = doc->virtadr; | 624 | void __iomem *docptr = doc->virtadr; |
626 | int i; | 625 | int i; |
627 | 626 | ||
628 | if (debug)printk("verifybuf of %d bytes: ", len); | 627 | if (debug) |
628 | printk("verifybuf of %d bytes: ", len); | ||
629 | 629 | ||
630 | /* Start read pipeline */ | 630 | /* Start read pipeline */ |
631 | ReadDOC(docptr, Mplus_ReadPipeInit); | 631 | ReadDOC(docptr, Mplus_ReadPipeInit); |
632 | ReadDOC(docptr, Mplus_ReadPipeInit); | 632 | ReadDOC(docptr, Mplus_ReadPipeInit); |
633 | 633 | ||
634 | for (i=0; i < len-2; i++) | 634 | for (i = 0; i < len - 2; i++) |
635 | if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { | 635 | if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) { |
636 | ReadDOC(docptr, Mplus_LastDataRead); | 636 | ReadDOC(docptr, Mplus_LastDataRead); |
637 | ReadDOC(docptr, Mplus_LastDataRead); | 637 | ReadDOC(docptr, Mplus_LastDataRead); |
638 | return i; | 638 | return i; |
639 | } | 639 | } |
640 | if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead)) | 640 | if (buf[len - 2] != ReadDOC(docptr, Mplus_LastDataRead)) |
641 | return len-2; | 641 | return len - 2; |
642 | if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead)) | 642 | if (buf[len - 1] != ReadDOC(docptr, Mplus_LastDataRead)) |
643 | return len-1; | 643 | return len - 1; |
644 | return 0; | 644 | return 0; |
645 | } | 645 | } |
646 | 646 | ||
@@ -648,10 +648,11 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) | |||
648 | { | 648 | { |
649 | struct nand_chip *this = mtd->priv; | 649 | struct nand_chip *this = mtd->priv; |
650 | struct doc_priv *doc = this->priv; | 650 | struct doc_priv *doc = this->priv; |
651 | void __iomem *docptr = doc->virtadr; | 651 | void __iomem *docptr = doc->virtadr; |
652 | int floor = 0; | 652 | int floor = 0; |
653 | 653 | ||
654 | if(debug)printk("select chip (%d)\n", chip); | 654 | if (debug) |
655 | printk("select chip (%d)\n", chip); | ||
655 | 656 | ||
656 | if (chip == -1) { | 657 | if (chip == -1) { |
657 | /* Disable flash internally */ | 658 | /* Disable flash internally */ |
@@ -660,7 +661,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip) | |||
660 | } | 661 | } |
661 | 662 | ||
662 | floor = chip / doc->chips_per_floor; | 663 | floor = chip / doc->chips_per_floor; |
663 | chip -= (floor * doc->chips_per_floor); | 664 | chip -= (floor * doc->chips_per_floor); |
664 | 665 | ||
665 | /* Assert ChipEnable and deassert WriteProtect */ | 666 | /* Assert ChipEnable and deassert WriteProtect */ |
666 | WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect); | 667 | WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect); |
@@ -674,72 +675,61 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip) | |||
674 | { | 675 | { |
675 | struct nand_chip *this = mtd->priv; | 676 | struct nand_chip *this = mtd->priv; |
676 | struct doc_priv *doc = this->priv; | 677 | struct doc_priv *doc = this->priv; |
677 | void __iomem *docptr = doc->virtadr; | 678 | void __iomem *docptr = doc->virtadr; |
678 | int floor = 0; | 679 | int floor = 0; |
679 | 680 | ||
680 | if(debug)printk("select chip (%d)\n", chip); | 681 | if (debug) |
682 | printk("select chip (%d)\n", chip); | ||
681 | 683 | ||
682 | if (chip == -1) | 684 | if (chip == -1) |
683 | return; | 685 | return; |
684 | 686 | ||
685 | floor = chip / doc->chips_per_floor; | 687 | floor = chip / doc->chips_per_floor; |
686 | chip -= (floor * doc->chips_per_floor); | 688 | chip -= (floor * doc->chips_per_floor); |
687 | 689 | ||
688 | /* 11.4.4 -- deassert CE before changing chip */ | 690 | /* 11.4.4 -- deassert CE before changing chip */ |
689 | doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE); | 691 | doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); |
690 | 692 | ||
691 | WriteDOC(floor, docptr, FloorSelect); | 693 | WriteDOC(floor, docptr, FloorSelect); |
692 | WriteDOC(chip, docptr, CDSNDeviceSelect); | 694 | WriteDOC(chip, docptr, CDSNDeviceSelect); |
693 | 695 | ||
694 | doc200x_hwcontrol(mtd, NAND_CTL_SETNCE); | 696 | doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); |
695 | 697 | ||
696 | doc->curchip = chip; | 698 | doc->curchip = chip; |
697 | doc->curfloor = floor; | 699 | doc->curfloor = floor; |
698 | } | 700 | } |
699 | 701 | ||
700 | static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd) | 702 | #define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE) |
703 | |||
704 | static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd, | ||
705 | unsigned int ctrl) | ||
701 | { | 706 | { |
702 | struct nand_chip *this = mtd->priv; | 707 | struct nand_chip *this = mtd->priv; |
703 | struct doc_priv *doc = this->priv; | 708 | struct doc_priv *doc = this->priv; |
704 | void __iomem *docptr = doc->virtadr; | 709 | void __iomem *docptr = doc->virtadr; |
705 | 710 | ||
706 | switch(cmd) { | 711 | if (ctrl & NAND_CTRL_CHANGE) { |
707 | case NAND_CTL_SETNCE: | 712 | doc->CDSNControl &= ~CDSN_CTRL_MSK; |
708 | doc->CDSNControl |= CDSN_CTRL_CE; | 713 | doc->CDSNControl |= ctrl & CDSN_CTRL_MSK; |
709 | break; | 714 | if (debug) |
710 | case NAND_CTL_CLRNCE: | 715 | printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); |
711 | doc->CDSNControl &= ~CDSN_CTRL_CE; | 716 | WriteDOC(doc->CDSNControl, docptr, CDSNControl); |
712 | break; | 717 | /* 11.4.3 -- 4 NOPs after CSDNControl write */ |
713 | case NAND_CTL_SETCLE: | 718 | DoC_Delay(doc, 4); |
714 | doc->CDSNControl |= CDSN_CTRL_CLE; | 719 | } |
715 | break; | 720 | if (cmd != NAND_CMD_NONE) { |
716 | case NAND_CTL_CLRCLE: | 721 | if (DoC_is_2000(doc)) |
717 | doc->CDSNControl &= ~CDSN_CTRL_CLE; | 722 | doc2000_write_byte(mtd, cmd); |
718 | break; | 723 | else |
719 | case NAND_CTL_SETALE: | 724 | doc2001_write_byte(mtd, cmd); |
720 | doc->CDSNControl |= CDSN_CTRL_ALE; | ||
721 | break; | ||
722 | case NAND_CTL_CLRALE: | ||
723 | doc->CDSNControl &= ~CDSN_CTRL_ALE; | ||
724 | break; | ||
725 | case NAND_CTL_SETWP: | ||
726 | doc->CDSNControl |= CDSN_CTRL_WP; | ||
727 | break; | ||
728 | case NAND_CTL_CLRWP: | ||
729 | doc->CDSNControl &= ~CDSN_CTRL_WP; | ||
730 | break; | ||
731 | } | 725 | } |
732 | if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl); | ||
733 | WriteDOC(doc->CDSNControl, docptr, CDSNControl); | ||
734 | /* 11.4.3 -- 4 NOPs after CSDNControl write */ | ||
735 | DoC_Delay(doc, 4); | ||
736 | } | 726 | } |
737 | 727 | ||
738 | static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr) | 728 | static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) |
739 | { | 729 | { |
740 | struct nand_chip *this = mtd->priv; | 730 | struct nand_chip *this = mtd->priv; |
741 | struct doc_priv *doc = this->priv; | 731 | struct doc_priv *doc = this->priv; |
742 | void __iomem *docptr = doc->virtadr; | 732 | void __iomem *docptr = doc->virtadr; |
743 | 733 | ||
744 | /* | 734 | /* |
745 | * Must terminate write pipeline before sending any commands | 735 | * Must terminate write pipeline before sending any commands |
@@ -756,9 +746,9 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col | |||
756 | if (command == NAND_CMD_SEQIN) { | 746 | if (command == NAND_CMD_SEQIN) { |
757 | int readcmd; | 747 | int readcmd; |
758 | 748 | ||
759 | if (column >= mtd->oobblock) { | 749 | if (column >= mtd->writesize) { |
760 | /* OOB area */ | 750 | /* OOB area */ |
761 | column -= mtd->oobblock; | 751 | column -= mtd->writesize; |
762 | readcmd = NAND_CMD_READOOB; | 752 | readcmd = NAND_CMD_READOOB; |
763 | } else if (column < 256) { | 753 | } else if (column < 256) { |
764 | /* First 256 bytes --> READ0 */ | 754 | /* First 256 bytes --> READ0 */ |
@@ -782,25 +772,26 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col | |||
782 | WriteDOC(column, docptr, Mplus_FlashAddress); | 772 | WriteDOC(column, docptr, Mplus_FlashAddress); |
783 | } | 773 | } |
784 | if (page_addr != -1) { | 774 | if (page_addr != -1) { |
785 | WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress); | 775 | WriteDOC((unsigned char)(page_addr & 0xff), docptr, Mplus_FlashAddress); |
786 | WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); | 776 | WriteDOC((unsigned char)((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress); |
787 | /* One more address cycle for higher density devices */ | 777 | /* One more address cycle for higher density devices */ |
788 | if (this->chipsize & 0x0c000000) { | 778 | if (this->chipsize & 0x0c000000) { |
789 | WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); | 779 | WriteDOC((unsigned char)((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress); |
790 | printk("high density\n"); | 780 | printk("high density\n"); |
791 | } | 781 | } |
792 | } | 782 | } |
793 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | 783 | WriteDOC(0, docptr, Mplus_WritePipeTerm); |
794 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | 784 | WriteDOC(0, docptr, Mplus_WritePipeTerm); |
795 | /* deassert ALE */ | 785 | /* deassert ALE */ |
796 | if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID) | 786 | if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || |
787 | command == NAND_CMD_READOOB || command == NAND_CMD_READID) | ||
797 | WriteDOC(0, docptr, Mplus_FlashControl); | 788 | WriteDOC(0, docptr, Mplus_FlashControl); |
798 | } | 789 | } |
799 | 790 | ||
800 | /* | 791 | /* |
801 | * program and erase have their own busy handlers | 792 | * program and erase have their own busy handlers |
802 | * status and sequential in needs no delay | 793 | * status and sequential in needs no delay |
803 | */ | 794 | */ |
804 | switch (command) { | 795 | switch (command) { |
805 | 796 | ||
806 | case NAND_CMD_PAGEPROG: | 797 | case NAND_CMD_PAGEPROG: |
@@ -817,55 +808,57 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col | |||
817 | WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); | 808 | WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd); |
818 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | 809 | WriteDOC(0, docptr, Mplus_WritePipeTerm); |
819 | WriteDOC(0, docptr, Mplus_WritePipeTerm); | 810 | WriteDOC(0, docptr, Mplus_WritePipeTerm); |
820 | while ( !(this->read_byte(mtd) & 0x40)); | 811 | while (!(this->read_byte(mtd) & 0x40)) ; |
821 | return; | 812 | return; |
822 | 813 | ||
823 | /* This applies to read commands */ | 814 | /* This applies to read commands */ |
824 | default: | 815 | default: |
825 | /* | 816 | /* |
826 | * If we don't have access to the busy pin, we apply the given | 817 | * If we don't have access to the busy pin, we apply the given |
827 | * command delay | 818 | * command delay |
828 | */ | 819 | */ |
829 | if (!this->dev_ready) { | 820 | if (!this->dev_ready) { |
830 | udelay (this->chip_delay); | 821 | udelay(this->chip_delay); |
831 | return; | 822 | return; |
832 | } | 823 | } |
833 | } | 824 | } |
834 | 825 | ||
835 | /* Apply this short delay always to ensure that we do wait tWB in | 826 | /* Apply this short delay always to ensure that we do wait tWB in |
836 | * any case on any machine. */ | 827 | * any case on any machine. */ |
837 | ndelay (100); | 828 | ndelay(100); |
838 | /* wait until command is processed */ | 829 | /* wait until command is processed */ |
839 | while (!this->dev_ready(mtd)); | 830 | while (!this->dev_ready(mtd)) ; |
840 | } | 831 | } |
841 | 832 | ||
842 | static int doc200x_dev_ready(struct mtd_info *mtd) | 833 | static int doc200x_dev_ready(struct mtd_info *mtd) |
843 | { | 834 | { |
844 | struct nand_chip *this = mtd->priv; | 835 | struct nand_chip *this = mtd->priv; |
845 | struct doc_priv *doc = this->priv; | 836 | struct doc_priv *doc = this->priv; |
846 | void __iomem *docptr = doc->virtadr; | 837 | void __iomem *docptr = doc->virtadr; |
847 | 838 | ||
848 | if (DoC_is_MillenniumPlus(doc)) { | 839 | if (DoC_is_MillenniumPlus(doc)) { |
849 | /* 11.4.2 -- must NOP four times before checking FR/B# */ | 840 | /* 11.4.2 -- must NOP four times before checking FR/B# */ |
850 | DoC_Delay(doc, 4); | 841 | DoC_Delay(doc, 4); |
851 | if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { | 842 | if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) { |
852 | if(debug) | 843 | if (debug) |
853 | printk("not ready\n"); | 844 | printk("not ready\n"); |
854 | return 0; | 845 | return 0; |
855 | } | 846 | } |
856 | if (debug)printk("was ready\n"); | 847 | if (debug) |
848 | printk("was ready\n"); | ||
857 | return 1; | 849 | return 1; |
858 | } else { | 850 | } else { |
859 | /* 11.4.2 -- must NOP four times before checking FR/B# */ | 851 | /* 11.4.2 -- must NOP four times before checking FR/B# */ |
860 | DoC_Delay(doc, 4); | 852 | DoC_Delay(doc, 4); |
861 | if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { | 853 | if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { |
862 | if(debug) | 854 | if (debug) |
863 | printk("not ready\n"); | 855 | printk("not ready\n"); |
864 | return 0; | 856 | return 0; |
865 | } | 857 | } |
866 | /* 11.4.2 -- Must NOP twice if it's ready */ | 858 | /* 11.4.2 -- Must NOP twice if it's ready */ |
867 | DoC_Delay(doc, 2); | 859 | DoC_Delay(doc, 2); |
868 | if (debug)printk("was ready\n"); | 860 | if (debug) |
861 | printk("was ready\n"); | ||
869 | return 1; | 862 | return 1; |
870 | } | 863 | } |
871 | } | 864 | } |
@@ -881,10 +874,10 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode) | |||
881 | { | 874 | { |
882 | struct nand_chip *this = mtd->priv; | 875 | struct nand_chip *this = mtd->priv; |
883 | struct doc_priv *doc = this->priv; | 876 | struct doc_priv *doc = this->priv; |
884 | void __iomem *docptr = doc->virtadr; | 877 | void __iomem *docptr = doc->virtadr; |
885 | 878 | ||
886 | /* Prime the ECC engine */ | 879 | /* Prime the ECC engine */ |
887 | switch(mode) { | 880 | switch (mode) { |
888 | case NAND_ECC_READ: | 881 | case NAND_ECC_READ: |
889 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); | 882 | WriteDOC(DOC_ECC_RESET, docptr, ECCConf); |
890 | WriteDOC(DOC_ECC_EN, docptr, ECCConf); | 883 | WriteDOC(DOC_ECC_EN, docptr, ECCConf); |
@@ -900,10 +893,10 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) | |||
900 | { | 893 | { |
901 | struct nand_chip *this = mtd->priv; | 894 | struct nand_chip *this = mtd->priv; |
902 | struct doc_priv *doc = this->priv; | 895 | struct doc_priv *doc = this->priv; |
903 | void __iomem *docptr = doc->virtadr; | 896 | void __iomem *docptr = doc->virtadr; |
904 | 897 | ||
905 | /* Prime the ECC engine */ | 898 | /* Prime the ECC engine */ |
906 | switch(mode) { | 899 | switch (mode) { |
907 | case NAND_ECC_READ: | 900 | case NAND_ECC_READ: |
908 | WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); | 901 | WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); |
909 | WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); | 902 | WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); |
@@ -916,12 +909,11 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode) | |||
916 | } | 909 | } |
917 | 910 | ||
918 | /* This code is only called on write */ | 911 | /* This code is only called on write */ |
919 | static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | 912 | static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code) |
920 | unsigned char *ecc_code) | ||
921 | { | 913 | { |
922 | struct nand_chip *this = mtd->priv; | 914 | struct nand_chip *this = mtd->priv; |
923 | struct doc_priv *doc = this->priv; | 915 | struct doc_priv *doc = this->priv; |
924 | void __iomem *docptr = doc->virtadr; | 916 | void __iomem *docptr = doc->virtadr; |
925 | int i; | 917 | int i; |
926 | int emptymatch = 1; | 918 | int emptymatch = 1; |
927 | 919 | ||
@@ -961,7 +953,8 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | |||
961 | often. It could be optimized away by examining the data in | 953 | often. It could be optimized away by examining the data in |
962 | the writebuf routine, and remembering the result. */ | 954 | the writebuf routine, and remembering the result. */ |
963 | for (i = 0; i < 512; i++) { | 955 | for (i = 0; i < 512; i++) { |
964 | if (dat[i] == 0xff) continue; | 956 | if (dat[i] == 0xff) |
957 | continue; | ||
965 | emptymatch = 0; | 958 | emptymatch = 0; |
966 | break; | 959 | break; |
967 | } | 960 | } |
@@ -969,17 +962,20 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | |||
969 | /* If emptymatch still =1, we do have an all-0xff data buffer. | 962 | /* If emptymatch still =1, we do have an all-0xff data buffer. |
970 | Return all-0xff ecc value instead of the computed one, so | 963 | Return all-0xff ecc value instead of the computed one, so |
971 | it'll look just like a freshly-erased page. */ | 964 | it'll look just like a freshly-erased page. */ |
972 | if (emptymatch) memset(ecc_code, 0xff, 6); | 965 | if (emptymatch) |
966 | memset(ecc_code, 0xff, 6); | ||
973 | #endif | 967 | #endif |
974 | return 0; | 968 | return 0; |
975 | } | 969 | } |
976 | 970 | ||
977 | static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) | 971 | static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, |
972 | u_char *read_ecc, u_char *isnull) | ||
978 | { | 973 | { |
979 | int i, ret = 0; | 974 | int i, ret = 0; |
980 | struct nand_chip *this = mtd->priv; | 975 | struct nand_chip *this = mtd->priv; |
981 | struct doc_priv *doc = this->priv; | 976 | struct doc_priv *doc = this->priv; |
982 | void __iomem *docptr = doc->virtadr; | 977 | void __iomem *docptr = doc->virtadr; |
978 | uint8_t calc_ecc[6]; | ||
983 | volatile u_char dummy; | 979 | volatile u_char dummy; |
984 | int emptymatch = 1; | 980 | int emptymatch = 1; |
985 | 981 | ||
@@ -1012,18 +1008,20 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ | |||
1012 | all-0xff data and stored ecc block. Check the stored ecc. */ | 1008 | all-0xff data and stored ecc block. Check the stored ecc. */ |
1013 | if (emptymatch) { | 1009 | if (emptymatch) { |
1014 | for (i = 0; i < 6; i++) { | 1010 | for (i = 0; i < 6; i++) { |
1015 | if (read_ecc[i] == 0xff) continue; | 1011 | if (read_ecc[i] == 0xff) |
1012 | continue; | ||
1016 | emptymatch = 0; | 1013 | emptymatch = 0; |
1017 | break; | 1014 | break; |
1018 | } | 1015 | } |
1019 | } | 1016 | } |
1020 | /* If emptymatch still =1, check the data block. */ | 1017 | /* If emptymatch still =1, check the data block. */ |
1021 | if (emptymatch) { | 1018 | if (emptymatch) { |
1022 | /* Note: this somewhat expensive test should not be triggered | 1019 | /* Note: this somewhat expensive test should not be triggered |
1023 | often. It could be optimized away by examining the data in | 1020 | often. It could be optimized away by examining the data in |
1024 | the readbuf routine, and remembering the result. */ | 1021 | the readbuf routine, and remembering the result. */ |
1025 | for (i = 0; i < 512; i++) { | 1022 | for (i = 0; i < 512; i++) { |
1026 | if (dat[i] == 0xff) continue; | 1023 | if (dat[i] == 0xff) |
1024 | continue; | ||
1027 | emptymatch = 0; | 1025 | emptymatch = 0; |
1028 | break; | 1026 | break; |
1029 | } | 1027 | } |
@@ -1032,7 +1030,8 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ | |||
1032 | erased block, in which case the ECC will not come out right. | 1030 | erased block, in which case the ECC will not come out right. |
1033 | We'll suppress the error and tell the caller everything's | 1031 | We'll suppress the error and tell the caller everything's |
1034 | OK. Because it is. */ | 1032 | OK. Because it is. */ |
1035 | if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc); | 1033 | if (!emptymatch) |
1034 | ret = doc_ecc_decode(rs_decoder, dat, calc_ecc); | ||
1036 | if (ret > 0) | 1035 | if (ret > 0) |
1037 | printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); | 1036 | printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); |
1038 | } | 1037 | } |
@@ -1059,11 +1058,10 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ | |||
1059 | * safer. The only problem with it is that any code that parses oobfree must | 1058 | * safer. The only problem with it is that any code that parses oobfree must |
1060 | * be able to handle out-of-order segments. | 1059 | * be able to handle out-of-order segments. |
1061 | */ | 1060 | */ |
1062 | static struct nand_oobinfo doc200x_oobinfo = { | 1061 | static struct nand_ecclayout doc200x_oobinfo = { |
1063 | .useecc = MTD_NANDECC_AUTOPLACE, | 1062 | .eccbytes = 6, |
1064 | .eccbytes = 6, | 1063 | .eccpos = {0, 1, 2, 3, 4, 5}, |
1065 | .eccpos = {0, 1, 2, 3, 4, 5}, | 1064 | .oobfree = {{8, 8}, {6, 2}} |
1066 | .oobfree = { {8, 8}, {6, 2} } | ||
1067 | }; | 1065 | }; |
1068 | 1066 | ||
1069 | /* Find the (I)NFTL Media Header, and optionally also the mirror media header. | 1067 | /* Find the (I)NFTL Media Header, and optionally also the mirror media header. |
@@ -1072,8 +1070,7 @@ static struct nand_oobinfo doc200x_oobinfo = { | |||
1072 | either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media | 1070 | either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media |
1073 | header. The page #s of the found media headers are placed in mh0_page and | 1071 | header. The page #s of the found media headers are placed in mh0_page and |
1074 | mh1_page in the DOC private structure. */ | 1072 | mh1_page in the DOC private structure. */ |
1075 | static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, | 1073 | static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror) |
1076 | const char *id, int findmirror) | ||
1077 | { | 1074 | { |
1078 | struct nand_chip *this = mtd->priv; | 1075 | struct nand_chip *this = mtd->priv; |
1079 | struct doc_priv *doc = this->priv; | 1076 | struct doc_priv *doc = this->priv; |
@@ -1082,17 +1079,19 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, | |||
1082 | size_t retlen; | 1079 | size_t retlen; |
1083 | 1080 | ||
1084 | for (offs = 0; offs < mtd->size; offs += mtd->erasesize) { | 1081 | for (offs = 0; offs < mtd->size; offs += mtd->erasesize) { |
1085 | ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); | 1082 | ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); |
1086 | if (retlen != mtd->oobblock) continue; | 1083 | if (retlen != mtd->writesize) |
1084 | continue; | ||
1087 | if (ret) { | 1085 | if (ret) { |
1088 | printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", | 1086 | printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", offs); |
1089 | offs); | ||
1090 | } | 1087 | } |
1091 | if (memcmp(buf, id, 6)) continue; | 1088 | if (memcmp(buf, id, 6)) |
1089 | continue; | ||
1092 | printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs); | 1090 | printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs); |
1093 | if (doc->mh0_page == -1) { | 1091 | if (doc->mh0_page == -1) { |
1094 | doc->mh0_page = offs >> this->page_shift; | 1092 | doc->mh0_page = offs >> this->page_shift; |
1095 | if (!findmirror) return 1; | 1093 | if (!findmirror) |
1094 | return 1; | ||
1096 | continue; | 1095 | continue; |
1097 | } | 1096 | } |
1098 | doc->mh1_page = offs >> this->page_shift; | 1097 | doc->mh1_page = offs >> this->page_shift; |
@@ -1105,8 +1104,8 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, | |||
1105 | /* Only one mediaheader was found. We want buf to contain a | 1104 | /* Only one mediaheader was found. We want buf to contain a |
1106 | mediaheader on return, so we'll have to re-read the one we found. */ | 1105 | mediaheader on return, so we'll have to re-read the one we found. */ |
1107 | offs = doc->mh0_page << this->page_shift; | 1106 | offs = doc->mh0_page << this->page_shift; |
1108 | ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); | 1107 | ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf); |
1109 | if (retlen != mtd->oobblock) { | 1108 | if (retlen != mtd->writesize) { |
1110 | /* Insanity. Give up. */ | 1109 | /* Insanity. Give up. */ |
1111 | printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n"); | 1110 | printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n"); |
1112 | return 0; | 1111 | return 0; |
@@ -1114,8 +1113,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, | |||
1114 | return 1; | 1113 | return 1; |
1115 | } | 1114 | } |
1116 | 1115 | ||
1117 | static inline int __init nftl_partscan(struct mtd_info *mtd, | 1116 | static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) |
1118 | struct mtd_partition *parts) | ||
1119 | { | 1117 | { |
1120 | struct nand_chip *this = mtd->priv; | 1118 | struct nand_chip *this = mtd->priv; |
1121 | struct doc_priv *doc = this->priv; | 1119 | struct doc_priv *doc = this->priv; |
@@ -1127,13 +1125,14 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, | |||
1127 | unsigned blocks, maxblocks; | 1125 | unsigned blocks, maxblocks; |
1128 | int offs, numheaders; | 1126 | int offs, numheaders; |
1129 | 1127 | ||
1130 | buf = kmalloc(mtd->oobblock, GFP_KERNEL); | 1128 | buf = kmalloc(mtd->writesize, GFP_KERNEL); |
1131 | if (!buf) { | 1129 | if (!buf) { |
1132 | printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); | 1130 | printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); |
1133 | return 0; | 1131 | return 0; |
1134 | } | 1132 | } |
1135 | if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out; | 1133 | if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1))) |
1136 | mh = (struct NFTLMediaHeader *) buf; | 1134 | goto out; |
1135 | mh = (struct NFTLMediaHeader *)buf; | ||
1137 | 1136 | ||
1138 | mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits); | 1137 | mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits); |
1139 | mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN); | 1138 | mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN); |
@@ -1155,8 +1154,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, | |||
1155 | /* Auto-determine UnitSizeFactor. The constraints are: | 1154 | /* Auto-determine UnitSizeFactor. The constraints are: |
1156 | - There can be at most 32768 virtual blocks. | 1155 | - There can be at most 32768 virtual blocks. |
1157 | - There can be at most (virtual block size - page size) | 1156 | - There can be at most (virtual block size - page size) |
1158 | virtual blocks (because MediaHeader+BBT must fit in 1). | 1157 | virtual blocks (because MediaHeader+BBT must fit in 1). |
1159 | */ | 1158 | */ |
1160 | mh->UnitSizeFactor = 0xff; | 1159 | mh->UnitSizeFactor = 0xff; |
1161 | while (blocks > maxblocks) { | 1160 | while (blocks > maxblocks) { |
1162 | blocks >>= 1; | 1161 | blocks >>= 1; |
@@ -1211,14 +1210,13 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, | |||
1211 | } | 1210 | } |
1212 | 1211 | ||
1213 | ret = numparts; | 1212 | ret = numparts; |
1214 | out: | 1213 | out: |
1215 | kfree(buf); | 1214 | kfree(buf); |
1216 | return ret; | 1215 | return ret; |
1217 | } | 1216 | } |
1218 | 1217 | ||
1219 | /* This is a stripped-down copy of the code in inftlmount.c */ | 1218 | /* This is a stripped-down copy of the code in inftlmount.c */ |
1220 | static inline int __init inftl_partscan(struct mtd_info *mtd, | 1219 | static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts) |
1221 | struct mtd_partition *parts) | ||
1222 | { | 1220 | { |
1223 | struct nand_chip *this = mtd->priv; | 1221 | struct nand_chip *this = mtd->priv; |
1224 | struct doc_priv *doc = this->priv; | 1222 | struct doc_priv *doc = this->priv; |
@@ -1235,15 +1233,16 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, | |||
1235 | if (inftl_bbt_write) | 1233 | if (inftl_bbt_write) |
1236 | end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift); | 1234 | end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift); |
1237 | 1235 | ||
1238 | buf = kmalloc(mtd->oobblock, GFP_KERNEL); | 1236 | buf = kmalloc(mtd->writesize, GFP_KERNEL); |
1239 | if (!buf) { | 1237 | if (!buf) { |
1240 | printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); | 1238 | printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); |
1241 | return 0; | 1239 | return 0; |
1242 | } | 1240 | } |
1243 | 1241 | ||
1244 | if (!find_media_headers(mtd, buf, "BNAND", 0)) goto out; | 1242 | if (!find_media_headers(mtd, buf, "BNAND", 0)) |
1243 | goto out; | ||
1245 | doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift); | 1244 | doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift); |
1246 | mh = (struct INFTLMediaHeader *) buf; | 1245 | mh = (struct INFTLMediaHeader *)buf; |
1247 | 1246 | ||
1248 | mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks); | 1247 | mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks); |
1249 | mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions); | 1248 | mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions); |
@@ -1319,8 +1318,10 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, | |||
1319 | parts[numparts].offset = ip->firstUnit << vshift; | 1318 | parts[numparts].offset = ip->firstUnit << vshift; |
1320 | parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift; | 1319 | parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift; |
1321 | numparts++; | 1320 | numparts++; |
1322 | if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit; | 1321 | if (ip->lastUnit > lastvunit) |
1323 | if (ip->flags & INFTL_LAST) break; | 1322 | lastvunit = ip->lastUnit; |
1323 | if (ip->flags & INFTL_LAST) | ||
1324 | break; | ||
1324 | } | 1325 | } |
1325 | lastvunit++; | 1326 | lastvunit++; |
1326 | if ((lastvunit << vshift) < end) { | 1327 | if ((lastvunit << vshift) < end) { |
@@ -1330,7 +1331,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, | |||
1330 | numparts++; | 1331 | numparts++; |
1331 | } | 1332 | } |
1332 | ret = numparts; | 1333 | ret = numparts; |
1333 | out: | 1334 | out: |
1334 | kfree(buf); | 1335 | kfree(buf); |
1335 | return ret; | 1336 | return ret; |
1336 | } | 1337 | } |
@@ -1342,11 +1343,12 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd) | |||
1342 | struct doc_priv *doc = this->priv; | 1343 | struct doc_priv *doc = this->priv; |
1343 | struct mtd_partition parts[2]; | 1344 | struct mtd_partition parts[2]; |
1344 | 1345 | ||
1345 | memset((char *) parts, 0, sizeof(parts)); | 1346 | memset((char *)parts, 0, sizeof(parts)); |
1346 | /* On NFTL, we have to find the media headers before we can read the | 1347 | /* On NFTL, we have to find the media headers before we can read the |
1347 | BBTs, since they're stored in the media header eraseblocks. */ | 1348 | BBTs, since they're stored in the media header eraseblocks. */ |
1348 | numparts = nftl_partscan(mtd, parts); | 1349 | numparts = nftl_partscan(mtd, parts); |
1349 | if (!numparts) return -EIO; | 1350 | if (!numparts) |
1351 | return -EIO; | ||
1350 | this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | | 1352 | this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT | |
1351 | NAND_BBT_SAVECONTENT | NAND_BBT_WRITE | | 1353 | NAND_BBT_SAVECONTENT | NAND_BBT_WRITE | |
1352 | NAND_BBT_VERSION; | 1354 | NAND_BBT_VERSION; |
@@ -1393,8 +1395,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) | |||
1393 | this->bbt_td->pages[0] = 2; | 1395 | this->bbt_td->pages[0] = 2; |
1394 | this->bbt_md = NULL; | 1396 | this->bbt_md = NULL; |
1395 | } else { | 1397 | } else { |
1396 | this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | | 1398 | this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION; |
1397 | NAND_BBT_VERSION; | ||
1398 | if (inftl_bbt_write) | 1399 | if (inftl_bbt_write) |
1399 | this->bbt_td->options |= NAND_BBT_WRITE; | 1400 | this->bbt_td->options |= NAND_BBT_WRITE; |
1400 | this->bbt_td->offs = 8; | 1401 | this->bbt_td->offs = 8; |
@@ -1404,8 +1405,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) | |||
1404 | this->bbt_td->reserved_block_code = 0x01; | 1405 | this->bbt_td->reserved_block_code = 0x01; |
1405 | this->bbt_td->pattern = "MSYS_BBT"; | 1406 | this->bbt_td->pattern = "MSYS_BBT"; |
1406 | 1407 | ||
1407 | this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | | 1408 | this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION; |
1408 | NAND_BBT_VERSION; | ||
1409 | if (inftl_bbt_write) | 1409 | if (inftl_bbt_write) |
1410 | this->bbt_md->options |= NAND_BBT_WRITE; | 1410 | this->bbt_md->options |= NAND_BBT_WRITE; |
1411 | this->bbt_md->offs = 8; | 1411 | this->bbt_md->offs = 8; |
@@ -1420,12 +1420,13 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) | |||
1420 | At least as nand_bbt.c is currently written. */ | 1420 | At least as nand_bbt.c is currently written. */ |
1421 | if ((ret = nand_scan_bbt(mtd, NULL))) | 1421 | if ((ret = nand_scan_bbt(mtd, NULL))) |
1422 | return ret; | 1422 | return ret; |
1423 | memset((char *) parts, 0, sizeof(parts)); | 1423 | memset((char *)parts, 0, sizeof(parts)); |
1424 | numparts = inftl_partscan(mtd, parts); | 1424 | numparts = inftl_partscan(mtd, parts); |
1425 | /* At least for now, require the INFTL Media Header. We could probably | 1425 | /* At least for now, require the INFTL Media Header. We could probably |
1426 | do without it for non-INFTL use, since all it gives us is | 1426 | do without it for non-INFTL use, since all it gives us is |
1427 | autopartitioning, but I want to give it more thought. */ | 1427 | autopartitioning, but I want to give it more thought. */ |
1428 | if (!numparts) return -EIO; | 1428 | if (!numparts) |
1429 | return -EIO; | ||
1429 | add_mtd_device(mtd); | 1430 | add_mtd_device(mtd); |
1430 | #ifdef CONFIG_MTD_PARTITIONS | 1431 | #ifdef CONFIG_MTD_PARTITIONS |
1431 | if (!no_autopart) | 1432 | if (!no_autopart) |
@@ -1439,7 +1440,6 @@ static inline int __init doc2000_init(struct mtd_info *mtd) | |||
1439 | struct nand_chip *this = mtd->priv; | 1440 | struct nand_chip *this = mtd->priv; |
1440 | struct doc_priv *doc = this->priv; | 1441 | struct doc_priv *doc = this->priv; |
1441 | 1442 | ||
1442 | this->write_byte = doc2000_write_byte; | ||
1443 | this->read_byte = doc2000_read_byte; | 1443 | this->read_byte = doc2000_read_byte; |
1444 | this->write_buf = doc2000_writebuf; | 1444 | this->write_buf = doc2000_writebuf; |
1445 | this->read_buf = doc2000_readbuf; | 1445 | this->read_buf = doc2000_readbuf; |
@@ -1457,7 +1457,6 @@ static inline int __init doc2001_init(struct mtd_info *mtd) | |||
1457 | struct nand_chip *this = mtd->priv; | 1457 | struct nand_chip *this = mtd->priv; |
1458 | struct doc_priv *doc = this->priv; | 1458 | struct doc_priv *doc = this->priv; |
1459 | 1459 | ||
1460 | this->write_byte = doc2001_write_byte; | ||
1461 | this->read_byte = doc2001_read_byte; | 1460 | this->read_byte = doc2001_read_byte; |
1462 | this->write_buf = doc2001_writebuf; | 1461 | this->write_buf = doc2001_writebuf; |
1463 | this->read_buf = doc2001_readbuf; | 1462 | this->read_buf = doc2001_readbuf; |
@@ -1489,16 +1488,15 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) | |||
1489 | struct nand_chip *this = mtd->priv; | 1488 | struct nand_chip *this = mtd->priv; |
1490 | struct doc_priv *doc = this->priv; | 1489 | struct doc_priv *doc = this->priv; |
1491 | 1490 | ||
1492 | this->write_byte = NULL; | ||
1493 | this->read_byte = doc2001plus_read_byte; | 1491 | this->read_byte = doc2001plus_read_byte; |
1494 | this->write_buf = doc2001plus_writebuf; | 1492 | this->write_buf = doc2001plus_writebuf; |
1495 | this->read_buf = doc2001plus_readbuf; | 1493 | this->read_buf = doc2001plus_readbuf; |
1496 | this->verify_buf = doc2001plus_verifybuf; | 1494 | this->verify_buf = doc2001plus_verifybuf; |
1497 | this->scan_bbt = inftl_scan_bbt; | 1495 | this->scan_bbt = inftl_scan_bbt; |
1498 | this->hwcontrol = NULL; | 1496 | this->cmd_ctrl = NULL; |
1499 | this->select_chip = doc2001plus_select_chip; | 1497 | this->select_chip = doc2001plus_select_chip; |
1500 | this->cmdfunc = doc2001plus_command; | 1498 | this->cmdfunc = doc2001plus_command; |
1501 | this->enable_hwecc = doc2001plus_enable_hwecc; | 1499 | this->ecc.hwctl = doc2001plus_enable_hwecc; |
1502 | 1500 | ||
1503 | doc->chips_per_floor = 1; | 1501 | doc->chips_per_floor = 1; |
1504 | mtd->name = "DiskOnChip Millennium Plus"; | 1502 | mtd->name = "DiskOnChip Millennium Plus"; |
@@ -1535,20 +1533,16 @@ static int __init doc_probe(unsigned long physadr) | |||
1535 | save_control = ReadDOC(virtadr, DOCControl); | 1533 | save_control = ReadDOC(virtadr, DOCControl); |
1536 | 1534 | ||
1537 | /* Reset the DiskOnChip ASIC */ | 1535 | /* Reset the DiskOnChip ASIC */ |
1538 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, | 1536 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl); |
1539 | virtadr, DOCControl); | 1537 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl); |
1540 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, | ||
1541 | virtadr, DOCControl); | ||
1542 | 1538 | ||
1543 | /* Enable the DiskOnChip ASIC */ | 1539 | /* Enable the DiskOnChip ASIC */ |
1544 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, | 1540 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl); |
1545 | virtadr, DOCControl); | 1541 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl); |
1546 | WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, | ||
1547 | virtadr, DOCControl); | ||
1548 | 1542 | ||
1549 | ChipID = ReadDOC(virtadr, ChipID); | 1543 | ChipID = ReadDOC(virtadr, ChipID); |
1550 | 1544 | ||
1551 | switch(ChipID) { | 1545 | switch (ChipID) { |
1552 | case DOC_ChipID_Doc2k: | 1546 | case DOC_ChipID_Doc2k: |
1553 | reg = DoC_2k_ECCStatus; | 1547 | reg = DoC_2k_ECCStatus; |
1554 | break; | 1548 | break; |
@@ -1564,15 +1558,13 @@ static int __init doc_probe(unsigned long physadr) | |||
1564 | ReadDOC(virtadr, Mplus_Power); | 1558 | ReadDOC(virtadr, Mplus_Power); |
1565 | 1559 | ||
1566 | /* Reset the Millennium Plus ASIC */ | 1560 | /* Reset the Millennium Plus ASIC */ |
1567 | tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | | 1561 | tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT; |
1568 | DOC_MODE_BDECT; | ||
1569 | WriteDOC(tmp, virtadr, Mplus_DOCControl); | 1562 | WriteDOC(tmp, virtadr, Mplus_DOCControl); |
1570 | WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); | 1563 | WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); |
1571 | 1564 | ||
1572 | mdelay(1); | 1565 | mdelay(1); |
1573 | /* Enable the Millennium Plus ASIC */ | 1566 | /* Enable the Millennium Plus ASIC */ |
1574 | tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | | 1567 | tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT; |
1575 | DOC_MODE_BDECT; | ||
1576 | WriteDOC(tmp, virtadr, Mplus_DOCControl); | 1568 | WriteDOC(tmp, virtadr, Mplus_DOCControl); |
1577 | WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); | 1569 | WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm); |
1578 | mdelay(1); | 1570 | mdelay(1); |
@@ -1596,7 +1588,7 @@ static int __init doc_probe(unsigned long physadr) | |||
1596 | goto notfound; | 1588 | goto notfound; |
1597 | } | 1589 | } |
1598 | /* Check the TOGGLE bit in the ECC register */ | 1590 | /* Check the TOGGLE bit in the ECC register */ |
1599 | tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; | 1591 | tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; |
1600 | tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; | 1592 | tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; |
1601 | tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; | 1593 | tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT; |
1602 | if ((tmp == tmpb) || (tmp != tmpc)) { | 1594 | if ((tmp == tmpb) || (tmp != tmpc)) { |
@@ -1626,11 +1618,11 @@ static int __init doc_probe(unsigned long physadr) | |||
1626 | if (ChipID == DOC_ChipID_DocMilPlus16) { | 1618 | if (ChipID == DOC_ChipID_DocMilPlus16) { |
1627 | WriteDOC(~newval, virtadr, Mplus_AliasResolution); | 1619 | WriteDOC(~newval, virtadr, Mplus_AliasResolution); |
1628 | oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); | 1620 | oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); |
1629 | WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it | 1621 | WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it |
1630 | } else { | 1622 | } else { |
1631 | WriteDOC(~newval, virtadr, AliasResolution); | 1623 | WriteDOC(~newval, virtadr, AliasResolution); |
1632 | oldval = ReadDOC(doc->virtadr, AliasResolution); | 1624 | oldval = ReadDOC(doc->virtadr, AliasResolution); |
1633 | WriteDOC(newval, virtadr, AliasResolution); // restore it | 1625 | WriteDOC(newval, virtadr, AliasResolution); // restore it |
1634 | } | 1626 | } |
1635 | newval = ~newval; | 1627 | newval = ~newval; |
1636 | if (oldval == newval) { | 1628 | if (oldval == newval) { |
@@ -1642,10 +1634,8 @@ static int __init doc_probe(unsigned long physadr) | |||
1642 | printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr); | 1634 | printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr); |
1643 | 1635 | ||
1644 | len = sizeof(struct mtd_info) + | 1636 | len = sizeof(struct mtd_info) + |
1645 | sizeof(struct nand_chip) + | 1637 | sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); |
1646 | sizeof(struct doc_priv) + | 1638 | mtd = kmalloc(len, GFP_KERNEL); |
1647 | (2 * sizeof(struct nand_bbt_descr)); | ||
1648 | mtd = kmalloc(len, GFP_KERNEL); | ||
1649 | if (!mtd) { | 1639 | if (!mtd) { |
1650 | printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); | 1640 | printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); |
1651 | ret = -ENOMEM; | 1641 | ret = -ENOMEM; |
@@ -1663,17 +1653,19 @@ static int __init doc_probe(unsigned long physadr) | |||
1663 | 1653 | ||
1664 | nand->priv = doc; | 1654 | nand->priv = doc; |
1665 | nand->select_chip = doc200x_select_chip; | 1655 | nand->select_chip = doc200x_select_chip; |
1666 | nand->hwcontrol = doc200x_hwcontrol; | 1656 | nand->cmd_ctrl = doc200x_hwcontrol; |
1667 | nand->dev_ready = doc200x_dev_ready; | 1657 | nand->dev_ready = doc200x_dev_ready; |
1668 | nand->waitfunc = doc200x_wait; | 1658 | nand->waitfunc = doc200x_wait; |
1669 | nand->block_bad = doc200x_block_bad; | 1659 | nand->block_bad = doc200x_block_bad; |
1670 | nand->enable_hwecc = doc200x_enable_hwecc; | 1660 | nand->ecc.hwctl = doc200x_enable_hwecc; |
1671 | nand->calculate_ecc = doc200x_calculate_ecc; | 1661 | nand->ecc.calculate = doc200x_calculate_ecc; |
1672 | nand->correct_data = doc200x_correct_data; | 1662 | nand->ecc.correct = doc200x_correct_data; |
1673 | 1663 | ||
1674 | nand->autooob = &doc200x_oobinfo; | 1664 | nand->ecc.layout = &doc200x_oobinfo; |
1675 | nand->eccmode = NAND_ECC_HW6_512; | 1665 | nand->ecc.mode = NAND_ECC_HW_SYNDROME; |
1676 | nand->options = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME; | 1666 | nand->ecc.size = 512; |
1667 | nand->ecc.bytes = 6; | ||
1668 | nand->options = NAND_USE_FLASH_BBT; | ||
1677 | 1669 | ||
1678 | doc->physadr = physadr; | 1670 | doc->physadr = physadr; |
1679 | doc->virtadr = virtadr; | 1671 | doc->virtadr = virtadr; |
@@ -1707,18 +1699,18 @@ static int __init doc_probe(unsigned long physadr) | |||
1707 | doclist = mtd; | 1699 | doclist = mtd; |
1708 | return 0; | 1700 | return 0; |
1709 | 1701 | ||
1710 | notfound: | 1702 | notfound: |
1711 | /* Put back the contents of the DOCControl register, in case it's not | 1703 | /* Put back the contents of the DOCControl register, in case it's not |
1712 | actually a DiskOnChip. */ | 1704 | actually a DiskOnChip. */ |
1713 | WriteDOC(save_control, virtadr, DOCControl); | 1705 | WriteDOC(save_control, virtadr, DOCControl); |
1714 | fail: | 1706 | fail: |
1715 | iounmap(virtadr); | 1707 | iounmap(virtadr); |
1716 | return ret; | 1708 | return ret; |
1717 | } | 1709 | } |
1718 | 1710 | ||
1719 | static void release_nanddoc(void) | 1711 | static void release_nanddoc(void) |
1720 | { | 1712 | { |
1721 | struct mtd_info *mtd, *nextmtd; | 1713 | struct mtd_info *mtd, *nextmtd; |
1722 | struct nand_chip *nand; | 1714 | struct nand_chip *nand; |
1723 | struct doc_priv *doc; | 1715 | struct doc_priv *doc; |
1724 | 1716 | ||
@@ -1747,8 +1739,8 @@ static int __init init_nanddoc(void) | |||
1747 | * generator polinomial degree = 4 | 1739 | * generator polinomial degree = 4 |
1748 | */ | 1740 | */ |
1749 | rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); | 1741 | rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); |
1750 | if (!rs_decoder) { | 1742 | if (!rs_decoder) { |
1751 | printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); | 1743 | printk(KERN_ERR "DiskOnChip: Could not create a RS decoder\n"); |
1752 | return -ENOMEM; | 1744 | return -ENOMEM; |
1753 | } | 1745 | } |
1754 | 1746 | ||
@@ -1758,7 +1750,7 @@ static int __init init_nanddoc(void) | |||
1758 | if (ret < 0) | 1750 | if (ret < 0) |
1759 | goto outerr; | 1751 | goto outerr; |
1760 | } else { | 1752 | } else { |
1761 | for (i=0; (doc_locations[i] != 0xffffffff); i++) { | 1753 | for (i = 0; (doc_locations[i] != 0xffffffff); i++) { |
1762 | doc_probe(doc_locations[i]); | 1754 | doc_probe(doc_locations[i]); |
1763 | } | 1755 | } |
1764 | } | 1756 | } |
@@ -1770,7 +1762,7 @@ static int __init init_nanddoc(void) | |||
1770 | goto outerr; | 1762 | goto outerr; |
1771 | } | 1763 | } |
1772 | return 0; | 1764 | return 0; |
1773 | outerr: | 1765 | outerr: |
1774 | free_rs(rs_decoder); | 1766 | free_rs(rs_decoder); |
1775 | return ret; | 1767 | return ret; |
1776 | } | 1768 | } |