diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/ata_mmc.c | 194 | ||||
-rw-r--r-- | firmware/export/ata_mmc.h | 42 |
2 files changed, 149 insertions, 87 deletions
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c index 7a187f092b..ea7c5f1737 100644 --- a/firmware/drivers/ata_mmc.c +++ b/firmware/drivers/ata_mmc.c | |||
@@ -18,6 +18,7 @@ | |||
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include <stdbool.h> | 19 | #include <stdbool.h> |
20 | #include "ata.h" | 20 | #include "ata.h" |
21 | #include "ata_mmc.h" | ||
21 | #include "kernel.h" | 22 | #include "kernel.h" |
22 | #include "thread.h" | 23 | #include "thread.h" |
23 | #include "led.h" | 24 | #include "led.h" |
@@ -106,22 +107,6 @@ static const unsigned char dummy[] = { | |||
106 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF | 107 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF |
107 | }; | 108 | }; |
108 | 109 | ||
109 | typedef struct | ||
110 | { | ||
111 | bool initialized; | ||
112 | unsigned char bitrate_register; | ||
113 | unsigned char rev; | ||
114 | unsigned char rev_fract; | ||
115 | unsigned int speed; /* bps */ | ||
116 | unsigned int read_timeout; /* n * 8 clock cycles */ | ||
117 | unsigned int write_timeout; /* n * 8 clock cycles */ | ||
118 | unsigned int size; /* in bytes */ | ||
119 | unsigned int manuf_month; | ||
120 | unsigned int manuf_year; | ||
121 | unsigned long serial_number; | ||
122 | unsigned char name[7]; | ||
123 | } tCardInfo; | ||
124 | |||
125 | static tCardInfo card_info[2]; | 110 | static tCardInfo card_info[2]; |
126 | 111 | ||
127 | /* private function declarations */ | 112 | /* private function declarations */ |
@@ -149,6 +134,8 @@ static int select_card(int card_no) | |||
149 | or_b(0x10, &PADRH); /* set clock gate PA12 CHECKME: mask? */ | 134 | or_b(0x10, &PADRH); /* set clock gate PA12 CHECKME: mask? */ |
150 | else /* external */ | 135 | else /* external */ |
151 | and_b(~0x10, &PADRH); /* clear clock gate PA12 CHECKME: mask?*/ | 136 | and_b(~0x10, &PADRH); /* clear clock gate PA12 CHECKME: mask?*/ |
137 | |||
138 | last_disk_activity = current_tick; | ||
152 | 139 | ||
153 | if (!card_info[card_no].initialized) | 140 | if (!card_info[card_no].initialized) |
154 | { | 141 | { |
@@ -177,6 +164,8 @@ static void deselect_card(void) | |||
177 | { | 164 | { |
178 | while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ | 165 | while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ |
179 | or_b(0x06, &PADRH); /* deassert CS (both cards) */ | 166 | or_b(0x06, &PADRH); /* deassert CS (both cards) */ |
167 | |||
168 | last_disk_activity = current_tick; | ||
180 | } | 169 | } |
181 | 170 | ||
182 | static void setup_sci1(int bitrate_register) | 171 | static void setup_sci1(int bitrate_register) |
@@ -235,8 +224,7 @@ static void read_transfer(unsigned char *buf, int len) | |||
235 | *buf = fliptable[(signed char)(RDR1)]; /* read & bitswap */ | 224 | *buf = fliptable[(signed char)(RDR1)]; /* read & bitswap */ |
236 | } | 225 | } |
237 | 226 | ||
238 | /* timeout is in bytes */ | 227 | static unsigned char poll_byte(int timeout) /* timeout is in bytes */ |
239 | static unsigned char poll_byte(int timeout) | ||
240 | { | 228 | { |
241 | int i; | 229 | int i; |
242 | unsigned char data = 0; /* stop the compiler complaining */ | 230 | unsigned char data = 0; /* stop the compiler complaining */ |
@@ -254,7 +242,7 @@ static unsigned char poll_byte(int timeout) | |||
254 | return fliptable[(signed char)data]; | 242 | return fliptable[(signed char)data]; |
255 | } | 243 | } |
256 | 244 | ||
257 | static unsigned char poll_busy(int timeout) | 245 | static unsigned char poll_busy(int timeout) /* timeout is in bytes */ |
258 | { | 246 | { |
259 | int i; | 247 | int i; |
260 | unsigned char data, dummy; | 248 | unsigned char data, dummy; |
@@ -362,101 +350,134 @@ static int send_data(char start_token, const unsigned char *buf, int len, | |||
362 | return ret; | 350 | return ret; |
363 | } | 351 | } |
364 | 352 | ||
353 | /* helper function to extract n (<=32) bits from an arbitrary position. | ||
354 | counting from MSB to LSB */ | ||
355 | unsigned long mmc_extract_bits( | ||
356 | const unsigned long *p, /* the start of the bitfield array */ | ||
357 | unsigned int start, /* bit no. to start reading */ | ||
358 | unsigned int size) /* how many bits to read */ | ||
359 | { | ||
360 | unsigned int bit_index; | ||
361 | unsigned int bits_to_use; | ||
362 | unsigned long mask; | ||
363 | unsigned long result; | ||
364 | |||
365 | if (size == 1) | ||
366 | { /* short cut */ | ||
367 | return ((p[start/32] >> (31 - (start % 32))) & 1); | ||
368 | } | ||
369 | |||
370 | result = 0; | ||
371 | while (size) | ||
372 | { | ||
373 | bit_index = start % 32; | ||
374 | bits_to_use = MIN(32 - bit_index, size); | ||
375 | mask = 0xFFFFFFFF >> (32 - bits_to_use); | ||
376 | |||
377 | result <<= bits_to_use; /* start last round */ | ||
378 | result |= (p[start/32] >> (32 - bits_to_use - bit_index)) & mask; | ||
379 | |||
380 | start += bits_to_use; | ||
381 | size -= bits_to_use; | ||
382 | } | ||
383 | |||
384 | return result; | ||
385 | } | ||
386 | |||
365 | static int initialize_card(int card_no) | 387 | static int initialize_card(int card_no) |
366 | { | 388 | { |
367 | int i, temp; | 389 | int i, temp; |
368 | unsigned char response; | 390 | unsigned char response[5]; |
369 | unsigned char cxd[16]; | ||
370 | tCardInfo *card = &card_info[card_no]; | 391 | tCardInfo *card = &card_info[card_no]; |
371 | 392 | ||
372 | static const char mantissa[] = { /* *10 */ | 393 | static const char mantissa[] = { /* *10 */ |
373 | 0, 10, 12, 13, 15, 20, 25, 30, | 394 | 0, 10, 12, 13, 15, 20, 25, 30, |
374 | 35, 40, 45, 50, 55, 60, 70, 80 | 395 | 35, 40, 45, 50, 55, 60, 70, 80 |
375 | }; | 396 | }; |
376 | static const int speed_exponent[] = { /* /10 */ | 397 | static const int exponent[] = { /* use varies */ |
377 | 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 | 398 | 1, 10, 100, 1000, 10000, 100000, 1000000, |
378 | }; | 399 | 10000000, 100000000, 1000000000 |
379 | |||
380 | static const int time_exponent[] = { /* reciprocal */ | ||
381 | 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100 | ||
382 | }; | 400 | }; |
383 | 401 | ||
384 | /* switch to SPI mode */ | 402 | /* switch to SPI mode */ |
385 | send_cmd(CMD_GO_IDLE_STATE, 0, &response); | 403 | send_cmd(CMD_GO_IDLE_STATE, 0, response); |
386 | if (response != 0x01) | 404 | if (response[0] != 0x01) |
387 | return -1; /* error response */ | 405 | return -1; /* error response */ |
388 | 406 | ||
389 | /* initialize card */ | 407 | /* initialize card */ |
390 | i = 0; | 408 | i = 0; |
391 | while (send_cmd(CMD_SEND_OP_COND, 0, &response) && (++i < 200)); | 409 | while (send_cmd(CMD_SEND_OP_COND, 0, response) && (++i < 200)); |
392 | if (response != 0x00) | 410 | if (response[0] != 0x00) |
393 | return -2; /* not ready */ | 411 | return -2; /* not ready */ |
394 | 412 | ||
395 | /* get CSD register */ | 413 | /* get OCR register */ |
396 | if (send_cmd(CMD_SEND_CSD, 0, &response)) | 414 | if (send_cmd(CMD_READ_OCR, 0, response)) |
397 | return -3; | 415 | return -3; |
398 | if (receive_data(cxd, 16, 50)) | 416 | card->ocr = (response[1] << 24) + (response[2] << 16) |
399 | return -4; | 417 | + (response[3] << 8) + response[4]; |
400 | 418 | ||
401 | /* check block size */ | 419 | /* check voltage */ |
402 | if (1 << (cxd[5] & 0x0F) != SECTOR_SIZE) | 420 | if (!(card->ocr & 0x00100000)) /* 3.2 .. 3.3 V */ |
421 | return -4; | ||
422 | |||
423 | /* get CSD register */ | ||
424 | if (send_cmd(CMD_SEND_CSD, 0, response)) | ||
403 | return -5; | 425 | return -5; |
426 | if (receive_data((unsigned char*)card->csd, 16, 20)) | ||
427 | return -6; | ||
404 | 428 | ||
405 | /* max transmission speed the card is capable of */ | 429 | /* check block size */ |
406 | card->speed = mantissa[(cxd[3] & 0x78) >> 3] | 430 | if ((1 << mmc_extract_bits(card->csd, 44, 4)) != SECTOR_SIZE) |
407 | * speed_exponent[(cxd[3] & 0x07)]; | 431 | return -7; |
408 | 432 | ||
409 | /* calculate the clock divider */ | 433 | /* max transmission speed, clock divider */ |
434 | temp = mmc_extract_bits(card->csd, 29, 3); | ||
435 | temp = (temp > 3) ? 3 : temp; | ||
436 | card->speed = mantissa[mmc_extract_bits(card->csd, 25, 4)] | ||
437 | * exponent[temp + 4]; | ||
410 | card->bitrate_register = (FREQ/4-1) / card->speed; | 438 | card->bitrate_register = (FREQ/4-1) / card->speed; |
411 | 439 | ||
412 | /* calculate read timeout in clock cycles from TSAC, NSAC and the actual | 440 | /* NSAC, TSAC, read timeout */ |
413 | * clock frequency */ | 441 | card->nsac = 100 * mmc_extract_bits(card->csd, 16, 8); |
414 | temp = (FREQ/4) / (card->bitrate_register + 1); /* actual frequency */ | 442 | card->tsac = mantissa[mmc_extract_bits(card->csd, 9, 4)]; |
415 | card->read_timeout = | 443 | temp = mmc_extract_bits(card->csd, 13, 3); |
416 | (temp * mantissa[(cxd[1] & 0x78) >> 3] + (1000 * cxd[2])) | 444 | card->read_timeout = ((FREQ/4) / (card->bitrate_register + 1) |
417 | / (time_exponent[cxd[1] & 0x07] * 8); | 445 | * card->tsac / exponent[9 - temp] |
418 | 446 | + (10 * card->nsac)); | |
419 | /* calculate write timeout */ | 447 | card->read_timeout /= 8; /* clocks -> bytes */ |
420 | temp = (cxd[12] & 0x1C) >> 2; | 448 | card->tsac *= exponent[temp]; |
421 | if (temp > 5) | 449 | |
422 | temp = 5; | 450 | /* r2w_factor, write timeout */ |
423 | card->write_timeout = card->read_timeout * (1 << temp); | 451 | temp = mmc_extract_bits(card->csd, 99, 3); |
424 | 452 | temp = (temp > 5) ? 5 : temp; | |
425 | /* calculate size */ | 453 | card->r2w_factor = 1 << temp; |
426 | card->size = ((unsigned int)(cxd[6] & 0x03) << 10) | 454 | card->write_timeout = card->read_timeout * card->r2w_factor; |
427 | + ((unsigned int)cxd[7] << 2) | ||
428 | + ((unsigned int)(cxd[8] & 0xC0) >> 6); | ||
429 | temp = ((cxd[9] & 0x03) << 1) + ((cxd[10] & 0x80) >> 7) + 2; | ||
430 | card->size *= (SECTOR_SIZE << temp); | ||
431 | 455 | ||
432 | /* switch to full speed */ | 456 | /* switch to full speed */ |
433 | setup_sci1(card->bitrate_register); | 457 | setup_sci1(card->bitrate_register); |
434 | 458 | ||
435 | /* get CID register */ | 459 | /* get CID register */ |
436 | if (send_cmd(CMD_SEND_CID, 0, &response)) | 460 | if (send_cmd(CMD_SEND_CID, 0, response)) |
437 | return -6; | 461 | return -8; |
438 | if (receive_data(cxd, 16, 50)) | 462 | if (receive_data((unsigned char*)card->cid, 16, 20)) |
439 | return -7; | 463 | return -9; |
440 | |||
441 | /* get data from CID */ | ||
442 | strncpy(card->name, &cxd[3], 6); | ||
443 | card->name[6] = '\0'; | ||
444 | |||
445 | card->rev = (cxd[9] & 0xF0) >> 4; | ||
446 | card->rev_fract = cxd[9] & 0x0F; | ||
447 | |||
448 | card->manuf_month = (cxd[14] & 0xF0) >> 4; | ||
449 | card->manuf_year = (cxd[14] & 0x0F) + 1997; | ||
450 | |||
451 | card->serial_number = ((unsigned long)cxd[10] << 24) | ||
452 | + ((unsigned long)cxd[11] << 16) | ||
453 | + ((unsigned long)cxd[12] << 8) | ||
454 | + (unsigned long)cxd[13]; | ||
455 | 464 | ||
456 | card->initialized = true; | 465 | card->initialized = true; |
457 | return 0; | 466 | return 0; |
458 | } | 467 | } |
459 | 468 | ||
469 | tCardInfo *mmc_card_info(int card_no) | ||
470 | { | ||
471 | tCardInfo *card = &card_info[card_no]; | ||
472 | |||
473 | if (!card->initialized) | ||
474 | { | ||
475 | select_card(card_no); | ||
476 | deselect_card(); | ||
477 | } | ||
478 | return card; | ||
479 | } | ||
480 | |||
460 | int ata_read_sectors(unsigned long start, | 481 | int ata_read_sectors(unsigned long start, |
461 | int incount, | 482 | int incount, |
462 | void* inbuf) | 483 | void* inbuf) |
@@ -467,9 +488,6 @@ int ata_read_sectors(unsigned long start, | |||
467 | unsigned char response; | 488 | unsigned char response; |
468 | tCardInfo *card = &card_info[current_card]; | 489 | tCardInfo *card = &card_info[current_card]; |
469 | 490 | ||
470 | if (incount <= 0) | ||
471 | return ret; | ||
472 | |||
473 | addr = start * SECTOR_SIZE; | 491 | addr = start * SECTOR_SIZE; |
474 | 492 | ||
475 | mutex_lock(&mmc_mutex); | 493 | mutex_lock(&mmc_mutex); |
@@ -482,6 +500,7 @@ int ata_read_sectors(unsigned long start, | |||
482 | ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response); | 500 | ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response); |
483 | if (ret == 0) | 501 | if (ret == 0) |
484 | ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout); | 502 | ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout); |
503 | last_disk_activity = current_tick; | ||
485 | } | 504 | } |
486 | else | 505 | else |
487 | { | 506 | { |
@@ -490,6 +509,7 @@ int ata_read_sectors(unsigned long start, | |||
490 | { | 509 | { |
491 | ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout); | 510 | ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout); |
492 | inbuf += SECTOR_SIZE; | 511 | inbuf += SECTOR_SIZE; |
512 | last_disk_activity = current_tick; | ||
493 | } | 513 | } |
494 | if (ret == 0) | 514 | if (ret == 0) |
495 | ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response); | 515 | ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response); |
@@ -519,9 +539,6 @@ int ata_write_sectors(unsigned long start, | |||
519 | if (start == 0) | 539 | if (start == 0) |
520 | panicf("Writing on sector 0\n"); | 540 | panicf("Writing on sector 0\n"); |
521 | 541 | ||
522 | if (count <= 0) | ||
523 | return ret; | ||
524 | |||
525 | addr = start * SECTOR_SIZE; | 542 | addr = start * SECTOR_SIZE; |
526 | 543 | ||
527 | mutex_lock(&mmc_mutex); | 544 | mutex_lock(&mmc_mutex); |
@@ -535,6 +552,7 @@ int ata_write_sectors(unsigned long start, | |||
535 | if (ret == 0) | 552 | if (ret == 0) |
536 | ret = send_data(DT_START_BLOCK, buf, SECTOR_SIZE, | 553 | ret = send_data(DT_START_BLOCK, buf, SECTOR_SIZE, |
537 | card->write_timeout); | 554 | card->write_timeout); |
555 | last_disk_activity = current_tick; | ||
538 | } | 556 | } |
539 | else | 557 | else |
540 | { | 558 | { |
@@ -544,12 +562,14 @@ int ata_write_sectors(unsigned long start, | |||
544 | ret = send_data(DT_START_WRITE_MULTIPLE, buf, SECTOR_SIZE, | 562 | ret = send_data(DT_START_WRITE_MULTIPLE, buf, SECTOR_SIZE, |
545 | card->write_timeout); | 563 | card->write_timeout); |
546 | buf += SECTOR_SIZE; | 564 | buf += SECTOR_SIZE; |
565 | last_disk_activity = current_tick; | ||
547 | } | 566 | } |
548 | if (ret == 0) | 567 | if (ret == 0) |
549 | { | 568 | { |
550 | response = DT_STOP_TRAN; | 569 | response = DT_STOP_TRAN; |
551 | write_transfer(&response, 1); | 570 | write_transfer(&response, 1); |
552 | poll_busy(card->write_timeout); | 571 | poll_busy(card->write_timeout); |
572 | last_disk_activity = current_tick; | ||
553 | } | 573 | } |
554 | } | 574 | } |
555 | } | 575 | } |
diff --git a/firmware/export/ata_mmc.h b/firmware/export/ata_mmc.h new file mode 100644 index 0000000000..afc0dc24af --- /dev/null +++ b/firmware/export/ata_mmc.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2004 by Jens Arnold | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef __ATA_MMC_H__ | ||
20 | #define __ATA_MMC_H__ | ||
21 | |||
22 | typedef struct | ||
23 | { | ||
24 | bool initialized; | ||
25 | unsigned char bitrate_register; | ||
26 | unsigned int read_timeout; /* n * 8 clock cycles */ | ||
27 | unsigned int write_timeout; /* n * 8 clock cycles */ | ||
28 | |||
29 | unsigned long ocr; /* OCR register */ | ||
30 | unsigned long csd[4]; /* CSD register, 16 bytes */ | ||
31 | unsigned long cid[4]; /* CID register, 16 bytes */ | ||
32 | unsigned int speed; /* bit/s */ | ||
33 | unsigned int nsac; /* clock cycles */ | ||
34 | unsigned int tsac; /* n * 0.1 ns */ | ||
35 | unsigned int r2w_factor; | ||
36 | } tCardInfo; | ||
37 | |||
38 | unsigned long mmc_extract_bits(const unsigned long *p, unsigned int start, | ||
39 | unsigned int size); | ||
40 | tCardInfo *mmc_card_info(int card_no); | ||
41 | |||
42 | #endif | ||