]>
Commit | Line | Data |
---|---|---|
affae2bf WD |
1 | /* |
2 | * (C) Copyright 2000, 2001 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * (C) Copyright 2001, Stuart Hughes, Lineo Inc, stuarth@lineo.com | |
6 | * Add support the Sharp chips on the mpc8260ads. | |
7 | * I started with board/ip860/flash.c and made changes I found in | |
8 | * the MTD project by David Schleef. | |
9 | * | |
8564acf9 WD |
10 | * (C) Copyright 2003 Arabella Software Ltd. |
11 | * Yuli Barcohen <yuli@arabellasw.com> | |
12 | * Re-written to support multi-bank flash SIMMs. | |
13 | * Added support for real protection and JFFS2. | |
14 | * | |
affae2bf WD |
15 | * See file CREDITS for list of people who contributed to this |
16 | * project. | |
17 | * | |
18 | * This program is free software; you can redistribute it and/or | |
19 | * modify it under the terms of the GNU General Public License as | |
20 | * published by the Free Software Foundation; either version 2 of | |
21 | * the License, or (at your option) any later version. | |
22 | * | |
23 | * This program is distributed in the hope that it will be useful, | |
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
26 | * GNU General Public License for more details. | |
27 | * | |
28 | * You should have received a copy of the GNU General Public License | |
29 | * along with this program; if not, write to the Free Software | |
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
31 | * MA 02111-1307 USA | |
32 | */ | |
33 | ||
34 | #include <common.h> | |
35 | ||
8564acf9 WD |
36 | /* Intel-compatible flash ID */ |
37 | #define INTEL_COMPAT 0x89898989 | |
38 | #define INTEL_ALT 0xB0B0B0B0 | |
affae2bf | 39 | |
8564acf9 WD |
40 | /* Intel-compatible flash commands */ |
41 | #define INTEL_PROGRAM 0x10101010 | |
42 | #define INTEL_ERASE 0x20202020 | |
43 | #define INTEL_CLEAR 0x50505050 | |
44 | #define INTEL_LOCKBIT 0x60606060 | |
45 | #define INTEL_PROTECT 0x01010101 | |
46 | #define INTEL_STATUS 0x70707070 | |
47 | #define INTEL_READID 0x90909090 | |
48 | #define INTEL_CONFIRM 0xD0D0D0D0 | |
49 | #define INTEL_RESET 0xFFFFFFFF | |
affae2bf | 50 | |
8564acf9 WD |
51 | /* Intel-compatible flash status bits */ |
52 | #define INTEL_FINISHED 0x80808080 | |
53 | #define INTEL_OK 0x80808080 | |
affae2bf | 54 | |
8564acf9 | 55 | flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ |
affae2bf WD |
56 | |
57 | /*----------------------------------------------------------------------- | |
8564acf9 WD |
58 | * This board supports 32-bit wide flash SIMMs (4x8-bit configuration.) |
59 | * Up to 32MB of flash supported (up to 4 banks.) | |
60 | * BCSR is used for flash presence detect (page 4-65 of the User's Manual) | |
61 | * | |
62 | * The following code can not run from flash! | |
affae2bf | 63 | */ |
affae2bf WD |
64 | unsigned long flash_init (void) |
65 | { | |
8564acf9 WD |
66 | ulong size = 0, sect_start, sect_size = 0, bank_size; |
67 | ushort sect_count = 0; | |
68 | int i, j, nbanks; | |
69 | vu_long *addr = (vu_long *)CFG_FLASH_BASE; | |
70 | vu_long *bcsr = (vu_long *)CFG_BCSR; | |
71 | ||
72 | switch (bcsr[2] & 0xF) { | |
73 | case 0: | |
74 | nbanks = 4; | |
75 | break; | |
76 | case 1: | |
77 | nbanks = 2; | |
78 | break; | |
79 | case 2: | |
80 | nbanks = 1; | |
81 | break; | |
82 | default: /* Unsupported configurations */ | |
83 | nbanks = CFG_MAX_FLASH_BANKS; | |
affae2bf WD |
84 | } |
85 | ||
8564acf9 WD |
86 | if (nbanks > CFG_MAX_FLASH_BANKS) |
87 | nbanks = CFG_MAX_FLASH_BANKS; | |
88 | ||
89 | for (i = 0; i < nbanks; i++) { | |
90 | *addr = INTEL_READID; /* Read Intelligent Identifier */ | |
91 | if ((addr[0] == INTEL_COMPAT) || (addr[0] == INTEL_ALT)) { | |
92 | switch (addr[1]) { | |
93 | case SHARP_ID_28F016SCL: | |
94 | case SHARP_ID_28F016SCZ: | |
95 | flash_info[i].flash_id = FLASH_MAN_SHARP | FLASH_LH28F016SCT; | |
96 | sect_count = 32; | |
97 | sect_size = 0x40000; | |
98 | break; | |
99 | default: | |
100 | flash_info[i].flash_id = FLASH_UNKNOWN; | |
101 | sect_count = CFG_MAX_FLASH_SECT; | |
102 | sect_size = | |
103 | CFG_FLASH_SIZE / CFG_MAX_FLASH_BANKS / CFG_MAX_FLASH_SECT; | |
104 | } | |
105 | } | |
106 | else | |
107 | flash_info[i].flash_id = FLASH_UNKNOWN; | |
108 | if (flash_info[i].flash_id == FLASH_UNKNOWN) { | |
109 | printf("### Unknown flash ID %08lX %08lX at address %08lX ###\n", | |
110 | addr[0], addr[1], (ulong)addr); | |
111 | size = 0; | |
112 | *addr = INTEL_RESET; /* Reset bank to Read Array mode */ | |
113 | break; | |
114 | } | |
115 | flash_info[i].sector_count = sect_count; | |
116 | flash_info[i].size = bank_size = sect_size * sect_count; | |
117 | size += bank_size; | |
118 | sect_start = (ulong)addr; | |
119 | for (j = 0; j < sect_count; j++) { | |
120 | addr = (vu_long *)sect_start; | |
121 | flash_info[i].start[j] = sect_start; | |
122 | flash_info[i].protect[j] = (addr[2] == 0x01010101); | |
123 | sect_start += sect_size; | |
124 | } | |
125 | *addr = INTEL_RESET; /* Reset bank to Read Array mode */ | |
126 | addr = (vu_long *)sect_start; | |
affae2bf | 127 | } |
affae2bf | 128 | |
8564acf9 WD |
129 | if (size == 0) { /* Unknown flash, fill with hard-coded values */ |
130 | sect_start = CFG_FLASH_BASE; | |
131 | for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { | |
132 | flash_info[i].flash_id = FLASH_UNKNOWN; | |
133 | flash_info[i].size = CFG_FLASH_SIZE / CFG_MAX_FLASH_BANKS; | |
134 | flash_info[i].sector_count = sect_count; | |
135 | for (j = 0; j < sect_count; j++) { | |
136 | flash_info[i].start[j] = sect_start; | |
137 | flash_info[i].protect[j] = 0; | |
138 | sect_start += sect_size; | |
139 | } | |
140 | } | |
141 | size = CFG_FLASH_SIZE; | |
142 | } | |
143 | else | |
144 | for (i = nbanks; i < CFG_MAX_FLASH_BANKS; i++) { | |
145 | flash_info[i].flash_id = FLASH_UNKNOWN; | |
146 | flash_info[i].size = 0; | |
147 | flash_info[i].sector_count = 0; | |
148 | } | |
affae2bf WD |
149 | |
150 | #if CFG_MONITOR_BASE >= CFG_FLASH_BASE | |
151 | /* monitor protection ON by default */ | |
152 | flash_protect(FLAG_PROTECT_SET, | |
153 | CFG_MONITOR_BASE, | |
3b57fe0a | 154 | CFG_MONITOR_BASE+monitor_flash_len-1, |
affae2bf WD |
155 | &flash_info[0]); |
156 | #endif | |
157 | ||
158 | #ifdef CFG_ENV_IS_IN_FLASH | |
159 | /* ENV protection ON by default */ | |
160 | flash_protect(FLAG_PROTECT_SET, | |
161 | CFG_ENV_ADDR, | |
162 | CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1, | |
163 | &flash_info[0]); | |
164 | #endif | |
165 | return (size); | |
166 | } | |
167 | ||
168 | /*----------------------------------------------------------------------- | |
169 | */ | |
170 | void flash_print_info (flash_info_t *info) | |
171 | { | |
172 | int i; | |
173 | ||
174 | if (info->flash_id == FLASH_UNKNOWN) { | |
175 | printf ("missing or unknown FLASH type\n"); | |
176 | return; | |
177 | } | |
178 | ||
179 | switch (info->flash_id & FLASH_VENDMASK) { | |
180 | case FLASH_MAN_INTEL: printf ("Intel "); break; | |
181 | case FLASH_MAN_SHARP: printf ("Sharp "); break; | |
182 | default: printf ("Unknown Vendor "); break; | |
183 | } | |
184 | ||
185 | switch (info->flash_id & FLASH_TYPEMASK) { | |
186 | case FLASH_28F016SV: printf ("28F016SV (16 Mbit, 32 x 64k)\n"); | |
187 | break; | |
188 | case FLASH_28F160S3: printf ("28F160S3 (16 Mbit, 32 x 512K)\n"); | |
189 | break; | |
190 | case FLASH_28F320S3: printf ("28F320S3 (32 Mbit, 64 x 512K)\n"); | |
191 | break; | |
192 | case FLASH_LH28F016SCT: printf ("28F016SC (16 Mbit, 32 x 64K)\n"); | |
193 | break; | |
194 | default: printf ("Unknown Chip Type\n"); | |
195 | break; | |
196 | } | |
197 | ||
198 | printf (" Size: %ld MB in %d Sectors\n", | |
199 | info->size >> 20, info->sector_count); | |
200 | ||
201 | printf (" Sector Start Addresses:"); | |
202 | for (i=0; i<info->sector_count; ++i) { | |
203 | if ((i % 5) == 0) | |
204 | printf ("\n "); | |
205 | printf (" %08lX%s", | |
206 | info->start[i], | |
207 | info->protect[i] ? " (RO)" : " " | |
208 | ); | |
209 | } | |
210 | printf ("\n"); | |
211 | } | |
212 | ||
213 | /*----------------------------------------------------------------------- | |
214 | */ | |
affae2bf WD |
215 | int flash_erase (flash_info_t *info, int s_first, int s_last) |
216 | { | |
217 | int flag, prot, sect; | |
218 | ulong start, now, last; | |
219 | ||
220 | if ((s_first < 0) || (s_first > s_last)) { | |
221 | if (info->flash_id == FLASH_UNKNOWN) { | |
222 | printf ("- missing\n"); | |
223 | } else { | |
224 | printf ("- no sectors to erase\n"); | |
225 | } | |
226 | return 1; | |
227 | } | |
228 | ||
229 | if ( ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) | |
230 | && ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_SHARP) ) { | |
231 | printf ("Can't erase unknown flash type %08lx - aborted\n", | |
232 | info->flash_id); | |
233 | return 1; | |
234 | } | |
235 | ||
236 | prot = 0; | |
237 | for (sect=s_first; sect<=s_last; ++sect) { | |
238 | if (info->protect[sect]) { | |
239 | prot++; | |
240 | } | |
241 | } | |
242 | ||
243 | if (prot) { | |
244 | printf ("- Warning: %d protected sectors will not be erased!\n", | |
245 | prot); | |
246 | } else { | |
247 | printf ("\n"); | |
248 | } | |
249 | ||
affae2bf WD |
250 | /* Start erase on unprotected sectors */ |
251 | for (sect = s_first; sect<=s_last; sect++) { | |
252 | if (info->protect[sect] == 0) { /* not protected */ | |
253 | vu_long *addr = (vu_long *)(info->start[sect]); | |
254 | ||
255 | last = start = get_timer (0); | |
256 | ||
257 | /* Disable interrupts which might cause a timeout here */ | |
258 | flag = disable_interrupts(); | |
259 | ||
affae2bf | 260 | /* Clear Status Register */ |
8564acf9 | 261 | *addr = INTEL_CLEAR; |
affae2bf | 262 | /* Single Block Erase Command */ |
8564acf9 | 263 | *addr = INTEL_ERASE; |
affae2bf | 264 | /* Confirm */ |
8564acf9 | 265 | *addr = INTEL_CONFIRM; |
affae2bf WD |
266 | |
267 | if((info->flash_id & FLASH_TYPEMASK) != FLASH_LH28F016SCT) { | |
268 | /* Resume Command, as per errata update */ | |
8564acf9 | 269 | *addr = INTEL_CONFIRM; |
affae2bf WD |
270 | } |
271 | ||
272 | /* re-enable interrupts if necessary */ | |
273 | if (flag) | |
274 | enable_interrupts(); | |
275 | ||
8564acf9 | 276 | while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) { |
affae2bf WD |
277 | if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) { |
278 | printf ("Timeout\n"); | |
8564acf9 | 279 | *addr = INTEL_RESET; /* reset bank */ |
affae2bf WD |
280 | return 1; |
281 | } | |
282 | /* show that we're waiting */ | |
283 | if ((now - last) > 1000) { /* every second */ | |
284 | putc ('.'); | |
285 | last = now; | |
286 | } | |
287 | } | |
288 | ||
8564acf9 WD |
289 | if (*addr != INTEL_OK) { |
290 | printf("Block erase failed at %08X, CSR=%08X\n", | |
291 | (uint)addr, (uint)*addr); | |
292 | *addr = INTEL_RESET; /* reset bank */ | |
293 | return 1; | |
294 | } | |
295 | ||
affae2bf | 296 | /* reset to read mode */ |
8564acf9 | 297 | *addr = INTEL_RESET; |
affae2bf WD |
298 | } |
299 | } | |
300 | ||
301 | printf (" done\n"); | |
302 | return 0; | |
303 | } | |
304 | ||
8564acf9 WD |
305 | /*----------------------------------------------------------------------- |
306 | * Write a word to Flash, returns: | |
307 | * 0 - OK | |
308 | * 1 - write timeout | |
309 | * 2 - Flash not erased | |
310 | */ | |
311 | static int write_word (flash_info_t *info, ulong dest, ulong data) | |
312 | { | |
313 | ulong start; | |
314 | int rc = 0; | |
315 | int flag; | |
316 | vu_long *addr = (vu_long *)dest; | |
317 | ||
318 | /* Check if Flash is (sufficiently) erased */ | |
319 | if ((*addr & data) != data) { | |
320 | return (2); | |
321 | } | |
322 | ||
323 | *addr = INTEL_CLEAR; /* Clear status register */ | |
324 | ||
325 | /* Disable interrupts which might cause a timeout here */ | |
326 | flag = disable_interrupts(); | |
327 | ||
328 | /* Write Command */ | |
329 | *addr = INTEL_PROGRAM; | |
330 | ||
331 | /* Write Data */ | |
332 | *addr = data; | |
333 | ||
334 | /* re-enable interrupts if necessary */ | |
335 | if (flag) | |
336 | enable_interrupts(); | |
337 | ||
338 | /* data polling for D7 */ | |
339 | start = get_timer (0); | |
340 | while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) { | |
341 | if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { | |
342 | printf("Write timed out\n"); | |
343 | rc = 1; | |
344 | break; | |
345 | } | |
346 | } | |
347 | if (*addr != INTEL_OK) { | |
348 | printf ("Write failed at %08X, CSR=%08X\n", (uint)addr, (uint)*addr); | |
349 | rc = 1; | |
350 | } | |
351 | ||
352 | *addr = INTEL_RESET; /* Reset to read array mode */ | |
353 | ||
354 | return rc; | |
355 | } | |
356 | ||
affae2bf WD |
357 | /*----------------------------------------------------------------------- |
358 | * Copy memory to flash, returns: | |
359 | * 0 - OK | |
360 | * 1 - write timeout | |
361 | * 2 - Flash not erased | |
362 | */ | |
363 | ||
364 | int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) | |
365 | { | |
366 | ulong cp, wp, data; | |
367 | int i, l, rc; | |
368 | ||
369 | wp = (addr & ~3); /* get lower word aligned address */ | |
370 | ||
8564acf9 WD |
371 | *(vu_long *)wp = INTEL_RESET; /* Reset to read array mode */ |
372 | ||
affae2bf WD |
373 | /* |
374 | * handle unaligned start bytes | |
375 | */ | |
376 | if ((l = addr - wp) != 0) { | |
377 | data = 0; | |
378 | for (i=0, cp=wp; i<l; ++i, ++cp) { | |
379 | data = (data << 8) | (*(uchar *)cp); | |
380 | } | |
381 | for (; i<4 && cnt>0; ++i) { | |
382 | data = (data << 8) | *src++; | |
383 | --cnt; | |
384 | ++cp; | |
385 | } | |
386 | for (; cnt==0 && i<4; ++i, ++cp) { | |
387 | data = (data << 8) | (*(uchar *)cp); | |
388 | } | |
389 | ||
390 | if ((rc = write_word(info, wp, data)) != 0) { | |
391 | return (rc); | |
392 | } | |
393 | wp += 4; | |
394 | } | |
395 | ||
396 | /* | |
397 | * handle word aligned part | |
398 | */ | |
399 | while (cnt >= 4) { | |
400 | data = 0; | |
401 | for (i=0; i<4; ++i) { | |
402 | data = (data << 8) | *src++; | |
403 | } | |
404 | if ((rc = write_word(info, wp, data)) != 0) { | |
405 | return (rc); | |
406 | } | |
407 | wp += 4; | |
408 | cnt -= 4; | |
409 | } | |
410 | ||
411 | if (cnt == 0) { | |
412 | return (0); | |
413 | } | |
414 | ||
415 | /* | |
416 | * handle unaligned tail bytes | |
417 | */ | |
418 | data = 0; | |
419 | for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { | |
420 | data = (data << 8) | *src++; | |
421 | --cnt; | |
422 | } | |
423 | for (; i<4; ++i, ++cp) { | |
424 | data = (data << 8) | (*(uchar *)cp); | |
425 | } | |
426 | ||
8564acf9 WD |
427 | rc = write_word(info, wp, data); |
428 | ||
429 | return rc; | |
affae2bf WD |
430 | } |
431 | ||
432 | /*----------------------------------------------------------------------- | |
8564acf9 | 433 | * Set/Clear sector's lock bit, returns: |
affae2bf | 434 | * 0 - OK |
8564acf9 | 435 | * 1 - Error (timeout, voltage problems, etc.) |
affae2bf | 436 | */ |
8564acf9 | 437 | int flash_real_protect(flash_info_t *info, long sector, int prot) |
affae2bf | 438 | { |
8564acf9 WD |
439 | ulong start; |
440 | int i; | |
441 | int rc = 0; | |
442 | vu_long *addr = (vu_long *)(info->start[sector]); | |
443 | int flag = disable_interrupts(); | |
444 | ||
445 | *addr = INTEL_CLEAR; /* Clear status register */ | |
446 | if (prot) { /* Set sector lock bit */ | |
447 | *addr = INTEL_LOCKBIT; /* Sector lock bit */ | |
448 | *addr = INTEL_PROTECT; /* set */ | |
449 | } | |
450 | else { /* Clear sector lock bit */ | |
451 | *addr = INTEL_LOCKBIT; /* All sectors lock bits */ | |
452 | *addr = INTEL_CONFIRM; /* clear */ | |
453 | } | |
affae2bf | 454 | |
8564acf9 WD |
455 | start = get_timer(0); |
456 | while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) { | |
457 | if (get_timer(start) > CFG_FLASH_UNLOCK_TOUT) { | |
458 | printf("Flash lock bit operation timed out\n"); | |
459 | rc = 1; | |
460 | break; | |
461 | } | |
affae2bf | 462 | } |
affae2bf | 463 | |
8564acf9 WD |
464 | if (*addr != INTEL_OK) { |
465 | printf("Flash lock bit operation failed at %08X, CSR=%08X\n", | |
466 | (uint)addr, (uint)*addr); | |
467 | rc = 1; | |
468 | } | |
affae2bf | 469 | |
8564acf9 WD |
470 | if (!rc) |
471 | info->protect[sector] = prot; | |
472 | ||
473 | /* | |
474 | * Clear lock bit command clears all sectors lock bits, so | |
475 | * we have to restore lock bits of protected sectors. | |
476 | */ | |
477 | if (!prot) | |
478 | for (i = 0; i < info->sector_count; i++) | |
479 | if (info->protect[i]) { | |
480 | addr = (vu_long *)(info->start[i]); | |
481 | *addr = INTEL_LOCKBIT; /* Sector lock bit */ | |
482 | *addr = INTEL_PROTECT; /* set */ | |
483 | udelay(CFG_FLASH_LOCK_TOUT * 1000); | |
484 | } | |
affae2bf | 485 | |
affae2bf WD |
486 | if (flag) |
487 | enable_interrupts(); | |
488 | ||
8564acf9 | 489 | *addr = INTEL_RESET; /* Reset to read array mode */ |
affae2bf | 490 | |
8564acf9 | 491 | return rc; |
affae2bf WD |
492 | } |
493 | ||
494 | /*----------------------------------------------------------------------- | |
8564acf9 WD |
495 | * Support for flash file system (JFFS2) |
496 | * | |
497 | * We use custom partition info function because we have to fit the | |
498 | * file system image between first sector (containing hard reset | |
499 | * configuration word) and the sector containing U-Boot image. Standard | |
500 | * partition info function does not allow for last sector specification | |
501 | * and assumes that the file system occupies flash bank up to and | |
502 | * including bank's last sector. | |
affae2bf | 503 | */ |
8564acf9 | 504 | #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CFG_JFFS_CUSTOM_PART) |
affae2bf | 505 | |
8564acf9 WD |
506 | #ifndef CFG_JFFS2_FIRST_SECTOR |
507 | #define CFG_JFFS2_FIRST_SECTOR 0 | |
508 | #endif | |
509 | #ifndef CFG_JFFS2_FIRST_BANK | |
510 | #define CFG_JFFS2_FIRST_BANK 0 | |
511 | #endif | |
512 | #ifndef CFG_JFFS2_NUM_BANKS | |
513 | #define CFG_JFFS2_NUM_BANKS 1 | |
514 | #endif | |
515 | #define CFG_JFFS2_LAST_BANK (CFG_JFFS2_FIRST_BANK + CFG_JFFS2_NUM_BANKS - 1) | |
affae2bf | 516 | |
8564acf9 | 517 | #include <jffs2/jffs2.h> |
affae2bf | 518 | |
8564acf9 | 519 | static struct part_info partition; |
affae2bf | 520 | |
8564acf9 WD |
521 | struct part_info *jffs2_part_info(int part_num) |
522 | { | |
523 | int i; | |
524 | ||
525 | if (part_num == 0) { | |
526 | if (partition.usr_priv == 0) { | |
527 | partition.offset = | |
528 | (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR]; | |
529 | for (i = CFG_JFFS2_FIRST_BANK; i <= CFG_JFFS2_LAST_BANK; i++) | |
530 | partition.size += flash_info[i].size; | |
531 | partition.size -= | |
532 | flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR] - | |
533 | flash_info[CFG_JFFS2_FIRST_BANK].start[0]; | |
534 | #ifdef CFG_JFFS2_LAST_SECTOR | |
535 | i = flash_info[CFG_JFFS2_LAST_BANK].sector_count - 1; | |
536 | partition.size -= | |
537 | flash_info[CFG_JFFS2_LAST_BANK].start[i] - | |
538 | flash_info[CFG_JFFS2_LAST_BANK].start[CFG_JFFS2_LAST_SECTOR]; | |
539 | #endif | |
540 | ||
541 | partition.usr_priv = (void *)1; | |
affae2bf | 542 | } |
8564acf9 | 543 | return &partition; |
affae2bf WD |
544 | } |
545 | return 0; | |
546 | } | |
8564acf9 WD |
547 | |
548 | #endif /* JFFS2 */ |