1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 Rob Purchase
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "ata-nand-target.h"
30 #define SECTOR_SIZE 512
32 /* ECC on read is implemented on the assumption that MLC-style 4-bit correction
33 is always used regardless of NAND chip type. This assumption is true for at
34 least D2 (MLC) and M200 (SLC). */
35 #define USE_ECC_CORRECTION
37 /* for compatibility */
38 int ata_spinup_time
= 0;
40 long last_disk_activity
= -1;
42 /** static, private data **/
43 static bool initialized
= false;
45 static long next_yield
= 0;
46 #define MIN_YIELD_PERIOD 1000
48 static struct mutex ata_mtx SHAREDBSS_ATTR
;
50 #if defined(COWON_D2) || defined(IAUDIO_7)
52 #define MAX_WRITE_CACHES 8
55 #define MAX_WRITE_CACHES 4
58 /* Sector type identifiers - main data area */
60 #define SECTYPE_MAIN_LPT 0x12
61 #define SECTYPE_MAIN_DATA 0x13
62 #define SECTYPE_MAIN_RANDOM_CACHE 0x15
63 #define SECTYPE_MAIN_INPLACE_CACHE 0x17
65 /* We don't touch the hidden area at all - these are for reference */
66 #define SECTYPE_HIDDEN_LPT 0x22
67 #define SECTYPE_HIDDEN_DATA 0x23
68 #define SECTYPE_HIDDEN_RANDOM_CACHE 0x25
69 #define SECTYPE_HIDDEN_INPLACE_CACHE 0x27
72 #define SECTYPE_FIRMWARE 0x40
74 #define SECTYPE_FIRMWARE 0xE0
77 /* Offsets to data within sector's spare area */
79 #define OFF_CACHE_PAGE_LOBYTE 2
80 #define OFF_CACHE_PAGE_HIBYTE 3
81 #define OFF_SECTOR_TYPE 4
84 #define OFF_LOG_SEG_LOBYTE 7
85 #define OFF_LOG_SEG_HIBYTE 6
87 #define OFF_LOG_SEG_LOBYTE 6
88 #define OFF_LOG_SEG_HIBYTE 7
91 /* Chip characteristics, initialised by nand_get_chip_info() */
93 static struct nand_info
* nand_data
= NULL
;
95 static int total_banks
= 0;
96 static int pages_per_bank
= 0;
97 static int sectors_per_page
= 0;
98 static int bytes_per_segment
= 0;
99 static int sectors_per_segment
= 0;
100 static int segments_per_bank
= 0;
101 static int pages_per_segment
= 0;
103 /* Maximum values for static buffers */
105 #define MAX_PAGE_SIZE 4096
106 #define MAX_SPARE_SIZE 128
107 #define MAX_BLOCKS_PER_BANK 8192
108 #define MAX_PAGES_PER_BLOCK 128
110 #define MAX_BLOCKS_PER_SEGMENT 4
112 #define MAX_SEGMENTS (MAX_BLOCKS_PER_BANK * MAX_BANKS / MAX_BLOCKS_PER_SEGMENT)
114 /* Logical/Physical translation table */
122 static struct lpt_entry lpt_lookup
[MAX_SEGMENTS
];
124 /* core_alloc()'d in nand_init() when the correct size has been determined */
125 #include "core_alloc.h"
126 static int lpt_handle
;
135 short inplace_phys_segment
;
136 short inplace_pages_used
;
138 short random_phys_segment
;
139 short page_map
[MAX_PAGES_PER_BLOCK
* MAX_BLOCKS_PER_SEGMENT
];
141 static struct write_cache write_caches
[MAX_WRITE_CACHES
];
143 static int write_caches_in_use
= 0;
146 /* Conversion functions */
148 static int phys_segment_to_page_addr(int phys_segment
, int page_in_seg
)
152 switch (nand_data
->planes
)
156 page_addr
= (phys_segment
* nand_data
->pages_per_block
);
163 page_addr
= phys_segment
* nand_data
->pages_per_block
* 2;
167 /* Data is located in block+1 */
168 page_addr
+= nand_data
->pages_per_block
;
171 if (nand_data
->planes
== 4 && page_in_seg
& 2)
173 /* Data is located in 2nd half of bank */
175 (nand_data
->blocks_per_bank
/2) * nand_data
->pages_per_block
;
182 page_addr
+= (page_in_seg
/ nand_data
->planes
);
188 /* NAND physical access functions */
190 static void nand_chip_select(int bank
)
194 /* Disable both chip selects */
195 NAND_GPIO_CLEAR(CS_GPIO_BIT
);
196 NFC_CTRL
|= NFC_CS0
| NFC_CS1
;
200 /* NFC chip select */
203 NFC_CTRL
&= ~NFC_CS0
;
209 NFC_CTRL
&= ~NFC_CS1
;
212 /* Secondary chip select */
214 NAND_GPIO_SET(CS_GPIO_BIT
);
216 NAND_GPIO_CLEAR(CS_GPIO_BIT
);
221 static void nand_read_id(int bank
, unsigned char* id_buf
)
225 /* Enable NFC bus clock */
228 /* Reset NAND controller */
231 /* Set slow cycle timings since the chip is as yet unidentified */
232 NFC_CTRL
= (NFC_CTRL
&~0xFFF) | 0x353;
234 nand_chip_select(bank
);
236 /* Set write protect */
237 NAND_GPIO_CLEAR(WE_GPIO_BIT
);
242 /* Set 8-bit data width */
243 NFC_CTRL
&= ~NFC_16BIT
;
245 /* Read ID command, single address cycle */
249 /* Read the 5 chip ID bytes */
250 for (i
= 0; i
< 5; i
++)
252 id_buf
[i
] = NFC_SDATA
& 0xFF;
255 nand_chip_select(-1);
257 /* Disable NFC bus clock */
258 BCLKCTR
&= ~DEV_NAND
;
262 static void nand_read_uid(int bank
, unsigned int* uid_buf
)
266 /* Enable NFC bus clock */
269 /* Set cycle timing (stp = 1, pw = 3, hold = 1) */
270 NFC_CTRL
= (NFC_CTRL
&~0xFFF) | 0x131;
272 nand_chip_select(bank
);
274 /* Set write protect */
275 NAND_GPIO_CLEAR(WE_GPIO_BIT
);
277 /* Set 8-bit data width */
278 NFC_CTRL
&= ~NFC_16BIT
;
280 /* Undocumented (SAMSUNG specific?) commands set the chip into a
281 special mode allowing a normally-hidden UID block to be read. */
288 /* Write row/column address */
289 for (i
= 0; i
< nand_data
->col_cycles
; i
++) NFC_SADDR
= 0;
290 for (i
= 0; i
< nand_data
->row_cycles
; i
++) NFC_SADDR
= 0;
295 /* Wait until complete */
296 while (!(NFC_CTRL
& NFC_READY
)) {};
298 /* Copy data to buffer (data repeats after 8 words) */
299 for (i
= 0; i
< 8; i
++)
301 uid_buf
[i
] = NFC_WDATA
;
304 /* Reset the chip back to normal mode */
307 nand_chip_select(-1);
309 /* Disable NFC bus clock */
310 BCLKCTR
&= ~DEV_NAND
;
314 static void nand_setup_read(int bank
, int row
, int column
)
318 /* Enable NFC bus clock */
321 /* Set cycle timing (stp = 1, pw = 3, hold = 1) */
322 NFC_CTRL
= (NFC_CTRL
&~0xFFF) | 0x131;
324 nand_chip_select(bank
);
326 /* Set write protect */
327 NAND_GPIO_CLEAR(WE_GPIO_BIT
);
329 /* Set 8-bit data width */
330 NFC_CTRL
&= ~NFC_16BIT
;
335 /* Write column address */
336 for (i
= 0; i
< nand_data
->col_cycles
; i
++)
338 NFC_SADDR
= column
& 0xFF;
339 column
= column
>> 8;
342 /* Write row address */
343 for (i
= 0; i
< nand_data
->row_cycles
; i
++)
345 NFC_SADDR
= row
& 0xFF;
349 /* End of read command */
352 /* Wait until complete */
353 while (!(NFC_CTRL
& NFC_READY
)) {};
357 static void nand_end_read(void)
359 nand_chip_select(-1);
361 /* Disable NFC bus clock */
362 BCLKCTR
&= ~DEV_NAND
;
366 static void nand_read_raw(int bank
, int row
, int column
, int size
, void* buf
)
370 nand_setup_read(bank
, row
, column
);
372 /* Read data into page buffer */
373 if (((unsigned int)buf
& 3) || (size
& 3))
375 /* Use byte copy since either the buffer or size are not word-aligned */
376 /* TODO: Byte copy only where necessary (use words for mid-section) */
377 for (i
= 0; i
< size
; i
++)
379 ((unsigned char*)buf
)[i
] = NFC_SDATA
;
384 /* Use 4-byte copy as buffer and size are both word-aligned */
385 for (i
= 0; i
< (size
/4); i
++)
387 ((unsigned int*)buf
)[i
] = NFC_WDATA
;
395 static void nand_get_chip_info(void)
397 unsigned char manuf_id
;
398 unsigned char id_buf
[8];
400 /* Read chip id from bank 0 */
401 nand_read_id(0, id_buf
);
403 manuf_id
= id_buf
[0];
405 /* Identify the chip geometry */
406 nand_data
= nand_identify(id_buf
);
408 if (nand_data
== NULL
)
410 panicf("Unknown NAND: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
411 id_buf
[0],id_buf
[1],id_buf
[2],id_buf
[3],id_buf
[4]);
414 pages_per_bank
= nand_data
->blocks_per_bank
* nand_data
->pages_per_block
;
416 segments_per_bank
= nand_data
->blocks_per_bank
/ nand_data
->planes
;
418 bytes_per_segment
= nand_data
->page_size
* nand_data
->pages_per_block
421 sectors_per_page
= nand_data
->page_size
/ SECTOR_SIZE
;
423 sectors_per_segment
= bytes_per_segment
/ SECTOR_SIZE
;
425 pages_per_segment
= sectors_per_segment
/ sectors_per_page
;
427 /* Establish how many banks are present */
428 nand_read_id(1, id_buf
);
430 if (id_buf
[0] == manuf_id
)
432 /* Bank 1 is populated, now check if banks 2/3 are valid */
433 nand_read_id(2, id_buf
);
435 if (id_buf
[0] == manuf_id
)
437 /* Bank 2 returned matching id - check if 2/3 are shadowing 0/1 */
438 unsigned int uid_buf0
[8];
439 unsigned int uid_buf2
[8];
441 nand_read_uid(0, uid_buf0
);
442 nand_read_uid(2, uid_buf2
);
444 if (memcmp(uid_buf0
, uid_buf2
, 32) == 0)
446 /* UIDs match, assume banks 2/3 are shadowing 0/1 */
451 /* UIDs differ, assume banks 2/3 are valid */
457 /* Bank 2 returned differing id - assume 2/3 are junk */
463 /* Bank 1 returned differing id - assume it is junk */
469 1. "BMP" tag at block 0, page 0, offset <page_size> [always present]
470 2. On most D2s, <page_size>+3 is 'M' and <page_size>+4 is no. of banks.
471 This is not present on some older players (formatted with early FW?)
474 nand_read_raw(0, 0, /* bank, page */
475 nand_data
->page_size
, /* offset */
476 8, id_buf
); /* length, dest */
478 if (strncmp(id_buf
, "BMP", 3)) panicf("BMP tag not present");
480 if (id_buf
[3] == 'M')
482 if (id_buf
[4] != total_banks
) panicf("BMPM total_banks mismatch");
487 static bool nand_read_sector_of_phys_page(int bank
, int page
,
488 int sector
, void* buf
)
492 int page_offset
= sector
* (SECTOR_SIZE
+ 16);
494 #ifdef USE_ECC_CORRECTION
495 unsigned long spare_buf
[4];
497 /* Set up the ECC controller to monitor reads from NFC_WDATA */
499 ECC_BASE
= (unsigned long)&NFC_WDATA
;
500 ECC_CTRL
|= ECC_M4EN
;
501 ECC_CTRL
&= ~ECC_ENC
;
502 ECC_CTRL
|= ECC_READY
;
506 /* Read the sector data */
507 nand_setup_read(bank
, page
, page_offset
);
509 /* Read data into page buffer */
510 if ((unsigned int)buf
& 3)
512 /* If unaligned, read into a temporary buffer and copy to destination.
513 This way, reads are always done through NFC_WDATA - otherwise they
514 would not be 'seen' by the ECC controller. */
515 static char temp_buf
[SECTOR_SIZE
];
517 unsigned int* ptr
= (unsigned int*) temp_buf
;
519 for (i
= 0; i
< (SECTOR_SIZE
/4); i
++)
524 memcpy(buf
, temp_buf
, SECTOR_SIZE
);
528 /* Use straight word copy as buffer and size are both word-aligned */
529 unsigned int* ptr
= (unsigned int*) buf
;
531 for (i
= 0; i
< (SECTOR_SIZE
/4); i
++)
537 #ifdef USE_ECC_CORRECTION
538 /* Stop monitoring before we read the OOB data */
539 ECC_CTRL
&= ~ECC_M4EN
;
542 /* Read a further 4 words (sector OOB data) */
543 spare_buf
[0] = NFC_WDATA
;
544 spare_buf
[1] = NFC_WDATA
;
545 spare_buf
[2] = NFC_WDATA
;
546 spare_buf
[3] = NFC_WDATA
;
548 /* Calculate MLC4 ECC using bytes 0,1,8-15 */
550 ECC_CTRL
|= ECC_M4EN
;
552 MLC_ECC0W
= *(unsigned short*)spare_buf
;
553 MLC_ECC1W
= spare_buf
[2];
554 MLC_ECC2W
= spare_buf
[3];
556 while (!(ECC_CTRL
& ECC_READY
)) {};
558 int errors
= ECC_ERR_NUM
& 7;
562 case 4: /* nothing to correct */
565 case 7: /* fail, can't correct */
569 default: /* between 1 and 4 errors */
572 unsigned char* char_buf
= (unsigned char*)buf
;
574 for (i
= 0; i
< errors
+ 1; i
++)
576 int offset
= 0x207 - ECC_ERRADDR(i
);
577 char_buf
[offset
] ^= ECC_ERRDATA(i
);
582 /* Disable ECC block */
583 ECC_CTRL
&= ~ECC_M4EN
;
593 static bool nand_read_sector_of_phys_segment(int bank
, int phys_segment
,
594 int page_in_seg
, int sector
,
597 int page_addr
= phys_segment_to_page_addr(phys_segment
,
600 return nand_read_sector_of_phys_page(bank
, page_addr
, sector
, buf
);
604 static bool nand_read_sector_of_logical_segment(int log_segment
, int sector
,
607 int page_in_segment
= sector
/ sectors_per_page
;
608 int sector_in_page
= sector
% sectors_per_page
;
611 struct lpt_entry
* lpt_lookup
= core_get_data(lpt_handle
);
613 int bank
= lpt_lookup
[log_segment
].bank
;
614 int phys_segment
= lpt_lookup
[log_segment
].phys_segment
;
616 /* Check if any of the write caches refer to this segment/page.
617 If present we need to read the cached page instead. */
622 while (!found
&& cache_num
< write_caches_in_use
)
624 if (write_caches
[cache_num
].log_segment
== log_segment
)
626 if (write_caches
[cache_num
].page_map
[page_in_segment
] != -1)
628 /* data is located in random pages cache */
631 bank
= write_caches
[cache_num
].random_bank
;
632 phys_segment
= write_caches
[cache_num
].random_phys_segment
;
635 write_caches
[cache_num
].page_map
[page_in_segment
];
637 else if (write_caches
[cache_num
].inplace_pages_used
!= -1 &&
638 write_caches
[cache_num
].inplace_pages_used
> page_in_segment
)
640 /* data is located in in-place pages cache */
643 bank
= write_caches
[cache_num
].inplace_bank
;
644 phys_segment
= write_caches
[cache_num
].inplace_phys_segment
;
650 return nand_read_sector_of_phys_segment(bank
, phys_segment
,
652 sector_in_page
, buf
);
656 /* Miscellaneous helper functions */
658 static inline unsigned char get_sector_type(char* spare_buf
)
660 return spare_buf
[OFF_SECTOR_TYPE
];
663 static inline unsigned short get_log_segment_id(int phys_seg
, char* spare_buf
)
667 return ((spare_buf
[OFF_LOG_SEG_HIBYTE
] << 8) |
668 spare_buf
[OFF_LOG_SEG_LOBYTE
])
670 + 984 * (phys_seg
/ 1024)
675 static inline unsigned short get_cached_page_id(char* spare_buf
)
677 return (spare_buf
[OFF_CACHE_PAGE_HIBYTE
] << 8) |
678 spare_buf
[OFF_CACHE_PAGE_LOBYTE
];
681 static int find_write_cache(int log_segment
)
685 for (i
= 0; i
< write_caches_in_use
; i
++)
686 if (write_caches
[i
].log_segment
== log_segment
)
693 static void read_random_writes_cache(int bank
, int phys_segment
)
697 unsigned char spare_buf
[16];
699 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, page
),
700 SECTOR_SIZE
, /* offset to first sector's spare */
703 log_segment
= get_log_segment_id(phys_segment
, spare_buf
);
705 if (log_segment
== -1)
708 /* Find which cache this is related to */
709 int cache_no
= find_write_cache(log_segment
);
713 if (write_caches_in_use
< MAX_WRITE_CACHES
)
715 cache_no
= write_caches_in_use
;
716 write_caches_in_use
++;
720 panicf("Max NAND write caches reached");
724 write_caches
[cache_no
].log_segment
= log_segment
;
725 write_caches
[cache_no
].random_bank
= bank
;
726 write_caches
[cache_no
].random_phys_segment
= phys_segment
;
729 /* Loop over each page in the phys segment (from page 1 onwards).
730 Read spare for 1st sector, store location of page in array. */
732 page
< (nand_data
->pages_per_block
* nand_data
->planes
);
735 unsigned short cached_page
;
737 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, page
),
738 SECTOR_SIZE
, /* offset to first sector's spare */
741 cached_page
= get_cached_page_id(spare_buf
);
743 if (cached_page
!= 0xFFFF)
744 write_caches
[cache_no
].page_map
[cached_page
] = page
;
750 static void read_inplace_writes_cache(int bank
, int phys_segment
)
754 unsigned char spare_buf
[16];
756 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, page
),
757 SECTOR_SIZE
, /* offset to first sector's spare */
760 log_segment
= get_log_segment_id(phys_segment
, spare_buf
);
762 if (log_segment
== -1)
765 /* Find which cache this is related to */
766 int cache_no
= find_write_cache(log_segment
);
770 if (write_caches_in_use
< MAX_WRITE_CACHES
)
772 cache_no
= write_caches_in_use
;
773 write_caches_in_use
++;
777 panicf("Max NAND write caches reached");
781 write_caches
[cache_no
].log_segment
= log_segment
;
783 /* Find how many pages have been written to the new segment */
784 while (log_segment
!= -1 &&
785 page
< (nand_data
->pages_per_block
* nand_data
->planes
) - 1)
788 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, page
),
789 SECTOR_SIZE
, 16, spare_buf
);
791 log_segment
= get_log_segment_id(phys_segment
, spare_buf
);
796 write_caches
[cache_no
].inplace_bank
= bank
;
797 write_caches
[cache_no
].inplace_phys_segment
= phys_segment
;
798 write_caches
[cache_no
].inplace_pages_used
= page
;
803 int nand_read_sectors(IF_MD2(int drive
,) unsigned long start
, int incount
,
806 #ifdef HAVE_MULTIDRIVE
807 (void)drive
; /* unused for now */
812 mutex_lock(&ata_mtx
);
819 int segment
= start
/ sectors_per_segment
;
820 int secmod
= start
% sectors_per_segment
;
822 while (incount
> 0 && secmod
< sectors_per_segment
)
824 if (!nand_read_sector_of_logical_segment(segment
, secmod
, inbuf
))
827 goto nand_read_error
;
830 if (TIME_AFTER(USEC_TIMER
, next_yield
))
832 next_yield
= USEC_TIMER
+ MIN_YIELD_PERIOD
;
836 inbuf
+= SECTOR_SIZE
;
845 goto nand_read_error
;
852 mutex_unlock(&ata_mtx
);
858 int nand_write_sectors(IF_MD2(int drive
,) unsigned long start
, int count
,
861 #ifdef HAVE_MULTIDRIVE
862 (void)drive
; /* unused for now */
865 /* TODO: Learn more about TNFTL and implement this one day... */
872 #ifdef HAVE_STORAGE_FLUSH
879 #ifdef STORAGE_GET_INFO
880 void nand_get_info(IF_MD2(int drive
,) struct storage_info
*info
)
882 #ifdef HAVE_MULTIDRIVE
883 (void)drive
; /* unused for now */
886 /* firmware version */
887 info
->revision
="0.00";
889 info
->vendor
="Rockbox";
890 info
->product
="Internal Storage";
893 info
->num_sectors
= sectors_per_segment
* segments_per_bank
* total_banks
;
894 info
->sector_size
= SECTOR_SIZE
;
901 int bank
, phys_segment
, lptbuf_size
;
902 unsigned char spare_buf
[16];
904 if (initialized
) return 0;
906 mutex_init(&ata_mtx
);
909 CSCFG2
= 0x018a8010 | tcc77x_cscfg_bw(TCC77X_CSCFG_BW8
);
911 GPIOC_FUNC
&= ~(CS_GPIO_BIT
| WE_GPIO_BIT
);
915 /* Set GPIO direction for chip select & write protect */
916 NAND_GPIO_OUT_EN(CS_GPIO_BIT
| WE_GPIO_BIT
);
918 /* Get chip characteristics and number of banks */
919 nand_get_chip_info();
922 /* Use chip info to allocate the correct size LPT buffer */
923 lptbuf_size
= sizeof(struct lpt_entry
) * segments_per_bank
* total_banks
;
924 lpt_handle
= core_alloc("lpt lookup", lptbuf_size
);
925 struct lpt_entry
* lpt_lookup
= core_get_data(lpt_handle
);
927 /* Use a static array in the bootloader */
928 lptbuf_size
= sizeof(lpt_lookup
);
931 memset(lpt_lookup
, 0xff, lptbuf_size
);
932 memset(write_caches
, 0xff, sizeof(write_caches
));
934 write_caches_in_use
= 0;
936 /* Scan banks to build up block translation table */
937 for (bank
= 0; bank
< total_banks
; bank
++)
939 for (phys_segment
= 0; phys_segment
< segments_per_bank
; phys_segment
++)
941 /* Read spare bytes from first sector of each segment */
942 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, 0),
943 SECTOR_SIZE
, /* offset */
946 int type
= get_sector_type(spare_buf
);
949 if (type
== SECTYPE_MAIN_INPLACE_CACHE
)
951 /* Since this type of segment is written to sequentially, its
952 job is complete if the final page has been written. In this
953 case we need to treat it as a normal data segment. */
954 nand_read_raw(bank
, phys_segment_to_page_addr
955 (phys_segment
, pages_per_segment
- 1),
956 SECTOR_SIZE
, 16, spare_buf
);
958 if (get_sector_type(spare_buf
) != 0xff)
960 type
= SECTYPE_MAIN_DATA
;
967 case SECTYPE_MAIN_DATA
:
969 /* Main data area segment */
970 unsigned short log_segment
=
971 get_log_segment_id(phys_segment
, spare_buf
);
973 if (log_segment
< segments_per_bank
* total_banks
)
976 lpt_lookup
= core_get_data(lpt_handle
);
978 if (lpt_lookup
[log_segment
].bank
== -1 ||
979 lpt_lookup
[log_segment
].phys_segment
== -1)
981 lpt_lookup
[log_segment
].bank
= bank
;
982 lpt_lookup
[log_segment
].phys_segment
= phys_segment
;
986 //panicf("duplicate data segment 0x%x!", log_segment);
992 case SECTYPE_MAIN_RANDOM_CACHE
:
994 /* Newly-written random page data (Main data area) */
995 read_random_writes_cache(bank
, phys_segment
);
999 case SECTYPE_MAIN_INPLACE_CACHE
:
1001 /* Newly-written sequential page data (Main data area) */
1002 read_inplace_writes_cache(bank
, phys_segment
);
1014 long nand_last_disk_activity(void)
1016 return last_disk_activity
;
1019 void nand_sleep(void)
1023 void nand_spin(void)
1027 void nand_spindown(int seconds
)
1032 #ifdef CONFIG_STORAGE_MULTI
1034 int nand_num_drives(int first_drive
)
1036 /* We don't care which logical drive number we have been assigned */
1042 void nand_sleepnow(void)
1046 bool nand_disk_is_active(void)
1051 int nand_soft_reset(void)
1056 int nand_spinup_time(void)
1061 void nand_enable(bool onoff
)
1066 #endif /* CONFIG_STORAGE_MULTI */