FS#8961 - Anti-Aliased Fonts.
[kugel-rb.git] / firmware / target / arm / ata-nand-telechips.c
blob7250211eb99b930371971469f19c256a040f7228
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"
30 #include "led.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)
53 #define FTL_V2
54 #define MAX_WRITE_CACHES 8
55 #else
56 #define FTL_V1
57 #define MAX_WRITE_CACHES 4
58 #endif
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
73 #ifdef FTL_V1
74 #define SECTYPE_FIRMWARE 0x40
75 #else
76 #define SECTYPE_FIRMWARE 0xE0
77 #endif
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
85 #ifdef FTL_V2
86 #define OFF_LOG_SEG_LOBYTE 7
87 #define OFF_LOG_SEG_HIBYTE 6
88 #else
89 #define OFF_LOG_SEG_LOBYTE 6
90 #define OFF_LOG_SEG_HIBYTE 7
91 #endif
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
111 #define MAX_BANKS 4
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 */
118 struct lpt_entry
120 short bank;
121 short phys_segment;
123 #ifdef BOOTLOADER
124 static struct lpt_entry lpt_lookup[MAX_SEGMENTS];
125 #else
126 /* buffer_alloc'd in nand_init() when the correct size has been determined */
127 static struct lpt_entry* lpt_lookup = NULL;
128 #endif
130 /* Write Caches */
132 struct write_cache
134 short log_segment;
135 short inplace_bank;
136 short inplace_phys_segment;
137 short inplace_pages_used;
138 short random_bank;
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)
151 int page_addr = 0;
153 switch (nand_data->planes)
155 case 1:
157 page_addr = (phys_segment * nand_data->pages_per_block);
158 break;
161 case 2:
162 case 4:
164 page_addr = phys_segment * nand_data->pages_per_block * 2;
166 if (page_in_seg & 1)
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 */
175 page_addr +=
176 (nand_data->blocks_per_bank/2) * nand_data->pages_per_block;
179 break;
183 page_addr += (page_in_seg / nand_data->planes);
185 return page_addr;
189 /* NAND physical access functions */
191 static void nand_chip_select(int bank)
193 if (bank == -1)
195 /* Disable both chip selects */
196 NAND_GPIO_CLEAR(CS_GPIO_BIT);
197 NFC_CTRL |= NFC_CS0 | NFC_CS1;
199 else
201 /* NFC chip select */
202 if (bank & 1)
204 NFC_CTRL &= ~NFC_CS0;
205 NFC_CTRL |= NFC_CS1;
207 else
209 NFC_CTRL |= NFC_CS0;
210 NFC_CTRL &= ~NFC_CS1;
213 /* Secondary chip select */
214 if (bank & 2)
215 NAND_GPIO_SET(CS_GPIO_BIT);
216 else
217 NAND_GPIO_CLEAR(CS_GPIO_BIT);
222 static void nand_read_id(int bank, unsigned char* id_buf)
224 int i;
226 /* Enable NFC bus clock */
227 BCLKCTR |= DEV_NAND;
229 /* Reset NAND controller */
230 NFC_RST = 0;
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);
240 /* Reset command */
241 NFC_CMD = 0xFF;
243 /* Set 8-bit data width */
244 NFC_CTRL &= ~NFC_16BIT;
246 /* Read ID command, single address cycle */
247 NFC_CMD = 0x90;
248 NFC_SADDR = 0x00;
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)
265 int i;
267 /* Enable NFC bus clock */
268 BCLKCTR |= DEV_NAND;
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. */
283 NFC_CMD = 0x30;
284 NFC_CMD = 0x65;
286 /* Read command */
287 NFC_CMD = 0x00;
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;
293 /* End of read */
294 NFC_CMD = 0x30;
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 */
306 NFC_CMD = 0xFF;
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)
317 int i;
319 /* Enable NFC bus clock */
320 BCLKCTR |= DEV_NAND;
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;
333 /* Read command */
334 NFC_CMD = 0x00;
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;
347 row = row >> 8;
350 /* End of read command */
351 NFC_CMD = 0x30;
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)
369 int i;
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;
383 else
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;
392 nand_end_read();
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
420 * nand_data->planes;
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 */
448 total_banks = 2;
450 else
452 /* UIDs differ, assume banks 2/3 are valid */
453 total_banks = 4;
456 else
458 /* Bank 2 returned differing id - assume 2/3 are junk */
459 total_banks = 2;
462 else
464 /* Bank 1 returned differing id - assume it is junk */
465 total_banks = 1;
469 Sanity checks:
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)
491 bool ret = true;
492 int i;
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 */
499 BCLKCTR |= DEV_ECC;
500 ECC_BASE = (unsigned long)&NFC_WDATA;
501 ECC_CTRL |= ECC_M4EN;
502 ECC_CTRL &= ~ECC_ENC;
503 ECC_CTRL |= ECC_READY;
504 ECC_CLR = 0;
505 #endif
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++)
522 *ptr++ = NFC_WDATA;
525 memcpy(buf, temp_buf, SECTOR_SIZE);
527 else
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++)
534 *ptr++ = NFC_WDATA;
538 #ifdef USE_ECC_CORRECTION
539 /* Stop monitoring before we read the OOB data */
540 ECC_CTRL &= ~ECC_M4EN;
541 BCLKCTR &= ~DEV_ECC;
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 */
550 BCLKCTR |= DEV_ECC;
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;
561 switch (errors)
563 case 4: /* nothing to correct */
564 break;
566 case 7: /* fail, can't correct */
567 ret = false;
568 break;
570 default: /* between 1 and 4 errors */
572 int i;
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;
585 BCLKCTR &= ~DEV_ECC;
586 #endif
588 nand_end_read();
590 return ret;
594 static bool nand_read_sector_of_phys_segment(int bank, int phys_segment,
595 int page_in_seg, int sector,
596 void* buf)
598 int page_addr = phys_segment_to_page_addr(phys_segment,
599 page_in_seg);
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,
606 void* buf)
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. */
617 int cache_num = 0;
618 bool found = false;
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 */
627 found = true;
629 bank = write_caches[cache_num].random_bank;
630 phys_segment = write_caches[cache_num].random_phys_segment;
632 page_in_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 */
639 found = true;
641 bank = write_caches[cache_num].inplace_bank;
642 phys_segment = write_caches[cache_num].inplace_phys_segment;
645 cache_num++;
648 return nand_read_sector_of_phys_segment(bank, phys_segment,
649 page_in_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)
663 (void)phys_seg;
665 return ((spare_buf[OFF_LOG_SEG_HIBYTE] << 8) |
666 spare_buf[OFF_LOG_SEG_LOBYTE])
667 #if defined(FTL_V1)
668 + 984 * (phys_seg / 1024)
669 #endif
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)
681 int i;
683 for (i = 0; i < write_caches_in_use; i++)
684 if (write_caches[i].log_segment == log_segment)
685 return i;
687 return -1;
691 static void read_random_writes_cache(int bank, int phys_segment)
693 int page = 0;
694 short log_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 */
699 16, spare_buf);
701 log_segment = get_log_segment_id(phys_segment, spare_buf);
703 if (log_segment == -1)
704 return;
706 /* Find which cache this is related to */
707 int cache_no = find_write_cache(log_segment);
709 if (cache_no == -1)
711 if (write_caches_in_use < MAX_WRITE_CACHES)
713 cache_no = write_caches_in_use;
714 write_caches_in_use++;
716 else
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;
726 #ifndef FTL_V1
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. */
729 for (page = 1;
730 page < (nand_data->pages_per_block * nand_data->planes);
731 page++)
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 */
737 16, spare_buf);
739 cached_page = get_cached_page_id(spare_buf);
741 if (cached_page != 0xFFFF)
742 write_caches[cache_no].page_map[cached_page] = page;
744 #endif /* !FTL_V1 */
748 static void read_inplace_writes_cache(int bank, int phys_segment)
750 int page = 0;
751 short log_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 */
756 16, spare_buf);
758 log_segment = get_log_segment_id(phys_segment, spare_buf);
760 if (log_segment == -1)
761 return;
763 /* Find which cache this is related to */
764 int cache_no = find_write_cache(log_segment);
766 if (cache_no == -1)
768 if (write_caches_in_use < MAX_WRITE_CACHES)
770 cache_no = write_caches_in_use;
771 write_caches_in_use++;
773 else
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)
785 page++;
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);
792 if (page != 0)
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,
802 void* inbuf)
804 #ifdef HAVE_MULTIDRIVE
805 (void)drive; /* unused for now */
806 #endif
808 int ret = 0;
810 mutex_lock(&ata_mtx);
812 led(true);
814 while (incount > 0)
816 int done = 0;
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))
824 ret = -1;
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;
832 yield();
834 #endif
836 inbuf += SECTOR_SIZE;
837 incount--;
838 secmod++;
839 done++;
842 if (done < 0)
844 ret = -1;
845 goto nand_read_error;
847 start += done;
850 nand_read_error:
852 mutex_unlock(&ata_mtx);
853 led(false);
855 return ret;
858 int nand_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
859 const void* outbuf)
861 #ifdef HAVE_MULTIDRIVE
862 (void)drive; /* unused for now */
863 #endif
865 /* TODO: Learn more about TNFTL and implement this one day... */
866 (void)start;
867 (void)count;
868 (void)outbuf;
869 return -1;
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 */
878 #endif
880 /* firmware version */
881 info->revision="0.00";
883 info->vendor="Rockbox";
884 info->product="Internal Storage";
886 /* blocks count */
887 info->num_sectors = sectors_per_segment * segments_per_bank * total_banks;
888 info->sector_size = SECTOR_SIZE;
890 #endif
893 int nand_init(void)
895 int bank, phys_segment, lptbuf_size;
896 unsigned char spare_buf[16];
898 if (initialized) return 0;
900 mutex_init(&ata_mtx);
902 #ifdef CPU_TCC77X
903 CSCFG2 = 0x318a8010;
905 GPIOC_FUNC &= ~(CS_GPIO_BIT | WE_GPIO_BIT);
906 GPIOC_FUNC |= 0x1;
907 #endif
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();
915 #ifndef BOOTLOADER
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);
919 #else
920 /* Use a static array in the bootloader */
921 lptbuf_size = sizeof(lpt_lookup);
922 #endif
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 */
937 16, spare_buf);
939 int type = get_sector_type(spare_buf);
941 #ifdef FTL_V2
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;
956 #endif
958 switch (type)
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;
974 else
976 //panicf("duplicate data segment 0x%x!", log_segment);
979 break;
982 case SECTYPE_MAIN_RANDOM_CACHE:
984 /* Newly-written random page data (Main data area) */
985 read_random_writes_cache(bank, phys_segment);
986 break;
989 case SECTYPE_MAIN_INPLACE_CACHE:
991 /* Newly-written sequential page data (Main data area) */
992 read_inplace_writes_cache(bank, phys_segment);
993 break;
999 initialized = true;
1001 return 0;
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)
1019 (void)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 */
1027 (void)first_drive;
1029 return 1;
1032 void nand_sleepnow(void)
1036 bool nand_disk_is_active(void)
1038 return false;
1041 int nand_soft_reset(void)
1043 return 0;
1046 int nand_spinup_time(void)
1048 return 0;
1051 void nand_enable(bool onoff)
1053 (void)onoff;
1056 #endif /* CONFIG_STORAGE_MULTI */