summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2004-10-06 20:43:12 +0000
committerJens Arnold <amiconn@rockbox.org>2004-10-06 20:43:12 +0000
commit6f9a7eb2c7d6f81e54b47c917be79f5126ba8982 (patch)
tree22dc11305494ed12060699821641813f6246b84a /firmware/drivers
parent30c1358f87c68d5bc78178bb3af9e8e3b8c660e6 (diff)
downloadrockbox-6f9a7eb2c7d6f81e54b47c917be79f5126ba8982.tar.gz
rockbox-6f9a7eb2c7d6f81e54b47c917be79f5126ba8982.zip
Enhanced MMC handling: Driver cleanup, timeout calculation fixed, allowed voltage check, maintain disk activity info (fixes immediate shutdown at end of playback). MMC debug menu item populated.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5193 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/ata_mmc.c194
1 files changed, 107 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
109typedef 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
125static tCardInfo card_info[2]; 110static 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
182static void setup_sci1(int bitrate_register) 171static 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 */ 227static unsigned char poll_byte(int timeout) /* timeout is in bytes */
239static 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
257static unsigned char poll_busy(int timeout) 245static 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 */
355unsigned 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
365static int initialize_card(int card_no) 387static 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
469tCardInfo *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
460int ata_read_sectors(unsigned long start, 481int 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 }