Trim down peak calculation a bit.
[kugel-rb.git] / firmware / drivers / ata_flash.c
blob2d31b413ac7b93b2d134e173bcfef5d08286bbc5
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Tomasz Malesinski
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 ****************************************************************************/
22 #include "storage.h"
23 #include <stdbool.h>
24 #include <string.h>
26 #if CONFIG_CPU == PNX0101
27 #include "pnx0101.h"
28 #endif
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"
43 #define SECTOR_SIZE (512)
45 long last_disk_activity = -1;
47 #if CONFIG_FLASH == FLASH_IFP7XX
48 static unsigned char flash_ce[4] = {0x20, 0x02, 0x10, 0x08};
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)))
55 #define SEGMENT_SIZE 1000
56 #define MAX_N_SEGMENTS 8
58 #endif
60 #define FLASH_MODEL_NONE 0
61 #define FLASH_MODEL_256 1
62 #define FLASH_MODEL_512 2
64 struct flash_disk
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;
74 static struct flash_disk flash_disk;
76 void flash_select_chip(int no, int sel)
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
86 static inline unsigned char flash_read_data(void)
88 return FLASH_REG_DATA;
91 static inline void flash_write_data(unsigned char data)
93 FLASH_REG_DATA = data;
96 /* TODO: these two doesn't work when inlined, probably some
97 delay is required */
99 static void flash_write_cmd(unsigned char cmd)
101 FLASH_REG_CMD = cmd;
104 static void flash_write_addr(unsigned char addr)
106 FLASH_REG_ADDR = addr;
109 static void flash_wait_ready(void)
111 int i;
112 for (i = 0; i < 5; i++)
113 while ((GPIO6_READ & 8) == 0);
116 static unsigned char model_n_sectors_order[] = {0, 19, 20};
118 int flash_map_sector(int sector, int* chip, int* chip_sector)
120 int ord, c;
121 if (flash_disk.model == FLASH_MODEL_NONE)
122 return -1;
124 ord = model_n_sectors_order[flash_disk.model];
125 c = sector >> ord;
126 *chip_sector = sector & ((1 << ord) - 1);
128 if (c >= flash_disk.n_chips)
129 return -1;
131 *chip = flash_disk.chip_no[c];
132 return 0;
135 int flash_read_id(int no) {
136 int id;
138 flash_select_chip(no, 1);
139 flash_write_cmd(0x90);
140 flash_write_addr(0);
142 flash_read_data();
143 id = flash_read_data();
145 flash_select_chip(no, 0);
146 return id;
149 int flash_read_sector(int sector, unsigned char* buf,
150 unsigned char* oob)
152 unsigned long *bufl = (unsigned long *)buf;
153 int chip, chip_sector;
154 int i;
156 if (flash_map_sector(sector, &chip, &chip_sector) < 0)
157 return -1;
159 flash_select_chip(chip, 1);
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);
169 flash_wait_ready();
171 if ((unsigned long)buf & 3)
173 for (i = 0; i < 512; i++)
174 buf[i] = flash_read_data();
176 else
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;
195 flash_write_cmd(0x05);
196 flash_write_addr((chip_sector & 3) * 0x10);
197 flash_write_addr(8);
198 flash_write_cmd(0xe0);
200 for (i = 0; i < 16; i++)
201 oob[i] = flash_read_data();
203 flash_select_chip(chip, 0);
204 return 0;
207 int flash_read_sector_oob(int sector, unsigned char* oob)
209 int chip, chip_sector;
210 int i;
212 if (flash_map_sector(sector, &chip, &chip_sector) < 0)
213 return -1;
215 flash_select_chip(chip, 1);
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);
225 flash_wait_ready();
227 for (i = 0; i < 16; i++)
228 oob[i] = flash_read_data();
230 flash_select_chip(chip, 0);
231 return 0;
234 static unsigned char model_n_segments[] = {0, 2, 4};
236 static inline int flash_get_n_segments(void)
238 return model_n_segments[flash_disk.model] * flash_disk.n_chips;
241 static inline int flash_get_n_phblocks(void)
243 return 1024;
246 static int model_n_sectors_in_block[] = {0, 256, 256};
248 static int flash_get_n_sectors_in_block(void)
250 return model_n_sectors_in_block[flash_disk.model];
253 static int flash_phblock_to_sector(int segment, int block)
255 return (segment * flash_get_n_phblocks() + block)
256 * flash_get_n_sectors_in_block();
259 static int flash_is_bad_block(unsigned char* oob)
261 /* TODO: should we check two pages? (see datasheet) */
262 return oob[0] != 0xff;
265 static int count_1(int n) {
266 int r = 0;
267 while (n != 0) {
268 r += (n & 1);
269 n >>= 1;
271 return r;
274 static int flash_get_logical_block_no(unsigned char* oob)
276 int no1, no2;
277 no1 = oob[6] + (oob[7] << 8);
278 no2 = oob[11] + (oob[12] << 8);
280 if (no1 == no2 && (no1 & 0xf000) == 0x1000)
281 return (no1 & 0xfff) >> 1;
283 if (count_1(no1 ^ no2) > 1)
284 return -1;
286 if ((no1 & 0xf000) == 0x1000
287 && (count_1(no1) & 1) == 0)
288 return (no1 & 0xfff) >> 1;
290 if ((no2 & 0xf000) == 0x1000
291 && (count_1(no2) & 1) == 0)
292 return (no2 & 0xfff) >> 1;
294 return -1;
297 int flash_disk_scan(void)
299 int n_segments, n_phblocks;
300 unsigned char oob[16];
301 int s, b;
303 /* TODO: checking for double blocks */
305 n_segments = flash_get_n_segments();
306 n_phblocks = flash_get_n_phblocks();
308 flash_disk.cur_block = -1;
309 flash_disk.cur_phblock_start = -1;
311 for (s = 0; s < n_segments; s++)
313 for (b = 0; b < n_phblocks; b++)
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))
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;
327 return 0;
330 int flash_disk_find_block(int block)
332 int seg, bmod, phb;
333 unsigned char oob[16];
334 int r;
336 if (block >= SEGMENT_SIZE * flash_get_n_segments())
337 return -1;
339 if (block == flash_disk.cur_block)
340 return flash_disk.cur_phblock_start;
342 seg = block / SEGMENT_SIZE;
343 bmod = block % SEGMENT_SIZE;
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;
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;
359 int flash_disk_read_sectors(unsigned long start,
360 int count,
361 void* buf)
363 int block, secmod, done;
364 int phb;
365 char oob[16];
367 block = start / flash_get_n_sectors_in_block();
368 secmod = start % flash_get_n_sectors_in_block();
370 phb = flash_disk_find_block(block);
371 done = 0;
372 while (count > 0 && secmod < flash_get_n_sectors_in_block())
374 if (phb >= 0)
375 flash_read_sector(phb + secmod, buf, oob);
376 else
377 memset(buf, 0, SECTOR_SIZE);
379 buf += SECTOR_SIZE;
380 count--;
381 secmod++;
382 done++;
384 return done;
387 int nand_read_sectors(IF_MD2(int drive,)
388 unsigned long start,
389 int incount,
390 void* inbuf)
392 while (incount > 0)
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;
401 return 0;
404 int nand_write_sectors(IF_MD2(int drive,)
405 unsigned long start,
406 int count,
407 const void* buf)
409 (void)start;
410 (void)count;
411 (void)buf;
412 return -1;
415 int nand_init(void)
417 int i, id, id2;
419 id = flash_read_id(0);
420 switch (id)
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;
433 flash_disk.n_chips = 1;
434 flash_disk.chip_no[0] = 0;
435 for (i = 1; i < 4; i++)
437 id2 = flash_read_id(i);
438 if (id2 == id)
439 flash_disk.chip_no[flash_disk.n_chips++] = i;
442 if (flash_disk_scan() < 0)
443 return -2;
445 return 0;
448 long nand_last_disk_activity(void)
450 return last_disk_activity;
453 #ifdef STORAGE_GET_INFO
454 void nand_get_info(struct storage_info *info)
456 unsigned long blocks;
457 int i;
459 /* firmware version */
460 info->revision="0.00";
462 /* vendor field, need better name? */
463 info->vendor="Rockbox";
464 /* model field, need better name? */
465 info->product="TNFL";
467 /* blocks count */
468 info->num_sectors = 0;
469 info->sector_size=SECTOR_SIZE;
471 info->serial=0;
473 #endif
475 #ifdef CONFIG_STORAGE_MULTI
476 int nand_num_drives(int first_drive)
478 /* We don't care which logical drive number(s) we have been assigned */
479 (void)first_drive;
481 return 1;
483 #endif