summaryrefslogtreecommitdiff
path: root/firmware/drivers/ata_flash.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/ata_flash.c')
-rw-r--r--firmware/drivers/ata_flash.c484
1 files changed, 0 insertions, 484 deletions
diff --git a/firmware/drivers/ata_flash.c b/firmware/drivers/ata_flash.c
deleted file mode 100644
index fbdd7f04ee..0000000000
--- a/firmware/drivers/ata_flash.c
+++ /dev/null
@@ -1,484 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Tomasz Malesinski
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "storage.h"
23#include <stdbool.h>
24#include <string.h>
25
26#if CONFIG_CPU == PNX0101
27#include "pnx0101.h"
28#endif
29
30/*
31#include "kernel.h"
32#include "thread.h"
33#include "led.h"
34#include "cpu.h"
35#include "system.h"
36#include "debug.h"
37#include "panic.h"
38#include "usb.h"
39#include "power.h"
40#include "string.h"
41*/
42
43#define SECTOR_SIZE (512)
44
45static long last_disk_activity = -1;
46
47#if CONFIG_FLASH == FLASH_IFP7XX
48static unsigned char flash_ce[4] = {0x20, 0x02, 0x10, 0x08};
49
50#define FLASH_IO_BASE 0x28000000
51#define FLASH_REG_DATA (*((volatile unsigned char*)(FLASH_IO_BASE)))
52#define FLASH_REG_CMD (*((volatile unsigned char*)(FLASH_IO_BASE + 4)))
53#define FLASH_REG_ADDR (*((volatile unsigned char*)(FLASH_IO_BASE + 8)))
54
55#define SEGMENT_SIZE 1000
56#define MAX_N_SEGMENTS 8
57
58#endif
59
60#define FLASH_MODEL_NONE 0
61#define FLASH_MODEL_256 1
62#define FLASH_MODEL_512 2
63
64struct flash_disk
65{
66 unsigned short block_map[MAX_N_SEGMENTS][SEGMENT_SIZE];
67 short cur_block;
68 int cur_phblock_start;
69 int n_chips;
70 unsigned char chip_no[4];
71 unsigned char model;
72};
73
74static struct flash_disk flash_disk;
75
76static void flash_select_chip(int no, int sel)
77{
78#if CONFIG_FLASH == FLASH_IFP7XX
79 if (sel)
80 GPIO5_CLR = flash_ce[no];
81 else
82 GPIO5_SET = flash_ce[no];
83#endif
84}
85
86static inline unsigned char flash_read_data(void)
87{
88 return FLASH_REG_DATA;
89}
90
91static inline void flash_write_data(unsigned char data)
92{
93 FLASH_REG_DATA = data;
94}
95
96/* TODO: these two doesn't work when inlined, probably some
97 delay is required */
98
99static void flash_write_cmd(unsigned char cmd)
100{
101 FLASH_REG_CMD = cmd;
102}
103
104static void flash_write_addr(unsigned char addr)
105{
106 FLASH_REG_ADDR = addr;
107}
108
109static void flash_wait_ready(void)
110{
111 int i;
112 for (i = 0; i < 5; i++)
113 while ((GPIO6_READ & 8) == 0);
114}
115
116static unsigned char model_n_sectors_order[] = {0, 19, 20};
117
118static int flash_map_sector(int sector, int* chip, int* chip_sector)
119{
120 int ord, c;
121 if (flash_disk.model == FLASH_MODEL_NONE)
122 return -1;
123
124 ord = model_n_sectors_order[flash_disk.model];
125 c = sector >> ord;
126 *chip_sector = sector & ((1 << ord) - 1);
127
128 if (c >= flash_disk.n_chips)
129 return -1;
130
131 *chip = flash_disk.chip_no[c];
132 return 0;
133}
134
135static int flash_read_id(int no) {
136 int id;
137
138 flash_select_chip(no, 1);
139 flash_write_cmd(0x90);
140 flash_write_addr(0);
141
142 flash_read_data();
143 id = flash_read_data();
144
145 flash_select_chip(no, 0);
146 return id;
147}
148
149static int flash_read_sector(int sector, unsigned char* buf,
150 unsigned char* oob)
151{
152 unsigned long *bufl = (unsigned long *)buf;
153 int chip, chip_sector;
154 int i;
155
156 if (flash_map_sector(sector, &chip, &chip_sector) < 0)
157 return -1;
158
159 flash_select_chip(chip, 1);
160
161 flash_write_cmd(0x00);
162 flash_write_addr(0);
163 flash_write_addr((chip_sector << 1) & 7);
164 flash_write_addr((chip_sector >> 2) & 0xff);
165 flash_write_addr((chip_sector >> 10) & 0xff);
166 flash_write_addr((chip_sector >> 18) & 0xff);
167 flash_write_cmd(0x30);
168
169 flash_wait_ready();
170
171 if ((unsigned long)buf & 3)
172 {
173 for (i = 0; i < 512; i++)
174 buf[i] = flash_read_data();
175 }
176 else
177 {
178 for (i = 0; i < 512 / 4; i++) {
179 unsigned long v;
180#ifdef ROCKBOX_LITTLE_ENDIAN
181 v = flash_read_data();
182 v |= (unsigned long)flash_read_data() << 8;
183 v |= (unsigned long)flash_read_data() << 16;
184 v |= (unsigned long)flash_read_data() << 24;
185#else
186 v = (unsigned long)flash_read_data() << 24;
187 v |= (unsigned long)flash_read_data() << 16;
188 v |= (unsigned long)flash_read_data() << 8;
189 v |= flash_read_data();
190#endif
191 bufl[i] = v;
192 }
193 }
194
195 flash_write_cmd(0x05);
196 flash_write_addr((chip_sector & 3) * 0x10);
197 flash_write_addr(8);
198 flash_write_cmd(0xe0);
199
200 for (i = 0; i < 16; i++)
201 oob[i] = flash_read_data();
202
203 flash_select_chip(chip, 0);
204 return 0;
205}
206
207static int flash_read_sector_oob(int sector, unsigned char* oob)
208{
209 int chip, chip_sector;
210 int i;
211
212 if (flash_map_sector(sector, &chip, &chip_sector) < 0)
213 return -1;
214
215 flash_select_chip(chip, 1);
216
217 flash_write_cmd(0x00);
218 flash_write_addr((chip_sector & 3) * 0x10);
219 flash_write_addr(8);
220 flash_write_addr((chip_sector >> 2) & 0xff);
221 flash_write_addr((chip_sector >> 10) & 0xff);
222 flash_write_addr((chip_sector >> 18) & 0xff);
223 flash_write_cmd(0x30);
224
225 flash_wait_ready();
226
227 for (i = 0; i < 16; i++)
228 oob[i] = flash_read_data();
229
230 flash_select_chip(chip, 0);
231 return 0;
232}
233
234static unsigned char model_n_segments[] = {0, 2, 4};
235
236static inline int flash_get_n_segments(void)
237{
238 return model_n_segments[flash_disk.model] * flash_disk.n_chips;
239}
240
241static inline int flash_get_n_phblocks(void)
242{
243 return 1024;
244}
245
246static int model_n_sectors_in_block[] = {0, 256, 256};
247
248static int flash_get_n_sectors_in_block(void)
249{
250 return model_n_sectors_in_block[flash_disk.model];
251}
252
253static int flash_phblock_to_sector(int segment, int block)
254{
255 return (segment * flash_get_n_phblocks() + block)
256 * flash_get_n_sectors_in_block();
257}
258
259static int flash_is_bad_block(unsigned char* oob)
260{
261 /* TODO: should we check two pages? (see datasheet) */
262 return oob[0] != 0xff;
263}
264
265static int count_1(int n) {
266 int r = 0;
267 while (n != 0) {
268 r += (n & 1);
269 n >>= 1;
270 }
271 return r;
272}
273
274static int flash_get_logical_block_no(unsigned char* oob)
275{
276 int no1, no2;
277 no1 = oob[6] + (oob[7] << 8);
278 no2 = oob[11] + (oob[12] << 8);
279
280 if (no1 == no2 && (no1 & 0xf000) == 0x1000)
281 return (no1 & 0xfff) >> 1;
282
283 if (count_1(no1 ^ no2) > 1)
284 return -1;
285
286 if ((no1 & 0xf000) == 0x1000
287 && (count_1(no1) & 1) == 0)
288 return (no1 & 0xfff) >> 1;
289
290 if ((no2 & 0xf000) == 0x1000
291 && (count_1(no2) & 1) == 0)
292 return (no2 & 0xfff) >> 1;
293
294 return -1;
295}
296
297static int flash_disk_scan(void)
298{
299 int n_segments, n_phblocks;
300 unsigned char oob[16];
301 int s, b;
302
303 /* TODO: checking for double blocks */
304
305 n_segments = flash_get_n_segments();
306 n_phblocks = flash_get_n_phblocks();
307
308 flash_disk.cur_block = -1;
309 flash_disk.cur_phblock_start = -1;
310
311 for (s = 0; s < n_segments; s++)
312 {
313 for (b = 0; b < n_phblocks; b++)
314 {
315 int r;
316 r = flash_read_sector_oob(flash_phblock_to_sector(s, b),
317 oob);
318 if (r >= 0 && !flash_is_bad_block(oob))
319 {
320 int lb;
321 lb = flash_get_logical_block_no(oob);
322 if (lb >= 0 && lb < SEGMENT_SIZE)
323 flash_disk.block_map[s][lb] = b;
324 }
325 }
326 }
327 return 0;
328}
329
330static int flash_disk_find_block(int block)
331{
332 int seg, bmod, phb;
333 unsigned char oob[16];
334 int r;
335
336 if (block >= SEGMENT_SIZE * flash_get_n_segments())
337 return -1;
338
339 if (block == flash_disk.cur_block)
340 return flash_disk.cur_phblock_start;
341
342 seg = block / SEGMENT_SIZE;
343 bmod = block % SEGMENT_SIZE;
344
345 phb = flash_disk.block_map[seg][bmod];
346 r = flash_read_sector_oob(flash_phblock_to_sector(seg, phb), oob);
347 if (r < 0)
348 return -1;
349 if (flash_is_bad_block(oob))
350 return -1;
351 if (flash_get_logical_block_no(oob) != bmod)
352 return -1;
353
354 flash_disk.cur_block = block;
355 flash_disk.cur_phblock_start = flash_phblock_to_sector(seg, phb);
356 return flash_disk.cur_phblock_start;
357}
358
359static int flash_disk_read_sectors(unsigned long start,
360 int count,
361 void* buf)
362{
363 int block, secmod, done;
364 int phb;
365 char oob[16];
366
367 block = start / flash_get_n_sectors_in_block();
368 secmod = start % flash_get_n_sectors_in_block();
369
370 phb = flash_disk_find_block(block);
371 done = 0;
372 while (count > 0 && secmod < flash_get_n_sectors_in_block())
373 {
374 if (phb >= 0)
375 flash_read_sector(phb + secmod, buf, oob);
376 else
377 memset(buf, 0, SECTOR_SIZE);
378
379 buf += SECTOR_SIZE;
380 count--;
381 secmod++;
382 done++;
383 }
384 return done;
385}
386
387int nand_read_sectors(IF_MD(int drive,)
388 unsigned long start,
389 int incount,
390 void* inbuf)
391{
392 while (incount > 0)
393 {
394 int done = flash_disk_read_sectors(start, incount, inbuf);
395 if (done < 0)
396 return -1;
397 start += done;
398 incount -= done;
399 inbuf += SECTOR_SIZE * done;
400 }
401 return 0;
402}
403
404int nand_write_sectors(IF_MD(int drive,)
405 unsigned long start,
406 int count,
407 const void* buf)
408{
409 (void)start;
410 (void)count;
411 (void)buf;
412 return -1;
413}
414
415int nand_init(void)
416{
417 int i, id, id2;
418
419 id = flash_read_id(0);
420 switch (id)
421 {
422 case 0xda:
423 flash_disk.model = FLASH_MODEL_256;
424 break;
425 case 0xdc:
426 flash_disk.model = FLASH_MODEL_512;
427 break;
428 default:
429 flash_disk.model = FLASH_MODEL_NONE;
430 return -1;
431 }
432
433 flash_disk.n_chips = 1;
434 flash_disk.chip_no[0] = 0;
435 for (i = 1; i < 4; i++)
436 {
437 id2 = flash_read_id(i);
438 if (id2 == id)
439 flash_disk.chip_no[flash_disk.n_chips++] = i;
440 }
441
442 if (flash_disk_scan() < 0)
443 return -2;
444
445 return 0;
446}
447
448long nand_last_disk_activity(void)
449{
450 return last_disk_activity;
451}
452
453#ifdef STORAGE_GET_INFO
454void nand_get_info(struct storage_info *info)
455{
456 unsigned long blocks;
457 int i;
458
459 /* firmware version */
460 info->revision="0.00";
461
462 /* vendor field, need better name? */
463 info->vendor="Rockbox";
464 /* model field, need better name? */
465 info->product="TNFL";
466
467 /* blocks count */
468 info->num_sectors = 0;
469 info->sector_size=SECTOR_SIZE;
470
471 info->serial=0;
472}
473#endif
474
475#ifdef CONFIG_STORAGE_MULTI
476int nand_num_drives(int first_drive)
477{
478 /* We don't care which logical drive number(s) we have been assigned */
479 (void)first_drive;
480
481 return 1;
482}
483#endif
484