diff options
Diffstat (limited to 'firmware/target/arm/as3525')
-rw-r--r-- | firmware/target/arm/as3525/ata_sd_as3525.c | 256 |
1 files changed, 145 insertions, 111 deletions
diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c index 9405832595..bc2866219a 100644 --- a/firmware/target/arm/as3525/ata_sd_as3525.c +++ b/firmware/target/arm/as3525/ata_sd_as3525.c | |||
@@ -28,7 +28,9 @@ | |||
28 | #include "hotswap.h" | 28 | #include "hotswap.h" |
29 | #include "system.h" | 29 | #include "system.h" |
30 | #include "cpu.h" | 30 | #include "cpu.h" |
31 | #include <stdio.h> | ||
31 | #include <stdlib.h> | 32 | #include <stdlib.h> |
33 | #include <string.h> | ||
32 | #include "as3525.h" | 34 | #include "as3525.h" |
33 | #include "pl180.h" | 35 | #include "pl180.h" |
34 | #include "panic.h" | 36 | #include "panic.h" |
@@ -41,36 +43,36 @@ | |||
41 | #endif | 43 | #endif |
42 | 44 | ||
43 | /* command flags */ | 45 | /* command flags */ |
44 | #define MMC_NO_FLAGS (0<<0) | 46 | #define MCI_NO_FLAGS (0<<0) |
45 | #define MMC_RESP (1<<0) | 47 | #define MCI_RESP (1<<0) |
46 | #define MMC_LONG_RESP (1<<1) | 48 | #define MCI_LONG_RESP (1<<1) |
47 | #define MMC_ARG (1<<2) | 49 | #define MCI_ARG (1<<2) |
48 | 50 | ||
49 | /* ARM PL180 registers */ | 51 | /* ARM PL180 registers */ |
50 | #define MMC_POWER(i) (*(volatile unsigned char *) (pl180_base[i]+0x00)) | 52 | #define MCI_POWER(i) (*(volatile unsigned char *) (pl180_base[i]+0x00)) |
51 | #define MMC_CLOCK(i) (*(volatile unsigned long *) (pl180_base[i]+0x04)) | 53 | #define MCI_CLOCK(i) (*(volatile unsigned long *) (pl180_base[i]+0x04)) |
52 | #define MMC_ARGUMENT(i) (*(volatile unsigned long *) (pl180_base[i]+0x08)) | 54 | #define MCI_ARGUMENT(i) (*(volatile unsigned long *) (pl180_base[i]+0x08)) |
53 | #define MMC_COMMAND(i) (*(volatile unsigned long *) (pl180_base[i]+0x0C)) | 55 | #define MCI_COMMAND(i) (*(volatile unsigned long *) (pl180_base[i]+0x0C)) |
54 | #define MMC_RESPCMD(i) (*(volatile unsigned long *) (pl180_base[i]+0x10)) | 56 | #define MCI_RESPCMD(i) (*(volatile unsigned long *) (pl180_base[i]+0x10)) |
55 | #define MMC_RESP0(i) (*(volatile unsigned long *) (pl180_base[i]+0x14)) | 57 | #define MCI_RESP0(i) (*(volatile unsigned long *) (pl180_base[i]+0x14)) |
56 | #define MMC_RESP1(i) (*(volatile unsigned long *) (pl180_base[i]+0x18)) | 58 | #define MCI_RESP1(i) (*(volatile unsigned long *) (pl180_base[i]+0x18)) |
57 | #define MMC_RESP2(i) (*(volatile unsigned long *) (pl180_base[i]+0x1C)) | 59 | #define MCI_RESP2(i) (*(volatile unsigned long *) (pl180_base[i]+0x1C)) |
58 | #define MMC_RESP3(i) (*(volatile unsigned long *) (pl180_base[i]+0x20)) | 60 | #define MCI_RESP3(i) (*(volatile unsigned long *) (pl180_base[i]+0x20)) |
59 | #define MMC_DATA_TIMER(i) (*(volatile unsigned long *) (pl180_base[i]+0x24)) | 61 | #define MCI_DATA_TIMER(i) (*(volatile unsigned long *) (pl180_base[i]+0x24)) |
60 | #define MMC_DATA_LENGTH(i) (*(volatile unsigned short*) (pl180_base[i]+0x28)) | 62 | #define MCI_DATA_LENGTH(i) (*(volatile unsigned short*) (pl180_base[i]+0x28)) |
61 | #define MMC_DATA_CTRL(i) (*(volatile unsigned char *) (pl180_base[i]+0x2C)) | 63 | #define MCI_DATA_CTRL(i) (*(volatile unsigned char *) (pl180_base[i]+0x2C)) |
62 | #define MMC_DATA_CNT(i) (*(volatile unsigned short*) (pl180_base[i]+0x30)) | 64 | #define MCI_DATA_CNT(i) (*(volatile unsigned short*) (pl180_base[i]+0x30)) |
63 | #define MMC_STATUS(i) (*(volatile unsigned long *) (pl180_base[i]+0x34)) | 65 | #define MCI_STATUS(i) (*(volatile unsigned long *) (pl180_base[i]+0x34)) |
64 | #define MMC_CLEAR(i) (*(volatile unsigned long *) (pl180_base[i]+0x38)) | 66 | #define MCI_CLEAR(i) (*(volatile unsigned long *) (pl180_base[i]+0x38)) |
65 | #define MMC_MASK0(i) (*(volatile unsigned long *) (pl180_base[i]+0x3C)) | 67 | #define MCI_MASK0(i) (*(volatile unsigned long *) (pl180_base[i]+0x3C)) |
66 | #define MMC_MASK1(i) (*(volatile unsigned long *) (pl180_base[i]+0x40)) | 68 | #define MCI_MASK1(i) (*(volatile unsigned long *) (pl180_base[i]+0x40)) |
67 | #define MMC_SELECT(i) (*(volatile unsigned long *) (pl180_base[i]+0x44)) | 69 | #define MCI_SELECT(i) (*(volatile unsigned long *) (pl180_base[i]+0x44)) |
68 | #define MMC_FIFO_CNT(i) (*(volatile unsigned long *) (pl180_base[i]+0x48)) | 70 | #define MCI_FIFO_CNT(i) (*(volatile unsigned long *) (pl180_base[i]+0x48)) |
69 | 71 | ||
70 | #define MMC_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) | 72 | #define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) |
71 | /* volumes */ | 73 | /* volumes */ |
72 | #define NAND_AS3525 0 | 74 | #define NAND_AS3525 0 /* embedded SD card */ |
73 | #define SD_AS3525 1 | 75 | #define SD_AS3525 1 /* SD slot if present */ |
74 | 76 | ||
75 | static const int pl180_base[NUM_VOLUMES] = { | 77 | static const int pl180_base[NUM_VOLUMES] = { |
76 | NAND_FLASH_BASE | 78 | NAND_FLASH_BASE |
@@ -87,11 +89,10 @@ static tSDCardInfo card_info[NUM_VOLUMES]; | |||
87 | /* for compatibility */ | 89 | /* for compatibility */ |
88 | static long last_disk_activity = -1; | 90 | static long last_disk_activity = -1; |
89 | 91 | ||
90 | #define MIN_YIELD_PERIOD 1000 | 92 | #define MIN_YIELD_PERIOD 5 /* ticks */ |
91 | static long next_yield = 0; | 93 | static long next_yield = 0; |
92 | 94 | ||
93 | /* Shoot for around 75% usage */ | 95 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; |
94 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; | ||
95 | static const char sd_thread_name[] = "ata/sd"; | 96 | static const char sd_thread_name[] = "ata/sd"; |
96 | static struct mutex sd_mtx SHAREDBSS_ATTR; | 97 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
97 | static struct event_queue sd_queue; | 98 | static struct event_queue sd_queue; |
@@ -100,14 +101,14 @@ static inline void mci_delay(void) { int i = 0xffff; while(i--) ; } | |||
100 | 101 | ||
101 | static void mci_set_clock_divider(const int drive, int divider) | 102 | static void mci_set_clock_divider(const int drive, int divider) |
102 | { | 103 | { |
103 | int clock = MMC_CLOCK(drive); | 104 | int clock = MCI_CLOCK(drive); |
104 | 105 | ||
105 | if(divider > 1) | 106 | if(divider > 1) |
106 | { | 107 | { |
107 | /* use divide logic */ | 108 | /* use divide logic */ |
108 | clock &= ~MCI_CLOCK_BYPASS; | 109 | clock &= ~MCI_CLOCK_BYPASS; |
109 | 110 | ||
110 | /* convert divider to MMC_CLOCK logic */ | 111 | /* convert divider to MCI_CLOCK logic */ |
111 | divider = (divider/2) - 1; | 112 | divider = (divider/2) - 1; |
112 | if(divider >= 256) | 113 | if(divider >= 256) |
113 | divider = 255; | 114 | divider = 255; |
@@ -119,7 +120,7 @@ static void mci_set_clock_divider(const int drive, int divider) | |||
119 | divider = 0; | 120 | divider = 0; |
120 | } | 121 | } |
121 | 122 | ||
122 | MMC_CLOCK(drive) = clock | divider; | 123 | MCI_CLOCK(drive) = clock | divider; |
123 | 124 | ||
124 | mci_delay(); | 125 | mci_delay(); |
125 | } | 126 | } |
@@ -129,51 +130,51 @@ static bool send_cmd(const int drive, const int cmd, const int arg, | |||
129 | { | 130 | { |
130 | int val, status; | 131 | int val, status; |
131 | 132 | ||
132 | while(MMC_STATUS(drive) & MCI_CMD_ACTIVE); | 133 | while(MCI_STATUS(drive) & MCI_CMD_ACTIVE); |
133 | 134 | ||
134 | if(MMC_COMMAND(drive) & MCI_COMMAND_ENABLE) /* clears existing command */ | 135 | if(MCI_COMMAND(drive) & MCI_COMMAND_ENABLE) /* clears existing command */ |
135 | { | 136 | { |
136 | MMC_COMMAND(drive) = 0; | 137 | MCI_COMMAND(drive) = 0; |
137 | mci_delay(); | 138 | mci_delay(); |
138 | } | 139 | } |
139 | 140 | ||
140 | val = cmd | MCI_COMMAND_ENABLE; | 141 | val = cmd | MCI_COMMAND_ENABLE; |
141 | if(flags & MMC_RESP) | 142 | if(flags & MCI_RESP) |
142 | { | 143 | { |
143 | val |= MCI_COMMAND_RESPONSE; | 144 | val |= MCI_COMMAND_RESPONSE; |
144 | if(flags & MMC_LONG_RESP) | 145 | if(flags & MCI_LONG_RESP) |
145 | val |= MCI_COMMAND_LONG_RESPONSE; | 146 | val |= MCI_COMMAND_LONG_RESPONSE; |
146 | } | 147 | } |
147 | 148 | ||
148 | MMC_CLEAR(drive) = 0x7ff; | 149 | MCI_CLEAR(drive) = 0x7ff; |
149 | 150 | ||
150 | MMC_ARGUMENT(drive) = (flags & MMC_ARG) ? arg : 0; | 151 | MCI_ARGUMENT(drive) = (flags & MCI_ARG) ? arg : 0; |
151 | MMC_COMMAND(drive) = val; | 152 | MCI_COMMAND(drive) = val; |
152 | 153 | ||
153 | while(MMC_STATUS(drive) & MCI_CMD_ACTIVE); /* wait for cmd completion */ | 154 | while(MCI_STATUS(drive) & MCI_CMD_ACTIVE); /* wait for cmd completion */ |
154 | 155 | ||
155 | MMC_COMMAND(drive) = 0; | 156 | MCI_COMMAND(drive) = 0; |
156 | MMC_ARGUMENT(drive) = ~0; | 157 | MCI_ARGUMENT(drive) = ~0; |
157 | 158 | ||
158 | status = MMC_STATUS(drive); | 159 | status = MCI_STATUS(drive); |
159 | MMC_CLEAR(drive) = 0x7ff; | 160 | MCI_CLEAR(drive) = 0x7ff; |
160 | 161 | ||
161 | if(flags & MMC_RESP) | 162 | if(flags & MCI_RESP) |
162 | { | 163 | { |
163 | if(status & MCI_CMD_TIMEOUT) | 164 | if(status & MCI_CMD_TIMEOUT) |
164 | return false; | 165 | return false; |
165 | else if(status & (MCI_CMD_CRC_FAIL /* FIXME? */ | MCI_CMD_RESP_END)) | 166 | else if(status & (MCI_CMD_CRC_FAIL /* FIXME? */ | MCI_CMD_RESP_END)) |
166 | { /* resp received */ | 167 | { /* resp received */ |
167 | if(flags & MMC_LONG_RESP) | 168 | if(flags & MCI_LONG_RESP) |
168 | { | 169 | { |
169 | /* store the response in little endian order for the words */ | 170 | /* store the response in little endian order for the words */ |
170 | response[0] = MMC_RESP3(drive); | 171 | response[0] = MCI_RESP3(drive); |
171 | response[1] = MMC_RESP2(drive); | 172 | response[1] = MCI_RESP2(drive); |
172 | response[2] = MMC_RESP1(drive); | 173 | response[2] = MCI_RESP1(drive); |
173 | response[3] = MMC_RESP0(drive); | 174 | response[3] = MCI_RESP0(drive); |
174 | } | 175 | } |
175 | else | 176 | else |
176 | response[0] = MMC_RESP0(drive); | 177 | response[0] = MCI_RESP0(drive); |
177 | return true; | 178 | return true; |
178 | } | 179 | } |
179 | } | 180 | } |
@@ -191,13 +192,13 @@ static int sd_init_card(const int drive) | |||
191 | int max_tries = 100; /* max acmd41 attemps */ | 192 | int max_tries = 100; /* max acmd41 attemps */ |
192 | bool sdhc; | 193 | bool sdhc; |
193 | 194 | ||
194 | if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MMC_NO_FLAGS, NULL)) | 195 | if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_FLAGS, NULL)) |
195 | return -1; | 196 | return -1; |
196 | 197 | ||
197 | mci_delay(); | 198 | mci_delay(); |
198 | 199 | ||
199 | sdhc = false; | 200 | sdhc = false; |
200 | if(send_cmd(drive, SD_SEND_IF_COND, 0x1AA, MMC_RESP|MMC_ARG, &response)) | 201 | if(send_cmd(drive, SD_SEND_IF_COND, 0x1AA, MCI_RESP|MCI_ARG, &response)) |
201 | if((response & 0xFFF) == 0x1AA) | 202 | if((response & 0xFFF) == 0x1AA) |
202 | sdhc = true; | 203 | sdhc = true; |
203 | 204 | ||
@@ -205,7 +206,7 @@ static int sd_init_card(const int drive) | |||
205 | mci_delay(); | 206 | mci_delay(); |
206 | 207 | ||
207 | /* app_cmd */ | 208 | /* app_cmd */ |
208 | if( !send_cmd(drive, SD_APP_CMD, 0, MMC_RESP|MMC_ARG, &response) || | 209 | if( !send_cmd(drive, SD_APP_CMD, 0, MCI_RESP|MCI_ARG, &response) || |
209 | !(response & (1<<5)) ) | 210 | !(response & (1<<5)) ) |
210 | { | 211 | { |
211 | return -2; | 212 | return -2; |
@@ -213,7 +214,7 @@ static int sd_init_card(const int drive) | |||
213 | 214 | ||
214 | /* acmd41 */ | 215 | /* acmd41 */ |
215 | if(!send_cmd(drive, SD_APP_OP_COND, (sdhc ? 0x40FF8000 : (1<<23)), | 216 | if(!send_cmd(drive, SD_APP_OP_COND, (sdhc ? 0x40FF8000 : (1<<23)), |
216 | MMC_RESP|MMC_ARG, &card_info[drive].ocr)) | 217 | MCI_RESP|MCI_ARG, &card_info[drive].ocr)) |
217 | return -3; | 218 | return -3; |
218 | 219 | ||
219 | } while(!(card_info[drive].ocr & (1<<31)) && max_tries--); | 220 | } while(!(card_info[drive].ocr & (1<<31)) && max_tries--); |
@@ -222,18 +223,18 @@ static int sd_init_card(const int drive) | |||
222 | return -4; | 223 | return -4; |
223 | 224 | ||
224 | /* send CID */ | 225 | /* send CID */ |
225 | if(!send_cmd(drive, SD_ALL_SEND_CID, 0, MMC_RESP|MMC_LONG_RESP|MMC_ARG, | 226 | if(!send_cmd(drive, SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP|MCI_ARG, |
226 | card_info[drive].cid)) | 227 | card_info[drive].cid)) |
227 | return -5; | 228 | return -5; |
228 | 229 | ||
229 | /* send RCA */ | 230 | /* send RCA */ |
230 | if(!send_cmd(drive, SD_SEND_RELATIVE_ADDR, 0, MMC_RESP|MMC_ARG, | 231 | if(!send_cmd(drive, SD_SEND_RELATIVE_ADDR, 0, MCI_RESP|MCI_ARG, |
231 | &card_info[drive].rca)) | 232 | &card_info[drive].rca)) |
232 | return -6; | 233 | return -6; |
233 | 234 | ||
234 | /* send CSD */ | 235 | /* send CSD */ |
235 | if(!send_cmd(drive, SD_SEND_CSD, card_info[drive].rca, | 236 | if(!send_cmd(drive, SD_SEND_CSD, card_info[drive].rca, |
236 | MMC_RESP|MMC_LONG_RESP|MMC_ARG, card_info[drive].csd)) | 237 | MCI_RESP|MCI_LONG_RESP|MCI_ARG, card_info[drive].csd)) |
237 | return -7; | 238 | return -7; |
238 | 239 | ||
239 | /* These calculations come from the Sandisk SD card product manual */ | 240 | /* These calculations come from the Sandisk SD card product manual */ |
@@ -259,16 +260,16 @@ static int sd_init_card(const int drive) | |||
259 | } | 260 | } |
260 | #endif | 261 | #endif |
261 | 262 | ||
262 | if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MMC_ARG, NULL)) | 263 | if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_ARG, NULL)) |
263 | return -9; | 264 | return -9; |
264 | 265 | ||
265 | if(!send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MMC_ARG, NULL)) | 266 | if(!send_cmd(drive, SD_APP_CMD, card_info[drive].rca, MCI_ARG, NULL)) |
266 | return -10; | 267 | return -10; |
267 | 268 | ||
268 | if(!send_cmd(drive, SD_SET_BUS_WIDTH, card_info[drive].rca | 2, MMC_ARG, NULL)) | 269 | if(!send_cmd(drive, SD_SET_BUS_WIDTH, card_info[drive].rca | 2, MCI_ARG, NULL)) |
269 | return -11; | 270 | return -11; |
270 | 271 | ||
271 | if(!send_cmd(drive, SD_SET_BLOCKLEN, card_info[drive].block_size, MMC_ARG, | 272 | if(!send_cmd(drive, SD_SET_BLOCKLEN, card_info[drive].block_size, MCI_ARG, |
272 | NULL)) | 273 | NULL)) |
273 | return -12; | 274 | return -12; |
274 | 275 | ||
@@ -354,23 +355,21 @@ static void sd_thread(void) | |||
354 | } | 355 | } |
355 | static void init_pl180_controller(const int drive) | 356 | static void init_pl180_controller(const int drive) |
356 | { | 357 | { |
357 | #ifdef BOOTLOADER | 358 | MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0; |
358 | MMC_COMMAND(drive) = MMC_DATA_CTRL(drive) = 0; | 359 | MCI_CLEAR(drive) = 0x7ff; |
359 | MMC_CLEAR(drive) = 0x7ff; | ||
360 | 360 | ||
361 | MMC_MASK0(drive) = MMC_MASK1(drive) = 0; /* disable all interrupts */ | 361 | MCI_MASK0(drive) = MCI_MASK1(drive) = 0; /* disable all interrupts */ |
362 | 362 | ||
363 | MMC_POWER(drive) = MCI_POWER_UP|(10 /*voltage*/ << 2); /* use OF voltage */ | 363 | MCI_POWER(drive) = MCI_POWER_UP|(10 /*voltage*/ << 2); /* use OF voltage */ |
364 | mci_delay(); | 364 | mci_delay(); |
365 | 365 | ||
366 | MMC_POWER(drive) |= MCI_POWER_ON; | 366 | MCI_POWER(drive) |= MCI_POWER_ON; |
367 | mci_delay(); | 367 | mci_delay(); |
368 | 368 | ||
369 | MMC_SELECT(drive) = 0; | 369 | MCI_SELECT(drive) = 0; |
370 | 370 | ||
371 | MMC_CLOCK(drive) = MCI_CLOCK_ENABLE; | 371 | MCI_CLOCK(drive) = MCI_CLOCK_ENABLE; |
372 | MMC_CLOCK(drive) &= ~MCI_CLOCK_POWERSAVE; | 372 | MCI_CLOCK(drive) &= ~MCI_CLOCK_POWERSAVE; |
373 | #endif /* BOOTLOADER */ | ||
374 | 373 | ||
375 | /* set MCLK divider */ | 374 | /* set MCLK divider */ |
376 | mci_set_clock_divider(drive, 200); | 375 | mci_set_clock_divider(drive, 200); |
@@ -380,7 +379,6 @@ int sd_init(void) | |||
380 | { | 379 | { |
381 | int ret; | 380 | int ret; |
382 | 381 | ||
383 | #ifdef BOOTLOADER /* No need to do twice the same thing */ | ||
384 | CGU_IDE = (1<<7) /* AHB interface enable */ | | 382 | CGU_IDE = (1<<7) /* AHB interface enable */ | |
385 | (1<<6) /* interface enable */ | | 383 | (1<<6) /* interface enable */ | |
386 | (2<<2) /* clock didiver = 2+1 */ | | 384 | (2<<2) /* clock didiver = 2+1 */ | |
@@ -391,16 +389,15 @@ int sd_init(void) | |||
391 | CGU_PERI |= CGU_MCI_CLOCK_ENABLE; | 389 | CGU_PERI |= CGU_MCI_CLOCK_ENABLE; |
392 | #endif | 390 | #endif |
393 | 391 | ||
394 | CCU_IO &= ~8; /* bits 3:2 = 01, xpd is SD interface */ | ||
395 | CCU_IO |= 4; | ||
396 | |||
397 | #endif | ||
398 | init_pl180_controller(NAND_AS3525); | 392 | init_pl180_controller(NAND_AS3525); |
399 | ret = sd_init_card(NAND_AS3525); | 393 | ret = sd_init_card(NAND_AS3525); |
400 | if(ret < 0) | 394 | if(ret < 0) |
401 | return ret; | 395 | return ret; |
402 | 396 | ||
403 | #ifdef HAVE_MULTIVOLUME | 397 | #ifdef HAVE_MULTIVOLUME |
398 | CCU_IO &= ~8; /* bits 3:2 = 01, xpd is SD interface */ | ||
399 | CCU_IO |= 4; | ||
400 | |||
404 | init_pl180_controller(SD_AS3525); | 401 | init_pl180_controller(SD_AS3525); |
405 | ret = sd_init_card(SD_AS3525); | 402 | ret = sd_init_card(SD_AS3525); |
406 | if(ret < 0) | 403 | if(ret < 0) |
@@ -451,36 +448,39 @@ int sd_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const vo | |||
451 | (void)start; | 448 | (void)start; |
452 | (void)count; | 449 | (void)count; |
453 | (void)buf; | 450 | (void)buf; |
454 | return 0; /* TODO */ | 451 | return -1; /* TODO */ |
455 | } | 452 | } |
456 | 453 | ||
457 | static bool sd_poll_status(const int drive, unsigned int trigger, long timeout) | 454 | static int sd_poll_status(const int drive, unsigned int trigger, long timeout) |
458 | { | 455 | { |
459 | long t = current_tick; | 456 | long t = current_tick; |
457 | //int my_next_yield =0; | ||
458 | int status; | ||
460 | 459 | ||
461 | while ((MMC_STATUS(drive) & trigger) == 0) | 460 | while (((status = MCI_STATUS(drive)) & trigger) == 0) |
462 | { | 461 | { |
463 | long time = current_tick; | 462 | long time = current_tick; |
464 | 463 | ||
465 | if (TIME_AFTER(time, next_yield)) | 464 | /* |
465 | if (TIME_AFTER(time, my_next_yield)) | ||
466 | { | 466 | { |
467 | long ty = current_tick; | 467 | long ty = current_tick; |
468 | yield(); | 468 | yield(); |
469 | timeout += current_tick - ty; | 469 | timeout += current_tick - ty; |
470 | next_yield = ty + MIN_YIELD_PERIOD; | 470 | my_next_yield = ty + MIN_YIELD_PERIOD; |
471 | } | 471 | } |
472 | 472 | */ | |
473 | if (TIME_AFTER(time, t + timeout)) | 473 | if (TIME_AFTER(time, t + timeout)) |
474 | return false; | 474 | break; |
475 | } | 475 | } |
476 | 476 | ||
477 | return true; | 477 | return status; |
478 | } | 478 | } |
479 | 479 | ||
480 | static int sd_wait_for_state(const int drive, unsigned int state) | 480 | static int sd_wait_for_state(const int drive, unsigned int state) |
481 | { | 481 | { |
482 | unsigned int response = 0; | 482 | unsigned int response = 0; |
483 | unsigned int timeout = 0x80000; | 483 | unsigned int timeout = 100; /* ticks */ |
484 | 484 | ||
485 | long t = current_tick; | 485 | long t = current_tick; |
486 | 486 | ||
@@ -489,7 +489,7 @@ static int sd_wait_for_state(const int drive, unsigned int state) | |||
489 | long us; | 489 | long us; |
490 | 490 | ||
491 | if(!send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, | 491 | if(!send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, |
492 | MMC_RESP|MMC_ARG, &response)) | 492 | MCI_RESP|MCI_ARG, &response)) |
493 | return -1; | 493 | return -1; |
494 | 494 | ||
495 | if (((response >> 9) & 0xf) == state) | 495 | if (((response >> 9) & 0xf) == state) |
@@ -517,14 +517,14 @@ int sd_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | |||
517 | int ret; | 517 | int ret; |
518 | unsigned char *buf_end, *buf = inbuf; | 518 | unsigned char *buf_end, *buf = inbuf; |
519 | int remaining = incount; | 519 | int remaining = incount; |
520 | const unsigned long *fifo_base = MMC_FIFO(drive); | 520 | const unsigned long *fifo_base = MCI_FIFO(drive); |
521 | 521 | ||
522 | /* skip SanDisk OF */ | 522 | /* skip SanDisk OF */ |
523 | if (drive == NAND_AS3525) | 523 | if (drive == NAND_AS3525) |
524 | #if defined(SANSA_E200V2) || defined(SANSA_FUZE) | 524 | #if defined(SANSA_E200V2) || defined(SANSA_FUZE) |
525 | start += 61440; | 525 | start += 61440; |
526 | #else | 526 | #else |
527 | start += 20480; | 527 | start += 20480; |
528 | #endif | 528 | #endif |
529 | /* TODO: Add DMA support. */ | 529 | /* TODO: Add DMA support. */ |
530 | 530 | ||
@@ -542,6 +542,7 @@ int sd_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | |||
542 | if (card_info[drive].initialized < 0) | 542 | if (card_info[drive].initialized < 0) |
543 | { | 543 | { |
544 | ret = card_info[drive].initialized; | 544 | ret = card_info[drive].initialized; |
545 | panicf("card not initalised"); | ||
545 | goto sd_read_error; | 546 | goto sd_read_error; |
546 | } | 547 | } |
547 | 548 | ||
@@ -549,7 +550,13 @@ int sd_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | |||
549 | 550 | ||
550 | ret = sd_wait_for_state(drive, SD_TRAN); | 551 | ret = sd_wait_for_state(drive, SD_TRAN); |
551 | if (ret < 0) | 552 | if (ret < 0) |
553 | { | ||
554 | panicf("wait for state failed"); | ||
552 | goto sd_read_error; | 555 | goto sd_read_error; |
556 | } | ||
557 | |||
558 | disable_irq(); /* FIXME: data transfer is too slow and error prone when | ||
559 | * interrupts are enabled */ | ||
553 | 560 | ||
554 | while(remaining) | 561 | while(remaining) |
555 | { | 562 | { |
@@ -558,20 +565,22 @@ int sd_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | |||
558 | int transfer = (remaining >= 128) ? 127 : remaining; /* sectors */ | 565 | int transfer = (remaining >= 128) ? 127 : remaining; /* sectors */ |
559 | 566 | ||
560 | if(card_info[drive].ocr & (1<<30) ) /* SDHC */ | 567 | if(card_info[drive].ocr & (1<<30) ) /* SDHC */ |
561 | ret = send_cmd(drive, SD_READ_MULTIPLE_BLOCK, start, MMC_ARG, NULL); | 568 | ret = send_cmd(drive, SD_READ_MULTIPLE_BLOCK, start, MCI_ARG, NULL); |
562 | else | 569 | else |
563 | ret = send_cmd(drive, SD_READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, | 570 | ret = send_cmd(drive, SD_READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, |
564 | MMC_ARG, NULL); | 571 | MCI_ARG, NULL); |
565 | 572 | ||
566 | if (ret < 0) | 573 | if (ret < 0) |
574 | { | ||
575 | panicf("read multiple blocks failed"); | ||
567 | goto sd_read_error; | 576 | goto sd_read_error; |
568 | 577 | } | |
569 | /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ | 578 | /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ |
570 | 579 | ||
571 | 580 | ||
572 | MMC_DATA_TIMER(drive) = 0x1000000; /* FIXME: arbitrary */ | 581 | MCI_DATA_TIMER(drive) = 0x1000000; /* FIXME: arbitrary */ |
573 | MMC_DATA_LENGTH(drive) = transfer * card_info[drive].block_size; | 582 | MCI_DATA_LENGTH(drive) = transfer * card_info[drive].block_size; |
574 | MMC_DATA_CTRL(drive) = (1<<0) /* enable */ | | 583 | MCI_DATA_CTRL(drive) = (1<<0) /* enable */ | |
575 | (1<<1) /* from card to controller */ | | 584 | (1<<1) /* from card to controller */ | |
576 | (9<<4) /* 2^9 = 512 */ ; | 585 | (9<<4) /* 2^9 = 512 */ ; |
577 | 586 | ||
@@ -580,43 +589,68 @@ int sd_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | |||
580 | while(buf < buf_end) | 589 | while(buf < buf_end) |
581 | { | 590 | { |
582 | /* Wait for the FIFO to be half full */ | 591 | /* Wait for the FIFO to be half full */ |
583 | if (!sd_poll_status(drive, ((1<<15)), 100)) | 592 | const int trigger = MCI_RX_FIFO_HALF_FULL|MCI_RX_FIFO_FULL; |
584 | { | 593 | int controller_status = sd_poll_status(drive, trigger, 100); |
585 | ret = -42; | 594 | |
586 | goto sd_read_error; | 595 | controller_status &= ~(MCI_RX_ACTIVE|MCI_RX_DATA_AVAIL| |
596 | MCI_DATA_BLOCK_END|MCI_DATA_END); | ||
597 | |||
598 | if(!controller_status || (controller_status & ~trigger)) | ||
599 | panicf("incorrect status 0x%x", controller_status & ~trigger); | ||
600 | |||
601 | if(((intptr_t)buf & 3) == 0) | ||
602 | { /* aligned destination buffer */ | ||
603 | asm volatile( | ||
604 | "ldmia %2, {r0-r7} \n" /* load 8 * 4 bytes */ | ||
605 | "stmia %1!, {r0-r7} \n" /* store 8 * 4 bytes */ | ||
606 | :"=r"(buf) /* output */ | ||
607 | :"r"(buf), "r"(fifo_base) /* input */ | ||
608 | :"r0","r1","r2","r3","r4","r5","r6","r7" /* clobbers */ | ||
609 | ); | ||
610 | } | ||
611 | else | ||
612 | { /* non aligned destination buffer */ | ||
613 | int tmp[8]; | ||
614 | asm volatile( | ||
615 | "ldmia %1, {r0-r7} \n" /* load 8 * 4 bytes */ | ||
616 | "stmia %0, {r0-r7} \n" /* store 8 * 4 bytes */ | ||
617 | :/* no output */ | ||
618 | :"r"(tmp), "r"(fifo_base) /* input */ | ||
619 | :"r0","r1","r2","r3","r4","r5","r6","r7" /* clobbers */ | ||
620 | ); | ||
621 | memcpy(buf, tmp, 32); | ||
622 | buf = &buf[32]; | ||
587 | } | 623 | } |
588 | |||
589 | asm volatile( | ||
590 | "ldmia %2, {r0-r7} \n" /* load 8 * 4 bytes */ | ||
591 | "stmia %1!, {r0-r7} \n" /* store 8 * 4 bytes */ | ||
592 | :"=r"(buf) /* output */ | ||
593 | :"r"(buf), "r"(fifo_base) /* input */ | ||
594 | :"r0","r1","r2","r3","r4","r5","r6","r7","r8" /* clobbers */ | ||
595 | ); | ||
596 | } | 624 | } |
597 | 625 | ||
598 | remaining -= transfer; | 626 | remaining -= transfer; |
599 | start += transfer; | 627 | start += transfer; |
600 | last_disk_activity = current_tick; | 628 | last_disk_activity = current_tick; |
601 | 629 | ||
602 | if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MMC_NO_FLAGS, NULL)) | 630 | if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_NO_FLAGS, NULL)) |
603 | { | 631 | { |
604 | ret = -666; | 632 | ret = -666; |
633 | panicf("STOP TRANSMISSION failed"); | ||
605 | goto sd_read_error; | 634 | goto sd_read_error; |
606 | } | 635 | } |
607 | 636 | ||
608 | ret = sd_wait_for_state(drive, SD_TRAN); | 637 | ret = sd_wait_for_state(drive, SD_TRAN); |
609 | if (ret < 0) | 638 | if (ret < 0) |
639 | { | ||
640 | panicf(" wait for state TRAN failed"); | ||
610 | goto sd_read_error; | 641 | goto sd_read_error; |
611 | 642 | } | |
612 | } | 643 | } |
613 | while (1) | 644 | while (1) |
614 | { | 645 | { |
615 | mutex_unlock(&sd_mtx); | 646 | mutex_unlock(&sd_mtx); |
616 | 647 | ||
648 | enable_irq(); | ||
649 | |||
617 | return ret; | 650 | return ret; |
618 | 651 | ||
619 | sd_read_error: | 652 | sd_read_error: |
653 | panicf("read error : %d",ret); | ||
620 | card_info[drive].initialized = 0; | 654 | card_info[drive].initialized = 0; |
621 | } | 655 | } |
622 | } | 656 | } |