Trim down peak calculation a bit.
[kugel-rb.git] / firmware / target / arm / ata-nand-telechips.c
blob81dde339382595fcc09fc5b6268280b9e3e9a9d3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
21 #include "nand.h"
22 #include "ata-nand-target.h"
23 #include "system.h"
24 #include <string.h>
25 #include "led.h"
26 #include "panic.h"
27 #include "nand_id.h"
28 #include "storage.h"
29 #include "buffer.h"
31 #define SECTOR_SIZE 512
33 /* ECC on read is implemented on the assumption that MLC-style 4-bit correction
34 is always used regardless of NAND chip type. This assumption is true for at
35 least D2 (MLC) and M200 (SLC). */
36 #define USE_ECC_CORRECTION
38 /* for compatibility */
39 int ata_spinup_time = 0;
41 long last_disk_activity = -1;
43 /** static, private data **/
44 static bool initialized = false;
46 static long next_yield = 0;
47 #define MIN_YIELD_PERIOD 1000
49 static struct mutex ata_mtx SHAREDBSS_ATTR;
51 #if defined(COWON_D2) || defined(IAUDIO_7)
52 #define FTL_V2
53 #define MAX_WRITE_CACHES 8
54 #else
55 #define FTL_V1
56 #define MAX_WRITE_CACHES 4
57 #endif
59 /* Sector type identifiers - main data area */
61 #define SECTYPE_MAIN_LPT 0x12
62 #define SECTYPE_MAIN_DATA 0x13
63 #define SECTYPE_MAIN_RANDOM_CACHE 0x15
64 #define SECTYPE_MAIN_INPLACE_CACHE 0x17
66 /* We don't touch the hidden area at all - these are for reference */
67 #define SECTYPE_HIDDEN_LPT 0x22
68 #define SECTYPE_HIDDEN_DATA 0x23
69 #define SECTYPE_HIDDEN_RANDOM_CACHE 0x25
70 #define SECTYPE_HIDDEN_INPLACE_CACHE 0x27
72 #ifdef FTL_V1
73 #define SECTYPE_FIRMWARE 0x40
74 #else
75 #define SECTYPE_FIRMWARE 0xE0
76 #endif
78 /* Offsets to data within sector's spare area */
80 #define OFF_CACHE_PAGE_LOBYTE 2
81 #define OFF_CACHE_PAGE_HIBYTE 3
82 #define OFF_SECTOR_TYPE 4
84 #ifdef FTL_V2
85 #define OFF_LOG_SEG_LOBYTE 7
86 #define OFF_LOG_SEG_HIBYTE 6
87 #else
88 #define OFF_LOG_SEG_LOBYTE 6
89 #define OFF_LOG_SEG_HIBYTE 7
90 #endif
92 /* Chip characteristics, initialised by nand_get_chip_info() */
94 static struct nand_info* nand_data = NULL;
96 static int total_banks = 0;
97 static int pages_per_bank = 0;
98 static int sectors_per_page = 0;
99 static int bytes_per_segment = 0;
100 static int sectors_per_segment = 0;
101 static int segments_per_bank = 0;
102 static int pages_per_segment = 0;
104 /* Maximum values for static buffers */
106 #define MAX_PAGE_SIZE 4096
107 #define MAX_SPARE_SIZE 128
108 #define MAX_BLOCKS_PER_BANK 8192
109 #define MAX_PAGES_PER_BLOCK 128
110 #define MAX_BANKS 4
111 #define MAX_BLOCKS_PER_SEGMENT 4
113 #define MAX_SEGMENTS (MAX_BLOCKS_PER_BANK * MAX_BANKS / MAX_BLOCKS_PER_SEGMENT)
115 /* Logical/Physical translation table */
117 struct lpt_entry
119 short bank;
120 short phys_segment;
122 #ifdef BOOTLOADER
123 static struct lpt_entry lpt_lookup[MAX_SEGMENTS];
124 #else
125 /* buffer_alloc'd in nand_init() when the correct size has been determined */
126 static struct lpt_entry* lpt_lookup = NULL;
127 #endif
129 /* Write Caches */
131 struct write_cache
133 short log_segment;
134 short inplace_bank;
135 short inplace_phys_segment;
136 short inplace_pages_used;
137 short random_bank;
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)
150 int page_addr = 0;
152 switch (nand_data->planes)
154 case 1:
156 page_addr = (phys_segment * nand_data->pages_per_block);
157 break;
160 case 2:
161 case 4:
163 page_addr = phys_segment * nand_data->pages_per_block * 2;
165 if (page_in_seg & 1)
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 */
174 page_addr +=
175 (nand_data->blocks_per_bank/2) * nand_data->pages_per_block;
178 break;
182 page_addr += (page_in_seg / nand_data->planes);
184 return page_addr;
188 /* NAND physical access functions */
190 static void nand_chip_select(int bank)
192 if (bank == -1)
194 /* Disable both chip selects */
195 NAND_GPIO_CLEAR(CS_GPIO_BIT);
196 NFC_CTRL |= NFC_CS0 | NFC_CS1;
198 else
200 /* NFC chip select */
201 if (bank & 1)
203 NFC_CTRL &= ~NFC_CS0;
204 NFC_CTRL |= NFC_CS1;
206 else
208 NFC_CTRL |= NFC_CS0;
209 NFC_CTRL &= ~NFC_CS1;
212 /* Secondary chip select */
213 if (bank & 2)
214 NAND_GPIO_SET(CS_GPIO_BIT);
215 else
216 NAND_GPIO_CLEAR(CS_GPIO_BIT);
221 static void nand_read_id(int bank, unsigned char* id_buf)
223 int i;
225 /* Enable NFC bus clock */
226 BCLKCTR |= DEV_NAND;
228 /* Reset NAND controller */
229 NFC_RST = 0;
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);
239 /* Reset command */
240 NFC_CMD = 0xFF;
242 /* Set 8-bit data width */
243 NFC_CTRL &= ~NFC_16BIT;
245 /* Read ID command, single address cycle */
246 NFC_CMD = 0x90;
247 NFC_SADDR = 0x00;
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)
264 int i;
266 /* Enable NFC bus clock */
267 BCLKCTR |= DEV_NAND;
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. */
282 NFC_CMD = 0x30;
283 NFC_CMD = 0x65;
285 /* Read command */
286 NFC_CMD = 0x00;
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;
292 /* End of read */
293 NFC_CMD = 0x30;
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 */
305 NFC_CMD = 0xFF;
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)
316 int i;
318 /* Enable NFC bus clock */
319 BCLKCTR |= DEV_NAND;
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;
332 /* Read command */
333 NFC_CMD = 0x00;
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;
346 row = row >> 8;
349 /* End of read command */
350 NFC_CMD = 0x30;
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)
368 int i;
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;
382 else
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;
391 nand_end_read();
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
419 * nand_data->planes;
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 */
447 total_banks = 2;
449 else
451 /* UIDs differ, assume banks 2/3 are valid */
452 total_banks = 4;
455 else
457 /* Bank 2 returned differing id - assume 2/3 are junk */
458 total_banks = 2;
461 else
463 /* Bank 1 returned differing id - assume it is junk */
464 total_banks = 1;
468 Sanity checks:
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)
490 bool ret = true;
491 int i;
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 */
498 BCLKCTR |= DEV_ECC;
499 ECC_BASE = (unsigned long)&NFC_WDATA;
500 ECC_CTRL |= ECC_M4EN;
501 ECC_CTRL &= ~ECC_ENC;
502 ECC_CTRL |= ECC_READY;
503 ECC_CLR = 0;
504 #endif
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++)
521 *ptr++ = NFC_WDATA;
524 memcpy(buf, temp_buf, SECTOR_SIZE);
526 else
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++)
533 *ptr++ = NFC_WDATA;
537 #ifdef USE_ECC_CORRECTION
538 /* Stop monitoring before we read the OOB data */
539 ECC_CTRL &= ~ECC_M4EN;
540 BCLKCTR &= ~DEV_ECC;
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 */
549 BCLKCTR |= DEV_ECC;
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;
560 switch (errors)
562 case 4: /* nothing to correct */
563 break;
565 case 7: /* fail, can't correct */
566 ret = false;
567 break;
569 default: /* between 1 and 4 errors */
571 int i;
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;
584 BCLKCTR &= ~DEV_ECC;
585 #endif
587 nand_end_read();
589 return ret;
593 static bool nand_read_sector_of_phys_segment(int bank, int phys_segment,
594 int page_in_seg, int sector,
595 void* buf)
597 int page_addr = phys_segment_to_page_addr(phys_segment,
598 page_in_seg);
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,
605 void* buf)
607 int page_in_segment = sector / sectors_per_page;
608 int sector_in_page = sector % sectors_per_page;
610 int bank = lpt_lookup[log_segment].bank;
611 int phys_segment = lpt_lookup[log_segment].phys_segment;
613 /* Check if any of the write caches refer to this segment/page.
614 If present we need to read the cached page instead. */
616 int cache_num = 0;
617 bool found = false;
619 while (!found && cache_num < write_caches_in_use)
621 if (write_caches[cache_num].log_segment == log_segment)
623 if (write_caches[cache_num].page_map[page_in_segment] != -1)
625 /* data is located in random pages cache */
626 found = true;
628 bank = write_caches[cache_num].random_bank;
629 phys_segment = write_caches[cache_num].random_phys_segment;
631 page_in_segment =
632 write_caches[cache_num].page_map[page_in_segment];
634 else if (write_caches[cache_num].inplace_pages_used != -1 &&
635 write_caches[cache_num].inplace_pages_used > page_in_segment)
637 /* data is located in in-place pages cache */
638 found = true;
640 bank = write_caches[cache_num].inplace_bank;
641 phys_segment = write_caches[cache_num].inplace_phys_segment;
644 cache_num++;
647 return nand_read_sector_of_phys_segment(bank, phys_segment,
648 page_in_segment,
649 sector_in_page, buf);
653 /* Miscellaneous helper functions */
655 static inline unsigned char get_sector_type(char* spare_buf)
657 return spare_buf[OFF_SECTOR_TYPE];
660 static inline unsigned short get_log_segment_id(int phys_seg, char* spare_buf)
662 (void)phys_seg;
664 return ((spare_buf[OFF_LOG_SEG_HIBYTE] << 8) |
665 spare_buf[OFF_LOG_SEG_LOBYTE])
666 #if defined(FTL_V1)
667 + 984 * (phys_seg / 1024)
668 #endif
672 static inline unsigned short get_cached_page_id(char* spare_buf)
674 return (spare_buf[OFF_CACHE_PAGE_HIBYTE] << 8) |
675 spare_buf[OFF_CACHE_PAGE_LOBYTE];
678 static int find_write_cache(int log_segment)
680 int i;
682 for (i = 0; i < write_caches_in_use; i++)
683 if (write_caches[i].log_segment == log_segment)
684 return i;
686 return -1;
690 static void read_random_writes_cache(int bank, int phys_segment)
692 int page = 0;
693 short log_segment;
694 unsigned char spare_buf[16];
696 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page),
697 SECTOR_SIZE, /* offset to first sector's spare */
698 16, spare_buf);
700 log_segment = get_log_segment_id(phys_segment, spare_buf);
702 if (log_segment == -1)
703 return;
705 /* Find which cache this is related to */
706 int cache_no = find_write_cache(log_segment);
708 if (cache_no == -1)
710 if (write_caches_in_use < MAX_WRITE_CACHES)
712 cache_no = write_caches_in_use;
713 write_caches_in_use++;
715 else
717 panicf("Max NAND write caches reached");
721 write_caches[cache_no].log_segment = log_segment;
722 write_caches[cache_no].random_bank = bank;
723 write_caches[cache_no].random_phys_segment = phys_segment;
725 #ifndef FTL_V1
726 /* Loop over each page in the phys segment (from page 1 onwards).
727 Read spare for 1st sector, store location of page in array. */
728 for (page = 1;
729 page < (nand_data->pages_per_block * nand_data->planes);
730 page++)
732 unsigned short cached_page;
734 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page),
735 SECTOR_SIZE, /* offset to first sector's spare */
736 16, spare_buf);
738 cached_page = get_cached_page_id(spare_buf);
740 if (cached_page != 0xFFFF)
741 write_caches[cache_no].page_map[cached_page] = page;
743 #endif /* !FTL_V1 */
747 static void read_inplace_writes_cache(int bank, int phys_segment)
749 int page = 0;
750 short log_segment;
751 unsigned char spare_buf[16];
753 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page),
754 SECTOR_SIZE, /* offset to first sector's spare */
755 16, spare_buf);
757 log_segment = get_log_segment_id(phys_segment, spare_buf);
759 if (log_segment == -1)
760 return;
762 /* Find which cache this is related to */
763 int cache_no = find_write_cache(log_segment);
765 if (cache_no == -1)
767 if (write_caches_in_use < MAX_WRITE_CACHES)
769 cache_no = write_caches_in_use;
770 write_caches_in_use++;
772 else
774 panicf("Max NAND write caches reached");
778 write_caches[cache_no].log_segment = log_segment;
780 /* Find how many pages have been written to the new segment */
781 while (log_segment != -1 &&
782 page < (nand_data->pages_per_block * nand_data->planes) - 1)
784 page++;
785 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page),
786 SECTOR_SIZE, 16, spare_buf);
788 log_segment = get_log_segment_id(phys_segment, spare_buf);
791 if (page != 0)
793 write_caches[cache_no].inplace_bank = bank;
794 write_caches[cache_no].inplace_phys_segment = phys_segment;
795 write_caches[cache_no].inplace_pages_used = page;
800 int nand_read_sectors(IF_MD2(int drive,) unsigned long start, int incount,
801 void* inbuf)
803 #ifdef HAVE_MULTIDRIVE
804 (void)drive; /* unused for now */
805 #endif
807 int ret = 0;
809 mutex_lock(&ata_mtx);
811 led(true);
813 while (incount > 0)
815 int done = 0;
816 int segment = start / sectors_per_segment;
817 int secmod = start % sectors_per_segment;
819 while (incount > 0 && secmod < sectors_per_segment)
821 if (!nand_read_sector_of_logical_segment(segment, secmod, inbuf))
823 ret = -1;
824 goto nand_read_error;
827 if (TIME_AFTER(USEC_TIMER, next_yield))
829 next_yield = USEC_TIMER + MIN_YIELD_PERIOD;
830 yield();
833 inbuf += SECTOR_SIZE;
834 incount--;
835 secmod++;
836 done++;
839 if (done < 0)
841 ret = -1;
842 goto nand_read_error;
844 start += done;
847 nand_read_error:
849 mutex_unlock(&ata_mtx);
850 led(false);
852 return ret;
855 int nand_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
856 const void* outbuf)
858 #ifdef HAVE_MULTIDRIVE
859 (void)drive; /* unused for now */
860 #endif
862 /* TODO: Learn more about TNFTL and implement this one day... */
863 (void)start;
864 (void)count;
865 (void)outbuf;
866 return -1;
869 #ifdef HAVE_STORAGE_FLUSH
870 int nand_flush(void)
872 return 0;
874 #endif
876 #ifdef STORAGE_GET_INFO
877 void nand_get_info(IF_MD2(int drive,) struct storage_info *info)
879 #ifdef HAVE_MULTIDRIVE
880 (void)drive; /* unused for now */
881 #endif
883 /* firmware version */
884 info->revision="0.00";
886 info->vendor="Rockbox";
887 info->product="Internal Storage";
889 /* blocks count */
890 info->num_sectors = sectors_per_segment * segments_per_bank * total_banks;
891 info->sector_size = SECTOR_SIZE;
893 #endif
896 int nand_init(void)
898 int bank, phys_segment, lptbuf_size;
899 unsigned char spare_buf[16];
901 if (initialized) return 0;
903 mutex_init(&ata_mtx);
905 #ifdef CPU_TCC77X
906 CSCFG2 = 0x018a8010 | tcc77x_cscfg_bw(TCC77X_CSCFG_BW8);
908 GPIOC_FUNC &= ~(CS_GPIO_BIT | WE_GPIO_BIT);
909 GPIOC_FUNC |= 0x1;
910 #endif
912 /* Set GPIO direction for chip select & write protect */
913 NAND_GPIO_OUT_EN(CS_GPIO_BIT | WE_GPIO_BIT);
915 /* Get chip characteristics and number of banks */
916 nand_get_chip_info();
918 #ifndef BOOTLOADER
919 /* Use chip info to allocate the correct size LPT buffer */
920 lptbuf_size = sizeof(struct lpt_entry) * segments_per_bank * total_banks;
921 lpt_lookup = buffer_alloc(lptbuf_size);
922 #else
923 /* Use a static array in the bootloader */
924 lptbuf_size = sizeof(lpt_lookup);
925 #endif
927 memset(lpt_lookup, 0xff, lptbuf_size);
928 memset(write_caches, 0xff, sizeof(write_caches));
930 write_caches_in_use = 0;
932 /* Scan banks to build up block translation table */
933 for (bank = 0; bank < total_banks; bank++)
935 for (phys_segment = 0; phys_segment < segments_per_bank; phys_segment++)
937 /* Read spare bytes from first sector of each segment */
938 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, 0),
939 SECTOR_SIZE, /* offset */
940 16, spare_buf);
942 int type = get_sector_type(spare_buf);
944 #ifdef FTL_V2
945 if (type == SECTYPE_MAIN_INPLACE_CACHE)
947 /* Since this type of segment is written to sequentially, its
948 job is complete if the final page has been written. In this
949 case we need to treat it as a normal data segment. */
950 nand_read_raw(bank, phys_segment_to_page_addr
951 (phys_segment, pages_per_segment - 1),
952 SECTOR_SIZE, 16, spare_buf);
954 if (get_sector_type(spare_buf) != 0xff)
956 type = SECTYPE_MAIN_DATA;
959 #endif
961 switch (type)
963 case SECTYPE_MAIN_DATA:
965 /* Main data area segment */
966 unsigned short log_segment =
967 get_log_segment_id(phys_segment, spare_buf);
969 if (log_segment < segments_per_bank * total_banks)
971 if (lpt_lookup[log_segment].bank == -1 ||
972 lpt_lookup[log_segment].phys_segment == -1)
974 lpt_lookup[log_segment].bank = bank;
975 lpt_lookup[log_segment].phys_segment = phys_segment;
977 else
979 //panicf("duplicate data segment 0x%x!", log_segment);
982 break;
985 case SECTYPE_MAIN_RANDOM_CACHE:
987 /* Newly-written random page data (Main data area) */
988 read_random_writes_cache(bank, phys_segment);
989 break;
992 case SECTYPE_MAIN_INPLACE_CACHE:
994 /* Newly-written sequential page data (Main data area) */
995 read_inplace_writes_cache(bank, phys_segment);
996 break;
1002 initialized = true;
1004 return 0;
1007 long nand_last_disk_activity(void)
1009 return last_disk_activity;
1012 void nand_sleep(void)
1016 void nand_spin(void)
1020 void nand_spindown(int seconds)
1022 (void)seconds;
1025 #ifdef CONFIG_STORAGE_MULTI
1027 int nand_num_drives(int first_drive)
1029 /* We don't care which logical drive number we have been assigned */
1030 (void)first_drive;
1032 return 1;
1035 void nand_sleepnow(void)
1039 bool nand_disk_is_active(void)
1041 return false;
1044 int nand_soft_reset(void)
1046 return 0;
1049 int nand_spinup_time(void)
1051 return 0;
1054 void nand_enable(bool onoff)
1056 (void)onoff;
1059 #endif /* CONFIG_STORAGE_MULTI */