summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Purchase <shotofadds@rockbox.org>2008-01-25 21:37:59 +0000
committerRob Purchase <shotofadds@rockbox.org>2008-01-25 21:37:59 +0000
commit59914786289033648db9bd5f4222978767e4d665 (patch)
treec8fad961c9c20a8799d9821e3240099b9375323b
parentb4f80fb93fe290d4498a9f1eecd2f15f0c19abf8 (diff)
downloadrockbox-59914786289033648db9bd5f4222978767e4d665.tar.gz
rockbox-59914786289033648db9bd5f4222978767e4d665.zip
Read ID codes & raw page data from D2 NAND flash (work in progress;
no logical->physical address translation yet) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16167 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--bootloader/telechips.c4
-rw-r--r--firmware/export/tcc780x.h28
-rw-r--r--firmware/target/arm/tcc780x/ata-nand-tcc780x.c343
3 files changed, 365 insertions, 10 deletions
diff --git a/bootloader/telechips.c b/bootloader/telechips.c
index a51b6775a1..f5669d0bbf 100644
--- a/bootloader/telechips.c
+++ b/bootloader/telechips.c
@@ -68,6 +68,10 @@ void* main(void)
68 68
69 _backlight_on(); 69 _backlight_on();
70 70
71#if defined(COWON_D2)
72 ata_init();
73#endif
74
71 while(!do_power_off) { 75 while(!do_power_off) {
72 line = 0; 76 line = 0;
73 printf("Hello World!"); 77 printf("Hello World!");
diff --git a/firmware/export/tcc780x.h b/firmware/export/tcc780x.h
index df55c6f03d..78211acf0a 100644
--- a/firmware/export/tcc780x.h
+++ b/firmware/export/tcc780x.h
@@ -85,6 +85,22 @@
85#define CKSEL_PLL1 1 85#define CKSEL_PLL1 1
86#define CKSEL_XIN 4 86#define CKSEL_XIN 4
87 87
88/* Device bits for SWRESET & BCLKCTR */
89
90#define DEV_LCDC (1<<2)
91#define DEV_SDMMC (1<<6)
92#define DEV_NAND (1<<9)
93#define DEV_DAI (1<<14)
94#define DEV_ECC (1<<16)
95#define DEV_RTC (1<<21)
96#define DEV_SDRAM (1<<22)
97#define DEV_COP (1<<23)
98#define DEV_ADC (1<<24)
99#define DEV_TIMER (1<<26)
100#define DEV_CPU (1<<27)
101#define DEV_IRQ (1<<28)
102#define DEV_MAIN (1<<31)
103
88/* IRQ Controller */ 104/* IRQ Controller */
89 105
90#define IEN (*(volatile unsigned long *)0xF3001000) 106#define IEN (*(volatile unsigned long *)0xF3001000)
@@ -111,12 +127,12 @@
111#define TREF1 (*(volatile unsigned long *)0xF3003018) 127#define TREF1 (*(volatile unsigned long *)0xF3003018)
112 128
113#define TIREQ (*(volatile unsigned long *)0xF3003060) 129#define TIREQ (*(volatile unsigned long *)0xF3003060)
114/* ref. value reached */ 130
115#define TF0 (1<<8) 131/* TIREQ flags */
116#define TF1 (1<<9) 132#define TF0 (1<<8) /* Timer 0 reference value reached */
117/* irq. status */ 133#define TF1 (1<<9) /* Timer 1 reference value reached */
118#define TI0 (1<<0) 134#define TI0 (1<<0) /* Timer 0 IRQ flag */
119#define TI1 (1<<1) 135#define TI1 (1<<1) /* Timer 1 IRQ flag */
120 136
121#define TC32EN (*(volatile unsigned long *)0xF3003080) 137#define TC32EN (*(volatile unsigned long *)0xF3003080)
122#define TC32LDV (*(volatile unsigned long *)0xF3003084) 138#define TC32LDV (*(volatile unsigned long *)0xF3003084)
diff --git a/firmware/target/arm/tcc780x/ata-nand-tcc780x.c b/firmware/target/arm/tcc780x/ata-nand-tcc780x.c
index 5aed090d5c..813172f590 100644
--- a/firmware/target/arm/tcc780x/ata-nand-tcc780x.c
+++ b/firmware/target/arm/tcc780x/ata-nand-tcc780x.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2007 Dave Chapman 10 * Copyright (C) 2008 Rob Purchase
11 * 11 *
12 * All files in this archive are subject to the GNU General Public License. 12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement. 13 * See the file COPYING in the source tree root for full license agreement.
@@ -32,12 +32,335 @@ int ata_spinup_time = 0;
32 32
33long last_disk_activity = -1; 33long last_disk_activity = -1;
34 34
35/** static, private data **/ 35/** static, private data **/
36static bool initialized = false; 36static bool initialized = false;
37 37
38static long next_yield = 0; 38static long next_yield = 0;
39#define MIN_YIELD_PERIOD 2000 39#define MIN_YIELD_PERIOD 2000
40 40
41
42/* TCC780x NAND Flash Controller */
43
44#define NFC_CMD (*(volatile unsigned long *)0xF0053000)
45#define NFC_SADDR (*(volatile unsigned long *)0xF005300C)
46#define NFC_SDATA (*(volatile unsigned long *)0xF0053040)
47#define NFC_WDATA (*(volatile unsigned long *)0xF0053010)
48#define NFC_CTRL (*(volatile unsigned long *)0xF0053050)
49#define NFC_IREQ (*(volatile unsigned long *)0xF0053060)
50#define NFC_RST (*(volatile unsigned long *)0xF0053064)
51
52#define NFC_16BIT (1<<26)
53#define NFC_CS0 (1<<23)
54#define NFC_CS1 (1<<22)
55#define NFC_READY (1<<20)
56
57
58#if defined(COWON_D2)
59/*
60 ===== Temporary D2 testing code =====
61
62 (assumes SAMSUNG K9LAG08UOM (2GB) in 1, 2 or 4 banks)
63
64 Manufacturer Id: {0xec, 0xd5, 0x55, 0x25, 0x68}
65
66*/
67#define PAGE_SIZE 2048
68#define SPARE_SIZE 64
69#define PAGES_PER_BLOCK 128
70#define TOTAL_BLOCKS 8192
71#define TOTAL_PAGES (TOTAL_BLOCKS * PAGES_PER_BLOCK)
72#define COL_CYCLES 2
73#define ROW_CYCLES 3
74
75static int page_buf[PAGE_SIZE/4];
76
77static void nand_chip_select(int chip)
78{
79 if (chip == -1)
80 {
81 /* Disable both chip selects */
82 GPIOB_CLEAR = (1<<21);
83 NFC_CTRL |= NFC_CS0 | NFC_CS1;
84 }
85 else
86 {
87 /* NFC chip select */
88 if (chip & 1)
89 {
90 NFC_CTRL &= ~NFC_CS0;
91 NFC_CTRL |= NFC_CS1;
92 }
93 else
94 {
95 NFC_CTRL |= NFC_CS0;
96 NFC_CTRL &= ~NFC_CS1;
97 }
98
99 /* Secondary chip select */
100 if (chip & 2)
101 {
102 GPIOB_SET = (1<<21);
103 }
104 else
105 {
106 GPIOB_CLEAR = (1<<21);
107 }
108 }
109}
110
111static void nand_read_id(int chip, unsigned char* id_buf)
112{
113 int i;
114
115 /* Enable NFC bus clock */
116 BCLKCTR |= DEV_NAND;
117
118 /* Reset NAND controller */
119 NFC_RST = 0;
120
121 /* Set slow cycle timings since the chip is as yet unidentified */
122 NFC_CTRL = (NFC_CTRL &~0xFFF) | 0x353;
123
124 nand_chip_select(chip);
125
126 /* Set write protect */
127 GPIOB_CLEAR = (1<<19);
128
129 /* Reset command */
130 NFC_CMD = 0xFF;
131
132 /* Set 8-bit data width */
133 NFC_CTRL &= ~NFC_16BIT;
134
135 /* Read ID command, single address cycle */
136 NFC_CMD = 0x90;
137 NFC_SADDR = 0x00;
138
139 /* Read the 5 single bytes */
140 id_buf[0] = NFC_SDATA & 0xFF;
141 id_buf[1] = NFC_SDATA & 0xFF;
142 id_buf[2] = NFC_SDATA & 0xFF;
143 id_buf[3] = NFC_SDATA & 0xFF;
144 id_buf[4] = NFC_SDATA & 0xFF;
145
146 nand_chip_select(-1);
147
148 /* Disable NFC bus clock */
149 BCLKCTR &= ~DEV_NAND;
150}
151
152
153static void nand_read_uid(int chip)
154{
155 int i;
156
157 /* Enable NFC bus clock */
158 BCLKCTR |= DEV_NAND;
159
160 /* Set cycle timing (stp = 1, pw = 3, hold = 1) */
161 NFC_CTRL = (NFC_CTRL &~0xFFF) | 0x131;
162
163 nand_chip_select(chip);
164
165 /* Set write protect */
166 GPIOB_CLEAR = 1<<19;
167
168 /* Set 8-bit data width */
169 NFC_CTRL &= ~NFC_16BIT;
170
171 /* Undocumented (SAMSUNG specific?) commands set the chip into a
172 special mode allowing a normally-hidden UID block to be read. */
173 NFC_CMD = 0x30;
174 NFC_CMD = 0x65;
175
176 /* Read command */
177 NFC_CMD = 0x00;
178
179 /* Write row/column address */
180 for (i = 0; i < COL_CYCLES; i++) NFC_SADDR = 0;
181 for (i = 0; i < ROW_CYCLES; i++) NFC_SADDR = 0;
182
183 /* End of read */
184 NFC_CMD = 0x30;
185
186 /* Wait until complete */
187 while (!(NFC_CTRL & NFC_READY)) {};
188
189 /* Copy data to buffer (data repeats after 8 words) */
190 for (i = 0; i < 8; i++)
191 {
192 page_buf[i] = NFC_WDATA;
193 }
194
195 /* Reset the chip back to normal mode */
196 NFC_CMD = 0xFF;
197
198 nand_chip_select(-1);
199
200 /* Disable NFC bus clock */
201 BCLKCTR &= ~DEV_NAND;
202}
203
204
205/* NB: size must be divisible by 4 due to 32-bit read */
206static void nand_read(int chip, int row, int column, int size)
207{
208 int i;
209
210 /* Enable NFC bus clock */
211 BCLKCTR |= DEV_NAND;
212
213 /* Set cycle timing (stp = 1, pw = 3, hold = 1) */
214 NFC_CTRL = (NFC_CTRL &~0xFFF) | 0x131;
215
216 nand_chip_select(chip);
217
218 /* Set write protect */
219 GPIOB_CLEAR = (1<<19);
220
221 /* Set 8-bit data width */
222 NFC_CTRL &= ~NFC_16BIT;
223
224 /* Read command */
225 NFC_CMD = 0x00;
226
227 /* Write column address */
228 for (i = 0; i < COL_CYCLES; i++)
229 {
230 NFC_SADDR = column & 0xFF;
231 column = column >> 8;
232 }
233
234 /* Write row address */
235 for (i = 0; i < ROW_CYCLES; i++)
236 {
237 NFC_SADDR = row & 0xFF;
238 row = row >> 8;
239 }
240
241 /* End of read command */
242 NFC_CMD = 0x30;
243
244 /* Wait until complete */
245 while (!(NFC_CTRL & NFC_READY)) {};
246
247 /* Read data into page buffer */
248 for (i = 0; i < (size/4); i++)
249 {
250 page_buf[i] = NFC_WDATA;
251 }
252
253 nand_chip_select(-1);
254
255 /* Disable NFC bus clock */
256 BCLKCTR &= ~DEV_NAND;
257}
258
259
260/* TEMP testing function */
261#include <string.h>
262#include "lcd.h"
263
264extern int line;
265
266static void nand_test(void)
267{
268 int i,j,row;
269 unsigned char id_buf[5];
270 unsigned char str_buf[PAGE_SIZE];
271
272 /* Display ID codes & UID block for each bank */
273 for (i = 0; i < 4; i++)
274 {
275 printf("NAND bank %d:", i);
276
277 nand_read_id(i, id_buf);
278
279 printf("ID: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
280 id_buf[0],id_buf[1],id_buf[2],id_buf[3],id_buf[4]);
281
282 nand_read_uid(i);
283
284 for (j = 0; j < 8; j += 4)
285 {
286 printf("0x%08x 0x%08x 0x%08x 0x%08x",
287 page_buf[j],page_buf[j+1],page_buf[j+2],page_buf[j+3]);
288 }
289
290 line++;
291 }
292
293 while (!button_read_device()) {};
294
295 /* Now for fun, scan the raw pages for 'TAG' and display the contents */
296
297 row = 0;
298 while (row < TOTAL_PAGES)
299 {
300 bool found = false;
301 unsigned char* buf_ptr = (unsigned char*)page_buf;
302
303 line = 0;
304
305 /* Read a page from chip 0 */
306 nand_read(0, row, 0, PAGE_SIZE);
307
308 if (row % 512 == 0) printf("%dMb", row/512);
309
310 for (j = 0; j < PAGE_SIZE; j++)
311 {
312 if (buf_ptr[j] == 'T' && buf_ptr[j+1] == 'A' && buf_ptr[j+2] == 'G')
313 found = true;
314 }
315
316 if (found)
317 {
318 unsigned char* str_ptr = str_buf;
319
320 printf("Row %d:", row);
321
322 /* Copy ascii-readable parts out to a string */
323 for (i = 0; i < PAGE_SIZE; i++)
324 {
325 str_buf[i] = ' ';
326 if (buf_ptr[i] > 31 && buf_ptr[i] < 128)
327 {
328 *str_ptr++ = buf_ptr[i];
329 }
330 }
331
332 str_ptr = str_buf;
333
334 /* Nasty piece of code to display the text in a readable manner */
335 for (i = 1; i < 30; i++)
336 {
337 for (j = 0; j < 48; j++)
338 {
339 /* In the absence of a putc() we have this mess... */
340 unsigned char buf2[2];
341 buf2[0] = *str_ptr++;
342 buf2[1] = '\0';
343 lcd_puts(j,i,buf2);
344 }
345 }
346
347 /* Alternate hex display code
348 for (i = 0; i<112; i+=4)
349 {
350 printf("0x%08x 0x%08x 0x%08x 0x%08x",buf[i],buf[i+1],buf[i+2],buf[i+3]);
351 }
352 */
353
354 while (!button_read_device()) {};
355
356 lcd_clear_display();
357 }
358 row++;
359 }
360}
361#endif
362
363
41/* API Functions */ 364/* API Functions */
42 365
43void ata_led(bool onoff) 366void ata_led(bool onoff)
@@ -67,7 +390,7 @@ int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count,
67 390
68void ata_spindown(int seconds) 391void ata_spindown(int seconds)
69{ 392{
70 #warning function not implemented 393 /* null */
71 (void)seconds; 394 (void)seconds;
72} 395}
73 396
@@ -84,7 +407,7 @@ void ata_sleep(void)
84 407
85void ata_spin(void) 408void ata_spin(void)
86{ 409{
87 #warning function not implemented 410 /* null */
88} 411}
89 412
90/* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */ 413/* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */
@@ -109,5 +432,17 @@ void ata_enable(bool on)
109int ata_init(void) 432int ata_init(void)
110{ 433{
111 #warning function not implemented 434 #warning function not implemented
435
436 /* This needs to:
437 a) establish how many banks are present
438 (using nand_read_id() and nand_read_uid() above)
439 b) scan all banks for bad blocks
440 c) use this info to build a physical->logical address translation
441 (using an as yet unknown scheme)
442 */
443
444 /* TEMP - print out some diagnostics */
445 nand_test();
446
112 return 0; 447 return 0;
113} 448}