blob: d5b53d0819cfc36f52aa1b2d916e501dadbec602 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2 *
3 * (C)Copyright 2005 - 2008 Marvell. All Rights Reserved.
4 *
5 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
6 * The copyright notice above does not evidence any actual or intended
7 * publication of such source code.
8 * This Module contains Proprietary Information of Marvell and should be
9 * treated as Confidential.
10 * The information in this file is provided for the exclusive use of the
11 * licensees of Marvell.
12 * Such users have the right to use, modify, and incorporate this code into
13 * products for purposes authorized by the license agreement provided they
14 * include this notice and the associated copyright notice with any such
15 * product.
16 * The information in this file is provided "AS IS" without warranty.
17 *
18 * FILENAME: xllp_dfc.c
19 *
20 * PURPOSE: XLLP interface to the data flash controller (DFC).
21 *
22******************************************************************************/
23
24#include "Flash.h"
25#include "xllp_dfc.h"
26#include "xllp_dfc_defs.h"
27#include "platform_dfc_timing.h"
28#include "PlatformConfig.h"
29#include "PMUA.h"
30
31//++
32//************************************************************
33// Unit Test Support
34#ifdef _DFC_EM
35#include "em_devlib.h"
36#endif
37//************************************************************
38//--
39
40/*
41 * NAND Small block device ID's
42 */
43
44char Samsung[] ={ 0x71, 0x78, 0x79, 0x72,
45 0x74, 0x36, 0x76, 0x46,
46 0x56, 0x35, 0x75, 0x45,
47 0x55, 0x33, 0x73, 0x43,
48 0x53, 0x39, 0xE6, 0x49,
49 0x59, 0x00};
50
51char ST[] = {0x73, 0x35, 0x75, 0x45,
52 0x55, 0x76, 0x36, 0x46,
53 0x56, 0x79, 0x39, 0x49,
54 0x59, 0x00};
55
56char Micron[] = {0x00};
57
58char Hynix[] = {0x76, 0x56, 0x36, 0x46,
59 0x75, 0x55, 0x35, 0x45,
60 0x73, 0x53, 0x49, 0x00};
61
62char Toshiba[] = {0x46, 0x79, 0x75, 0x73, 0x72, 0xE6, 0x00};
63
64
65/*
66 * Large block NAND table
67 * This table contains the Manufacturer and Device ID's for the
68 * new MLC parts with a different Read ID formart
69 */
70// Manufacturer, Device,
71char LargeBlockTable[] = { SAMSUNG_CODE, 0xD5,
72 SAMSUNG_CODE, 0xD7,
73 HYNIX_CODE, 0xD5, //H27UAG8T2A
74// not yet known HYNIX_CODE, 0xD7, //H27UCG8V5A
75 0x0, 0x0}; //terminator
76
77/*
78 * Default settings:
79 * Large block:
80 * read - CMD1 = 0x00 pg_program - CMD1 = 0x80
81 * CMD2 = 0x30 CMD2 = 0x10
82 * ADDR_CYC = 5 ADDR_CYC = 5
83 * DBC = 1 DBC = 1
84 * NC = 0 NC = 0
85 * CMD_TYPE = 0x0 CMD_TYPE = 0x1
86 * CSEL = 0 CSEL = 0
87 * AUTO_RS = 0 AUTO_RS = 0
88 * read_id - CMD1 = 0x90 blk_erase- CMD1 = 0x60
89 * CMD2 = 0x00 CMD2 = 0xD0
90 * ADDR_CYC = 1 ADDR_CYCLE = 0X3
91 * DBC = 0 DBC = 1
92 * NC = 0 NC = 0
93 * CMD_TYPE = 0x3 CMD_TPYE = 0X3
94 * CSEL = 0 CSEL = 0
95 * AUTO_RS = 0 AUTO_RS = 0
96 * read_status - CMD1 = 0x70 CMD2 = 0x00
97 * ADDR_CYC = 0
98 * DBC = 0
99 * NC = 0
100 * CMD_TYPE = 0x6
101 * CSEL = 0
102 * AUTO_RS = 0
103 * Small Block
104 * read - CMD1 = 0x00 pg_program - CMD1 = 0x80
105 * CMD2 = 0x00 CMD2 = 0x10
106 * ADDR_CYC = 4 ADDR_CYC = 5
107 * DBC = 0 DBC = 1
108 * NC = 0 NC = 0
109 * CMD_TYPE = 0x0 CMD_TYPE = 0x1
110 * CSEL = 0 CSEL = 0
111 * AUTO_RS = 0 AUTO_RS = 0
112 * read_id - CMD1 = 0x90 blk_erase- CMD1 = 0x60
113 * CMD2 = 0x00 CMD2 = 0xD0
114 * ADDR_CYC = 1 ADDR_CYCLE = 0x3
115 * DBC = 0 DBC = 1
116 * NC = 0 NC = 0
117 * CMD_TYPE = 0x3 CMD_TPYE = 0x3
118 * CSEL = 0 CSEL = 0
119 * AUTO_RS = 0 AUTO_RS = 0
120 * read_status - CMD1 = 0x70
121 * CMD2 = 0x00
122 * ADDR_CYC = 0
123 * DBC = 0
124 * NC = 0
125 * CMD_TYPE = 0x6
126 * CSEL = 0
127 * AUTO_RS = 0
128 *
129 *
130 */
131
132// Read ReadID ReadStat Program Erase Reset
133static CMD_BLOCK CMD_ARRAY[DEVICE_TYPE_SIZE] =
134{
135//LARGE
136// Read ,ReadID ,ReadStat ,Program ,Erase ,Reset ,ReadONFIParameter
137{ 0x000D3000,0x00610090,0x00800070,0x002D1080,0x004BD060,0x00A000ff,0x100100EC},
138//SMALL
139// Read ,ReadID ,ReadStat ,Program ,Erase ,Reset ,Reserved
140{ 0x00040000,0x00610090,0x00800070,0x002D1080,0x004BD060,0x00A000ff,0x00000000}
141};
142
143static unsigned int DFCSetupCount = 0;
144/***********************************************************************
145////////////
146/////////////
147////////// D F C I N T E R F A C E R O U T I N E S
148////////////
149///////////
150/***********************************************************************/
151UINT_T XllpDfcInit(unsigned int width, P_NAND_Properties_T pNAND_Prop)
152{
153 NDCR_REG dfc_control_reg;
154 NDTR0CS0_REG dfc_timing0_reg;
155 NDTR1CS0_REG dfc_timing1_reg;
156 NDECCCTRL_REG dfc_ecc_ctrl_reg;
157 unsigned int buf[2]; // Read ID data should not be more than 5 bytes.
158 unsigned int Retval = 0;
159 unsigned int count = 0;
160
161 unsigned int OnfiSignature[2];
162 int status = NoError;
163
164 FlashBootType_T FlashBootType;
165
166 /*
167 ** Why Are we here?
168 ** Assume the first time, we're attempting to Boot and
169 ** will configure the DFC to the default timing and
170 ** specified bus width as passed in via the NAND properties structure.
171 ** If it's not the first time, but the current FlashBootType
172 ** is BOOT_FLASH, then adjust the bus width to that passed in (probably from 16 bit to 8 bit),
173 ** becasue the probe order was wrong the first time.
174 ** If it's not the first time, and the current FlashBootType is
175 ** SAVE_STATE_FLASH, don't do anyting. We're assuming that the SaveStateFlash
176 ** is identical to the BootFlash and the DFC doesn't need to be setup again.
177 */
178
179 FlashBootType = GetCurrentFlashBootType();
180 /*
181 * Setup Multifunction pins for NAND
182 */
183
184 ChipSelectDFC();
185
186 /*
187 * Initial DFC state:
188 * See values in xllp_dfc_defs.h
189 * - Disable all interrupts
190 * - Read_ID count = 2
191 * - SPARE and ECC enabled
192 * - DMA disabled
193 * - DWIDTH is x16
194 * - Small block PAGE_SZ
195 *
196 * Set timing to the worst (i.e. slowest) possible timing
197 * This can be adjusted after we determine the Flash type
198 */
199
200
201 dfc_control_reg.value = DFC_INITIAL_CONTROL;
202 dfc_control_reg.bits.DMWIDTH_M = (width == 8)? 0 : 1;
203 dfc_control_reg.bits.DMWIDTH_C = (width == 8)? 0 : 1;
204 dfc_timing0_reg.value = DFC_INITIAL_TIMING0;
205 dfc_timing1_reg.value = DFC_INITIAL_TIMING1;
206
207
208 // Write out Timing and Control registers
209 DFC_REG_WRITE(DFC_DREDEL, 0xFFFFFFFF);
210 DFC_REG_WRITE(DFC_TIMING_0, dfc_timing0_reg.value);
211 DFC_REG_WRITE(DFC_TIMING_1, dfc_timing1_reg.value);
212 DFC_REG_WRITE(DFC_CONTROL, dfc_control_reg.value);
213
214 //make sure BCH is off
215 DFC_REG_READ(DFC_ECCCTRL, dfc_ecc_ctrl_reg.value );
216 dfc_ecc_ctrl_reg.bits.BCH_EN = 0;
217 DFC_REG_WRITE(DFC_ECCCTRL, dfc_ecc_ctrl_reg.value );
218
219 // Only issue a reset on the first call
220 if (!DFCSetupCount)
221 { /*
222 * First, issue a reset command
223 */
224 Retval = xdfc_reset(pNAND_Prop);
225 if ( Retval != NoError )
226 return Retval;
227
228 DFCSetupCount++;
229 }
230
231 // not use ONFI anymore
232 //Legacy Read ID code
233
234 /*
235 * Get the device ID first and check if it is small block
236 * or large block. If large block go back and read all 4
237 * bytes from the read id to get device parameters.
238 */
239
240 buf[0] = 0; buf[1] = 0;
241 Retval = xdfc_readID(&buf[0], SMALL);
242 CheckErrorReturn(Retval);
243
244 if ( Retval == 0 )
245 {
246 pNAND_Prop->NAND_type = XllpCheckDeviceType(&buf[0], pNAND_Prop);
247 /*
248 * Once we determine Large or Small block set up the flash
249 * parameters structure and adjust the DFC Control register settings
250 */
251 if(pNAND_Prop->NAND_type == LARGE)
252 {
253 Retval = xdfc_readID(&buf[0], LARGE);
254 if ( Retval != 0 )
255 return Retval;
256 if ((buf[0] == 0) && (buf[1] == 0))
257 return DFCInitFailed;
258 pNAND_Prop->device_cmds = &CMD_ARRAY[LARGE];
259 XllpLoadProperties(&buf[0], pNAND_Prop);
260
261 //dfc_control_reg.value = *DFC_CONTROL;
262 DFC_REG_READ(DFC_CONTROL, dfc_control_reg.value);
263
264 dfc_control_reg.bits.PAGE_SZ = 1;
265 dfc_control_reg.bits.RA_START = 1;
266
267 //need to figure this out from PagesPerBlock param in NAND struct
268 //remember DFC funny, where 32 -> 0, 64-> 2, 128 -> 1, 256 -> 3
269 switch (pNAND_Prop->PagesPerBlock)
270 {
271 case(32):
272 dfc_control_reg.bits.PG_PER_BLK = 0;
273 break;
274 case(128):
275 dfc_control_reg.bits.PG_PER_BLK = 1;
276 break;
277 case(256):
278 dfc_control_reg.bits.PG_PER_BLK = 3;
279 break;
280 case(64):
281 default: //default to 64, just in case
282 dfc_control_reg.bits.PG_PER_BLK = 2;
283 break;
284 }
285 }
286 else // Its Small Block
287 {
288 pNAND_Prop->device_cmds = &CMD_ARRAY[SMALL];
289 pNAND_Prop->PageSize = 512;
290 pNAND_Prop->SpareAreaSize = 16;
291 //dfc_control_reg.value = *DFC_CONTROL;
292 DFC_REG_READ(DFC_CONTROL, dfc_control_reg.value);
293
294 dfc_control_reg.bits.PAGE_SZ = 0;
295 dfc_control_reg.bits.PG_PER_BLK = 0; // Assume 32 PG_PER_BLK
296 dfc_control_reg.bits.RA_START = 0;
297 pNAND_Prop->BlockSize = 512 * 32;
298 }
299
300 //*DFC_CONTROL = dfc_control_reg.value;
301 DFC_REG_WRITE(DFC_CONTROL, dfc_control_reg.value);
302 }//End xdfc_readID retval OK
303
304 /* Overwrite Some Device Specific Data
305 * NumOfBlocks and Timing are done by the DKB/OBM only since DKB/OBM needs to support more than
306 * what BootROM needs. BootROM does not use ScanNANDForBadBlocks routine
307 */
308 #if !(BOOTROM)
309 XllpDfcDeviceSpecificInit(pNAND_Prop);
310 #endif
311
312 return Retval;
313}//End XllpDfcInit
314
315void XllpDfcDeviceSpecificInit(P_NAND_Properties_T pNAND_Prop)
316{
317 FLASH_TIMING* pFT; // For use in timing override
318
319
320 switch (pNAND_Prop->ManufacturerCode)
321 {
322 case SAMSUNG_CODE:
323 {
324 if (pNAND_Prop->FlashID == 0xAA) // LARGE Block - Part K9K2G08R0A
325 {
326 pNAND_Prop->NumOfBlocks = 2048;
327 pFT = &SAMSUNG_MFG_TIMING[3]; // Override Timing
328 xdfc_setTiming(pFT);
329 }
330 else if (pNAND_Prop->FlashID == 0xBA) // JIL board
331 {
332 pNAND_Prop->NumOfBlocks = 2048;
333 pFT = &SAMSUNG_MFG_TIMING[4]; // Override Timing
334 xdfc_setTiming(pFT);
335 }
336 else if (pNAND_Prop->FlashID == 0xBC) // JIL 1.5 board
337 {
338 pNAND_Prop->NumOfBlocks = 4096;
339 pFT = &SAMSUNG_MFG_TIMING[4]; // Override Timing
340 xdfc_setTiming(pFT);
341 }
342 else // SMALL Block - All Supported
343 {
344 pNAND_Prop->NumOfBlocks = 4096;
345 pFT = &SAMSUNG_MFG_TIMING[1]; // Override Timing
346 xdfc_setTiming(pFT);
347 }
348 break;
349 }
350 case TOSHIBA_CODE:
351 {
352 if ((pNAND_Prop->FlashID == 0xBA) || (pNAND_Prop->FlashID == 0xAA)) // LARGE Block
353 {
354 pNAND_Prop->NumOfBlocks = 2048;
355 pNAND_Prop->PageSize = 2048;
356 pFT = &TOSHIBA_MFG_TIMING[1]; // Override Timing
357 xdfc_setTiming(pFT);
358 }
359 else if ((pNAND_Prop->FlashID == 0xB1) || (pNAND_Prop->FlashID == 0xA1))
360 {
361 pNAND_Prop->NumOfBlocks = 1024;
362 pNAND_Prop->PageSize = 2048;
363 pFT = &TOSHIBA_MFG_TIMING[0]; // Override Timing
364 xdfc_setTiming(pFT);
365 }
366 else if (pNAND_Prop->FlashID == 0xAC)
367 {
368 pNAND_Prop->NumOfBlocks = 2048;
369 pNAND_Prop->PageSize = 4096; // 4KB page
370 pFT = &TOSHIBA_MFG_TIMING[2]; // Override Timing
371 xdfc_setTiming(pFT);
372 }
373 break;
374 }
375 case HYNIX_CODE:
376 {
377 if ((pNAND_Prop->FlashID == 0xBC) || (pNAND_Prop->FlashID == 0xAC))
378 {
379 pNAND_Prop->NumOfBlocks = 4096;
380 pFT = &HYNIX_MFG_TIMING[1]; // Override Timing
381 xdfc_setTiming(pFT);
382 }
383 else if ((pNAND_Prop->FlashID == 0xBA) || (pNAND_Prop->FlashID == 0xAA))
384 {
385 pNAND_Prop->NumOfBlocks = 2048;
386 pFT = &HYNIX_MFG_TIMING[0]; // Override Timing
387 xdfc_setTiming(pFT);
388 }
389 else if (pNAND_Prop->FlashID == 0xA1)
390 {
391 pNAND_Prop->NumOfBlocks = 1024;
392 }
393
394 break;
395 }
396 case ST_CODE:
397 break;
398 case MICRON_CODE:
399 {
400 // Cover Parts #MT29F1GXXABA LB
401 if ((pNAND_Prop->FlashID == 0xA1) || (pNAND_Prop->FlashID == 0xB1))
402 {
403 pNAND_Prop->NumOfBlocks = 1024;
404 pFT = &MICRON_MFG_TIMING[1]; // Override Timing
405 xdfc_setTiming(pFT);
406 }
407 //if ((pNAND_Prop->FlashID == 0xBA) || (pNAND_Prop->FlashID == 0xAA))
408 if (pNAND_Prop->FlashID == 0xBA)
409 {
410 pNAND_Prop->NumOfBlocks = 2048;
411 pFT = &MICRON_MFG_TIMING[1]; // Override Timing
412 xdfc_setTiming(pFT);
413 }
414 if (pNAND_Prop->FlashID == 0xAA)
415 {
416 /* ESMT FM6BD2G1GXA (2A) */
417 pNAND_Prop->NumOfBlocks = 2048;
418 pFT = &ESMT_MFG_TIMING[1]; // Override Timing
419 xdfc_setTiming(pFT);
420 }
421 if (pNAND_Prop->FlashID == 0xAC)
422 {
423 pNAND_Prop->NumOfBlocks = 4096;
424 pFT = &MICRON_MFG_TIMING[2]; // Override Timing
425 xdfc_setTiming(pFT);
426 }
427 if (pNAND_Prop->FlashID == 0xBC)
428 {
429 pNAND_Prop->NumOfBlocks = 4096;
430 pFT = &MICRON_MFG_TIMING[3]; // Override Timing
431 xdfc_setTiming(pFT);
432 }
433 if (pNAND_Prop->FlashID == 0xB3)
434 {
435 pNAND_Prop->NumOfBlocks = 8192;
436 pFT = &MICRON_MFG_TIMING[3]; // Override Timing
437 xdfc_setTiming(pFT);
438 }
439 if (pNAND_Prop->FlashID == 0xD3)
440 {
441 pNAND_Prop->NumOfBlocks = 16384;
442 pFT = &MICRON_MFG_TIMING[4]; // Override Timing
443 xdfc_setTiming(pFT);
444 }
445 break;
446 }
447 case ESMT_CODE:
448 {
449 if ((pNAND_Prop->FlashID == 0xA1) || (pNAND_Prop->FlashID == 0xB1) ||
450 (pNAND_Prop->FlashID == 0x81) || (pNAND_Prop->FlashID == 0x61))
451 {
452 pNAND_Prop->NumOfBlocks = 1024;
453 pFT = &ESMT_MFG_TIMING[0]; // Override Timing
454 xdfc_setTiming(pFT);
455 }
456
457 if (pNAND_Prop->FlashID == 0xAA)
458 {
459 pNAND_Prop->NumOfBlocks = 2048;
460 pFT = &ESMT_MFG_TIMING[0]; // Override Timing
461 xdfc_setTiming(pFT);
462 }
463
464 break;
465 }
466 case JSC_CODE:
467 {
468 if ((pNAND_Prop->FlashID == 0xA1) || (pNAND_Prop->FlashID == 0xB1)
469 || (pNAND_Prop->FlashID == 0xAC) || (pNAND_Prop->FlashID == 0xBC))
470 {
471 pNAND_Prop->NumOfBlocks = 1024;
472 pFT = &JSC_MFG_TIMING[0]; // Override Timing
473 xdfc_setTiming(pFT);
474 }
475 break;
476 }
477
478 case FIDILEX_CODE:
479 {
480 if ((pNAND_Prop->FlashID == 0xA1) || (pNAND_Prop->FlashID == 0xB1))
481 {
482 pNAND_Prop->NumOfBlocks = 1024;
483 pFT = &FIDILEX_MFG_TIMING[0]; // Override Timing
484 xdfc_setTiming(pFT);
485 }
486 break;
487 }
488
489 case MACRONIX_CODE:
490 {
491 if ((pNAND_Prop->FlashID == 0xAA) || (pNAND_Prop->FlashID == 0xBA))
492 {
493 pNAND_Prop->NumOfBlocks = 2048;
494 pFT = &MACRONIX_MFG_TIMING[0]; // Override Timing
495 xdfc_setTiming(pFT);
496 }
497
498 if ((pNAND_Prop->FlashID == 0xAC) || (pNAND_Prop->FlashID == 0xBC))
499 {
500 pNAND_Prop->NumOfBlocks = 4096;
501 pFT = &MACRONIX_MFG_TIMING[0]; // Override Timing
502 xdfc_setTiming(pFT);
503 }
504 break;
505 }
506
507 case WINBOND_CODE:
508 {
509 if ((pNAND_Prop->FlashID == 0xA1) || (pNAND_Prop->FlashID == 0xB1))
510 {
511 pNAND_Prop->NumOfBlocks = 1024;
512 pFT = &WINBOND_MFG_TIMING[0]; // Override Timing
513 xdfc_setTiming(pFT);
514 }
515
516 if (pNAND_Prop->FlashID == 0xAA)
517 {
518 pNAND_Prop->NumOfBlocks = 2048;
519 pFT = &WINBOND_MFG_TIMING[1]; // Override Timing
520 xdfc_setTiming(pFT);
521 }
522 break;
523 }
524 default:
525 //assume that there are only 1K blocks
526 pNAND_Prop->NumOfBlocks = 1024;
527 break;
528 }//End switch (pNAND_Prop->ManufacturerCode)
529}
530
531DEVICE_TYPE XllpCheckDeviceType( P_DFC_BUFFER buffer, P_NAND_Properties_T pNAND_Prop)
532{
533 char maker, device;
534 DEVICE_TYPE type = LARGE;
535 int match = 0;
536 char * search_list;
537
538 maker = pNAND_Prop->ManufacturerCode = (buffer[0] & 0xFF);
539 device = pNAND_Prop->FlashID = ((buffer[0] >> 8) & 0xFF);
540
541 /*
542 * Check to see if this is a known small block device
543 */
544 switch (maker){
545 case SAMSUNG_CODE:
546 search_list = &Samsung[0];
547 break;
548 case TOSHIBA_CODE:
549 search_list = &Toshiba[0];
550 break;
551 case HYNIX_CODE:
552 search_list = &Hynix[0];
553 break;
554 case ST_CODE:
555 search_list = &ST[0];
556 break;
557 case MICRON_CODE:
558 search_list = &Micron[0];
559 break;
560 default:
561 return (type);
562 }
563 while (match == 0)
564 {
565 if(*search_list == device)
566 {
567 match = 1;
568 type = SMALL;
569 }
570 if(*search_list == 0)
571 match = 1;
572 search_list++;
573 }
574
575 return (type);
576}
577
578void XllpLoadProperties(P_DFC_BUFFER buffer, P_NAND_Properties_T pNAND_Prop)
579{
580 char maker, device, properties, planes, plane_size;
581 char pg_size, blk_size, spare_size, cell_type, organization;
582 int i;
583
584 maker = buffer[0] & 0xFF;
585 device = (buffer[0] >> 0x8) & 0xFF;
586 properties = (buffer[0] >> 24) & 0xFF;
587 pg_size = properties & 0x3;
588
589 /* initialize properties using legacy Read ID format */
590 //bits 2 and 3 of the 3rd ID byte tell us if its SLC or MLC
591 cell_type = (buffer[0] >> 18) & 0x3;
592
593 blk_size = (properties >> 4) & 0x3;
594 organization = (properties >> 6) & 0x1;
595
596 pNAND_Prop->PageSize = 1024 << pg_size;
597 pNAND_Prop->BlockSize = (64*1024) << blk_size;
598
599
600 /* now check for new MLC Read ID formats and overwrite properties if found */
601 for(i = 0; ; i+=2)
602 {
603 //check termination case
604 if(LargeBlockTable[i] == 0)
605 break;
606
607 //check for match
608 if((LargeBlockTable[i] == maker) && (LargeBlockTable[i+1] == device))
609 {
610 pNAND_Prop->PageSize = 2048 << pg_size;
611 //blk size indication bits in 4th byte: 0xB0 (bits 7, 5 and 4)
612 blk_size = ((properties >> 5) & 0x4) | ((properties >> 4) & 0x3);
613 pNAND_Prop->BlockSize = (128*1024) << blk_size;
614 cell_type = 2; //just used to indicate MLC
615 break;
616 }
617 }
618
619 switch(maker)
620 {
621 case MICRON_CODE:
622 if(cell_type == 0x0) //SLC
623 pNAND_Prop->SpareAreaSize = 64; //only documented size
624 else //MLC
625 if(pNAND_Prop->PageSize == 2048)
626 pNAND_Prop->SpareAreaSize = 112;
627 else
628 pNAND_Prop->SpareAreaSize = 218;
629 break;
630 case SAMSUNG_CODE:
631 if(cell_type != 0x0) //MLC
632 {
633 if((properties & 0x4) == 0x4)
634 pNAND_Prop->SpareAreaSize = 128;
635 if((properties & 0x8) == 0x8)
636 pNAND_Prop->SpareAreaSize = 218;
637 break;
638 }//let SLC parts fall thru to default statement
639 case TOSHIBA_CODE:
640 case HYNIX_CODE:
641 case ST_CODE:
642 default:
643 spare_size = (properties >> 2) & 0x1;
644 if(spare_size == 0)
645 {
646 pNAND_Prop->SpareAreaSize = (pNAND_Prop->PageSize / 512) * 8;
647 }
648 else
649 {
650 pNAND_Prop->SpareAreaSize = (pNAND_Prop->PageSize / 512) * 16;
651 }
652 }
653
654 //lastly, figure out how many pages there are per block
655 pNAND_Prop->PagesPerBlock = pNAND_Prop->BlockSize / pNAND_Prop->PageSize;
656
657}
658