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"
32 #define SECTOR_SIZE 512
34 /* ECC on read is implemented on the assumption that MLC-style 4-bit correction
35 is always used regardless of NAND chip type. This assumption is true for at
36 least D2 (MLC) and M200 (SLC). */
37 #define USE_ECC_CORRECTION
39 /* for compatibility */
40 int ata_spinup_time
= 0;
42 long last_disk_activity
= -1;
44 /** static, private data **/
45 static bool initialized
= false;
47 static long next_yield
= 0;
48 #define MIN_YIELD_PERIOD 1000
50 static struct mutex ata_mtx SHAREDBSS_ATTR
;
52 #if defined(COWON_D2) || defined(IAUDIO_7)
54 #define MAX_WRITE_CACHES 8
57 #define MAX_WRITE_CACHES 4
60 /* Sector type identifiers - main data area */
62 #define SECTYPE_MAIN_LPT 0x12
63 #define SECTYPE_MAIN_DATA 0x13
64 #define SECTYPE_MAIN_RANDOM_CACHE 0x15
65 #define SECTYPE_MAIN_INPLACE_CACHE 0x17
67 /* We don't touch the hidden area at all - these are for reference */
68 #define SECTYPE_HIDDEN_LPT 0x22
69 #define SECTYPE_HIDDEN_DATA 0x23
70 #define SECTYPE_HIDDEN_RANDOM_CACHE 0x25
71 #define SECTYPE_HIDDEN_INPLACE_CACHE 0x27
74 #define SECTYPE_FIRMWARE 0x40
76 #define SECTYPE_FIRMWARE 0xE0
79 /* Offsets to data within sector's spare area */
81 #define OFF_CACHE_PAGE_LOBYTE 2
82 #define OFF_CACHE_PAGE_HIBYTE 3
83 #define OFF_SECTOR_TYPE 4
86 #define OFF_LOG_SEG_LOBYTE 7
87 #define OFF_LOG_SEG_HIBYTE 6
89 #define OFF_LOG_SEG_LOBYTE 6
90 #define OFF_LOG_SEG_HIBYTE 7
93 /* Chip characteristics, initialised by nand_get_chip_info() */
95 static struct nand_info
* nand_data
= NULL
;
97 static int total_banks
= 0;
98 static int pages_per_bank
= 0;
99 static int sectors_per_page
= 0;
100 static int bytes_per_segment
= 0;
101 static int sectors_per_segment
= 0;
102 static int segments_per_bank
= 0;
103 static int pages_per_segment
= 0;
105 /* Maximum values for static buffers */
107 #define MAX_PAGE_SIZE 4096
108 #define MAX_SPARE_SIZE 128
109 #define MAX_BLOCKS_PER_BANK 8192
110 #define MAX_PAGES_PER_BLOCK 128
112 #define MAX_BLOCKS_PER_SEGMENT 4
114 #define MAX_SEGMENTS (MAX_BLOCKS_PER_BANK * MAX_BANKS / MAX_BLOCKS_PER_SEGMENT)
116 /* Logical/Physical translation table */
124 static struct lpt_entry lpt_lookup
[MAX_SEGMENTS
];
126 /* buffer_alloc'd in nand_init() when the correct size has been determined */
127 static struct lpt_entry
* lpt_lookup
= NULL
;
136 short inplace_phys_segment
;
137 short inplace_pages_used
;
139 short random_phys_segment
;
140 short page_map
[MAX_PAGES_PER_BLOCK
* MAX_BLOCKS_PER_SEGMENT
];
142 static struct write_cache write_caches
[MAX_WRITE_CACHES
];
144 static int write_caches_in_use
= 0;
147 /* Conversion functions */
149 static int phys_segment_to_page_addr(int phys_segment
, int page_in_seg
)
153 switch (nand_data
->planes
)
157 page_addr
= (phys_segment
* nand_data
->pages_per_block
);
164 page_addr
= phys_segment
* nand_data
->pages_per_block
* 2;
168 /* Data is located in block+1 */
169 page_addr
+= nand_data
->pages_per_block
;
172 if (nand_data
->planes
== 4 && page_in_seg
& 2)
174 /* Data is located in 2nd half of bank */
176 (nand_data
->blocks_per_bank
/2) * nand_data
->pages_per_block
;
183 page_addr
+= (page_in_seg
/ nand_data
->planes
);
189 /* NAND physical access functions */
191 static void nand_chip_select(int bank
)
195 /* Disable both chip selects */
196 NAND_GPIO_CLEAR(CS_GPIO_BIT
);
197 NFC_CTRL
|= NFC_CS0
| NFC_CS1
;
201 /* NFC chip select */
204 NFC_CTRL
&= ~NFC_CS0
;
210 NFC_CTRL
&= ~NFC_CS1
;
213 /* Secondary chip select */
215 NAND_GPIO_SET(CS_GPIO_BIT
);
217 NAND_GPIO_CLEAR(CS_GPIO_BIT
);
222 static void nand_read_id(int bank
, unsigned char* id_buf
)
226 /* Enable NFC bus clock */
229 /* Reset NAND controller */
232 /* Set slow cycle timings since the chip is as yet unidentified */
233 NFC_CTRL
= (NFC_CTRL
&~0xFFF) | 0x353;
235 nand_chip_select(bank
);
237 /* Set write protect */
238 NAND_GPIO_CLEAR(WE_GPIO_BIT
);
243 /* Set 8-bit data width */
244 NFC_CTRL
&= ~NFC_16BIT
;
246 /* Read ID command, single address cycle */
250 /* Read the 5 chip ID bytes */
251 for (i
= 0; i
< 5; i
++)
253 id_buf
[i
] = NFC_SDATA
& 0xFF;
256 nand_chip_select(-1);
258 /* Disable NFC bus clock */
259 BCLKCTR
&= ~DEV_NAND
;
263 static void nand_read_uid(int bank
, unsigned int* uid_buf
)
267 /* Enable NFC bus clock */
270 /* Set cycle timing (stp = 1, pw = 3, hold = 1) */
271 NFC_CTRL
= (NFC_CTRL
&~0xFFF) | 0x131;
273 nand_chip_select(bank
);
275 /* Set write protect */
276 NAND_GPIO_CLEAR(WE_GPIO_BIT
);
278 /* Set 8-bit data width */
279 NFC_CTRL
&= ~NFC_16BIT
;
281 /* Undocumented (SAMSUNG specific?) commands set the chip into a
282 special mode allowing a normally-hidden UID block to be read. */
289 /* Write row/column address */
290 for (i
= 0; i
< nand_data
->col_cycles
; i
++) NFC_SADDR
= 0;
291 for (i
= 0; i
< nand_data
->row_cycles
; i
++) NFC_SADDR
= 0;
296 /* Wait until complete */
297 while (!(NFC_CTRL
& NFC_READY
)) {};
299 /* Copy data to buffer (data repeats after 8 words) */
300 for (i
= 0; i
< 8; i
++)
302 uid_buf
[i
] = NFC_WDATA
;
305 /* Reset the chip back to normal mode */
308 nand_chip_select(-1);
310 /* Disable NFC bus clock */
311 BCLKCTR
&= ~DEV_NAND
;
315 static void nand_setup_read(int bank
, int row
, int column
)
319 /* Enable NFC bus clock */
322 /* Set cycle timing (stp = 1, pw = 3, hold = 1) */
323 NFC_CTRL
= (NFC_CTRL
&~0xFFF) | 0x131;
325 nand_chip_select(bank
);
327 /* Set write protect */
328 NAND_GPIO_CLEAR(WE_GPIO_BIT
);
330 /* Set 8-bit data width */
331 NFC_CTRL
&= ~NFC_16BIT
;
336 /* Write column address */
337 for (i
= 0; i
< nand_data
->col_cycles
; i
++)
339 NFC_SADDR
= column
& 0xFF;
340 column
= column
>> 8;
343 /* Write row address */
344 for (i
= 0; i
< nand_data
->row_cycles
; i
++)
346 NFC_SADDR
= row
& 0xFF;
350 /* End of read command */
353 /* Wait until complete */
354 while (!(NFC_CTRL
& NFC_READY
)) {};
358 static void nand_end_read(void)
360 nand_chip_select(-1);
362 /* Disable NFC bus clock */
363 BCLKCTR
&= ~DEV_NAND
;
367 static void nand_read_raw(int bank
, int row
, int column
, int size
, void* buf
)
371 nand_setup_read(bank
, row
, column
);
373 /* Read data into page buffer */
374 if (((unsigned int)buf
& 3) || (size
& 3))
376 /* Use byte copy since either the buffer or size are not word-aligned */
377 /* TODO: Byte copy only where necessary (use words for mid-section) */
378 for (i
= 0; i
< size
; i
++)
380 ((unsigned char*)buf
)[i
] = NFC_SDATA
;
385 /* Use 4-byte copy as buffer and size are both word-aligned */
386 for (i
= 0; i
< (size
/4); i
++)
388 ((unsigned int*)buf
)[i
] = NFC_WDATA
;
396 static void nand_get_chip_info(void)
398 unsigned char manuf_id
;
399 unsigned char id_buf
[8];
401 /* Read chip id from bank 0 */
402 nand_read_id(0, id_buf
);
404 manuf_id
= id_buf
[0];
406 /* Identify the chip geometry */
407 nand_data
= nand_identify(id_buf
);
409 if (nand_data
== NULL
)
411 panicf("Unknown NAND: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
412 id_buf
[0],id_buf
[1],id_buf
[2],id_buf
[3],id_buf
[4]);
415 pages_per_bank
= nand_data
->blocks_per_bank
* nand_data
->pages_per_block
;
417 segments_per_bank
= nand_data
->blocks_per_bank
/ nand_data
->planes
;
419 bytes_per_segment
= nand_data
->page_size
* nand_data
->pages_per_block
422 sectors_per_page
= nand_data
->page_size
/ SECTOR_SIZE
;
424 sectors_per_segment
= bytes_per_segment
/ SECTOR_SIZE
;
426 pages_per_segment
= sectors_per_segment
/ sectors_per_page
;
428 /* Establish how many banks are present */
429 nand_read_id(1, id_buf
);
431 if (id_buf
[0] == manuf_id
)
433 /* Bank 1 is populated, now check if banks 2/3 are valid */
434 nand_read_id(2, id_buf
);
436 if (id_buf
[0] == manuf_id
)
438 /* Bank 2 returned matching id - check if 2/3 are shadowing 0/1 */
439 unsigned int uid_buf0
[8];
440 unsigned int uid_buf2
[8];
442 nand_read_uid(0, uid_buf0
);
443 nand_read_uid(2, uid_buf2
);
445 if (memcmp(uid_buf0
, uid_buf2
, 32) == 0)
447 /* UIDs match, assume banks 2/3 are shadowing 0/1 */
452 /* UIDs differ, assume banks 2/3 are valid */
458 /* Bank 2 returned differing id - assume 2/3 are junk */
464 /* Bank 1 returned differing id - assume it is junk */
470 1. "BMP" tag at block 0, page 0, offset <page_size> [always present]
471 2. On most D2s, <page_size>+3 is 'M' and <page_size>+4 is no. of banks.
472 This is not present on some older players (formatted with early FW?)
475 nand_read_raw(0, 0, /* bank, page */
476 nand_data
->page_size
, /* offset */
477 8, id_buf
); /* length, dest */
479 if (strncmp(id_buf
, "BMP", 3)) panicf("BMP tag not present");
481 if (id_buf
[3] == 'M')
483 if (id_buf
[4] != total_banks
) panicf("BMPM total_banks mismatch");
488 static bool nand_read_sector_of_phys_page(int bank
, int page
,
489 int sector
, void* buf
)
493 int page_offset
= sector
* (SECTOR_SIZE
+ 16);
495 #ifdef USE_ECC_CORRECTION
496 unsigned long spare_buf
[4];
498 /* Set up the ECC controller to monitor reads from NFC_WDATA */
500 ECC_BASE
= (unsigned long)&NFC_WDATA
;
501 ECC_CTRL
|= ECC_M4EN
;
502 ECC_CTRL
&= ~ECC_ENC
;
503 ECC_CTRL
|= ECC_READY
;
507 /* Read the sector data */
508 nand_setup_read(bank
, page
, page_offset
);
510 /* Read data into page buffer */
511 if ((unsigned int)buf
& 3)
513 /* If unaligned, read into a temporary buffer and copy to destination.
514 This way, reads are always done through NFC_WDATA - otherwise they
515 would not be 'seen' by the ECC controller. */
516 static char temp_buf
[SECTOR_SIZE
];
518 unsigned int* ptr
= (unsigned int*) temp_buf
;
520 for (i
= 0; i
< (SECTOR_SIZE
/4); i
++)
525 memcpy(buf
, temp_buf
, SECTOR_SIZE
);
529 /* Use straight word copy as buffer and size are both word-aligned */
530 unsigned int* ptr
= (unsigned int*) buf
;
532 for (i
= 0; i
< (SECTOR_SIZE
/4); i
++)
538 #ifdef USE_ECC_CORRECTION
539 /* Stop monitoring before we read the OOB data */
540 ECC_CTRL
&= ~ECC_M4EN
;
543 /* Read a further 4 words (sector OOB data) */
544 spare_buf
[0] = NFC_WDATA
;
545 spare_buf
[1] = NFC_WDATA
;
546 spare_buf
[2] = NFC_WDATA
;
547 spare_buf
[3] = NFC_WDATA
;
549 /* Calculate MLC4 ECC using bytes 0,1,8-15 */
551 ECC_CTRL
|= ECC_M4EN
;
553 MLC_ECC0W
= *(unsigned short*)spare_buf
;
554 MLC_ECC1W
= spare_buf
[2];
555 MLC_ECC2W
= spare_buf
[3];
557 while (!(ECC_CTRL
& ECC_READY
)) {};
559 int errors
= ECC_ERR_NUM
& 7;
563 case 4: /* nothing to correct */
566 case 7: /* fail, can't correct */
570 default: /* between 1 and 4 errors */
573 unsigned char* char_buf
= (unsigned char*)buf
;
575 for (i
= 0; i
< errors
+ 1; i
++)
577 int offset
= 0x207 - ECC_ERRADDR(i
);
578 char_buf
[offset
] ^= ECC_ERRDATA(i
);
583 /* Disable ECC block */
584 ECC_CTRL
&= ~ECC_M4EN
;
594 static bool nand_read_sector_of_phys_segment(int bank
, int phys_segment
,
595 int page_in_seg
, int sector
,
598 int page_addr
= phys_segment_to_page_addr(phys_segment
,
601 return nand_read_sector_of_phys_page(bank
, page_addr
, sector
, buf
);
605 static bool nand_read_sector_of_logical_segment(int log_segment
, int sector
,
608 int page_in_segment
= sector
/ sectors_per_page
;
609 int sector_in_page
= sector
% sectors_per_page
;
611 int bank
= lpt_lookup
[log_segment
].bank
;
612 int phys_segment
= lpt_lookup
[log_segment
].phys_segment
;
614 /* Check if any of the write caches refer to this segment/page.
615 If present we need to read the cached page instead. */
620 while (!found
&& cache_num
< write_caches_in_use
)
622 if (write_caches
[cache_num
].log_segment
== log_segment
)
624 if (write_caches
[cache_num
].page_map
[page_in_segment
] != -1)
626 /* data is located in random pages cache */
629 bank
= write_caches
[cache_num
].random_bank
;
630 phys_segment
= write_caches
[cache_num
].random_phys_segment
;
633 write_caches
[cache_num
].page_map
[page_in_segment
];
635 else if (write_caches
[cache_num
].inplace_pages_used
!= -1 &&
636 write_caches
[cache_num
].inplace_pages_used
> page_in_segment
)
638 /* data is located in in-place pages cache */
641 bank
= write_caches
[cache_num
].inplace_bank
;
642 phys_segment
= write_caches
[cache_num
].inplace_phys_segment
;
648 return nand_read_sector_of_phys_segment(bank
, phys_segment
,
650 sector_in_page
, buf
);
654 /* Miscellaneous helper functions */
656 static inline unsigned char get_sector_type(char* spare_buf
)
658 return spare_buf
[OFF_SECTOR_TYPE
];
661 static inline unsigned short get_log_segment_id(int phys_seg
, char* spare_buf
)
665 return ((spare_buf
[OFF_LOG_SEG_HIBYTE
] << 8) |
666 spare_buf
[OFF_LOG_SEG_LOBYTE
])
668 + 984 * (phys_seg
/ 1024)
673 static inline unsigned short get_cached_page_id(char* spare_buf
)
675 return (spare_buf
[OFF_CACHE_PAGE_HIBYTE
] << 8) |
676 spare_buf
[OFF_CACHE_PAGE_LOBYTE
];
679 static int find_write_cache(int log_segment
)
683 for (i
= 0; i
< write_caches_in_use
; i
++)
684 if (write_caches
[i
].log_segment
== log_segment
)
691 static void read_random_writes_cache(int bank
, int phys_segment
)
695 unsigned char spare_buf
[16];
697 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, page
),
698 SECTOR_SIZE
, /* offset to first sector's spare */
701 log_segment
= get_log_segment_id(phys_segment
, spare_buf
);
703 if (log_segment
== -1)
706 /* Find which cache this is related to */
707 int cache_no
= find_write_cache(log_segment
);
711 if (write_caches_in_use
< MAX_WRITE_CACHES
)
713 cache_no
= write_caches_in_use
;
714 write_caches_in_use
++;
718 panicf("Max NAND write caches reached");
722 write_caches
[cache_no
].log_segment
= log_segment
;
723 write_caches
[cache_no
].random_bank
= bank
;
724 write_caches
[cache_no
].random_phys_segment
= phys_segment
;
727 /* Loop over each page in the phys segment (from page 1 onwards).
728 Read spare for 1st sector, store location of page in array. */
730 page
< (nand_data
->pages_per_block
* nand_data
->planes
);
733 unsigned short cached_page
;
735 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, page
),
736 SECTOR_SIZE
, /* offset to first sector's spare */
739 cached_page
= get_cached_page_id(spare_buf
);
741 if (cached_page
!= 0xFFFF)
742 write_caches
[cache_no
].page_map
[cached_page
] = page
;
748 static void read_inplace_writes_cache(int bank
, int phys_segment
)
752 unsigned char spare_buf
[16];
754 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, page
),
755 SECTOR_SIZE
, /* offset to first sector's spare */
758 log_segment
= get_log_segment_id(phys_segment
, spare_buf
);
760 if (log_segment
== -1)
763 /* Find which cache this is related to */
764 int cache_no
= find_write_cache(log_segment
);
768 if (write_caches_in_use
< MAX_WRITE_CACHES
)
770 cache_no
= write_caches_in_use
;
771 write_caches_in_use
++;
775 panicf("Max NAND write caches reached");
779 write_caches
[cache_no
].log_segment
= log_segment
;
781 /* Find how many pages have been written to the new segment */
782 while (log_segment
!= -1 &&
783 page
< (nand_data
->pages_per_block
* nand_data
->planes
) - 1)
786 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, page
),
787 SECTOR_SIZE
, 16, spare_buf
);
789 log_segment
= get_log_segment_id(phys_segment
, spare_buf
);
794 write_caches
[cache_no
].inplace_bank
= bank
;
795 write_caches
[cache_no
].inplace_phys_segment
= phys_segment
;
796 write_caches
[cache_no
].inplace_pages_used
= page
;
801 int nand_read_sectors(IF_MD2(int drive
,) unsigned long start
, int incount
,
804 #ifdef HAVE_MULTIDRIVE
805 (void)drive
; /* unused for now */
810 mutex_lock(&ata_mtx
);
817 int segment
= start
/ sectors_per_segment
;
818 int secmod
= start
% sectors_per_segment
;
820 while (incount
> 0 && secmod
< sectors_per_segment
)
822 if (!nand_read_sector_of_logical_segment(segment
, secmod
, inbuf
))
825 goto nand_read_error
;
828 #ifdef CPU_TCC780X /* 77x doesn't have USEC_TIMER yet */
829 if (TIME_AFTER(USEC_TIMER
, next_yield
))
831 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... */
873 #ifdef STORAGE_GET_INFO
874 void nand_get_info(IF_MD2(int drive
,) struct storage_info
*info
)
876 #ifdef HAVE_MULTIDRIVE
877 (void)drive
; /* unused for now */
880 /* firmware version */
881 info
->revision
="0.00";
883 info
->vendor
="Rockbox";
884 info
->product
="Internal Storage";
887 info
->num_sectors
= sectors_per_segment
* segments_per_bank
* total_banks
;
888 info
->sector_size
= SECTOR_SIZE
;
895 int bank
, phys_segment
, lptbuf_size
;
896 unsigned char spare_buf
[16];
898 if (initialized
) return 0;
900 mutex_init(&ata_mtx
);
905 GPIOC_FUNC
&= ~(CS_GPIO_BIT
| WE_GPIO_BIT
);
909 /* Set GPIO direction for chip select & write protect */
910 NAND_GPIO_OUT_EN(CS_GPIO_BIT
| WE_GPIO_BIT
);
912 /* Get chip characteristics and number of banks */
913 nand_get_chip_info();
916 /* Use chip info to allocate the correct size LPT buffer */
917 lptbuf_size
= sizeof(struct lpt_entry
) * segments_per_bank
* total_banks
;
918 lpt_lookup
= buffer_alloc(lptbuf_size
);
920 /* Use a static array in the bootloader */
921 lptbuf_size
= sizeof(lpt_lookup
);
924 memset(lpt_lookup
, 0xff, lptbuf_size
);
925 memset(write_caches
, 0xff, sizeof(write_caches
));
927 write_caches_in_use
= 0;
929 /* Scan banks to build up block translation table */
930 for (bank
= 0; bank
< total_banks
; bank
++)
932 for (phys_segment
= 0; phys_segment
< segments_per_bank
; phys_segment
++)
934 /* Read spare bytes from first sector of each segment */
935 nand_read_raw(bank
, phys_segment_to_page_addr(phys_segment
, 0),
936 SECTOR_SIZE
, /* offset */
939 int type
= get_sector_type(spare_buf
);
942 if (type
== SECTYPE_MAIN_INPLACE_CACHE
)
944 /* Since this type of segment is written to sequentially, its
945 job is complete if the final page has been written. In this
946 case we need to treat it as a normal data segment. */
947 nand_read_raw(bank
, phys_segment_to_page_addr
948 (phys_segment
, pages_per_segment
- 1),
949 SECTOR_SIZE
, 16, spare_buf
);
951 if (get_sector_type(spare_buf
) != 0xff)
953 type
= SECTYPE_MAIN_DATA
;
960 case SECTYPE_MAIN_DATA
:
962 /* Main data area segment */
963 unsigned short log_segment
=
964 get_log_segment_id(phys_segment
, spare_buf
);
966 if (log_segment
< segments_per_bank
* total_banks
)
968 if (lpt_lookup
[log_segment
].bank
== -1 ||
969 lpt_lookup
[log_segment
].phys_segment
== -1)
971 lpt_lookup
[log_segment
].bank
= bank
;
972 lpt_lookup
[log_segment
].phys_segment
= phys_segment
;
976 //panicf("duplicate data segment 0x%x!", log_segment);
982 case SECTYPE_MAIN_RANDOM_CACHE
:
984 /* Newly-written random page data (Main data area) */
985 read_random_writes_cache(bank
, phys_segment
);
989 case SECTYPE_MAIN_INPLACE_CACHE
:
991 /* Newly-written sequential page data (Main data area) */
992 read_inplace_writes_cache(bank
, phys_segment
);
1004 long nand_last_disk_activity(void)
1006 return last_disk_activity
;
1009 void nand_sleep(void)
1013 void nand_spin(void)
1017 void nand_spindown(int seconds
)
1022 #ifdef CONFIG_STORAGE_MULTI
1024 int nand_num_drives(int first_drive
)
1026 /* We don't care which logical drive number we have been assigned */
1032 void nand_sleepnow(void)
1036 bool nand_disk_is_active(void)
1041 int nand_soft_reset(void)
1046 int nand_spinup_time(void)
1051 void nand_enable(bool onoff
)
1056 #endif /* CONFIG_STORAGE_MULTI */