diff --git a/firmware/export/hotswap.h b/firmware/export/hotswap.h index 6872ca8..bdc3cd5 100644 --- a/firmware/export/hotswap.h +++ b/firmware/export/hotswap.h @@ -33,6 +33,11 @@ typedef struct unsigned long ocr; /* OCR register */ unsigned long csd[4]; /* CSD register, 16 bytes */ unsigned long cid[4]; /* CID register, 16 bytes */ +#if (CONFIG_STORAGE & STORAGE_SD) + unsigned long rca; /* RCA register, 4 bytes */ + unsigned char current_bank; +#endif + unsigned long speed; /* bit/s */ unsigned int nsac; /* clock cycles */ unsigned long tsac; /* n * 0.1 ns */ diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c index 488988d..7aee302 100644 --- a/firmware/target/arm/as3525/ata_sd_as3525.c +++ b/firmware/target/arm/as3525/ata_sd_as3525.c @@ -96,7 +96,10 @@ static void init_pl180_controller(const int drive); #define SECTOR_SIZE 512 #define BLOCKS_PER_BANK 0x7a7800 -static tSDCardInfo card_info[NUM_VOLUMES]; +#define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ +#define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ + +static tCardInfo card_info[NUM_VOLUMES]; /* for compatibility */ static long last_disk_activity = -1; @@ -145,12 +148,20 @@ void INT_GPIOA(void) #endif /* defined(SANSA_E200V2) || defined(SANSA_FUZE) */ #endif /* HAVE_HOTSWAP */ +#include "lcd.h" void INT_NAND(void) { const int status = MCI_STATUS(INTERNAL_AS3525); if(status & MCI_ERROR) + { + char buf[50]; + static int x = 0; + snprintf(buf, sizeof(buf), "%d 0x%x",++x, status&MCI_ERROR); + lcd_puts(0,0,buf); + lcd_update(); retry = true; + } wakeup_signal(&transfer_completion_signal); MCI_CLEAR(INTERNAL_AS3525) = status; @@ -170,7 +181,7 @@ void INT_MCI0(void) #endif static bool send_cmd(const int drive, const int cmd, const int arg, - const int flags, int *response) + const int flags, unsigned long *response) { int val, status; @@ -230,11 +241,18 @@ static bool send_cmd(const int drive, const int cmd, const int arg, static int sd_init_card(const int drive) { + tCardInfo* card = &card_info[drive]; unsigned int c_size; unsigned long c_mult; - int response; + unsigned long response; + int temp; int max_tries = 100; /* max acmd41 attemps */ bool sdhc; + static const char mantissa[] = { /* *10 */ + 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; + static const int exponent[] = { /* use varies */ + 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000 }; + if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_FLAGS, NULL)) return -1; @@ -262,66 +280,83 @@ static int sd_init_card(const int drive) /* acmd41 */ if(!send_cmd(drive, SD_APP_OP_COND, (sdhc ? 0x40FF8000 : (1<<23)), - MCI_RESP|MCI_ARG, &card_info[drive].ocr)) + MCI_RESP|MCI_ARG, &card->ocr)) return -3; - } while(!(card_info[drive].ocr & (1<<31)) && max_tries--); + } while(!(card->ocr & (1<<31)) && max_tries--); if(max_tries < 0) return -4; /* send CID */ if(!send_cmd(drive, SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP|MCI_ARG, - card_info[drive].cid)) + card->cid)) return -5; + /* ascii chars here */ + card->cid[0] = htobe32(card->cid[0]); + card->cid[1] = htobe32(card->cid[1]); + /* adjust year<=>month, 1997 <=> 2000 */ + temp = *((char*)card->cid+13); + *((char*)card->cid+13) = + (unsigned char)((temp >> 4) | (temp << 4)) + 3; + /* send RCA */ if(!send_cmd(drive, SD_SEND_RELATIVE_ADDR, 0, MCI_RESP|MCI_ARG, - &card_info[drive].rca)) + &card->rca)) return -6; /* send CSD */ - if(!send_cmd(drive, SD_SEND_CSD, card_info[drive].rca, - MCI_RESP|MCI_LONG_RESP|MCI_ARG, card_info[drive].csd)) + if(!send_cmd(drive, SD_SEND_CSD, card->rca, + MCI_RESP|MCI_LONG_RESP|MCI_ARG, card->csd)) return -7; /* These calculations come from the Sandisk SD card product manual */ - if( (card_info[drive].csd[3]>>30) == 0) + if( (card->csd[3]>>30) == 0) { + unsigned int max_read_bl_len; /* CSD version 1.0 */ - c_size = ((card_info[drive].csd[2] & 0x3ff) << 2) + (card_info[drive].csd[1]>>30) + 1; - c_mult = 4 << ((card_info[drive].csd[1] >> 15) & 7); - card_info[drive].max_read_bl_len = 1 << ((card_info[drive].csd[2] >> 16) & 15); - card_info[drive].block_size = BLOCK_SIZE; /* Always use 512 byte blocks */ - card_info[drive].numblocks = c_size * c_mult * (card_info[drive].max_read_bl_len/512); - card_info[drive].capacity = card_info[drive].numblocks * card_info[drive].block_size; + c_size = ((card->csd[2] & 0x3ff) << 2) + (card->csd[1]>>30) + 1; + c_mult = 4 << ((card->csd[1] >> 15) & 7); + max_read_bl_len = 1 << ((card->csd[2] >> 16) & 15); + card->blocksize = BLOCK_SIZE; /* Always use 512 byte blocks */ + card->numblocks = c_size * c_mult * (max_read_bl_len/512); } #ifdef HAVE_MULTIVOLUME - else if( (card_info[drive].csd[3]>>30) == 1) + else if( (card->csd[3]>>30) == 1) { /* CSD version 2.0 */ - c_size = ((card_info[drive].csd[2] & 0x3f) << 16) + (card_info[drive].csd[1]>>16) + 1; - card_info[drive].max_read_bl_len = 1 << ((card_info[drive].csd[2] >> 16) & 0xf); - card_info[drive].block_size = BLOCK_SIZE; /* Always use 512 byte blocks */ - card_info[drive].numblocks = c_size << 10; - card_info[drive].capacity = card_info[drive].numblocks * card_info[drive].block_size; + c_size = ((card->csd[2] & 0x3f) << 16) + (card->csd[1]>>16) + 1; + card->blocksize = BLOCK_SIZE; /* Always use 512 byte blocks */ + card->numblocks = c_size << 10; } #endif - if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_ARG, NULL)) + card->r2w_factor = (card->csd[0] >> 26) & 7; + + temp = card_extract_bits(card->csd, 29, 3); + card->speed = mantissa[card_extract_bits(card->csd, 25, 4)] + * exponent[temp > 2 ? 7 : temp + 4]; + + card->nsac = 100 * ((card->csd[3] >> 8) & 0xff); + + card->tsac = mantissa[(card->csd[3] >> 19) & 0xf] + * exponent[(card->csd[3] >> 16) & 0x7] / 10; + + if(!send_cmd(drive, SD_SELECT_CARD, card->rca, MCI_ARG, NULL)) return -9; - if(!send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MCI_ARG, NULL)) + if(!send_cmd(drive, SD_APP_CMD, card->rca, MCI_ARG, NULL)) return -10; - if(!send_cmd(drive, SD_SET_BUS_WIDTH, card_info[drive].rca | 2, MCI_ARG, NULL)) + if(!send_cmd(drive, SD_SET_BUS_WIDTH, card->rca | 2, MCI_ARG, NULL)) return -11; - if(!send_cmd(drive, SD_SET_BLOCKLEN, card_info[drive].block_size, MCI_ARG, + if(!send_cmd(drive, SD_SET_BLOCKLEN, card->blocksize, MCI_ARG, NULL)) return -12; - card_info[drive].initialized = 1; + card->initialized = 1; MCI_CLOCK(drive) |= MCI_CLOCK_BYPASS; /* full speed for controller clock */ mci_delay(); @@ -507,7 +542,7 @@ void sd_get_info(IF_MV2(int drive,) struct storage_info *info) #ifndef HAVE_MULTIVOLUME const int drive=0; #endif - info->sector_size=card_info[drive].block_size; + info->sector_size=card_info[drive].blocksize; info->num_sectors=card_info[drive].numblocks; info->vendor="Rockbox"; info->product = (drive == 0) ? "Internal Storage" : "SD Card Slot"; @@ -535,7 +570,7 @@ bool sd_present(IF_MV_NONVOID(int drive)) static int sd_wait_for_state(const int drive, unsigned int state) { - unsigned int response = 0; + unsigned long response = 0; unsigned int timeout = 100; /* ticks */ long t = current_tick; @@ -595,7 +630,7 @@ static int sd_select_bank(signed char bank) dma_enable_channel(0, card_data, MCI_FIFO(INTERNAL_AS3525), DMA_PERI_SD, DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL); - MCI_DATA_TIMER(INTERNAL_AS3525) = 0xffffffff;/* FIXME: arbitrary */ + MCI_DATA_TIMER(INTERNAL_AS3525) = SD_MAX_WRITE_TIMEOUT; MCI_DATA_LENGTH(INTERNAL_AS3525) = 512; MCI_DATA_CTRL(INTERNAL_AS3525) = (1<<0) /* enable */ | (0<<1) /* transfer direction */ | @@ -718,8 +753,9 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start, (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT, DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL); - MCI_DATA_TIMER(drive) = 0x1000000; /* FIXME: arbitrary */ - MCI_DATA_LENGTH(drive) = transfer * card_info[drive].block_size; + MCI_DATA_TIMER(drive) = write ? + SD_MAX_WRITE_TIMEOUT : SD_MAX_READ_TIMEOUT; + MCI_DATA_LENGTH(drive) = transfer * card_info[drive].blocksize; MCI_DATA_CTRL(drive) = (1<<0) /* enable */ | (!write<<1) /* transfer direction */ | (1<<3) /* DMA */ | @@ -840,35 +876,9 @@ void sd_enable(bool on) } } -/* move the sd-card info to mmc struct */ tCardInfo *card_get_info_target(int card_no) { - int i, temp; - static tCardInfo card; - static const char mantissa[] = { /* *10 */ - 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; - static const int exponent[] = { /* use varies */ - 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000 }; - - card.initialized = card_info[card_no].initialized; - card.ocr = card_info[card_no].ocr; - for(i=0; i<4; i++) card.csd[i] = card_info[card_no].csd[i]; - for(i=0; i<4; i++) card.cid[i] = card_info[card_no].cid[i]; - card.numblocks = card_info[card_no].numblocks; - card.blocksize = card_info[card_no].block_size; - temp = card_extract_bits(card.csd, 29, 3); - card.speed = mantissa[card_extract_bits(card.csd, 25, 4)] - * exponent[temp > 2 ? 7 : temp + 4]; - card.nsac = 100 * card_extract_bits(card.csd, 16, 8); - temp = card_extract_bits(card.csd, 13, 3); - card.tsac = mantissa[card_extract_bits(card.csd, 9, 4)] - * exponent[temp] / 10; - card.cid[0] = htobe32(card.cid[0]); /* ascii chars here */ - card.cid[1] = htobe32(card.cid[1]); /* ascii chars here */ - temp = *((char*)card.cid+13); /* adjust year<=>month, 1997 <=> 2000 */ - *((char*)card.cid+13) = (unsigned char)((temp >> 4) | (temp << 4)) + 3; - - return &card; + return &card_info[card_no]; } bool card_detect_target(void) diff --git a/firmware/target/arm/as3525/clock-target.h b/firmware/target/arm/as3525/clock-target.h index 560e067..a82fabc 100644 --- a/firmware/target/arm/as3525/clock-target.h +++ b/firmware/target/arm/as3525/clock-target.h @@ -79,8 +79,9 @@ #define AS3525_FCLK_FREQ 248000000 /* Boosted FCLK frequency */ #define AS3525_DRAM_FREQ 62000000 /* Initial DRAM frequency */ /* AS3525_PCLK_FREQ != AS3525_DRAM_FREQ/1 will boot to white lcd screen */ -#define AS3525_PCLK_FREQ AS3525_DRAM_FREQ/1 /* PCLK divided from DRAM freq */ -#define AS3525_DBOP_FREQ AS3525_PCLK_FREQ/1 /* DBOP divided from PCLK freq */ +#define AS3525_PCLK_FREQ AS3525_DRAM_FREQ/1 /* PCLK divided from DRAM freq */ +#define AS3525_PCLK_FREQ_US (AS3525_PCLK_FREQ/1000000) /* PCLK cycles each µs */ +#define AS3525_DBOP_FREQ (AS3525_PCLK_FREQ/1) /* DBOP divided from PCLK freq */ /** ****************************************************************************/ diff --git a/firmware/target/arm/ata-sd-target.h b/firmware/target/arm/ata-sd-target.h index b2ac6e2..3a2265d 100644 --- a/firmware/target/arm/ata-sd-target.h +++ b/firmware/target/arm/ata-sd-target.h @@ -24,23 +24,6 @@ #include "inttypes.h" #include "hotswap.h" -typedef struct -{ - int initialized; - - unsigned int ocr; /* OCR register */ - unsigned int csd[4]; /* CSD register */ - unsigned int cid[4]; /* CID register */ - unsigned int rca; - - uint64_t capacity; /* size in bytes */ - unsigned long numblocks; /* size in flash blocks */ - unsigned int block_size; /* block size in bytes */ - unsigned int max_read_bl_len;/* max read data block length */ - unsigned int block_exp; /* block size exponent */ - unsigned char current_bank; /* The bank that we are working with */ -} tSDCardInfo; - tCardInfo *card_get_info_target(int card_no); bool card_detect_target(void);