hm60x/hm801: Buttons rework.
[maemo-rb.git] / firmware / target / arm / ata-nand-telechips.c
blob2ae425f4c6763bbd8fc667b58512527d538a2f8b
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"
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)
51 #define FTL_V2
52 #define MAX_WRITE_CACHES 8
53 #else
54 #define FTL_V1
55 #define MAX_WRITE_CACHES 4
56 #endif
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
71 #ifdef FTL_V1
72 #define SECTYPE_FIRMWARE 0x40
73 #else
74 #define SECTYPE_FIRMWARE 0xE0
75 #endif
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
83 #ifdef FTL_V2
84 #define OFF_LOG_SEG_LOBYTE 7
85 #define OFF_LOG_SEG_HIBYTE 6
86 #else
87 #define OFF_LOG_SEG_LOBYTE 6
88 #define OFF_LOG_SEG_HIBYTE 7
89 #endif
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
109 #define MAX_BANKS 4
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 */
116 struct lpt_entry
118 short bank;
119 short phys_segment;
121 #ifdef BOOTLOADER
122 static struct lpt_entry lpt_lookup[MAX_SEGMENTS];
123 #else
124 /* core_alloc()'d in nand_init() when the correct size has been determined */
125 #include "core_alloc.h"
126 static int lpt_handle;
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 #ifndef BOOTLOADER
611 struct lpt_entry* lpt_lookup = core_get_data(lpt_handle);
612 #endif
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. */
619 int cache_num = 0;
620 bool found = false;
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 */
629 found = true;
631 bank = write_caches[cache_num].random_bank;
632 phys_segment = write_caches[cache_num].random_phys_segment;
634 page_in_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 */
641 found = true;
643 bank = write_caches[cache_num].inplace_bank;
644 phys_segment = write_caches[cache_num].inplace_phys_segment;
647 cache_num++;
650 return nand_read_sector_of_phys_segment(bank, phys_segment,
651 page_in_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)
665 (void)phys_seg;
667 return ((spare_buf[OFF_LOG_SEG_HIBYTE] << 8) |
668 spare_buf[OFF_LOG_SEG_LOBYTE])
669 #if defined(FTL_V1)
670 + 984 * (phys_seg / 1024)
671 #endif
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)
683 int i;
685 for (i = 0; i < write_caches_in_use; i++)
686 if (write_caches[i].log_segment == log_segment)
687 return i;
689 return -1;
693 static void read_random_writes_cache(int bank, int phys_segment)
695 int page = 0;
696 short log_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 */
701 16, spare_buf);
703 log_segment = get_log_segment_id(phys_segment, spare_buf);
705 if (log_segment == -1)
706 return;
708 /* Find which cache this is related to */
709 int cache_no = find_write_cache(log_segment);
711 if (cache_no == -1)
713 if (write_caches_in_use < MAX_WRITE_CACHES)
715 cache_no = write_caches_in_use;
716 write_caches_in_use++;
718 else
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;
728 #ifndef FTL_V1
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. */
731 for (page = 1;
732 page < (nand_data->pages_per_block * nand_data->planes);
733 page++)
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 */
739 16, spare_buf);
741 cached_page = get_cached_page_id(spare_buf);
743 if (cached_page != 0xFFFF)
744 write_caches[cache_no].page_map[cached_page] = page;
746 #endif /* !FTL_V1 */
750 static void read_inplace_writes_cache(int bank, int phys_segment)
752 int page = 0;
753 short log_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 */
758 16, spare_buf);
760 log_segment = get_log_segment_id(phys_segment, spare_buf);
762 if (log_segment == -1)
763 return;
765 /* Find which cache this is related to */
766 int cache_no = find_write_cache(log_segment);
768 if (cache_no == -1)
770 if (write_caches_in_use < MAX_WRITE_CACHES)
772 cache_no = write_caches_in_use;
773 write_caches_in_use++;
775 else
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)
787 page++;
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);
794 if (page != 0)
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,
804 void* inbuf)
806 #ifdef HAVE_MULTIDRIVE
807 (void)drive; /* unused for now */
808 #endif
810 int ret = 0;
812 mutex_lock(&ata_mtx);
814 led(true);
816 while (incount > 0)
818 int done = 0;
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))
826 ret = -1;
827 goto nand_read_error;
830 if (TIME_AFTER(USEC_TIMER, next_yield))
832 next_yield = USEC_TIMER + MIN_YIELD_PERIOD;
833 yield();
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;
872 #ifdef HAVE_STORAGE_FLUSH
873 int nand_flush(void)
875 return 0;
877 #endif
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 */
884 #endif
886 /* firmware version */
887 info->revision="0.00";
889 info->vendor="Rockbox";
890 info->product="Internal Storage";
892 /* blocks count */
893 info->num_sectors = sectors_per_segment * segments_per_bank * total_banks;
894 info->sector_size = SECTOR_SIZE;
896 #endif
899 int nand_init(void)
901 int bank, phys_segment, lptbuf_size;
902 unsigned char spare_buf[16];
904 if (initialized) return 0;
906 mutex_init(&ata_mtx);
908 #ifdef CPU_TCC77X
909 CSCFG2 = 0x018a8010 | tcc77x_cscfg_bw(TCC77X_CSCFG_BW8);
911 GPIOC_FUNC &= ~(CS_GPIO_BIT | WE_GPIO_BIT);
912 GPIOC_FUNC |= 0x1;
913 #endif
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();
921 #ifndef BOOTLOADER
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);
926 #else
927 /* Use a static array in the bootloader */
928 lptbuf_size = sizeof(lpt_lookup);
929 #endif
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 */
944 16, spare_buf);
946 int type = get_sector_type(spare_buf);
948 #ifdef FTL_V2
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;
963 #endif
965 switch (type)
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)
975 #ifndef BOOTLOADER
976 lpt_lookup = core_get_data(lpt_handle);
977 #endif
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;
984 else
986 //panicf("duplicate data segment 0x%x!", log_segment);
989 break;
992 case SECTYPE_MAIN_RANDOM_CACHE:
994 /* Newly-written random page data (Main data area) */
995 read_random_writes_cache(bank, phys_segment);
996 break;
999 case SECTYPE_MAIN_INPLACE_CACHE:
1001 /* Newly-written sequential page data (Main data area) */
1002 read_inplace_writes_cache(bank, phys_segment);
1003 break;
1009 initialized = true;
1011 return 0;
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)
1029 (void)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 */
1037 (void)first_drive;
1039 return 1;
1042 void nand_sleepnow(void)
1046 bool nand_disk_is_active(void)
1048 return false;
1051 int nand_soft_reset(void)
1053 return 0;
1056 int nand_spinup_time(void)
1058 return 0;
1061 void nand_enable(bool onoff)
1063 (void)onoff;
1066 #endif /* CONFIG_STORAGE_MULTI */